API Reference

A pathlib-first library for working with file sequences.

Path sequence classes come in two variations depending on the format of sequence string they support: simple, which prioritises simplicity to guarantee behaviour; or loose, which prioritises compatibility with more file names. Both variations share common base classes.

_images/inheritance.svg

If you aren’t sure which variation is right for you, choose simple if you have control over the format of sequence strings that you support, and choose loose if you don’t.

The simple and loose variants both come in a pure and concrete form, similar to the classes in pathlib. Pure path sequences contain pathlib.PurePath objects, and concrete path sequences contain pathlib.Path objects.

Pure Path Sequences

type pathseq.PurePathT_co = TypeVar(PurePathT_co, bound=pathlib.PurePath, covariant=True)

The type of pure paths contained in a BasePurePathSequence.

class pathseq.BasePurePathSequence(path: str)
class pathseq.BasePurePathSequence(path: PurePathT_co)

Bases: Sequence[PurePathT_co]

A generic class that represents a path sequence.

Raises:
  • NotASequenceError – When the given path does not represent a sequence.

  • ParseError – When the given path is not a valid path sequence.

property parts: tuple[str, ...]

A tuple giving access to the sequence’s various components.

>>> s = PurePathSequence(PurePosixPath('/path/to/image.1-3####.exr'))
>>> s.parts
('/', 'path', 'to', 'image.1-3####.exr')
property name: str

A string representing the final path component, excluding the drive and root.

Given that a sequence’s final path component must be the sequence’s files, the name will always be a valid sequence string.

>>> PurePathSequence('/path/to/image.1-3####.exr').name
'image.1-3####.exr'
property stem: str

The name, without any ranges, suffixes, or range strings.

>>> PurePathSequence('/path/to/images.1-3####.exr').stem
'images'
property file_num_seqs: Sequence[FileNumSequence[int] | FileNumSequence[Decimal]]

All file number sequences in the name.

>>> PurePathSequence('/path/to/texture.1011-1013<UDIM>_1-3#.tex').file_num_seqs
(FileNumSequence(1011-1013), FileNumSequence(1-3))
property suffix: str

The file extension of the paths in the sequence.

A simple path sequence will always have a file extension. Therefore this will never return the empty string.

>>> PurePathSequence('/path/to/image.1-3####.exr').suffix
'.exr'
property suffixes: Sequence[str]

A list of the file extensions of any path in the sequence.

>>> PurePathSequence('/path/to/file.1-3####.tar.gz').suffixes
('.tar', '.gz')
property parents: Sequence[PurePathT_co]

An immutable sequence providing access to the logical ancestors of the sequence.

>>> s = PurePathSequence(PureWindowsPath('c:/path/to/images.1-3####.exr'))
>>> s.parents[0]
PureWindowsPath('c:/path/to')
>>> s.parents[1]
PureWindowsPath('c:/path')
>>> s.parents[2]
PureWindowsPath('c:/')
property parent: PurePath

The logical parent of the sequence.

>>> s = PurePathSequence(PurePosixPath('/a/b/c/d.1-3#.exr'))
>>> s.parent
PurePosixPath('/a/b/c')
as_posix() str

Return a string representation of the sequence with forward slashes (/).

>>> s = PurePathSequence(PureWindowsPath('c:\\windows\\images.1-3#.exr'))
>>> str(s)
'c:\\windows\\images.1-3#.exr'
>>> s.as_posix()
'c:/windows/images.1-3#.exr'
is_relative_to(other: PurePath) bool

Return whether or not all files in this sequence are relative to the other path.

Raises:

ValueError – If this path sequence is given. The paths in a sequence cannot be relative to a sequence.

relative_to(other: str | PathLike[str], *, walk_up: bool = False) Self

Compute a version of this path relative to the path represented by other.

Note

walk_up is available only in Python 3.12 and newer.

Raises:

ValueError – When this sequence cannot be relative to the given path.

with_name(name: str) Self

Return a new sequence with the name changed.

Given that a sequence’s final path component must be the sequence’s files, the given name must also be a valid sequence string.

Raises:
with_stem(stem: str) Self

Return a new path with the stem changed.

>>> p = PurePathSequence('images.1-3#.exr')
>>> p.with_stem('textures')
PurePathSequence('textures.1-3#.exr')
Raises:

ValueError – If the new stem is invalid.

with_file_num_seqs(*seqs: FileNumSequence[int] | FileNumSequence[Decimal]) Self

Return a new sequence with the file number sequences changed.

Raises:

TypeError – If the given number of file number sequences does not match the sequence’s number of file number sequences.

path_with_file_nums(*numbers: int | Decimal) PurePathT_co

Return a path for the given file number(s) in the sequence.

Parameters:

numbers – The number to use in place of each range in the string.

>>> p = PurePathSequence(PurePosixPath('images.1-3#.exr'))
>>> p.path_with_file_nums(5)
PurePosixPath('images.5.exr')
with_suffix(suffix: str) Self

Return a new path sequence with the suffix changed.

If the given suffix is the empty string, the existing suffix will be removed. But if the path sequence has only one suffix, then a ValueError will be raised because removing the suffix will result in an invalid path sequence.

Parameters:

suffix – The new suffix to replace the existing suffix with.

Raises:

ValueError – If the given suffix would result in an invalid path sequence.

with_segments(*pathsegments: str | PathLike[str]) Self

Create a new sequence object of the same type by combining the given pathsegments.

has_subsamples() bool

Check whether this path sequence contains any decimal file numbers.

Concrete Path Sequences

type pathseq.PathT_co = TypeVar(PathT_co, bound=pathlib.Path, covariant=True)

The type of concrete paths contained in a BasePathSequence.

class pathseq.BasePathSequence(path: str)
class pathseq.BasePathSequence(path: PathT_co)

Bases: BasePurePathSequence[PathT_co]

A sequence of Path objects.

Raises:
  • NotASequenceError – When the given path does not represent a sequence, but a regular path.

  • ParseError – When the given path is not a valid path sequence.

expanduser() Self

Return a new sequence with expanded ~ and ~user constructs.

The expansion will be as returned by os.path.expanduser().

Raises:

RuntimeError – If a home directory can’t be resolved.

absolute() Self

Return a new sequence with the sequence’s paths made absolute.

Normalisation and symlink resolution are not performed.

iter_existing_paths() Iterable[PathT_co]

Iterate over the ranges of files that exist on disk.

This method will ignore the file number sequences in this path sequence, and iterate over all paths that could be represented by the sequence string and exist on disk.

Users who wish the file number sequences to be taken into account can use the existing __iter__() method and filter the results by whether they exist on disk.

resize_from_existing_paths() tuple[Self, Completeness]

Return a new a sequence using the ranges of files that exist on disk.

Each file number sequence in the path sequence will be ordered numerically.

Note

This method requires storing all file numbers in memory, so it may not be suitable for sequences with large numbers of files. Consider using iter_existing_paths() instead if memory usage is a concern.

Returns:

A tuple of the new path sequence and a Completeness value indicating whether or not the sequence is complete on disk. A sequence may be partially complete when:

  • The given sequence represents a single path, and that path does not exist on disk.

  • One or more dimensions in a multi-dimension sequence does not have a consistent number of files in each other dimension. For example, a sequence file.1-2#_1-2#.exr would be partially complete if only the files file.1_1.exr, file.1_2.exr, and file.2_1.exr exist on disk, but file.2_2.exr does not.

Simple Path Sequences

class pathseq.PurePathSequence(path: str)
class pathseq.PurePathSequence(path: PurePathT_co)

Bases: BasePurePathSequence[PathT_co]

A sequence of PurePath objects.

Raises:
  • NotASequenceError – When the given path does not represent a sequence, but a regular path.

  • ParseError – When the given path is not a valid path sequence.

property parsed: ParsedSequence

The parsed sequence string, as a tree of objects.

class pathseq.PathSequence(path: str)
class pathseq.PathSequence(path: PathT_co)

Bases: PurePathSequence[PathT_co], BasePathSequence[PathT_co]

A sequence of Path objects.

Raises:
  • NotASequenceError – When the given path does not represent a sequence, but a regular path.

  • ParseError – When the given path is not a valid path sequence.

Loose Path Sequences

class pathseq.LoosePurePathSequence(path: str)
class pathseq.LoosePurePathSequence(path: PurePathT_co)

Bases: BasePurePathSequence[PurePathT_co]

A sequence of PurePath objects.

Raises:
  • NotASequenceError – When the given path does not represent a sequence, but a regular path.

  • ParseError – When the given path is not a valid path sequence.

property parsed: ParsedLooseSequence

The parsed sequence string, as a tree of objects.

property suffix: str

The file extension of the paths in the sequence.

If there is no suffix, this will be the empty string.

>>> LoosePurePathSequence('file1-3###').suffix
''
with_suffix(suffix: str) Self

Return a new path sequence with the suffix changed.

If the given suffix is the empty string, the existing suffix will be removed. But if the path sequence has only one suffix, then a ValueError will be raised because removing the suffix will result in an invalid path sequence.

Parameters:

suffix – The new suffix to replace the existing suffix with.

Raises:

ValueError – If the given suffix would result in an invalid path sequence.

property stem: str

The final path component, without any pre-range separator, ranges, post-range separator, or suffixes.

>>> LoosePurePathSequence('/path/to/images.1-3####.exr').stem
'images'
>>> LoosePurePathSequence('/path/to/1-3####_images.exr').stem
'images'
>>> LoosePurePathSequence('/path/to/images.exr.1-3####').stem
'images'

If the ranges do not start or end the path then, unlike pathlib.PurePath.stem, this will never contain a suffix if the range is in the path and the paths have multiple suffixes:

>>> LoosePurePathSequence('/path/to/images.1-3####.tar.gz').stem
'images'
>>> LoosePurePathSequence('/path/to/1-3####_images.tar.gz').stem
'images.tar'
>>> LoosePurePathSequence('/path/to/images.tar.gz.1-3####').stem
'images.tar'

If the paths have no stem, then the empty string is returned:

>>> LoosePurePathSequence('1-3#.tar.gz').stem
''
class pathseq.LoosePathSequence(path: str)
class pathseq.LoosePathSequence(path: PathT_co)

Bases: LoosePurePathSequence[PathT_co], BasePathSequence[PathT_co]

A sequence of Path objects.

Raises:
  • NotASequenceError – When the given path does not represent a sequence, but a regular path.

  • ParseError – When the given path is not a valid path sequence.

Exceptions

exception pathseq.NotASequenceError(seq: str)

Bases: ParseError

Raised when parsing a string that does not represent a sequence, but a regular path.

In other words, the given sequence string has no range present.

exception pathseq.ParseError(seq: str, column: int, end_column: int = -1, reason: str | None = None)

Bases: ValueError

Raised when parsing a sequence string fails.

Parameters:
  • seq – The sequence string that failed parsing.

  • column – The index of the character of the part of the string that failed parsing.

  • end – The index of the last character of the part of the string that failed parsing.

  • reason – A human readable explanation of why parsing failed.

seq: str

The sequence string that failed parsing.

column: int

The index of the character of the part of the string that failed parsing.

end: int

The index of the last character of the part of the string that failed parsing.

File Number Sequences

type pathseq.FileNumT = TypeVar(FileNumT, int, decimal.Decimal)

The type of file numbers in a FileNumSequence.

class pathseq.FileNumSequence

Bases: Sequence[FileNumT]

A sequence of file numbers.

Warning

The constructor is not considered public. Instead, use the from_str() and from_file_nums() class methods.

classmethod from_str(seq: str) FileNumSequence[int] | FileNumSequence[Decimal]

Parse a range string in a file number sequence.

Parameters:

seq – The range string to parse (e.g. ‘1001-1005,1010-1015’).

Returns:

The resulting file number sequence.

classmethod from_file_nums(file_nums: Iterable[FileNumT]) FileNumSequence[FileNumT]

Create a file number sequence from an iterable of file numbers.

The given numbers are put into the sequence in the order they are provided.

Parameters:

file_nums – The file numbers to turn into a sequence.

Returns:

The resulting file number sequence.

static has_subsamples(file_num_seq: FileNumSequence[int] | FileNumSequence[Decimal]) TypeGuard[FileNumSequence[Decimal]]

Check whether this file number sequence contains any decimal numbers.

Parsed Path Sequences

These classes represent a parsed path sequence in a tree structure. Access to a parsed sequence can be useful for renaming sequences or converting sequence strings between different formats.

See also

See Sequence String Formats for the specification of what is valid in each part of a sequence.

class pathseq.ParsedSequence(stem: str, pre_range: Literal['', '_', '.'], ranges: Ranges, suffixes: tuple[str, ...])

A parsed path sequence.

stem: str

The name of the sequence, without the pre-range separator, ranges, and suffixes.

pre_range: Literal['', '_', '.']

An optional single character separator between the stem and the ranges.

ranges: Ranges

The file numbers of the files in the sequence and their formatting.

suffixes: tuple[str, ...]

The file extensions of the files in the path sequence.

Each suffix includes the leading “.”.

with_stem(stem: str) Self

Return a new parsed sequence with the stem changed.

If the stem is removed, the pre-range separator will be as well.

with_suffix(suffix: str) Self

Return a new parsed sequence with the suffix changed.

Parameters:

suffix – The new suffix to replace the existing one with. This must start with a “.” or be the empty string.

Raises:

ValueError – If an invalid suffix is given.

type pathseq.ParsedLooseSequence = pathseq.RangesStartName | pathseq.RangesInName | pathseq.RangesEndName
class pathseq.RangesStartName(pre_range: Literal[''], ranges: Ranges, post_range: Literal['_', ''], stem: str, suffixes: tuple[str, ...])

A parsed loose path sequence where the range starts a path’s name.

pre_range: Literal['']

An optional single character separator between the ranges and the previous component.

This is always empty for file names where the ranges start the name, but is included so that RangesStartName, RangesInName, and RangesEndName all have the same attributes.

ranges: Ranges

The file numbers of the files in the sequence and their formatting.

post_range: Literal['_', '']

An optional single character separator between the ranges and the next component.

In sequences where the ranges start the name, this separates the ranges from the stem.

stem: str

The name of the sequence, without the pre-range separator, ranges, post-range separator, and suffixes.

suffixes: tuple[str, ...]

The file extensions of the files in the path sequence.

Each suffix includes the leading “.”.

with_stem(stem: str) Self

Return a new parsed sequence with the stem changed.

If the stem is removed, the post-range separator will be as well.

with_suffix(suffix: str) Self

Return a new parsed sequence with the suffix changed.

Parameters:

suffix – The new suffix to replace the existing one with. This must start with a “.” or be the empty string.

Raises:

ValueError – If an invalid suffix is given.

class pathseq.RangesInName(stem: str, pre_range: str, ranges: Ranges, post_range: str, suffixes: tuple[str, ...])

A parsed loose range sequence where the range follows a path’s stem.

stem: str

The name of the sequence, without the pre-range separator, ranges, post-range separator, and suffixes.

pre_range: str

An optional single character separator between the ranges and the previous component.

In sequences where the ranges are in the name, this separates the ranges from the stem.

ranges: Ranges

The file numbers of the files in the sequence and their formatting.

post_range: str

An optional separator between the ranges and the next component.

In sequences where the ranges are in the name, this separates the ranges from the suffixes.

suffixes: tuple[str, ...]

The file extensions of the files in the path sequence.

Each suffix includes the leading “.”.

with_stem(stem: str) Self

Return a new parsed sequence with the stem changed.

If the stem is removed, the pre-range separator will be as well.

with_suffix(suffix: str) Self

Return a new parsed sequence with the suffix changed.

Parameters:

suffix – The new suffix to replace the existing one with. This must start with a “.” or be the empty string.

Raises:

ValueError – If an invalid suffix is given.

class pathseq.RangesEndName(stem: str, suffixes: tuple[str, ...], pre_range: str, ranges: Ranges, post_range: Literal[''])

A parsed loose range sequence where the range ends a path’s name.

stem: str

The name of the sequence, without the pre-range separator, ranges, post-range separator, and suffixes.

suffixes: tuple[str, ...]

The file extensions of the files in the path sequence.

Each suffix includes the leading “.”.

pre_range: str

An optional single character separator between the ranges and the previous component.

In sequences where the ranges are in the name, this separates the ranges from the suffixes.

ranges: Ranges

The file numbers of the files in the sequence and their formatting.

post_range: Literal['']

An optional separator between the ranges and the next component.

This is always empty for file names where the ranges end the name, but is included so that RangesStartName, RangesInName, and RangesEndName all have the same attributes.

with_stem(stem: str) Self

Return a new parsed sequence with the stem changed.

with_suffix(suffix: str) Self

Return a new parsed sequence with the suffix changed.

Parameters:

suffix – The new suffix to replace the existing one with. This must start with a “.” or be the empty string.

Raises:

ValueError – If an invalid suffix is given.

class pathseq.PaddedRange(file_nums: 'FileNumSequence[FileNumT]', pad_format: 'str')
file_nums: FileNumSequence[FileNumT]

The file numbers of each file in the sequence.

pad_format: str

The definition of how a file number is formatted in each file’s name in the sequence.

format(number: int | Decimal) str

Format the given number using the range’s padding rules.

static has_subsamples(range_: PaddedRange[int] | PaddedRange[Decimal]) TypeGuard[PaddedRange[Decimal]]

Check whether this file number sequence contains any decimal numbers.

class pathseq.Ranges(ranges: 'tuple[PaddedRange[int] | PaddedRange[decimal.Decimal], ...]', inter_ranges: 'tuple[str, ...]')
ranges: tuple[PaddedRange[int] | PaddedRange[Decimal], ...]

Each range specifier in the sequence.

inter_ranges: tuple[str, ...]

The inter-range separators between each range in the sequence.

The number of inter-range separators is guaranteed to be 1 - len(self.ranges).

Formatter

class pathseq.Formatter

A Formatter formats a parsed sequence into a string.

The purpose of the class is primarily for converting from a simple or loose sequence into other sequence formats by overriding this class.

Example

>>> class HoudiniFormatter(pathseq.Formatter):
...   def range(self, range_):
...       return "$F"
...
>>> seq = pathseq.PathSequence("image.1-5#.exr")
>>> HoudiniFormatter().format(seq.parsed)
'image.$F.exr'
include_all_suffixes

Whether to include all suffixes in the formatted sequence.

This is set by format() to indicate whether the suffixes have been cleanly separated from the stem or not. If this is False, then the stem and suffixes will overlap and both include all but the last suffix.

stem(stem: str) str
pre_range(pre_range: str) str
range(range_: PaddedRange[int] | PaddedRange[Decimal]) str
inter_range(inter_range: str) str
ranges(ranges: Ranges) str
post_range(post_range: str) str
suffixes(suffixes: tuple[str, ...]) str
format(seq: ParsedSequence | ParsedLooseSequence) str

Format the given path sequence into a string.

The parsed sequence is traversed, and each node is formatted according to the implementation of the associated method on this class.

Parameters:

seq – The path sequence to format into a string.

Returns:

The formatter path sequence.

splice_inter_ranges(strings: Iterable[str], inter_ranges: Iterable[str]) str

Format the given range strings and inter-range strings together.

Raises:

TypeError – If the given number of strings does not match the number of inter-range strings minus one.