dtlibs.xos

A collection of functions which extend os, os.path and shutil.

class dtlibs.xos.Filename(name, relative=None)

Intelligently handle a file path.

The filename is broken down into basepath/relpath/basename.extension. basepath and relpath always end in a trailing slash, and extension, if it exists starts with a .. This means that the the full path is always basepath + relpath + basename + extension.

If relpath or extension are not used, then it they are an empty string.

In addition, the following properties are supported:

Property Return value
fullname basepath/relpath/basename.extension
relname relpath/basename.extension
path basepath/relpath
filename basename.extension

The extension is interpreted to be at the first .. All paths returned are normalised using normpath().

Examples:

>>> path = Filename('/tmp/folder/and/file.ext', '/tmp/folder')
>>> path.basepath
'/tmp/folder/'
>>> path.relname
'and/file.ext'
>>> path.fullname
'/tmp/folder/and/file.ext'
>>> path.path
'/tmp/folder/and/'
>>> path.filename
'file.ext'
>>> Filename('/path/file').extension
''
>>> Filename('/path/file').fullname
'/path/file'
basename
basepath
exists()
extension
filename
fullname
path
relname
relpath
dtlibs.xos.create(file, mode=None)

Similar to builtin open(), but raise an exception if file exists.

The mode can be specified as for open(), but cannot contain read, write, update or append modes, since the file created is always opened in write mode.

dtlibs.xos.getfiles(path)

Return a generator of Filename objects for each file in path.

Each Filename object returned represents a single file in a tree relative to path. Directories are ignored.

dtlibs.xos.hasroot(path, root)

Return true if path has the root specified.

>>> hasroot('/usr/share/doc/python32', '/usr/share')
True
>>> hasroot('../folder', '../')
True
>>> hasroot('/usr/share', '/usr/sh')
False
dtlibs.xos.iswindowspath(path)

Return true if path is recognised as having a drive letter.

>>> iswindowspath('c:\windows')
True
>>> iswindowspath('c:/windows')
True
>>> iswindowspath('/usr/share')
False
dtlibs.xos.levels(path, root=None)

Return the number of levels in the path relative to root.

The following conditions are fulfilled:

  1. If root is missing, then path is not relative to anything (even if it is a relative path), and levels is always a number with the exception of cases defined by 5. below.
  2. If root is absolute and path is relative, then paths is assumed to be relative to root. In this case levels(path, root) gives the same result as levels(path, None).
  3. If root is relative then path must also be relative, or None is returned.
  4. If root and path are both relative then they are assume to be relative to the same position. i.e. levels('share/doc', 'lib') is the same as levels('/share/doc', '/lib').
  5. If the final path, relative to root, has negative levels (e.g. ‘../share’), then None will be returned.
  6. On windows, the drive letter is used in the comparison, but is not counted as a level.
dtlibs.xos.normpath(path)

Similar to os.path.normpath(), but not dependant on OS.

This always returns the same string, regardless of operating system. Note that this can result in an incorrect path on unusual systems.

For example, the following should work on any system:

>>> normpath(r'\usr/local')
'/usr/local'
>>> normpath(r'c:\windows\system')
'c:/windows/system'
dtlibs.xos.remove_empty(root)

Remove all empty directories in root, including subfolders.

class dtlibs.xos.safewriter(name, text=False, backup=None)

Provide a safe environment for writing files.

safewriter is a context manager which acts similar to the file object returned by open(). However, it works by writing to a temporary file first, so that data is not lost if for any reason the write fails.

safewriter is typically instantiated as a context manager:

with safewriter('file') as f:
    f.write(b'spam')

If an exception occurs before the context manager exits, the temporary file is removed and the original data left untouched. If the write is a success, the temporary file is renamed to the target filename, after optionally backing the target up.

This is all done as safely as possible, given the provisions of tempfile.mkstemp() and os.rename(). Under normal circumstances, the only possibility of a race condition is that a new file with the same name as the target could be created after the target is removed and before the temporary file is renamed. This will only be possible on certain platforms where os.rename() does not automatically overwrite.

abort()
close()
name

Return the name of the file to be written to.

This allows for writing to files using custom methods requiring a name, e.g. as a sqlite database:

with safewriter('database.sqlite') as f:
    conn = sqlite.connect(f.name)
    ... # write stuff to database
    conn.close()
dtlibs.xos.walkstats(root)

Iterate over the dirs in path and yield (base, stats) tuples.

Each stats object is itself a dict of {path: stats} within root. path is the relative path, but is not recursive. i.e. the first iteration of walkstats('/usr') would include, for example, ‘/usr/share’ but not ‘/usr/share/doc’