scipathgen 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.
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: scipathgen
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Template-based path generation for data pipelines
|
|
5
|
+
Project-URL: Repository, https://github.com/example/scipathgen
|
|
6
|
+
Project-URL: Issues, https://github.com/example/scipathgen/issues
|
|
7
|
+
Author: SciStack Contributors
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Keywords: batch-processing,data-pipeline,file-discovery,metadata,path,template
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# SciPathGen
|
|
31
|
+
|
|
32
|
+
Template-based path generation for data pipelines.
|
|
33
|
+
|
|
34
|
+
Generates file paths with associated metadata from a template and metadata value combinations.
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from scipathgen import PathGenerator
|
|
40
|
+
|
|
41
|
+
paths = PathGenerator(
|
|
42
|
+
"{subject}/trial_{trial}.mat",
|
|
43
|
+
root_folder="/data/experiment",
|
|
44
|
+
subject=range(3),
|
|
45
|
+
trial=range(5),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
for path, meta in paths:
|
|
49
|
+
print(path, meta)
|
|
50
|
+
# /data/experiment/0/trial_0.mat {'subject': 0, 'trial': 0}
|
|
51
|
+
# /data/experiment/0/trial_1.mat {'subject': 0, 'trial': 1}
|
|
52
|
+
# ...
|
|
53
|
+
|
|
54
|
+
# Supports indexing and length
|
|
55
|
+
print(len(paths)) # 15
|
|
56
|
+
path, meta = paths[0]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If `root_folder` is omitted, paths are resolved relative to the current working directory via `Path.resolve()`.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# SciPathGen
|
|
2
|
+
|
|
3
|
+
Template-based path generation for data pipelines.
|
|
4
|
+
|
|
5
|
+
Generates file paths with associated metadata from a template and metadata value combinations.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from scipathgen import PathGenerator
|
|
11
|
+
|
|
12
|
+
paths = PathGenerator(
|
|
13
|
+
"{subject}/trial_{trial}.mat",
|
|
14
|
+
root_folder="/data/experiment",
|
|
15
|
+
subject=range(3),
|
|
16
|
+
trial=range(5),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
for path, meta in paths:
|
|
20
|
+
print(path, meta)
|
|
21
|
+
# /data/experiment/0/trial_0.mat {'subject': 0, 'trial': 0}
|
|
22
|
+
# /data/experiment/0/trial_1.mat {'subject': 0, 'trial': 1}
|
|
23
|
+
# ...
|
|
24
|
+
|
|
25
|
+
# Supports indexing and length
|
|
26
|
+
print(len(paths)) # 15
|
|
27
|
+
path, meta = paths[0]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If `root_folder` is omitted, paths are resolved relative to the current working directory via `Path.resolve()`.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "scipathgen"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Template-based path generation for data pipelines"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "SciStack Contributors" }
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"path",
|
|
17
|
+
"template",
|
|
18
|
+
"file-discovery",
|
|
19
|
+
"metadata",
|
|
20
|
+
"data-pipeline",
|
|
21
|
+
"batch-processing",
|
|
22
|
+
]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Development Status :: 4 - Beta",
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
"Intended Audience :: Science/Research",
|
|
27
|
+
"License :: OSI Approved :: MIT License",
|
|
28
|
+
"Operating System :: OS Independent",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3.10",
|
|
31
|
+
"Programming Language :: Python :: 3.11",
|
|
32
|
+
"Programming Language :: Python :: 3.12",
|
|
33
|
+
"Topic :: Scientific/Engineering",
|
|
34
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
35
|
+
"Typing :: Typed",
|
|
36
|
+
]
|
|
37
|
+
dependencies = []
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
dev = [
|
|
41
|
+
"pytest>=7.0",
|
|
42
|
+
"pytest-cov>=4.0",
|
|
43
|
+
"mypy>=1.0",
|
|
44
|
+
"ruff>=0.1.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Repository = "https://github.com/example/scipathgen"
|
|
49
|
+
Issues = "https://github.com/example/scipathgen/issues"
|
|
50
|
+
|
|
51
|
+
[tool.hatch.build.targets.sdist]
|
|
52
|
+
include = [
|
|
53
|
+
"/src",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[tool.hatch.build.targets.wheel]
|
|
57
|
+
packages = ["src/scipathgen"]
|
|
58
|
+
|
|
59
|
+
[tool.pytest.ini_options]
|
|
60
|
+
testpaths = ["tests"]
|
|
61
|
+
pythonpath = ["src"]
|
|
62
|
+
|
|
63
|
+
[tool.mypy]
|
|
64
|
+
python_version = "3.10"
|
|
65
|
+
strict = true
|
|
66
|
+
warn_return_any = true
|
|
67
|
+
warn_unused_configs = true
|
|
68
|
+
|
|
69
|
+
[tool.ruff]
|
|
70
|
+
target-version = "py310"
|
|
71
|
+
line-length = 88
|
|
72
|
+
|
|
73
|
+
[tool.ruff.lint]
|
|
74
|
+
select = [
|
|
75
|
+
"E", # pycodestyle errors
|
|
76
|
+
"W", # pycodestyle warnings
|
|
77
|
+
"F", # Pyflakes
|
|
78
|
+
"I", # isort
|
|
79
|
+
"B", # flake8-bugbear
|
|
80
|
+
"C4", # flake8-comprehensions
|
|
81
|
+
"UP", # pyupgrade
|
|
82
|
+
]
|
|
83
|
+
ignore = [
|
|
84
|
+
"E501", # line too long (handled by formatter)
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
[tool.ruff.lint.isort]
|
|
88
|
+
known-first-party = ["scipathgen"]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Path generation utilities for data pipelines.
|
|
2
|
+
|
|
3
|
+
This package provides template-based path generation for creating file paths
|
|
4
|
+
organized by metadata combinations (subject, trial, session, etc.).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from scipathgen.generator import PathGenerator
|
|
8
|
+
|
|
9
|
+
__all__ = ["PathGenerator"]
|
|
10
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Path generation from templates and metadata combinations."""
|
|
2
|
+
|
|
3
|
+
from itertools import product
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Iterator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PathGenerator:
|
|
9
|
+
"""
|
|
10
|
+
Generate file paths with associated metadata from a template and metadata values.
|
|
11
|
+
|
|
12
|
+
This class helps separate path resolution from data loading by generating
|
|
13
|
+
all combinations of metadata values along with their fully resolved paths.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
path_template: A format string with placeholders for metadata fields.
|
|
17
|
+
Uses Python's str.format() syntax, e.g., "{subject}/trial_{trial}.mat"
|
|
18
|
+
root_folder: Optional root folder path. If provided, paths are resolved
|
|
19
|
+
relative to this folder. If None, paths are resolved
|
|
20
|
+
relative to the current working directory (via Path.resolve()).
|
|
21
|
+
**metadata: Keyword arguments where each key is a metadata field name and
|
|
22
|
+
each value is an iterable of values for that field.
|
|
23
|
+
|
|
24
|
+
Example:
|
|
25
|
+
>>> paths = PathGenerator(
|
|
26
|
+
... "{subject}/trial_{trial}.mat",
|
|
27
|
+
... root_folder="/data/experiment",
|
|
28
|
+
... subject=range(3),
|
|
29
|
+
... trial=range(5)
|
|
30
|
+
... )
|
|
31
|
+
|
|
32
|
+
>>> for path, meta in paths:
|
|
33
|
+
... print(path, meta)
|
|
34
|
+
# /data/experiment/0/trial_0.mat {'subject': 0, 'trial': 0}
|
|
35
|
+
# /data/experiment/0/trial_1.mat {'subject': 0, 'trial': 1}
|
|
36
|
+
# ...
|
|
37
|
+
|
|
38
|
+
>>> # Can also access by index or get length
|
|
39
|
+
>>> print(len(paths)) # 15
|
|
40
|
+
>>> path, meta = paths[0]
|
|
41
|
+
>>> print(path) # /data/experiment/0/trial_0.mat
|
|
42
|
+
>>> print(meta) # {'subject': 0, 'trial': 0}
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
path_template: str,
|
|
48
|
+
root_folder: str | Path | None = None,
|
|
49
|
+
**metadata: Any,
|
|
50
|
+
):
|
|
51
|
+
self.path_template = path_template
|
|
52
|
+
self.root_folder = Path(root_folder) if root_folder is not None else None
|
|
53
|
+
self.metadata_keys = list(metadata.keys())
|
|
54
|
+
self.metadata_values = [list(v) for v in metadata.values()]
|
|
55
|
+
|
|
56
|
+
# Pre-compute all combinations for efficient indexing
|
|
57
|
+
self._items: list[tuple[Path, dict[str, Any]]] = []
|
|
58
|
+
for combo in product(*self.metadata_values):
|
|
59
|
+
meta = dict(zip(self.metadata_keys, combo))
|
|
60
|
+
relative_path = Path(path_template.format(**meta))
|
|
61
|
+
if self.root_folder is not None:
|
|
62
|
+
full_path = (self.root_folder / relative_path).resolve()
|
|
63
|
+
else:
|
|
64
|
+
full_path = relative_path.resolve()
|
|
65
|
+
self._items.append((full_path, meta))
|
|
66
|
+
|
|
67
|
+
def __iter__(self) -> Iterator[tuple[Path, dict[str, Any]]]:
|
|
68
|
+
"""Iterate over all path/metadata combinations."""
|
|
69
|
+
return iter(self._items)
|
|
70
|
+
|
|
71
|
+
def __len__(self) -> int:
|
|
72
|
+
"""Return the total number of path/metadata combinations."""
|
|
73
|
+
return len(self._items)
|
|
74
|
+
|
|
75
|
+
def __getitem__(self, index: int) -> tuple[Path, dict[str, Any]]:
|
|
76
|
+
"""Get a specific path/metadata combination by index."""
|
|
77
|
+
return self._items[index]
|
|
78
|
+
|
|
79
|
+
def __repr__(self) -> str:
|
|
80
|
+
"""Return a string representation of the PathGenerator."""
|
|
81
|
+
return (
|
|
82
|
+
f"PathGenerator({self.path_template!r}, "
|
|
83
|
+
f"root_folder={self.root_folder!r}, "
|
|
84
|
+
f"{', '.join(f'{k}=...' for k in self.metadata_keys)})"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def to_list(self) -> list[tuple[Path, dict[str, Any]]]:
|
|
88
|
+
"""Return all path/metadata combinations as a list."""
|
|
89
|
+
return list(self._items)
|