37. path
— Object oriented filesystem paths.¶
This module defines the Path class which is used throughout pyFormex for handling filesystem paths.
The Path class provides object oriented handling of filesystem paths.
It has many similarities to the classes in the pathlib
module of
Python3. But there are some important differences and these are
mostly inpired by the specialized requirements of pyFormex as opposed
to the more general requirements of Python.
Our Path class derives from Python’s str
. This was almost a necessity,
because pyFormex uses a lot of external programs with their own file
naming rules. Very often we need string methods to build the proper
file names. The constant switching between Path and str is a real
hindrance in using the Python pathlib classes. Because our Path is a
str, it can be used immediately in all places and all functions as
before, which allowed for a gradual transition from using os.path and
other modules to our Path.
Unlike pathlib, we do not discern between pure paths and concrete paths. The basic usage of a file path in pyFormex is to use the file. There is hardly a need for file paths besides concrete paths.
While pyFormex is currently almost exclusively used on Linux, the Path class makes it rather straightforward to port it to other OSes, as all the path related code is concentrated in a single module.
Despite the differences, there are also quite some similarities with the pathlib classes. Most of the methods are named likewise, so that even changing to the use of pathlib could be done inside this single module.
Our Path class has however a lot more methods available that those of pathlib. Since we are not bound to pathlib, we can as well move all path and file related functionally into this module and extend the Path class with any interesting functionality that has common use.
In order for this module to be of general use however, we have kept things that are strictly pyFormex oriented out of this module.
This version is for Python3 only. See pyFormex 1.0.7 for a version that supports both Python2.7 and Python3.x.
37.1. Classes defined in module path¶
-
class
path.
Path
[source]¶ A filesystem path which also behaves like a str.
A Path instance represents a valid path to a file in the filesystem, existing or not. Path is thus a subclass of str that can only represent strings that are valid as file paths. The constructor will always normalize the path.
Parameters: args (path_like, …) – One or more path components that will be concatenated to form the new Path. Each component can be a str or a Path. It can be relative or absolute. If multiple absolute components are specified, the last one is used. The following all create the same Path:
>>> Path('/pyformex/gui/menus') Path('/pyformex/gui/menus') >>> Path('/pyformex', 'gui', 'menus') Path('/pyformex/gui/menus') >>> Path('/pyformex', Path('gui'), 'menus') Path('/pyformex/gui/menus')
But this is different:
>>> Path('/pyformex', '/gui', 'menus') Path('/gui/menus')
Spurious slashes and single and double dots are collapsed:
>>> Path('/pyformex//gui///menus') Path('/pyformex/gui/menus') >>> Path('/pyformex/./gui/menus') Path('/pyformex/gui/menus') >>> Path('/pyformex/../gui/menus') Path('/gui/menus')
Note
The collapsing of double dots is different from the
pathlib
behavior. Our Path class follows theos.path.normpath()
behavior here.Operators: The slash operator helps create child paths, similarly to
os.path.join()
. The plus operator can be used to add a trailing part without a slash separator. The equal operator allows comparing paths.>>> p = Path('/etc') / 'init.d' / 'apache2' >>> p Path('/etc/init.d/apache2') >>> p + '.d' Path('/etc/init.d/apache2.d') >>> p1 = Path('/etc') + '/init.d/apache2' >>> p1 == p True
Note
Unlike the
pathlib
, our Path class does not provide the possibility to join a str and a Path with a slash operator: the first component must be a Path.Properties: The following properties give access to different components of the Path:
parts
: a tuple with the various parts of the Path,parent
: the parent directory of the Pathparents
: a tuple with the subsequent parent Pathsname
: a string with the final component of the Pathsuffix
: the file extension of the final component, if anystem
: the final component without its suffixlsuffix
: the suffix in lower caseftype
: the suffix in lower case and without the leading dot
Note
We currently do not have the following properties available with pathlib: drive, root, anchor, suffixes
Examples
>>> Path('/a/b') Path('/a/b') >>> Path('a/b//c') Path('a/b/c') >>> Path('a/b/./c') Path('a/b/c') >>> Path('a/b/../c') Path('a/c') >>> Path('a/b/.../c') Path('a/b/.../c') >>> Path('//a/b') Path('//a/b') >>> Path('///a/b') Path('/a/b') >>> p = Path('/etc/init.d/') >>> p.parts ('/', 'etc', 'init.d') >>> p.parent Path('/etc') >>> p.parents (Path('/etc'), Path('/')) >>> p0 = Path('pyformex/gui/menus') >>> p0.parts ('pyformex', 'gui', 'menus') >>> p0.parents (Path('pyformex/gui'), Path('pyformex'), Path('.')) >>> Path('../pyformex').parents (Path('..'), Path('.')) >>> p.name 'init.d' >>> p.stem 'init' >>> p.suffix '.d' >>> p1 = Path('Aa.Bb') >>> p1.suffix, p1.lsuffix, p1.ftype ('.Bb', '.bb', 'bb') >>> p.exists() True >>> p.is_dir() True >>> p.is_file() False >>> p.is_symlink() False >>> p.is_absolute() True >>> Path('/var/run').is_symlink() True
-
parts
¶ Split the Path in its components.
Returns: tuple of str – The various components of the Path Examples
>>> Path('/a/b/c/d').parts ('/', 'a', 'b', 'c', 'd') >>> Path('a/b//d').parts ('a', 'b', 'd') >>> Path('a/b/./d').parts ('a', 'b', 'd') >>> Path('a/b/../d').parts ('a', 'd') >>> Path('a/b/.../d').parts ('a', 'b', '...', 'd')
-
parents
¶ Return the parents of the Path.
Returns: tuple of Path – The subsequent parent directories of the Path
-
parent
¶ Return the parent directory.
Returns: Path – The parent directory of the Path.
-
name
¶ Return the final path component.
Returns: str – The final component of the Path.
-
stem
¶ Return the final path component without its suffix.
Returns: str – The final component of the Path without its suffix
.Examples
>>> Path('aA.bB').stem 'aA'
-
suffix
¶ Return the file extension of the Path component.
The file extension is the last substring of the final component starting at a dot that is neither the start nor the end of the component.
Returns: str – The file extension of the Path, including the leading dot. Examples
>>> Path('aA.bB').suffix '.bB'
-
lsuffix
¶ Return the file extension in lower case.
Returns: str – The suffix of the Path, converted to lower case. Examples
>>> Path('aA.bB').lsuffix '.bb'
-
ftype
¶ Return the file extension in lower case and with the leading dot.
Returns: str – The lsuffix of the Path without the leading dot. Examples
>>> Path('aA.bB').ftype 'bb'
-
without_suffix
¶ Return the Path without the suffix.
The file suffix is the last substring of the final component starting at a dot that is neither the start nor the end of the component.
Returns: Path – The Path without the suffix. Notes
This is equivalent to:
self.parent / self.stem
If the path has no suffix, the output is identical to the input.
Examples
>>> f = Path('/dD/aA.bB') >>> f.without_suffix Path('/dD/aA') >>> f.parent / f.stem Path('/dD/aA')
-
is_badlink
()[source]¶ Return True if the Path exists and is a bad symlink
A bad symlink is a symlink that points to a non-existing file
-
is_absolute
()[source]¶ Return True if the Path is absolute.
The Path is absolute if it start with a ‘/’.
>>> Path('/a/b').is_absolute() True >>> Path('a/b').is_absolute() False
-
with_name
(name)[source]¶ Return a new Path with the filename changed.
Parameters: name (str) – Name to replace the last component of the Path Returns: Path – A Path where the last component has been changed to name
.Examples
>>> Path('data/testrun.inp').with_name('testimg.png') Path('data/testimg.png')
-
with_suffix
(suffix)[source]¶ Return a new Path with the suffix changed.
Parameters: suffix (str) – Suffix to replace the last component’s suffix()
. The replacement string will normally start with a dot. If it doesn’t, not dot is added. See Examples.Returns: Path – A Path where the suffix of the last component has been changed to suffix
.Examples
>>> Path('data/testrun.inp').with_suffix('.cfg') Path('data/testrun.cfg') >>> Path('data/testrun.inp').with_suffix('_1.inp') Path('data/testrun_1.inp')
-
absolute
()[source]¶ Return an absolute version of the path.
Returns: Path – The absolute filesystem path of the Path. This also works if the Path does not exist. It does not resolve symlinks. See also
resolve()
- return an absolute path resolving any symlinks.
Examples
>>> Path('.').absolute() # doctest: +ELLIPSIS Path('/home/.../pyformex') >>> Path('something').absolute() # doctest: +ELLIPSIS Path('/home/.../pyformex/something')
-
resolve
()[source]¶ Return absolute path resolving all symlinks.
Returns: Path – The absolute filesystem path of the Path, resolving all symlinks. This also works if any of the Path components does not exist. Examples
>>> Path('/var/run').resolve() Path('/run') >>> Path('something/inside').resolve() # doctest: +ELLIPSIS Path('/home/.../pyformex/something/inside')
-
expanduser
()[source]¶ Expand the ~ and ~user in Path.
A leading ‘~’ in the Path is expanded tot the home directory of the user executing the code. A leading ‘~user’ is expanded to the home directory of the user named ‘user’.
Returns: Path – The Path with ~ and ~user expanded, the latter only if user exists. Examples
>>> Path('~').expanduser() # doctest: +ELLIPSIS Path('/home/...') >>> Path('~root').expanduser() Path('/root')
-
as_uri
()[source]¶ Return the Path as an URI.
Returns: str – A string starting with ‘file://’ followed by the resolved absolute path of the Path. Also ~ and ~user are expanded (if user exists). Examples
>>> Path('~/some/file.html').as_uri() # doctest: +ELLIPSIS 'file:///home/.../some/file.html'
-
samefile
(other_file)[source]¶ Test whether two pathnames reference the same actual file
Parameters: other (path_like) – Another file path to compare with. Returns: bool – True if the other file is actually the same file as self. Examples
>>> Path.home().samefile(Path('~').expanduser()) True
-
commonprefix
(*other)[source]¶ Return the longest common leading part in a list of paths.
Parameters: *other (one or more path_like) – Other file path(s) to compare with. Returns: Path – The longest common leading part in all the file paths. Examples
>>> p = Path('/etc/password') >>> q = Path('/etc/profile') >>> p.commonprefix(p,q,'/etc/pam.d') Path('/etc/p') >>> p.commonprefix(p,q,'/etc/group') Path('/etc') >>> p.commonpath(p,q,'/etc/pam.d') Path('/etc')
-
commonpath
(*other)[source]¶ Return the longest common sub-path in a list of paths.
Parameters: *other (one or more path_like) – Other file path(s) to compare with. Returns: Path – The longest common sub-path in all the file paths. Examples
>>> p = Path('/etc/password') >>> p.commonpath(p,'/etc/pam.d') Path('/etc')
-
joinpath
(*other)[source]¶ Join two or more path components.
Parameters: *other (one or more path_like) – Other path components to join to self. Notes
This alternative to using the slash operator is especially useful if the components are a computed and/or long sequence.
Examples
>>> home = Path.home() >>> p1 = home.joinpath('.config', 'pyformex', 'pyformex.conf') >>> p2 = home / '.config' / 'pyformex' / 'pyformex.conf' >>> p1 == p2 True
-
relative_to
(other)[source]¶ Return a relative path version of a path.
Parameters: other (path_like) – Another file path to compare with. Returns: Path – Path relative to other pointing to same file as self. See also
absolute()
- make a Path absolute
Examples
>>> p1 = Path('/usr/local/bin') >>> p2 = p1.relative_to('/usr/bin') >>> p2 Path('../local/bin') >>> p2.absolute() # doctest: +ELLIPSIS Path('/home/.../local/bin')
-
mkdir
(mode=509, parents=False, exist_ok=False)[source]¶ Create a directory.
Parameters: - mode (int) – The mode to be set on the created directory.
- parents (bool) – If True, nonexisting intermediate directories will also be created. The default requires all parent directories to exist.
- exist_ok (bool) – If True and the target already exist and is a directory, it will be silently accepted. The default (False) will raise an exeption if the target exists.
-
removeTree
(top=True)[source]¶ Recursively delete a directory tree.
Parameters: top (bool) – If True (default), the top level directory will be removed as well. If False, the top level directory will be kept, and only its contents will be removed.
-
move
(dst)[source]¶ Rename or move a file or directory
Parameters: dst (path_like) – Destination path. Returns: Path – The new Path. Notes
Changing a directory component will move the file. Moving a file accross file system boundaries may not work. If the destination is an existing file, it will be overwritten.
-
symlink
(dst)[source]¶ Create a symlink for this Path.
Parameters: dst (path_like) – Path of the symlink, which will point to self if successfully created.
-
touch
()[source]¶ Create an empty file or update an existing file’s timestamp.
If the file does not exist, it is create as an empty file. If the file exists, it remains unchanged but its time of last modification is set to the current time.
-
truncate
()[source]¶ Create an empty file or truncate an existing file.
If the file does not exist, it is create as an empty file. If the file exists, its contents is erased.
-
chmod
(mode)[source]¶ Change the access permissions of a file.
Parameters: mode (int) – Permission mode to set on the file. This is usually given as an octal number reflecting the access mode bitfield. Typical values in a trusted environment are 0o664 for files and 0o775 for directories. If you want to deny all access for others, the values are 0o660 and 0o770 respectively.
-
stat
()[source]¶ Return the full stat info for the file.
Returns: stat_result – The full stat results for the file Path. Notes
The return value can be interrogated using Python’s stat module. Often used values can also be got from Path methods
mtime()
,size()
,owner()
,group()
.
-
open
(mode='r', buffering=-1, encoding=None, errors=None)[source]¶ Open the file pointed to by the Path.
Parameters are like in Python’s built-in
open()
function.
-
read_text
(encoding=None, errors=None)[source]¶ Open the file in text mode, read it, and close the file.
-
write_text
(text, encoding=None, errors=None)[source]¶ Open the file in text mode, write to it, and close the file.
Examples
>>> p = Path('my_text_file') >>> p.write_text('Text file contents') 18 >>> p.read_text() 'Text file contents'
-
walk
()[source]¶ Recursively walk through a directory.
This walks top-down through the directory, yielding tuples
root, dirs, files
, likeos.walk()
.
-
dirs
()[source]¶ List the subdirectories in a directory path.
Returns: list of str – A list of the names of all directory type entries in the Path. If the Path is not a directory or not accessible, an exception is raised.
-
files
()[source]¶ List the files in a directory path.
Returns: list of str – A list of the names of all file type entries in the Path. If the Path is not a directory or not accessible, an exception is raised.
-
glob
(recursive=False)[source]¶ Return a list of paths matching a pathname pattern.
For a Path including wildcards (, ?, [], *), finds all existing files (of any type, including directories) matching the Path. The ‘**’ wildcard matches all files and any number of subdirectories.
Returns: list of Path – A sorted list of existing files matching the pattern. Note
This method works differently from
pathlib.Path.glob()
. The wildcards are part of the calling input Path and operation is like that ofglob.glob()
.Parameters: recursive (bool) – If True, operation is recursive and a ‘**’ wildcard matches all files and zero or any subdirectories. See also
listTree()
- find files matching regular expressions
Examples
>>> Path('/etc/init.d').glob() [Path('/etc/init.d')] >>> Path('pyformex/pr*.py').glob() [Path('pyformex/process.py'), Path('pyformex/project.py')] >>> Path('pyformex/**/pa*.py').glob() [Path('pyformex/plugins/partition.py')] >>> Path('pyformex/**/pa*.py').glob(recursive=True) [Path('pyformex/path.py'), Path('pyformex/plugins/partition.py')] >>> Path('**/q*.py').glob() [] >>> Path('**/q*.py').glob(recursive=True) [Path('pyformex/gui/qtutils.py')]
-
listTree
(listdirs=False, topdown=True, sorted=False, excludedirs=[], excludefiles=[], includedirs=[], includefiles=[], symlinks=True)[source]¶ List recursively all files matching some regular expressions.
This scans a directory tree for all files matching specified regular expressions.
Parameters: - listdirs (bool) – If True, matching directories are listed as well. The default is to only list files.
- topdown (bool) – If True (default) the directories are scanned top down, and files are listed in that order.
- sorted (bool) – If True, directories on the same level and files within a directory, will be sorted. The default is to treat items on the same level in an undefined order.
- excludedirs (re or list of re’s) – Regular expression(s) for dirnames to exclude from the tree scan.
- excludefiles (re) – Regular expression(s) for filenames to exclude from the file list.
- includedirs (re or list of re’s, optional) – Regular expression(s) for dirnames to include in the tree scan.
- includefiles (re) – Regular expression(s) for filenames to include in the file list.
- symlinks (bool) – If True, symlinks are included in the listed results. If False, symlinks are removed.
Returns: list of str – The list of all existing file names (and possibly directory names) under the Path that satisfy the provided patterns. An exception is raised if the Path is not an existing directory.
Notes
If neither exclude nor include patterns are provided, all subdirectories are scanned and all files are reported. If only exclude patterns are provided, all directories and files except those matching any of the exclude patterns. If only include patterns are provided, only those matching at least on of the patterns are included. If both exclude and include patterns are provided, items are only listed if they match at least one of the include patterns but none of the exclude patterns
The use of
excludedirs
and/orincludedirs
forces top down handling.
-
filetype
(compressed=['.gz', '.bz2'])[source]¶ Return a normalized file type based on the filename suffix.
The returned suffix is in most cases the part of the filename starting at the last dot. However, if the thus obtained suffix is one of the specified compressed types (default: .gz or .bz2) and the file contains another dot that is not at the start of the filename, the returned suffix starts at the penultimate dot. This allows for transparent handling of compressed files.
Parameters: compressed (list of str) – List of suffixes that are considered compressed file types. Returns: str – The filetype. This is the file suffix converted to lower case and without the leading dot. If the suffix is included in compressed
, the returned suffix also includes the preceding suffix part, if any.See also
ftype()
- the file type without accounting for compressed types
Examples
>>> Path('pyformex').filetype() '' >>> Path('pyformex.pgf').filetype() 'pgf' >>> Path('pyformex.pgf.gz').filetype() 'pgf.gz' >>> Path('pyformex.gz').filetype() 'gz' >>> Path('abcd/pyformex.GZ').filetype() 'gz'
-
ftype_compr
(compressed=['.gz', '.bz2'])[source]¶ Return the file type and compression based on suffix.
Parameters: compressed (list of str) – List of suffixes that are considered compressed file types. Returns: - ftype (str) – File type based on the last suffix if it is not a compression type, or on the penultimate suffix if the file is compressed.
- compr (str) – Compression type. This is the last suffix if it is one of the compressed types, or an empty string otherwise.
Examples
>>> Path('pyformex').ftype_compr() ('', '') >>> Path('pyformex.pgf').ftype_compr() ('pgf', '') >>> Path('pyformex.pgf.gz').ftype_compr() ('pgf', 'gz') >>> Path('pyformex.gz').ftype_compr() ('gz', '')
37.2. Functions defined in module path¶
-
path.
matchAny
(target, *regexps)[source]¶ Check whether target matches any of the regular expressions.
Parameters: - target (str) – String to match with the regular expressions.
- *regexp (sequence of regular expressions.) – The regular expressions to match the target string.
Returns: bool – True, if target matches at least one of the provided regular expressions. False if no matches.
Examples
>>> matchAny('test.jpg', '.*[.]png', '.*[.]jpg') True >>> matchAny('test.jpeg', '.*[.]png', '.*[.]jpg') False >>> matchAny('test.jpg') False