pathseq 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pathseq-0.1.0/PKG-INFO +134 -0
- pathseq-0.1.0/README.rst +107 -0
- pathseq-0.1.0/pyproject.toml +92 -0
- pathseq-0.1.0/src/pathseq/__init__.py +44 -0
- pathseq-0.1.0/src/pathseq/_arithmetic_sequence.py +154 -0
- pathseq-0.1.0/src/pathseq/_ast/__init__.py +22 -0
- pathseq-0.1.0/src/pathseq/_ast/_base.py +236 -0
- pathseq-0.1.0/src/pathseq/_ast/_formatter.py +38 -0
- pathseq-0.1.0/src/pathseq/_ast/_loose_type.py +219 -0
- pathseq-0.1.0/src/pathseq/_ast/_type.py +64 -0
- pathseq-0.1.0/src/pathseq/_base.py +510 -0
- pathseq-0.1.0/src/pathseq/_decimal_range.py +172 -0
- pathseq-0.1.0/src/pathseq/_error.py +72 -0
- pathseq-0.1.0/src/pathseq/_file_num_seq.py +232 -0
- pathseq-0.1.0/src/pathseq/_formatter.py +85 -0
- pathseq-0.1.0/src/pathseq/_from_disk.py +73 -0
- pathseq-0.1.0/src/pathseq/_loose_path_sequence.py +14 -0
- pathseq-0.1.0/src/pathseq/_loose_pure_path_sequence.py +126 -0
- pathseq-0.1.0/src/pathseq/_parse_file_num_seq.py +77 -0
- pathseq-0.1.0/src/pathseq/_parse_loose_path_sequence.py +525 -0
- pathseq-0.1.0/src/pathseq/_parse_path_sequence.py +327 -0
- pathseq-0.1.0/src/pathseq/_path_sequence.py +14 -0
- pathseq-0.1.0/src/pathseq/_pure_path_sequence.py +58 -0
- pathseq-0.1.0/src/pathseq/py.typed +0 -0
pathseq-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: pathseq
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A pathlib-like library for working with file sequences.
|
|
5
|
+
Author: Ashley Whetter
|
|
6
|
+
Author-email: Ashley Whetter <ashley@awhetter.co.uk>
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Environment :: Plugins
|
|
9
|
+
Classifier: Framework :: Sphinx :: Extension
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Requires-Dist: lark
|
|
21
|
+
Requires-Dist: python-statemachine
|
|
22
|
+
Requires-Dist: typing-extensions
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Project-URL: Documentation, https://pathseq.readthedocs.org
|
|
25
|
+
Project-URL: Source, https://github.com/AWhetter/pathseq
|
|
26
|
+
Description-Content-Type: text/x-rst
|
|
27
|
+
|
|
28
|
+
pathseq
|
|
29
|
+
=======
|
|
30
|
+
|
|
31
|
+
.. image:: https://readthedocs.org/projects/pathseq/badge/?version=latest
|
|
32
|
+
:target: https://pathseq.readthedocs.org
|
|
33
|
+
:alt: Documentation
|
|
34
|
+
|
|
35
|
+
.. image:: https://github.com/AWhetter/pathseq/actions/workflows/main.yml/badge.svg?branch=main
|
|
36
|
+
:target: https://github.com/AWhetter/pathseq/actions/workflows/main.yml?query=branch%3Amain
|
|
37
|
+
:alt: Github Build Status
|
|
38
|
+
|
|
39
|
+
.. image:: https://img.shields.io/pypi/v/pathseq.svg
|
|
40
|
+
:target: https://pypi.org/project/pathseq/
|
|
41
|
+
:alt: PyPI Version
|
|
42
|
+
|
|
43
|
+
.. image:: https://img.shields.io/pypi/pyversions/pathseq.svg
|
|
44
|
+
:target: https://pypi.org/project/pathseq/
|
|
45
|
+
:alt: Supported Python Versions
|
|
46
|
+
|
|
47
|
+
A pathlib-first library for working with file sequences.
|
|
48
|
+
|
|
49
|
+
TODO: Note special features
|
|
50
|
+
|
|
51
|
+
* Multi-dimension ranges (eg animated udims)
|
|
52
|
+
* pathlib-first API
|
|
53
|
+
* Support for UDIM tokens
|
|
54
|
+
* Sequence compression?
|
|
55
|
+
|
|
56
|
+
Getting Started
|
|
57
|
+
---------------
|
|
58
|
+
|
|
59
|
+
The following section demonstrates how to install ``pathseq`` and some basic usage.
|
|
60
|
+
Full documentation is available here: https://pathseq.readthedocs.io/en/latest/
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
Installation
|
|
64
|
+
~~~~~~~~~~~~
|
|
65
|
+
|
|
66
|
+
``pathseq`` can be installed through pip:
|
|
67
|
+
|
|
68
|
+
.. code-block:: bash
|
|
69
|
+
|
|
70
|
+
pip install pathseq
|
|
71
|
+
|
|
72
|
+
Usage
|
|
73
|
+
~~~~~
|
|
74
|
+
|
|
75
|
+
TODO
|
|
76
|
+
|
|
77
|
+
For more detailed usage, see the documentation:
|
|
78
|
+
https://pathseq.readthedocs.io/en/latest/
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
Contributing
|
|
82
|
+
------------
|
|
83
|
+
|
|
84
|
+
Running the tests
|
|
85
|
+
~~~~~~~~~~~~~~~~~
|
|
86
|
+
|
|
87
|
+
Tests are executed through `tox <https://tox.readthedocs.io/en/latest/>`_.
|
|
88
|
+
|
|
89
|
+
.. code-block:: bash
|
|
90
|
+
|
|
91
|
+
tox
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
Code Style
|
|
95
|
+
~~~~~~~~~~
|
|
96
|
+
|
|
97
|
+
Code is formatted using `black <https://github.com/python/black>`_.
|
|
98
|
+
|
|
99
|
+
You can check your formatting using black's check mode:
|
|
100
|
+
|
|
101
|
+
.. code-block:: bash
|
|
102
|
+
|
|
103
|
+
tox -e format
|
|
104
|
+
|
|
105
|
+
You can also get black to format your changes for you:
|
|
106
|
+
|
|
107
|
+
.. code-block:: bash
|
|
108
|
+
|
|
109
|
+
tox -e format -- src/ tests/
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
Release Notes
|
|
113
|
+
~~~~~~~~~~~~~
|
|
114
|
+
|
|
115
|
+
Release notes are managed through `towncrier <https://towncrier.readthedocs.io/en/stable/index.html>`_.
|
|
116
|
+
When making a pull request you will need to create a news fragment to document your change:
|
|
117
|
+
|
|
118
|
+
.. code-block:: bash
|
|
119
|
+
|
|
120
|
+
tox -e release_notes -- create --help
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
Versioning
|
|
124
|
+
----------
|
|
125
|
+
|
|
126
|
+
We use `SemVer <https://semver.org/>`_ for versioning.
|
|
127
|
+
For the versions available, see the `tags on this repository <https://github.com/AWhetter/pathseq/tags>`_.
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
License
|
|
131
|
+
-------
|
|
132
|
+
|
|
133
|
+
This project is licensed under the MIT License.
|
|
134
|
+
See the `LICENSE.rst <LICENSE.rst>`_ file for details.
|
pathseq-0.1.0/README.rst
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
pathseq
|
|
2
|
+
=======
|
|
3
|
+
|
|
4
|
+
.. image:: https://readthedocs.org/projects/pathseq/badge/?version=latest
|
|
5
|
+
:target: https://pathseq.readthedocs.org
|
|
6
|
+
:alt: Documentation
|
|
7
|
+
|
|
8
|
+
.. image:: https://github.com/AWhetter/pathseq/actions/workflows/main.yml/badge.svg?branch=main
|
|
9
|
+
:target: https://github.com/AWhetter/pathseq/actions/workflows/main.yml?query=branch%3Amain
|
|
10
|
+
:alt: Github Build Status
|
|
11
|
+
|
|
12
|
+
.. image:: https://img.shields.io/pypi/v/pathseq.svg
|
|
13
|
+
:target: https://pypi.org/project/pathseq/
|
|
14
|
+
:alt: PyPI Version
|
|
15
|
+
|
|
16
|
+
.. image:: https://img.shields.io/pypi/pyversions/pathseq.svg
|
|
17
|
+
:target: https://pypi.org/project/pathseq/
|
|
18
|
+
:alt: Supported Python Versions
|
|
19
|
+
|
|
20
|
+
A pathlib-first library for working with file sequences.
|
|
21
|
+
|
|
22
|
+
TODO: Note special features
|
|
23
|
+
|
|
24
|
+
* Multi-dimension ranges (eg animated udims)
|
|
25
|
+
* pathlib-first API
|
|
26
|
+
* Support for UDIM tokens
|
|
27
|
+
* Sequence compression?
|
|
28
|
+
|
|
29
|
+
Getting Started
|
|
30
|
+
---------------
|
|
31
|
+
|
|
32
|
+
The following section demonstrates how to install ``pathseq`` and some basic usage.
|
|
33
|
+
Full documentation is available here: https://pathseq.readthedocs.io/en/latest/
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Installation
|
|
37
|
+
~~~~~~~~~~~~
|
|
38
|
+
|
|
39
|
+
``pathseq`` can be installed through pip:
|
|
40
|
+
|
|
41
|
+
.. code-block:: bash
|
|
42
|
+
|
|
43
|
+
pip install pathseq
|
|
44
|
+
|
|
45
|
+
Usage
|
|
46
|
+
~~~~~
|
|
47
|
+
|
|
48
|
+
TODO
|
|
49
|
+
|
|
50
|
+
For more detailed usage, see the documentation:
|
|
51
|
+
https://pathseq.readthedocs.io/en/latest/
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
Contributing
|
|
55
|
+
------------
|
|
56
|
+
|
|
57
|
+
Running the tests
|
|
58
|
+
~~~~~~~~~~~~~~~~~
|
|
59
|
+
|
|
60
|
+
Tests are executed through `tox <https://tox.readthedocs.io/en/latest/>`_.
|
|
61
|
+
|
|
62
|
+
.. code-block:: bash
|
|
63
|
+
|
|
64
|
+
tox
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
Code Style
|
|
68
|
+
~~~~~~~~~~
|
|
69
|
+
|
|
70
|
+
Code is formatted using `black <https://github.com/python/black>`_.
|
|
71
|
+
|
|
72
|
+
You can check your formatting using black's check mode:
|
|
73
|
+
|
|
74
|
+
.. code-block:: bash
|
|
75
|
+
|
|
76
|
+
tox -e format
|
|
77
|
+
|
|
78
|
+
You can also get black to format your changes for you:
|
|
79
|
+
|
|
80
|
+
.. code-block:: bash
|
|
81
|
+
|
|
82
|
+
tox -e format -- src/ tests/
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
Release Notes
|
|
86
|
+
~~~~~~~~~~~~~
|
|
87
|
+
|
|
88
|
+
Release notes are managed through `towncrier <https://towncrier.readthedocs.io/en/stable/index.html>`_.
|
|
89
|
+
When making a pull request you will need to create a news fragment to document your change:
|
|
90
|
+
|
|
91
|
+
.. code-block:: bash
|
|
92
|
+
|
|
93
|
+
tox -e release_notes -- create --help
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
Versioning
|
|
97
|
+
----------
|
|
98
|
+
|
|
99
|
+
We use `SemVer <https://semver.org/>`_ for versioning.
|
|
100
|
+
For the versions available, see the `tags on this repository <https://github.com/AWhetter/pathseq/tags>`_.
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
License
|
|
104
|
+
-------
|
|
105
|
+
|
|
106
|
+
This project is licensed under the MIT License.
|
|
107
|
+
See the `LICENSE.rst <LICENSE.rst>`_ file for details.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pathseq"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A pathlib-like library for working with file sequences."
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Ashley Whetter", email = "ashley@awhetter.co.uk"},
|
|
7
|
+
]
|
|
8
|
+
readme = "README.rst"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 4 - Beta",
|
|
11
|
+
"Environment :: Plugins",
|
|
12
|
+
"Framework :: Sphinx :: Extension",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Natural Language :: English",
|
|
16
|
+
"Programming Language :: Python",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
|
+
]
|
|
24
|
+
requires-python = ">=3.10"
|
|
25
|
+
dependencies = [
|
|
26
|
+
"lark",
|
|
27
|
+
"python-statemachine",
|
|
28
|
+
"typing_extensions",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Source = "https://github.com/AWhetter/pathseq"
|
|
33
|
+
Documentation = "https://pathseq.readthedocs.org"
|
|
34
|
+
|
|
35
|
+
[dependency-groups]
|
|
36
|
+
dev = [
|
|
37
|
+
{include-group = "test"},
|
|
38
|
+
{include-group = "format"},
|
|
39
|
+
{include-group = "lint"},
|
|
40
|
+
{include-group = "typecheck"},
|
|
41
|
+
{include-group = "doc"},
|
|
42
|
+
]
|
|
43
|
+
test = [
|
|
44
|
+
"fileseq",
|
|
45
|
+
"hypothesis",
|
|
46
|
+
"pytest",
|
|
47
|
+
]
|
|
48
|
+
format = [
|
|
49
|
+
"ruff",
|
|
50
|
+
]
|
|
51
|
+
lint = [
|
|
52
|
+
"ruff",
|
|
53
|
+
]
|
|
54
|
+
typecheck = [
|
|
55
|
+
"mypy",
|
|
56
|
+
]
|
|
57
|
+
doc = [
|
|
58
|
+
"furo",
|
|
59
|
+
"sphinx",
|
|
60
|
+
"sphinx-design",
|
|
61
|
+
]
|
|
62
|
+
release_notes = [
|
|
63
|
+
"towncrier",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[build-system]
|
|
67
|
+
requires = ["uv_build>=0.8.5,<0.9.0"]
|
|
68
|
+
build-backend = "uv_build"
|
|
69
|
+
|
|
70
|
+
[tool.uv.build-backend]
|
|
71
|
+
module-name = "pathseq"
|
|
72
|
+
|
|
73
|
+
[tool.pylint]
|
|
74
|
+
disable = "R,unused-argument"
|
|
75
|
+
|
|
76
|
+
[tool.towncrier]
|
|
77
|
+
directory = "doc/changes"
|
|
78
|
+
filename = "CHANGELOG.rst"
|
|
79
|
+
package = "pathseq"
|
|
80
|
+
title_format = "pathseq v{version} ({project_date})"
|
|
81
|
+
|
|
82
|
+
[tool.pytest.ini_options]
|
|
83
|
+
markers = [
|
|
84
|
+
"todo",
|
|
85
|
+
]
|
|
86
|
+
addopts = "--doctest-glob='[!0]*.rst' --doctest-modules --ignore=doc/source/conf.py"
|
|
87
|
+
doctest_optionflags = "ELLIPSIS"
|
|
88
|
+
testpaths = [
|
|
89
|
+
"tests",
|
|
90
|
+
"doc/source",
|
|
91
|
+
"src",
|
|
92
|
+
]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""A pathlib-first library for working with file sequences."""
|
|
2
|
+
|
|
3
|
+
from ._ast import (
|
|
4
|
+
FileNumT,
|
|
5
|
+
PaddedRange,
|
|
6
|
+
ParsedLooseSequence,
|
|
7
|
+
ParsedSequence,
|
|
8
|
+
Ranges,
|
|
9
|
+
RangesEndName,
|
|
10
|
+
RangesInName,
|
|
11
|
+
RangesStartName,
|
|
12
|
+
)
|
|
13
|
+
from ._base import BasePathSequence, BasePurePathSequence, PathT_co, PurePathT_co
|
|
14
|
+
from ._error import IncompleteDimensionError, NotASequenceError, ParseError
|
|
15
|
+
from ._file_num_seq import FileNumSequence
|
|
16
|
+
from ._loose_path_sequence import LoosePathSequence
|
|
17
|
+
from ._loose_pure_path_sequence import LoosePurePathSequence
|
|
18
|
+
from ._path_sequence import PathSequence
|
|
19
|
+
from ._pure_path_sequence import PurePathSequence
|
|
20
|
+
|
|
21
|
+
__version__ = "0.1.0"
|
|
22
|
+
|
|
23
|
+
__all__ = (
|
|
24
|
+
"BasePathSequence",
|
|
25
|
+
"BasePurePathSequence",
|
|
26
|
+
"FileNumSequence",
|
|
27
|
+
"FileNumT",
|
|
28
|
+
"IncompleteDimensionError",
|
|
29
|
+
"LoosePathSequence",
|
|
30
|
+
"LoosePurePathSequence",
|
|
31
|
+
"NotASequenceError",
|
|
32
|
+
"PaddedRange",
|
|
33
|
+
"ParsedLooseSequence",
|
|
34
|
+
"ParseError",
|
|
35
|
+
"ParsedSequence",
|
|
36
|
+
"PathSequence",
|
|
37
|
+
"PathT_co",
|
|
38
|
+
"PurePathSequence",
|
|
39
|
+
"PurePathT_co",
|
|
40
|
+
"Ranges",
|
|
41
|
+
"RangesEndName",
|
|
42
|
+
"RangesInName",
|
|
43
|
+
"RangesStartName",
|
|
44
|
+
)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from collections.abc import Iterator, Sequence
|
|
2
|
+
import decimal
|
|
3
|
+
from typing import overload, Protocol, TypeVar
|
|
4
|
+
|
|
5
|
+
from typing_extensions import Self # PY311
|
|
6
|
+
|
|
7
|
+
from ._ast import FileNumT
|
|
8
|
+
from ._decimal_range import DecimalRange
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
FileNumT_cov = TypeVar("FileNumT_cov", covariant=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RangeProtocol(Protocol[FileNumT_cov]):
|
|
15
|
+
@property
|
|
16
|
+
def start(self) -> FileNumT_cov: ...
|
|
17
|
+
@property
|
|
18
|
+
def step(self) -> FileNumT_cov: ...
|
|
19
|
+
|
|
20
|
+
def __iter__(self) -> Iterator[FileNumT_cov]: ...
|
|
21
|
+
|
|
22
|
+
def __len__(self) -> int: ...
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def remove_exponent(d: decimal.Decimal) -> decimal.Decimal:
|
|
26
|
+
"""Remove the exponent and trailing zeros from the given decimal."""
|
|
27
|
+
return d.quantize(decimal.Decimal(1)) if d == d.to_integral() else d.normalize()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ArithmeticSequence(Sequence[FileNumT]):
|
|
31
|
+
def __init__(
|
|
32
|
+
self, start: FileNumT, end: FileNumT | None = None, step: FileNumT | None = None
|
|
33
|
+
) -> None:
|
|
34
|
+
end = end if end is not None else start
|
|
35
|
+
step = step if step is not None else start.__class__(1)
|
|
36
|
+
|
|
37
|
+
# Normalise to a positive step value
|
|
38
|
+
if step < 0:
|
|
39
|
+
start, end = (end, start)
|
|
40
|
+
step = -step
|
|
41
|
+
|
|
42
|
+
stop: FileNumT
|
|
43
|
+
if start < end:
|
|
44
|
+
# Normalise the end value to match the step
|
|
45
|
+
remainder = divmod(end - start, step)[1]
|
|
46
|
+
if remainder:
|
|
47
|
+
stop = end + (step - remainder)
|
|
48
|
+
end -= remainder
|
|
49
|
+
else:
|
|
50
|
+
stop = end + step
|
|
51
|
+
elif start == end:
|
|
52
|
+
# We treat the end as inclusive, ranges don't.
|
|
53
|
+
stop = end + step
|
|
54
|
+
# Normalise to a step of 1
|
|
55
|
+
step = start.__class__(1)
|
|
56
|
+
else:
|
|
57
|
+
stop = end
|
|
58
|
+
|
|
59
|
+
self._range: RangeProtocol[FileNumT]
|
|
60
|
+
self._end: FileNumT
|
|
61
|
+
if isinstance(start, int):
|
|
62
|
+
self._range = range(start, stop, step)
|
|
63
|
+
self._end = end
|
|
64
|
+
else:
|
|
65
|
+
self._range = DecimalRange(
|
|
66
|
+
remove_exponent(start), remove_exponent(stop), remove_exponent(step)
|
|
67
|
+
)
|
|
68
|
+
self._end = remove_exponent(end)
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def start(self) -> FileNumT:
|
|
72
|
+
return self._range.start
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def end(self) -> FileNumT:
|
|
76
|
+
return self._end
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def step(self) -> FileNumT:
|
|
80
|
+
return self._range.step
|
|
81
|
+
|
|
82
|
+
def __eq__(self, other: object) -> bool:
|
|
83
|
+
if not isinstance(other, ArithmeticSequence):
|
|
84
|
+
return NotImplemented
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
isinstance(self.start, other.start.__class__)
|
|
88
|
+
and self.start == other.start
|
|
89
|
+
and self.end == other.end
|
|
90
|
+
and self.step == other.step
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def __hash__(self) -> int:
|
|
94
|
+
return hash((type(self), self.start, self.end, self.step))
|
|
95
|
+
|
|
96
|
+
def __contains__(self, item: object) -> bool:
|
|
97
|
+
return any(item == x for x in self._range)
|
|
98
|
+
|
|
99
|
+
def __iter__(self) -> Iterator[FileNumT]:
|
|
100
|
+
return iter(self._range)
|
|
101
|
+
|
|
102
|
+
def __len__(self) -> int:
|
|
103
|
+
return len(self._range)
|
|
104
|
+
|
|
105
|
+
def __str__(self) -> str:
|
|
106
|
+
if len(self) == 1:
|
|
107
|
+
return str(self.start)
|
|
108
|
+
|
|
109
|
+
result = f"{self.start}-{self.end}"
|
|
110
|
+
if self.step != 1:
|
|
111
|
+
result += f"x{self.step}"
|
|
112
|
+
elif len(self) == 2:
|
|
113
|
+
return ",".join(str(x) for x in self)
|
|
114
|
+
|
|
115
|
+
return result
|
|
116
|
+
|
|
117
|
+
def __repr__(self) -> str:
|
|
118
|
+
if self.step == 1:
|
|
119
|
+
return f"{self.__class__.__name__}({self.start}, {self.end})"
|
|
120
|
+
|
|
121
|
+
return f"{self.__class__.__name__}({self.start}, {self.end}, {self.step})"
|
|
122
|
+
|
|
123
|
+
@overload
|
|
124
|
+
def __getitem__(self, index: int) -> FileNumT: ...
|
|
125
|
+
|
|
126
|
+
@overload
|
|
127
|
+
def __getitem__(self, index: slice) -> Self: ...
|
|
128
|
+
|
|
129
|
+
def __getitem__(self, index: int | slice) -> FileNumT | Self:
|
|
130
|
+
if isinstance(index, slice):
|
|
131
|
+
start_i, stop_i, step = index.indices(len(self))
|
|
132
|
+
if step > 0:
|
|
133
|
+
if start_i >= stop_i:
|
|
134
|
+
raise IndexError("slice creates an empty arithemtic sequence")
|
|
135
|
+
else:
|
|
136
|
+
if start_i <= stop_i:
|
|
137
|
+
raise IndexError("slice creates an empty arithemtic sequence")
|
|
138
|
+
|
|
139
|
+
start = self[index.start]
|
|
140
|
+
try:
|
|
141
|
+
stop = self[index.stop + 1]
|
|
142
|
+
except IndexError:
|
|
143
|
+
stop = self.end
|
|
144
|
+
|
|
145
|
+
return self.__class__(start, stop, self.step * index.step)
|
|
146
|
+
|
|
147
|
+
if index < 0:
|
|
148
|
+
index += len(self)
|
|
149
|
+
if index < 0:
|
|
150
|
+
raise IndexError("index out of range")
|
|
151
|
+
elif index >= len(self):
|
|
152
|
+
raise IndexError("index out of range")
|
|
153
|
+
|
|
154
|
+
return self._range.start + index * self._range.step
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from ._base import FileNum, FileNumT, PaddedRange, Ranges
|
|
2
|
+
from ._formatter import Formatter
|
|
3
|
+
from ._loose_type import (
|
|
4
|
+
ParsedLooseSequence,
|
|
5
|
+
RangesStartName,
|
|
6
|
+
RangesInName,
|
|
7
|
+
RangesEndName,
|
|
8
|
+
)
|
|
9
|
+
from ._type import ParsedSequence
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"FileNum",
|
|
13
|
+
"FileNumT",
|
|
14
|
+
"Formatter",
|
|
15
|
+
"PaddedRange",
|
|
16
|
+
"ParsedLooseSequence",
|
|
17
|
+
"ParsedSequence",
|
|
18
|
+
"Ranges",
|
|
19
|
+
"RangesStartName",
|
|
20
|
+
"RangesInName",
|
|
21
|
+
"RangesEndName",
|
|
22
|
+
]
|