[Bf-python] Extending Blender's Python API: expandpath(), GetAbsolutePath(), Get('scenefile'), Get('scenefiledir'), image.filenameAbsolute

Dietrich Bollmann diresu at web.de
Mon Jul 30 09:04:58 CEST 2007


Hi Campbell Barton,

after a while - the patch with 'Blender.sys.cleanpath()'.

On Tue, 2007-07-17 at 23:55 +1000, Campbell Barton wrote:
> Hi, quick reply on these topics....
> 1)
> Blender.GetAbsolutePath()
> This would be good, though Id do a little differently
> 
> use sys.expandpath
> ADD sys.cleanpath
> 
> cleanpath would deal with removing ../foo/../foo/.
> and expandpath makes absolute.

Ok - I posted the patch with 'Blender.sys.cleanpath()' on the 
Blender patch tracker:
https://projects.blender.org/tracker/index.php?func=detail&aid=6986&group_id=9&atid=127

A simple example:

  >>> Blender.sys.cleanpath('/foo//bar/./dummy/../baz')
  '/foo/bar/baz'

The blender convention to start paths relative to the current
Blender file with the prefix '//' is preserved:

  >>> Blender.sys.cleanpath('/foo/bar')
  '/foo/bar'
  >>> Blender.sys.cleanpath('//foo/bar')
  '//foo/bar'
  >>> Blender.sys.cleanpath('///foo/bar')
  '//foo/bar'

The pattern '/../' is only reduced as much as the given path allowes:

  >>> Blender.sys.cleanpath('/foo/bar/../../../baz')
  '/../baz'
  >>> Blender.sys.cleanpath('//foo/bar/../../../baz')
  '//../baz'

I based my code on a rework of the function `BLI_cleanup_dir()' in
file blender/source/blender/blenlib/intern/util.c.  Here are some of
the simpler problematic cases which where wrongly reduced by the
original version of `BLI_cleanup_dir()':

  >>> Blender.sys.cleanpath('/foo//../')   
  '/'
  >>> Blender.sys.cleanpath('/foo/./../')
  '/'
  >>> Blender.sys.cleanpath('/foo/../../')
  '/../'

A more complicated example :)
  
  >>>
Blender.sys.cleanpath('///one/two///././//./three//.///./././four/../..//././///..//..//./../foo///.//.//
dummy/..//./bar//five/six/../seven/.///./..//./..///./baz')
  '//../foo/bar/baz'

There are also two simple scripts to test the function:

- on unix / linux:
  
  blender -P test-blender-sys-cleanpath-unix.py

- on windows (hope the windows tests are ok):

  blender -P test-blender-sys-cleanpath-win.py 

The code was only tested with the blender 2.44 sources on linux as this
is the only OS I have - I hope it works for Mac and MS also. If there
are any problems please let me know.

Thanks for your help - and congratulations for being a "Digital
Pioneer" in beautiful Amsterdam for such a nice long time :)

Dietrich

> 2)
>  >   - Blender.Get('scenefile')
>  >   - Blender.Get('scenefiledir')
> 
> Dosnt 'filename' do this?
> and for the dir...
>    sys.dirname(Blender.Get('filename'))
> 
> 
> 3)
> I find sys.expandpath(image.filename) is fine to pass on to the 
> operating system or for pythons own file arguments, only bad thing is 
> the ..//../ in the path but the OS supports that.
> 
> 4) - Sounds like a bug- do you mean the icon in the image menu?
should 
> probably be cleared when python reloads.
> 
> 
> 
> 
> Dietrich Bollmann wrote:
> > Hi,
> > 
> > I needed some functionality to get the absolute path of a texture
> > image - and as I couldn't find anything and nobody responded to my
> > posting ( http://www.blender.org/forum/viewtopic.php?p=62764#62764 )
> > I finally implemented my own method:
> > 
> >   Blender.GetAbsolutePath()
> > 
> > Example:
> > 
> >   the scene file is '/home/dietrich/blender/scene/cube.blend'
> > 
> >   >>> Blender.GetAbsolutePath('//../foo/bar')
> >   '/home/dietrich/blender/foo/bar'
> > 
> > Today by chance I found the function `Blender.sys.expandpath()'
> > which more or less does what I want - but not as nice as my 
> > function, as the returned path is not brought into the 
> > canonical form (/.//foo/../bar/./ --> /bar/):
> > 
> >   >>>
> >
Blender.sys.expandpath('//../.././/.///.././/../././foo//././/.////one/./two/../three/../../bar')
> > 
> >
'/home/dietrich/blender/yafray/textures/tiles/exp/../.././/.///.././/../././foo//././/.////one/./two/../three/../../bar'
> >   >>>
> >
Blender.GetAbsolutePath('//../.././/.///.././/../././foo//././/.////one/./two/../three/../../bar')
> >   '/home/dietrich/blender/foo/bar'
> > 
> > I thought to create a patch with my new function but now don't know
> > how to proceed...
> > 
> > Different ideas are:
> > 
> >   - leave my new function as it is (`Blender.GetAbsolutePath()')
> >     probably not a good idea as there would be two similar functions
> >     at different places
> >     
> >   - rename my function to `Blender.sys.expandpathSimplify()'
> > 
> >   - put my function into `expandpath()'
> > 
> >   - give the function `expandpath()' a second facultative argument
> >     which might be 'raw' or 'simplify' with one of the two the
default
> > 
> >   - make a third function `simplify()' which could be used to
simplify
> >     whatever path there is
> > 
> >   - other ideas?
> > 
> > What do you think would be best?
> > 
> > 
> > * second question
> > 
> > I implemented two new setting keys usable with Blender.Get() as I
> > couldn't find anything similar in the documentation:
> > 
> >   - Blender.Get('scenefile')
> >   - Blender.Get('scenefiledir')
> > 
> > The first returnes the path of the scenefile, the second its
> > directory:
> > 
> >   >>> Blender.Get('scenefile')
> >   '/home/dietrich/blender/scene/cube.blend'
> >   >>> Blender.Get('scenefiledir')
> >   '/home/dietrich/blender/scene/'
> > 
> > I this usable for others also and should I make it a patch?
> > 
> > 
> > * third question
> > 
> > My first solution to my problem - obtaining the absolute path of an
> > image - was to implement `image.filenameAbsolute':
> > 
> > Example:
> > 
> >   with the scene file:  '/home/dietrich/blender/scene/cube.blend'
> >   and the image:        '//../tex/stone.png'
> > 
> >   >>> image.filenameAbsolute
> >   '/home/dietrich/blender/tex/stone.png'
> > 
> > which would result in the same as:
> >   
> >   >>> Blender.GetAbsolutePath(image.filename)
> >   '/home/dietrich/blender/tex/stone.png'
> > 
> > Is this worth a path?  Or should people just use something like the
> > second form?
> > 
> > 
> > * a last question
> > 
> > When loading a new image into a texture with:
> > 
> >   >>> image.filenameAbsolute =
'/home/dietrich/blender/tex/stone.png'
> >   >>> image.reload()
> > 
> > and redrawing the windows with  
> > 
> >   >>> Blender.Redraw()
> > 
> > or  
> > 
> >   >>> Blender.Window.RedrawAll()
> > 
> > The image preview window still shows the old image.  Only hitting
the
> > [Reload] button on the GUI or reselecting the images in the outliner
> > etc. redraws the preview window.
> > 
> > Is this a bug?  Is there some other redraw function?
> > 
> > Sorry for too many subjects in one mail and thanks for your help :)
> > 
> > Dietrich
> > 
> > 
> > _______________________________________________
> > Bf-python mailing list
> > Bf-python at blender.org
> > http://lists.blender.org/mailman/listinfo/bf-python
> > 
> 
> 







More information about the Bf-python mailing list