python-backpack 2.0.3__tar.gz → 2.0.4__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.
- {python_backpack-2.0.3 → python_backpack-2.0.4}/PKG-INFO +2 -2
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/file_utils.py +27 -22
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/version.py +3 -2
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_file_utils.py +23 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_json_user_settings.py +8 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/.github/workflows/codecov_tests.yml +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/.gitignore +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/LICENSE +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/README.md +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/__init__.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/__init__.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/cache.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/custom_errors.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/folder_utils.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/json_metadata.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/json_user_settings.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/json_utils.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/logger.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/patterns.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/strings.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack/test_utils.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/backpack.code-workspace +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/codecov.yml +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/coverage.bat +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/pyproject.toml +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/ruff.toml +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/__init__.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_cache.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_errors.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_files/edited.txt +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_files/edited_remove.txt +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_files/locked_file.txt +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_files/origin.txt +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_files/origin_remove.txt +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_files/unlocked_file.txt +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_folder_utils.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_json/data.json +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_json/data_broken.json +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_json/save/data_saved.json +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_json_utils.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_jsonmd.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_misc.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_strings.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/tests/test_test_utils.py +0 -0
- {python_backpack-2.0.3 → python_backpack-2.0.4}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: python-backpack
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: Lightweight utilities for JSON, filesystem operations, strings, caching, and scripting.
|
|
5
5
|
Project-URL: Homepage, https://github.com/MaxRocamora/python-backpack
|
|
6
6
|
Project-URL: Repository, https://github.com/MaxRocamora/python-backpack.git
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# https://github.com/MaxRocamora/python-backpack
|
|
5
5
|
# ----------------------------------------------------------------------------------------
|
|
6
6
|
|
|
7
|
+
import re
|
|
7
8
|
from collections.abc import Sequence
|
|
8
9
|
|
|
9
10
|
from backpack.logger import get_logger
|
|
@@ -94,11 +95,12 @@ def file_is_writeable(filepath: str) -> bool:
|
|
|
94
95
|
return False
|
|
95
96
|
|
|
96
97
|
|
|
97
|
-
def get_version_from_filename(filename: str) -> str:
|
|
98
|
+
def get_version_from_filename(filename: str, separator: str | None = None) -> str:
|
|
98
99
|
"""Extracts version from filename.
|
|
99
100
|
|
|
100
101
|
Args:
|
|
101
102
|
filename: (str) file name to extract version from
|
|
103
|
+
separator: delimiter that must precede the version; when omitted, use supported delimiters
|
|
102
104
|
Returns:
|
|
103
105
|
str : version extracted from filename
|
|
104
106
|
|
|
@@ -107,29 +109,32 @@ def get_version_from_filename(filename: str) -> str:
|
|
|
107
109
|
get_version_from_filename('myfile-9.txt') -> '9'
|
|
108
110
|
get_version_from_filename('myfile.130.txt') -> '130'
|
|
109
111
|
get_version_from_filename('myfile_v1002.txt') -> '1002'
|
|
112
|
+
get_version_from_filename('XD_shot_0000.0003.ma') -> '0003'
|
|
113
|
+
get_version_from_filename('ANM_shot_0010.0003.ma') -> '0003'
|
|
110
114
|
|
|
111
115
|
"""
|
|
112
116
|
|
|
113
117
|
filename_no_ext = filename.rsplit('.', 1)[0]
|
|
114
118
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
119
|
+
if separator is not None:
|
|
120
|
+
if not separator:
|
|
121
|
+
raise ValueError('separator must not be empty')
|
|
122
|
+
|
|
123
|
+
version = filename_no_ext.rsplit(separator, 1)[-1]
|
|
124
|
+
if version.isdigit():
|
|
125
|
+
log.info(
|
|
126
|
+
f'Extracted version: {version} from filename: {filename} using separator: {separator}'
|
|
127
|
+
)
|
|
128
|
+
return version
|
|
129
|
+
|
|
130
|
+
log.info(f'No numeric version found in filename: {filename} using separator: {separator}')
|
|
131
|
+
return '0'
|
|
132
|
+
|
|
133
|
+
match = re.search(r'(?:^|[_.-])v?(\d+)$', filename_no_ext)
|
|
134
|
+
if match:
|
|
135
|
+
version = match.group(1)
|
|
136
|
+
log.info(f'Extracted version: {version} from filename: {filename}')
|
|
137
|
+
return version
|
|
138
|
+
|
|
139
|
+
log.info(f'No numeric version found in filename: {filename}')
|
|
140
|
+
return '0'
|
|
@@ -11,10 +11,11 @@
|
|
|
11
11
|
# 1.1.4 07/2025 - Moved from pipenv to poetry for dependency management.toml
|
|
12
12
|
# 2.0.1 05/2026 - Remove tox workflow and setup.py, standardize uv + coverage tooling
|
|
13
13
|
# 2.0.2 05/2026 - Add PyPI long description metadata and release polish
|
|
14
|
-
# 2.0.3 06/2026 - Add type hints
|
|
14
|
+
# 2.0.3 06/2026 - Add type hints, refactor backpack.cache to use functools.lru_cache, added tests.
|
|
15
|
+
# 2.0.4 08/2026 - Fixed get_version_from_filename().
|
|
15
16
|
# ----------------------------------------------------------------------------------------
|
|
16
17
|
|
|
17
|
-
__version__ = '2.0.
|
|
18
|
+
__version__ = '2.0.4'
|
|
18
19
|
|
|
19
20
|
VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH = map(int, __version__.split('.'))
|
|
20
21
|
|
|
@@ -79,8 +79,31 @@ def test_file_is_writeable(tmp_path):
|
|
|
79
79
|
('myfile.txt', '0'),
|
|
80
80
|
('mod_asset.1004.ma', '1004'),
|
|
81
81
|
('script_nuke_s100_v1005.ma', '1005'),
|
|
82
|
+
('XD_shot_0000.0003.ma', '0003'),
|
|
83
|
+
('ANM_shot_0010.0003.ma', '0003'),
|
|
82
84
|
],
|
|
83
85
|
)
|
|
84
86
|
def test_get_version_from_filename(filename: str, expected_version: str):
|
|
85
87
|
"""Version extraction should handle supported separators and invalid values."""
|
|
86
88
|
assert get_version_from_filename(filename) == expected_version
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@pytest.mark.parametrize(
|
|
92
|
+
('filename', 'separator', 'expected_version'),
|
|
93
|
+
[
|
|
94
|
+
('XD_shot_0000.0003.ma', '.', '0003'),
|
|
95
|
+
('XD_shot_0000.0003.ma', '_', '0'),
|
|
96
|
+
('myfile_v1002.txt', 'v', '1002'),
|
|
97
|
+
],
|
|
98
|
+
)
|
|
99
|
+
def test_get_version_from_filename_with_separator(
|
|
100
|
+
filename: str, separator: str, expected_version: str
|
|
101
|
+
):
|
|
102
|
+
"""An explicit separator constrains version extraction to its final token."""
|
|
103
|
+
assert get_version_from_filename(filename, separator) == expected_version
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_get_version_from_filename_rejects_empty_separator():
|
|
107
|
+
"""An empty separator is not a meaningful version delimiter."""
|
|
108
|
+
with pytest.raises(ValueError, match='separator must not be empty'):
|
|
109
|
+
get_version_from_filename('myfile_23.txt', '')
|
|
@@ -65,3 +65,11 @@ def test_user_settings_creates_missing_directory(settings_home):
|
|
|
65
65
|
|
|
66
66
|
assert target_dir.exists() is True
|
|
67
67
|
assert Path(js.filepath).parent == target_dir
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_os_user_folder_returns_home_directory(monkeypatch):
|
|
71
|
+
"""The unpatched property should resolve the current user's home directory."""
|
|
72
|
+
monkeypatch.undo()
|
|
73
|
+
settings = object.__new__(JsonUserSettings)
|
|
74
|
+
|
|
75
|
+
assert settings.os_user_folder == str(Path.home())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|