Skip to content

Commit 1e4b6a5

Browse files
committed
Clean up Formatter and write its documentation
1 parent 2cd3eee commit 1e4b6a5

25 files changed

Lines changed: 471 additions & 301 deletions

README.rst

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ pathseq
1919

2020
A pathlib-first library for working with file sequences.
2121

22-
TODO: Note special features
23-
2422
* Multi-dimension ranges (eg animated udims)
2523
* pathlib-first API
2624
* Support for UDIM tokens
27-
* Sequence compression?
25+
2826

2927
Getting Started
3028
---------------
@@ -36,20 +34,83 @@ Full documentation is available here: https://pathseq.readthedocs.io/en/latest/
3634
Installation
3735
~~~~~~~~~~~~
3836

39-
``pathseq`` can be installed through pip:
37+
``pathseq`` can be installed from PyPI:
4038

4139
.. code-block:: bash
4240
4341
pip install pathseq
4442
43+
4544
Usage
4645
~~~~~
4746

48-
TODO
49-
5047
For more detailed usage, see the documentation:
5148
https://pathseq.readthedocs.io/en/latest/
5249

50+
Now, let's get started:
51+
52+
.. code-block:: pycon
53+
54+
>>> from pathseq import PathSequence
55+
>>> seq = PathSequence("tests/fixtures/simple/images.1-5####.exr")
56+
>>> for path in seq:
57+
... path
58+
...
59+
PosixPath('tests/fixtures/simple/images.0001.exr')
60+
PosixPath('tests/fixtures/simple/images.0002.exr')
61+
PosixPath('tests/fixtures/simple/images.0003.exr')
62+
PosixPath('tests/fixtures/simple/images.0004.exr')
63+
PosixPath('tests/fixtures/simple/images.0005.exr')
64+
65+
>>> seq2 = PathSequence("tests/fixtures/simple/images.####.exr").with_existing_paths()
66+
>>> seq2 == seq
67+
True
68+
69+
>>> seq.parent
70+
PosixPath('tests/fixtures/simple')
71+
>>> seq3 = seq.parent / PathSequence("images.1-5####.exr")
72+
>>> seq3 == seq
73+
True
74+
75+
>>> anim_udims = PathSequence("/path/to/textures.1011-1012<UDIM>_1-3#.tex")
76+
>>> for path in anim_udims:
77+
... path
78+
...
79+
PosixPath('/path/to/textures.1011_1.tex')
80+
PosixPath('/path/to/textures.1011_2.tex')
81+
PosixPath('/path/to/textures.1011_3.tex')
82+
PosixPath('/path/to/textures.1012_1.tex')
83+
PosixPath('/path/to/textures.1012_2.tex')
84+
PosixPath('/path/to/textures.1012_3.tex')
85+
86+
A wide range of sequence string formats are supported:
87+
88+
.. code-block:: pycon
89+
90+
>>> from pathseq import LoosePathSequence
91+
>>> seq = LoosePathSequence("/path/to/images.1-5####.exr")
92+
93+
>>> seq = LoosePathSequence("/path/to/1-5####_images.exr")
94+
>>> seq[0]
95+
PosixPath('/path/to/0001_images.exr')
96+
>>> seq.suffixes
97+
('.exr',)
98+
99+
>>> LoosePathSequence("/path/to/1-5####_archives.tar.gz").suffixes
100+
('.tar', '.gz')
101+
102+
>>> seq = LoosePathSequence("/path/to/images.exr.1-5####")
103+
>>> seq[0]
104+
PosixPath('/path/to/images.exr.0001')
105+
>>> seq.suffixes
106+
('.exr',)
107+
108+
>>> LoosePathSequence("/path/to/images.1001-1005<UDIM>.exr")[0]
109+
PosixPath('/path/to/images.1001.exr')
110+
111+
>>> LoosePathSequence("/path/to/images.1001-1005<UVTILE>.exr")[0]
112+
PosixPath('/path/to/images.u1_v1.exr')
113+
53114
54115
Contributing
55116
------------

doc/source/api.rst

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ API Reference
2727
Pure Path Sequences
2828
-------------------
2929

30-
.. py:data:: PurePathT_co
31-
:value: TypeVar(PurePathT_co, bound=pathlib.PurePath, covariant=True)
32-
:canonical: pathseq._base.PurePathT_co
30+
.. py:type:: PurePathT_co
31+
:canonical: TypeVar(PurePathT_co, bound=pathlib.PurePath, covariant=True)
3332

3433
The type of pure paths contained in a :class:`~.BasePurePathSequence`.
3534

@@ -41,9 +40,8 @@ API Reference
4140
Concrete Path Sequences
4241
-----------------------
4342

44-
.. py:data:: PathT_co
45-
:value: TypeVar(PathT_co, bound=pathlib.Path, covariant=True)
46-
:canonical: pathseq._base.PathT_co
43+
.. py:type:: PathT_co
44+
:canonical: TypeVar(PathT_co, bound=pathlib.Path, covariant=True)
4745

4846
The type of concrete paths contained in a :class:`~.BasePathSequence`.
4947

@@ -93,10 +91,8 @@ API Reference
9391
File Number Sequences
9492
---------------------
9593

96-
.. py:data:: FileNumT
97-
:type: typing.TypeVar
98-
:value: TypeVar(FileNumT, int, decimal.Decimal)
99-
:canonical: pathseq._ast._base.FileNumT
94+
.. py:type:: FileNumT
95+
:canonical: TypeVar(FileNumT, int, decimal.Decimal)
10096

10197
The type of file numbers in a :class:`~.FileNumSequence`.
10298

@@ -119,8 +115,8 @@ API Reference
119115
.. autoclass:: ParsedSequence
120116
:members:
121117

122-
.. py:data:: ParsedLooseSequence
123-
:value: pathseq.RangesStartName | pathseq.RangesInName | pathseq.RangesEndName
118+
.. py:type:: ParsedLooseSequence
119+
:canonical: pathseq.RangesStartName | pathseq.RangesInName | pathseq.RangesEndName
124120

125121
.. autoclass:: RangesStartName
126122
:members:
@@ -136,3 +132,10 @@ API Reference
136132

137133
.. autoclass:: Ranges
138134
:members:
135+
136+
Formatter
137+
---------
138+
139+
.. autoclass:: Formatter
140+
:members:
141+
:undoc-members:

doc/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
:mod:`pathseq` is a pathlib-first library for working with file sequences.
55

6-
Install PathSeq using pip:
6+
Install PathSeq from PyPI:
77

88
.. code-block:: bash
99

doc/source/user/convert.rst

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
***********************************
2+
Converting Between Sequence Formats
3+
***********************************
4+
5+
Different applications and use cases can require different formats of
6+
sequence strings.
7+
PathSeq supports converting a path sequence to other formats by overriding the
8+
:class:`~pathseq.Formatter` class.
9+
10+
Without any changes, the Formatter class will format
11+
a path sequence into a string without any changes.
12+
13+
.. code-block:: pycon
14+
15+
>>> seq = PathSequence("image.1-5#.exr")
16+
>>> pathseq.Formatter().format(seq.parsed)
17+
'image.1-5#.exr'
18+
19+
To convert to another format, the methods of a Formatter can be overriden.
20+
For example, a basic formatter for Houdini strings might look like this:
21+
22+
.. code-block:: pycon
23+
24+
>>> class HoudiniFormatter(pathseq.Formatter):
25+
... def range(self, range_):
26+
... return "$F"
27+
...
28+
>>> seq = PathSequence("image.1-5#.exr")
29+
>>> HoudiniFormatter().format(seq.parsed)
30+
'image.$F.exr'
31+
32+
There is a method on the Formatter for each attribute on a parsed sequence.
33+
So any part of a path sequence can be changed.
34+
35+
.. code-block:: pycon
36+
37+
>>> class DemoFormatter(pathseq.Formatter):
38+
... def stem(self, stem):
39+
... return "stem"
40+
... def prefix(self, prefix):
41+
... return "|prefix"
42+
... def range(self, range_):
43+
... return "|range"
44+
... def inter_range(self, inter_range):
45+
... return "|inter_range"
46+
... def postfix(self, postfix):
47+
... return "|postfix"
48+
... def suffixes(self, suffixes):
49+
... return "|suffixes"
50+
...
51+
>>> seq = PathSequence("image.1-5#.exr")
52+
>>> DemoFormatter().format(seq.parsed)
53+
'stem|prefix|range|suffixes'
54+
55+
The order of the parts in a :ref:`loose <loose-format>` can even be changed
56+
by overriding the :meth:`~pathseq.Formatter.format` or
57+
:meth:`~pathseq.Formatter.ranges` methods.
58+
For example, a naive formatter to convert a loose format range into
59+
a :ref:`simple <simple-format>` might look like this:
60+
61+
.. code-block:: pycon
62+
63+
>>> class ToSimpleFormatter(pathseq.Formatter):
64+
... def format(self, seq):
65+
... return (
66+
... self.stem(seq.stem)
67+
... + self.prefix(seq.prefix or ".")
68+
... + self.ranges(seq.ranges)
69+
... + self.suffixes(seq.suffixes)
70+
... )
71+
...
72+
>>> seq = LoosePathSequence("1-5#image.exr")
73+
>>> ToSimpleFormatter().format(seq.parsed)
74+
'image.1-5#.exr'

doc/source/user/index.rst

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,5 @@ User Guide
55
.. toctree::
66
:maxdepth: 2
77

8+
convert
89
format
9-
10-
* Reformatting and setting new ranges
11-
* Complex equality and normalisation
12-
* Conversions

src/pathseq/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""A pathlib-first library for working with file sequences."""
22

33
from ._ast import (
4-
FileNumT,
4+
Formatter,
55
PaddedRange,
66
ParsedLooseSequence,
77
ParsedSequence,
@@ -12,7 +12,7 @@
1212
)
1313
from ._base import BasePathSequence, BasePurePathSequence, PathT_co, PurePathT_co
1414
from ._error import IncompleteDimensionError, NotASequenceError, ParseError
15-
from ._file_num_seq import FileNumSequence
15+
from ._file_num_seq import FileNumSequence, FileNumT
1616
from ._loose_path_sequence import LoosePathSequence
1717
from ._loose_pure_path_sequence import LoosePurePathSequence
1818
from ._path_sequence import PathSequence
@@ -25,6 +25,7 @@
2525
"BasePurePathSequence",
2626
"FileNumSequence",
2727
"FileNumT",
28+
"Formatter",
2829
"IncompleteDimensionError",
2930
"LoosePathSequence",
3031
"LoosePurePathSequence",

src/pathseq/_ast/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
from ._base import FileNum, FileNumT, PaddedRange, Ranges
21
from ._formatter import Formatter
32
from ._loose_type import (
43
ParsedLooseSequence,
54
RangesStartName,
65
RangesInName,
76
RangesEndName,
87
)
8+
from ._ranges import PaddedRange, Ranges
99
from ._type import ParsedSequence
1010

1111
__all__ = [
12-
"FileNum",
13-
"FileNumT",
1412
"Formatter",
1513
"PaddedRange",
1614
"ParsedLooseSequence",

0 commit comments

Comments
 (0)