pysequitur 0.1.2__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.
Files changed (42) hide show
  1. pysequitur-0.1.2/LICENCE +7 -0
  2. pysequitur-0.1.2/PKG-INFO +136 -0
  3. pysequitur-0.1.2/README.md +109 -0
  4. pysequitur-0.1.2/pyproject.toml +84 -0
  5. pysequitur-0.1.2/src/pysequitur/__init__.py +31 -0
  6. pysequitur-0.1.2/src/pysequitur/examples/examples.py +66 -0
  7. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01001.dpx +0 -0
  8. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01002.dpx +0 -0
  9. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01003.dpx +0 -0
  10. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01004.dpx +0 -0
  11. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01005.dpx +0 -0
  12. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01006.dpx +0 -0
  13. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01007.dpx +0 -0
  14. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01008.dpx +0 -0
  15. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01009.dpx +0 -0
  16. pysequitur-0.1.2/src/pysequitur/examples/files/plate.01010.dpx +0 -0
  17. pysequitur-0.1.2/src/pysequitur/examples/files/render_001_final.exr +0 -0
  18. pysequitur-0.1.2/src/pysequitur/examples/files/render_002_final.exr +0 -0
  19. pysequitur-0.1.2/src/pysequitur/examples/files/render_003_final.exr +0 -0
  20. pysequitur-0.1.2/src/pysequitur/examples/files/render_004_final.exr +0 -0
  21. pysequitur-0.1.2/src/pysequitur/examples/files/render_005_final.exr +0 -0
  22. pysequitur-0.1.2/src/pysequitur/examples/files/render_006_final.exr +0 -0
  23. pysequitur-0.1.2/src/pysequitur/examples/files/render_007_final.exr +0 -0
  24. pysequitur-0.1.2/src/pysequitur/examples/files/render_008_final.exr +0 -0
  25. pysequitur-0.1.2/src/pysequitur/examples/files/render_009_final.exr +0 -0
  26. pysequitur-0.1.2/src/pysequitur/examples/files/render_010_final.exr +0 -0
  27. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0100.exr +0 -0
  28. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0101.exr +0 -0
  29. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0102.exr +0 -0
  30. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0103.exr +0 -0
  31. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0104.exr +0 -0
  32. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0105.exr +0 -0
  33. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0106.exr +0 -0
  34. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0107.exr +0 -0
  35. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0108.exr +0 -0
  36. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0109.exr +0 -0
  37. pysequitur-0.1.2/src/pysequitur/examples/files/shot-0110.exr +0 -0
  38. pysequitur-0.1.2/src/pysequitur/examples/utils.py +62 -0
  39. pysequitur-0.1.2/src/pysequitur/file_sequence.py +1889 -0
  40. pysequitur-0.1.2/src/pysequitur/file_sequence_bak.py +1735 -0
  41. pysequitur-0.1.2/src/pysequitur/file_sequence_bak_bak.py +1717 -0
  42. pysequitur-0.1.2/src/pysequitur/main.py +17 -0
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2024 Alex Harding (alexharding.ooo)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysequitur
3
+ Version: 0.1.2
4
+ Summary: parsing and manipulation tool for file sequences
5
+ License: MIT
6
+ License-File: LICENCE
7
+ Keywords: vfx,file-sequence,image-sequence,file-management
8
+ Author: arcadeperfect
9
+ Author-email: alex.harding.info@gmail.com
10
+ Requires-Python: >=3.9,<4.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Multimedia :: Graphics
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Dist: docformatter (>=1.7.5,<2.0.0)
24
+ Project-URL: Repository, https://github.com/arcadeperfect/pysequitur
25
+ Description-Content-Type: text/markdown
26
+
27
+ # PySequitur
28
+
29
+ Library for identifying and manipulating sequences of files. It is geared towards visual effects and animation related scenarios, although it can be used with any sequence of files. Emphasis on file system manipulation and flexible handing of anomalous sequences is the main differentiating feature from other similar libraries.
30
+
31
+ CLI and integration for Nuke coming soon.
32
+
33
+ No external dependencies, easy to use in VFX pipeline with no privileges.
34
+
35
+ ## Features
36
+
37
+ - **File Sequence Handling**
38
+ - Parse and manage frame-based file sequences
39
+ - Support for many naming conventions and patterns
40
+ - Handle missing or duplicate frames, inconsistent padding
41
+
42
+ - **Flexible Component System**
43
+ - Parse filenames into components (prefix, delimiter, frame number, suffix, extension)
44
+ - Modify individual components while preserving others
45
+ - Match sequences against optionally specified components
46
+
47
+ - **Sequence Operations**
48
+ - Rename sequences
49
+ - Move sequences around
50
+ - Delete sequences
51
+ - Copy sequences
52
+ - Offset frame numbers
53
+ - Adjust or repair frame number padding
54
+
55
+ ## Installation
56
+
57
+ ```bash
58
+ # TODO: Add installation instructions once package is published
59
+ ```
60
+
61
+ ## Quick Start
62
+
63
+ ```python
64
+ from pathlib import Path
65
+ from pysequitur import FileSequence, Components
66
+
67
+ # Parse sequences from a directory
68
+ sequences = FileSequence.find_sequences_in_path(Path("/path/to/files"))
69
+
70
+ # Create a virtual sequence from a list of file names
71
+ file_list = ["render_001.exr", "render_002.exr", "render_003.exr"]
72
+ sequence = FileSequence.find_sequences_in_filename_list(file_list)[0]
73
+
74
+ # Basic sequence operations
75
+ sequence.move_to(Path("/new/directory"))
76
+ sequence.rename_to(Components(prefix="new_name"))
77
+ sequence.offset_frames(100) # Shift all frame numbers by 100
78
+ sequence.delete_files()
79
+ new_sequence = sequence.copy_to(Components(prefix="new_name"), Path("/new/directory"))
80
+
81
+ # Match sequences by components
82
+ components = Components(prefix="render", extension="exr")
83
+ matches = FileSequence.match_components_in_path(components, Path("/path/to/files"))
84
+
85
+ # Match sequence by pattern string
86
+ sequence = FileSequence.match_sequence_string_in_directory("render_####.exr", Path("/path/to/files"))
87
+ ```
88
+
89
+ ## Core Classes
90
+
91
+ ### Components
92
+
93
+ Configuration class for specifying filename components during operations. Any parameter can be None.
94
+
95
+ ```python
96
+ components = Components(
97
+ prefix="file_name",
98
+ delimiter=".",
99
+ padding=4,
100
+ suffix="_final",
101
+ extension="exr",
102
+ frame_number=None # Optional frame number for specific frame operations
103
+ )
104
+ ```
105
+ Equals: "file_name.####_final.exr"
106
+
107
+ ### FileSequence
108
+ Main class.
109
+ Manages collections of related Items as a single unit, where Items represent single files.
110
+
111
+ Key Features:
112
+ - Static methods for finding sequences in directories or filename lists
113
+ - Match sequences against Components or sequence string patterns
114
+ - Sequence manipulation operations (rename, move, copy, delete)
115
+ - Frame operations (offset, padding adjustment)
116
+ - Sequence analysis (missing frames, duplicates, problems detection)
117
+ - Existence status checking (TRUE, FALSE, PARTIAL)
118
+
119
+ ## File Naming Convention
120
+
121
+ The library parses filenames into the following components:
122
+ ```
123
+ <prefix><delimiter><frame><suffix>.<extension>
124
+ ```
125
+
126
+ Example: `render_001_final.exr`
127
+ - prefix: "render"
128
+ - delimiter: "_"
129
+ - frame: "001"
130
+ - suffix: "_final"
131
+ - extension: "exr"
132
+
133
+ ---
134
+
135
+ See examples folder for more usage scenarios
136
+
@@ -0,0 +1,109 @@
1
+ # PySequitur
2
+
3
+ Library for identifying and manipulating sequences of files. It is geared towards visual effects and animation related scenarios, although it can be used with any sequence of files. Emphasis on file system manipulation and flexible handing of anomalous sequences is the main differentiating feature from other similar libraries.
4
+
5
+ CLI and integration for Nuke coming soon.
6
+
7
+ No external dependencies, easy to use in VFX pipeline with no privileges.
8
+
9
+ ## Features
10
+
11
+ - **File Sequence Handling**
12
+ - Parse and manage frame-based file sequences
13
+ - Support for many naming conventions and patterns
14
+ - Handle missing or duplicate frames, inconsistent padding
15
+
16
+ - **Flexible Component System**
17
+ - Parse filenames into components (prefix, delimiter, frame number, suffix, extension)
18
+ - Modify individual components while preserving others
19
+ - Match sequences against optionally specified components
20
+
21
+ - **Sequence Operations**
22
+ - Rename sequences
23
+ - Move sequences around
24
+ - Delete sequences
25
+ - Copy sequences
26
+ - Offset frame numbers
27
+ - Adjust or repair frame number padding
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ # TODO: Add installation instructions once package is published
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ```python
38
+ from pathlib import Path
39
+ from pysequitur import FileSequence, Components
40
+
41
+ # Parse sequences from a directory
42
+ sequences = FileSequence.find_sequences_in_path(Path("/path/to/files"))
43
+
44
+ # Create a virtual sequence from a list of file names
45
+ file_list = ["render_001.exr", "render_002.exr", "render_003.exr"]
46
+ sequence = FileSequence.find_sequences_in_filename_list(file_list)[0]
47
+
48
+ # Basic sequence operations
49
+ sequence.move_to(Path("/new/directory"))
50
+ sequence.rename_to(Components(prefix="new_name"))
51
+ sequence.offset_frames(100) # Shift all frame numbers by 100
52
+ sequence.delete_files()
53
+ new_sequence = sequence.copy_to(Components(prefix="new_name"), Path("/new/directory"))
54
+
55
+ # Match sequences by components
56
+ components = Components(prefix="render", extension="exr")
57
+ matches = FileSequence.match_components_in_path(components, Path("/path/to/files"))
58
+
59
+ # Match sequence by pattern string
60
+ sequence = FileSequence.match_sequence_string_in_directory("render_####.exr", Path("/path/to/files"))
61
+ ```
62
+
63
+ ## Core Classes
64
+
65
+ ### Components
66
+
67
+ Configuration class for specifying filename components during operations. Any parameter can be None.
68
+
69
+ ```python
70
+ components = Components(
71
+ prefix="file_name",
72
+ delimiter=".",
73
+ padding=4,
74
+ suffix="_final",
75
+ extension="exr",
76
+ frame_number=None # Optional frame number for specific frame operations
77
+ )
78
+ ```
79
+ Equals: "file_name.####_final.exr"
80
+
81
+ ### FileSequence
82
+ Main class.
83
+ Manages collections of related Items as a single unit, where Items represent single files.
84
+
85
+ Key Features:
86
+ - Static methods for finding sequences in directories or filename lists
87
+ - Match sequences against Components or sequence string patterns
88
+ - Sequence manipulation operations (rename, move, copy, delete)
89
+ - Frame operations (offset, padding adjustment)
90
+ - Sequence analysis (missing frames, duplicates, problems detection)
91
+ - Existence status checking (TRUE, FALSE, PARTIAL)
92
+
93
+ ## File Naming Convention
94
+
95
+ The library parses filenames into the following components:
96
+ ```
97
+ <prefix><delimiter><frame><suffix>.<extension>
98
+ ```
99
+
100
+ Example: `render_001_final.exr`
101
+ - prefix: "render"
102
+ - delimiter: "_"
103
+ - frame: "001"
104
+ - suffix: "_final"
105
+ - extension: "exr"
106
+
107
+ ---
108
+
109
+ See examples folder for more usage scenarios
@@ -0,0 +1,84 @@
1
+ [tool.poetry]
2
+ name = "pysequitur"
3
+ version = "0.1.2"
4
+ description = "parsing and manipulation tool for file sequences"
5
+ authors = ["arcadeperfect <alex.harding.info@gmail.com>"]
6
+ readme = "README.md"
7
+ packages = [{include = "pysequitur", from = "src"}]
8
+ license = "MIT"
9
+ repository = "https://github.com/arcadeperfect/pysequitur" # Add this
10
+ keywords = ["vfx", "file-sequence", "image-sequence", "file-management"] # Add this
11
+ classifiers = [ # Add this
12
+ "Development Status :: 4 - Beta",
13
+ "Intended Audience :: Developers",
14
+ "Topic :: Multimedia :: Graphics",
15
+ "Topic :: Software Development :: Libraries :: Python Modules",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3.9",
18
+ ]
19
+
20
+ [tool.poetry.dependencies]
21
+ python = "^3.9"
22
+ docformatter = "^1.7.5"
23
+
24
+ [tool.poetry.group.dev.dependencies]
25
+ pytest = "^8.3.3"
26
+ pytest-cov = "^4.1.0" # Add this for coverage reports
27
+ pyyaml = "^6.0.2"
28
+ mypy = "^1.0"
29
+ black = "^24.10.0"
30
+ flake8 = "^7.0.0" # Moved to correct section
31
+ pylint = "^3.1.0"
32
+ isort = "^5.13.2"
33
+ docformatter = "^1.7.5"
34
+
35
+ [build-system]
36
+ requires = ["poetry-core"]
37
+ build-backend = "poetry.core.masonry.api"
38
+
39
+ [tool.poetry.scripts]
40
+ pysequitur = "pysequitur.main:main"
41
+ lint = "pylint src/pysequitur"
42
+ format = "black src/pysequitur"
43
+ typecheck = "mypy src/pysequitur"
44
+ sort-imports = "isort src/pysequitur"
45
+ check = "flake8 src/pysequitur"
46
+
47
+ # Tool configurations
48
+ [tool.black]
49
+ line-length = 88
50
+ target-version = ['py312']
51
+ include = '\.pyi?$'
52
+
53
+ [tool.isort]
54
+ profile = "black"
55
+ multi_line_output = 3
56
+ line_length = 88
57
+
58
+ [tool.mypy]
59
+ python_version = "3.12"
60
+ warn_return_any = true
61
+ warn_unused_configs = true
62
+ disallow_untyped_defs = true
63
+ check_untyped_defs = true
64
+ exclude = '^tests/'
65
+
66
+ [tool.pylint.MASTER]
67
+ ignore = ["tests", "test_*.py"]
68
+
69
+ [tool.pylint.messages_control]
70
+ disable = [
71
+ "C0301", # line-too-long
72
+ # "C0111", # missing-docstring
73
+ # "C0103", # invalid-name
74
+ # "C0330", # bad-continuation
75
+ # "C0326", # bad-whitespace
76
+ ]
77
+
78
+ [tool.pylint.format]
79
+ max-line-length = 88
80
+
81
+ [tool.pytest.ini_options] # Add this section
82
+ testpaths = ["tests"]
83
+ addopts = "--cov=pysequitur --cov-report=xml --cov-report=term-missing"
84
+ python_files = "test_*.py"
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2024 Alex Harding (alexharding.ooo)
2
+ # This file is part of PySequitur which is released under MIT license.
3
+ # See file LICENSE for full license details.
4
+ """
5
+ PySequitur - A tool for parsing and manipulating file sequences.
6
+
7
+ This package provides tools for working with frame-based file sequences,
8
+ commonly used in VFX and animation pipelines.
9
+
10
+ Classes:
11
+ Item: Represents a single item in a file sequence
12
+ FileSequence: Manages collections of related files as a sequence
13
+ Components: Configuration class for specifying filename components
14
+ """
15
+
16
+ from typing import List, Type
17
+
18
+ __version__ = "0.1.0"
19
+
20
+ from .file_sequence import Item, FileSequence, Components # type: ignore
21
+
22
+ # Type definitions for better IDE support
23
+ ItemType = Type[Item]
24
+ FileSequenceType = Type[FileSequence]
25
+ ComponentsType = Type[Components]
26
+
27
+ __all__: List[str] = [
28
+ "Item",
29
+ "FileSequence",
30
+ "Components",
31
+ ]
@@ -0,0 +1,66 @@
1
+ from pysequitur import Components, FileSequence
2
+ from pysequitur.examples.utils import create_some_sequences
3
+ import os
4
+
5
+
6
+ def run_examples():
7
+
8
+ # generate some empty files
9
+ temp_files_directory = create_some_sequences()
10
+
11
+ print("\n\nGenerated these files:\n")
12
+
13
+ for file in sorted(os.listdir(temp_files_directory)):
14
+ print(file)
15
+
16
+
17
+ ## Parse a directory of files
18
+
19
+ parsed_sequences = FileSequence.from_directory(temp_files_directory)
20
+
21
+ print("\n\nFound sequences:\n")
22
+ for seq in parsed_sequences:
23
+ print(seq)
24
+
25
+
26
+ ## Parse by components:
27
+
28
+ sequences = FileSequence.from_components_in_directory(Components(prefix="render"), temp_files_directory)
29
+
30
+ print("\n\nParser found one sequence with prefix 'render':\n")
31
+ for seq in sequences:
32
+ print(seq)
33
+
34
+ sequences = FileSequence.from_components_in_directory(Components(extension="exr"), temp_files_directory)
35
+
36
+ print("\n\nParser found two sequence with extension 'exr':\n")
37
+ for seq in sequences:
38
+ print(seq)
39
+
40
+ sequences = FileSequence.from_components_in_directory(Components(prefix="render", extension="exr"), temp_files_directory)
41
+
42
+ print("\n\nParser found one sequence with prefix 'render' and extension 'exr':\n")
43
+ for seq in sequences:
44
+ print(seq)
45
+
46
+
47
+ ## Parse by filename
48
+
49
+ seq = FileSequence.from_sequence_string_in_directory("render_###_final.exr", temp_files_directory)
50
+
51
+ print("\n\nParsed a single sequence:\n")
52
+ print(seq)
53
+
54
+
55
+
56
+ ## Operations:
57
+
58
+ seq = FileSequence.from_sequence_string_in_directory("render_###_final.exr", temp_files_directory)
59
+
60
+ seq.move_to("/new/directory")
61
+ seq.rename_to("new_name")
62
+ seq.offset_frames(100) # Shift all frame numbers by 100
63
+ new_sequence = seq.copy_to("/new/directory")
64
+
65
+ print("\n\nRenamed sequence:\n")
66
+ print(new_sequence)
@@ -0,0 +1,62 @@
1
+ from pysequitur import Components, FileSequence
2
+ import os
3
+ from pathlib import Path
4
+
5
+ seq1 = Components(
6
+ prefix="render",
7
+ delimiter=".",
8
+ padding=4,
9
+ suffix="exr",
10
+ extension="exr",
11
+ )
12
+
13
+
14
+ def create_some_sequences():
15
+
16
+ components_1 = Components(
17
+ prefix="render",
18
+ delimiter="_",
19
+ padding=3,
20
+ suffix="_final",
21
+ extension="exr",
22
+ )
23
+
24
+ components_2 = Components(
25
+ prefix="plate",
26
+ delimiter=".",
27
+ padding=5,
28
+ extension="dpx",
29
+ )
30
+
31
+ components_3 = Components(
32
+ prefix="shot",
33
+ delimiter="-",
34
+ padding=4,
35
+ extension="exr",
36
+ )
37
+
38
+ directory = os.path.dirname(os.path.abspath(__file__)) + "/files"
39
+
40
+ generate_file_sequence(components_1, 1, 10,directory )
41
+ generate_file_sequence(components_2, 1001, 1010, directory)
42
+ generate_file_sequence(components_3, 100, 110, directory)
43
+
44
+ return directory
45
+
46
+
47
+ def generate_file_sequence(
48
+ components: Components, first_frame: int, last_frame: int, directory
49
+ ) -> None:
50
+
51
+ padding = max(len(str(last_frame)), components.padding)
52
+
53
+
54
+
55
+ if components.suffix == None:
56
+ components.suffix = ""
57
+
58
+ for frame_number in range(first_frame, last_frame + 1):
59
+ this_frame = f"{components.prefix}{components.delimiter}{str(frame_number).zfill(padding)}{components.suffix}.{components.extension}"
60
+ p = Path(Path(directory) / this_frame)
61
+ p.touch()
62
+