maestral.utils.path

This module contains functions for common path operations.

Module Contents

maestral.utils.path.Path[source]
maestral.utils.path.is_child(path, parent)[source]

Checks if path semantically is inside parent. Neither path needs to refer to an actual item on the drive. This function is case-sensitive.

Parameters
  • path (str) – Item path.

  • parent (str) – Parent path.

Returns

Whether path semantically lies inside parent.

Return type

bool

maestral.utils.path.is_equal_or_child(path, parent)[source]

Checks if path semantically is inside parent or equals parent. Neither path needs to refer to an actual item on the drive. This function is case-sensitive.

Parameters
  • path (str) – Item path.

  • parent (str) – Parent path.

Returns

True if path semantically lies inside parent or path == parent.

Return type

bool

maestral.utils.path.normalize_case(string)[source]

Converts a string to lower case. Todo: Follow Python 2.5 / Dropbox conventions.

Parameters

string (str) – Original string.

Returns

Lowercase string.

Return type

str

maestral.utils.path.normalize_unicode(string)[source]

Normalizes a string to replace all decomposed unicode characters with their single character equivalents.

Parameters

string (str) – Original string.

Returns

Normalized string.

Return type

str

maestral.utils.path.normalize(string)[source]

Replicates the path normalization performed by Dropbox servers. This typically only involves converting the path to lower case, with a few (undocumented) exceptions:

  • Unicode normalization: decomposed characters are converted to composed characters.

  • Lower casing of non-ascii characters: Dropbox uses the Python 2.5 behavior for conversion to lower case. This means that some cyrillic characters are incorrectly lower-cased. For example: “Ꙋ”.lower() -> “Ꙋ” instead of “ꙋ” “ΣΣΣ”.lower() -> “σσσ” instead of “σσς”

  • Trailing spaces are stripped from folder names. We do not perform this normalization here because the Dropbox API will raise sync errors for such names anyways.

Note that calling normalize() on an already normalized path will return the unmodified input.

Todo: Follow Python 2.5 / Dropbox conventions instead of Python 3 conventions.

Parameters

string (str) – Original path.

Returns

Normalized path.

Return type

str

maestral.utils.path.is_fs_case_sensitive(path)[source]

Checks if path lies on a partition with a case-sensitive file system.

Parameters

path (str) – Path to check.

Returns

Whether path lies on a partition with a case-sensitive file system.

Return type

bool

maestral.utils.path.equivalent_path_candidates(path, root=osp.sep, norm_func=normalize)[source]

Given a “normalized” path using an injective (one-directional) normalization function, this method returns a list of matching un-normalized local paths.

If no such local path exists, the normalized path itself is returned. If a local path can be followed up to a certain parent in the hierarchy, it will be taken and the remaining normalized path will be appended.

Example

Assume the normalization function is str.lower(). If a root directory contains two folders “/parent/subfolder/child” and “/parent/Subfolder/child”, two matches will be returned for “path = /parent/subfolder/child/file.txt”.

Parameters
  • path (str) – Normalized path relative to root.

  • root (str) – Parent directory to search in. There are significant performance improvements if a root directory with a small tree is given.

  • norm_func (Callable) – Normalization function to use. Defaults to normalize().

Returns

Candidates for correctly cased local paths.

Return type

List[str]

maestral.utils.path.denormalize_path(path, root=osp.sep)[source]

Returns a denormalized version of the given path as far as corresponding nodes with the same normalization exist in the given root directory. If multiple matches are found, only one is returned. If path does not exist in root root or root does not exist, the return value will be os.path.join(root, path).

Parameters
  • path (str) – Original path relative to root.

  • root (str) – Parent directory to search in. There are significant performance improvements if a root directory with a small tree is given.

Returns

Absolute and cased version of given path.

Return type

str

maestral.utils.path.to_existing_unnormalized_path(path, root=osp.sep)[source]

Returns a cased version of the given path if corresponding nodes (with arbitrary casing) exist in the given root directory. If multiple matches are found, only one is returned.

Parameters
  • path (str) – Original path relative to root.

  • root (str) – Parent directory to search in. There are significant performance improvements if a root directory with a small tree is given.

Returns

Absolute and cased version of given path.

Raises

FileNotFoundError – if path does not exist in root root or root itself does not exist.

Return type

str

maestral.utils.path.normalized_path_exists(path, root=osp.sep)[source]

Checks if a path exists in given root directory, similar to os.path.exists but case-insensitive. Normalisation is performed as by Dropbox servers (lower case and unicode normalisation).

Parameters
  • path (str) – Path relative to root.

  • root (str) – Directory where we will look for path. There are significant performance improvements if a root directory with a small tree is given.

Returns

Whether an arbitrarily cased version of path exists.

Return type

bool

maestral.utils.path.generate_cc_name(path, suffix='conflicting copy')[source]

Generates a path for a conflicting copy of path. The file name is created by inserting the given suffix between the filename and the extension. For instance:

“my_file.txt” -> “my_file (conflicting copy).txt”

If a file with the resulting path already exists (case-insensitive!), we additionally append an integer number, for instance:

“my_file.txt” -> “my_file (conflicting copy 1).txt”

Parameters
  • path (str) – Original path name.

  • suffix (str) – Suffix to use. Defaults to “conflicting copy”.

Returns

New path.

Return type

str

maestral.utils.path.delete(path, raise_error=False)[source]

Deletes a file or folder at path. Symlinks will not be followed.

Parameters
  • path (str) – Path of item to delete.

  • raise_error (bool) – Whether to raise errors or return them.

Returns

Any caught exception during the deletion.

Return type

Optional[OSError]

maestral.utils.path.move(src_path, dest_path, raise_error=False, preserve_dest_permissions=False)[source]

Moves a file or folder from src_path to dest_path. If either the source or the destination path no longer exist, this function does nothing. Any other exceptions are either raised or returned if raise_error is False.

Parameters
  • src_path (str) – Path of item to move.

  • dest_path (str) – Destination path. Any existing file at this path will be replaced by the move. Any existing empty folder will be replaced if the source is also a folder.

  • raise_error (bool) – Whether to raise errors or return them.

  • preserve_dest_permissions – Whether to apply the permissions of the source path to the destination path. Permissions will not be set recursively.

Returns

Any caught exception during the move.

Return type

Optional[OSError]

maestral.utils.path.walk(root, listdir=os.scandir)[source]

Iterates recursively over the content of a folder.

Parameters
Returns

Iterator over (path, stat) results.

Return type

Iterator[Tuple[str, os.stat_result]]

maestral.utils.path.content_hash(local_path, chunk_size=65536)[source]

Computes content hash of a local file.

Parameters
  • local_path (str) – Absolute path on local drive.

  • chunk_size (int) – Size of chunks to hash in bytes.

Returns

Content hash to compare with Dropbox’s content hash and mtime just before the hash was computed.

Return type

Tuple[Optional[str], Optional[float]]

maestral.utils.path.fs_max_lengths_for_path(path='/')[source]

Return the maximum length of file names and paths allowed on a file system.

Parameters

path (str) – Path to check. This can be specified because different paths may be residing on different file systems. If the given path does not exist, the first existing parent directory in the tree be taken.

Returns

Tuple giving the maximum file name and total path lengths.

Return type

Tuple[int, int]

Opener that does not follow symlinks. Uses os.open() under the hood.

Parameters
  • path (Path) – Path to open.

  • flags (int) – Flags passed to os.open(). O_NOFOLLOW will be added.

Returns

Open file descriptor.

Return type

int

maestral.utils.path.exists(path)[source]

Returns whether an item exists at the path. Returns True for symlinks.

Parameters

path (Path) –

Return type

bool

maestral.utils.path.isfile(path)[source]

Returns whether a file exists at the path. Returns True for symlinks.

Parameters

path (Path) –

Return type

bool

maestral.utils.path.isdir(path)[source]

Returns whether a folder exists at the path. Returns False for symlinks.

Parameters

path (Path) –

Return type

bool

maestral.utils.path.getsize(path)[source]

Returns the size. Returns False for symlinks.

Parameters

path (Path) –

Return type

int

Returns the symlink target of a file.

Parameters

local_path (str) – Absolute path on local drive.

Returns

Symlink target of local file. None if the local path does not refer to a symlink or does not exist.

Return type

Optional[str]