python-backpack 2.0.0__py3-none-any.whl → 2.0.2__py3-none-any.whl

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.
backpack/file_utils.py CHANGED
@@ -84,3 +84,44 @@ def file_is_writeable(filepath: str) -> bool:
84
84
  log.info(x.strerror)
85
85
 
86
86
  return False
87
+
88
+
89
+ def get_version_from_filename(filename: str) -> str:
90
+ """Extracts version from filename.
91
+
92
+ Args:
93
+ filename: (str) file name to extract version from
94
+ Returns:
95
+ str : version extracted from filename
96
+
97
+ Examples:
98
+ get_version_from_filename('myfile_23.txt') -> '23'
99
+ get_version_from_filename('myfile-9.txt') -> '9'
100
+ get_version_from_filename('myfile.130.txt') -> '130'
101
+ get_version_from_filename('myfile_v1002.txt') -> '1002'
102
+
103
+ """
104
+
105
+ filename_no_ext = filename.rsplit('.', 1)[0]
106
+
107
+ # guess is the separator is an underscore, dash, dot or v, and the version is the last part before the extension
108
+ separators = ['_', '-', '.', 'v']
109
+ if not any(sep in filename_no_ext for sep in separators):
110
+ log.info(f'No separator found in filename: {filename_no_ext}. Using fallback extraction.')
111
+ else:
112
+ for sep in separators:
113
+ if sep in filename_no_ext:
114
+ parts = filename_no_ext.split(sep)
115
+ version_part = parts[-1].split('.')[0] # Get the last part before the extension
116
+ if version_part.replace('.', '').isdigit(): # Check if it's a valid version number
117
+ log.info(
118
+ f'Extracted version: {version_part} from filename: {filename} using separator: {sep}'
119
+ )
120
+ return version_part
121
+
122
+ # Fallback: extract from the entire filename
123
+ version = filename_no_ext.lstrip('v')
124
+ version = version.replace('_', '.').replace('-', '.')
125
+ version = version if version.replace('.', '').isdigit() else '0'
126
+ log.info(f'Extracted version: {version} from filename: {filename}')
127
+ return version
backpack/json_utils.py CHANGED
@@ -40,7 +40,7 @@ def json_save(data: dict, json_file: str) -> bool:
40
40
  """
41
41
 
42
42
  if not os.path.exists(os.path.dirname(json_file)):
43
- os.makedirs(os.path.dirname(json_file))
43
+ os.makedirs(os.path.dirname(json_file), exist_ok=True)
44
44
 
45
45
  try:
46
46
  with open(json_file, 'w') as f:
backpack/version.py CHANGED
@@ -9,12 +9,13 @@
9
9
  # 1.1.2 07/2025 - Update actions versions, remove unused badge from README
10
10
  # 1.1.3 07/2025 - Improve test class names and docstrings for clarity, ruff formatting
11
11
  # 1.1.4 07/2025 - Moved from pipenv to poetry for dependency management.toml
12
- # 2.0.0 03/2026 - Remove tox workflow and setup.py, standardize Poetry + coverage tooling
12
+ # 2.0.1 05/2026 - Remove tox workflow and setup.py, standardize uv + coverage tooling
13
+ # 2.0.2 05/2026 - Add PyPI long description metadata and release polish
13
14
  # ----------------------------------------------------------------------------------------
14
15
 
15
16
  VERSION_MAJOR = 2
16
17
  VERSION_MINOR = 0
17
- VERSION_PATCH = 0
18
+ VERSION_PATCH = 2
18
19
 
19
20
  version = f'{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_PATCH}'
20
21
 
@@ -0,0 +1,155 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-backpack
3
+ Version: 2.0.2
4
+ Summary: A collection of personal scripts for json, File/Folder Operations, String Validation, Custom Errors, Cache and stuff.
5
+ Author: Maximiliano Rocamora
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+
10
+ [![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/python-backpack.svg?style=flat-square&logo=appveyor)](https://pypi.python.org/pypi/python-backpack/)
11
+ [![PyPI version](https://badge.fury.io/py/python-backpack.svg?style=flat-square&logo=appveyor)](https://badge.fury.io/py/python-backpack)
12
+ [![GitHub version](https://badge.fury.io/gh/MaxRocamora%2Fpython-backpack.svg?style=flat-square&logo=appveyor)](https://badge.fury.io/gh/MaxRocamora%2Fpython-backpack)
13
+ [![codecov](https://codecov.io/gh/MaxRocamora/python-backpack/graph/badge.svg?token=6D1xwYdXW2)](https://codecov.io/gh/MaxRocamora/python-backpack)
14
+
15
+
16
+ # Python-Backpack
17
+
18
+ Python-Backpack is a lightweight utility collection for common scripting tasks:
19
+
20
+ - JSON load/save helpers with validation
21
+ - user settings persistence under the OS user directory
22
+ - metadata export/import to JSON files
23
+ - file and folder operations
24
+ - string normalization and case conversion
25
+ - cache decorator with expiration support
26
+ - custom exceptions, logging helper, singleton pattern, and testing helpers
27
+
28
+ ## Compatibility
29
+
30
+ - Python 3.11+
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ pip install python-backpack
36
+ ```
37
+
38
+ ## Package API Reference
39
+
40
+ ### Cache (`backpack.cache`)
41
+
42
+ - `timed_lru_cache(seconds: int, maxsize: int = 128)`
43
+ - `functools.lru_cache` decorator with expiration time.
44
+ - Wrapped calls support `force_clear=True` and `show_log=True`.
45
+
46
+ ### Custom Errors (`backpack.custom_errors`)
47
+
48
+ - `EnvironmentVariableNotFoundError(var_name: str)`
49
+ - Raised when a required environment variable is missing.
50
+ - `ApplicationNotFoundError(app_name: str)`
51
+ - Raised when a required application is not found.
52
+
53
+ ### File Utils (`backpack.file_utils`)
54
+
55
+ - `replace_strings_in_file(ascii_file: str, strings: list, new_string: str) -> None`
56
+ - Replaces multiple string occurrences in a text file.
57
+ - `remove_line_from_file(ascii_file: str, strings: list, verbose: bool = False) -> None`
58
+ - Removes exact matching lines from a text file.
59
+ - `file_is_writeable(filepath: str) -> bool`
60
+ - Checks whether a file can be opened for read/write.
61
+ - `get_version_from_filename(filename: str) -> str`
62
+ - Extracts a numeric version token from a filename.
63
+
64
+ ### Folder Utils (`backpack.folder_utils`)
65
+
66
+ - `browse_folder(folder: str) -> bool`
67
+ - Opens a folder in Windows Explorer.
68
+ - `create_folders(folders: list, force_empty: bool = False, verbose: bool = False)`
69
+ - Creates multiple folders.
70
+ - `create_folder(path: str, force_empty: bool = False, verbose: bool = True)`
71
+ - Creates a folder and optionally clears it if it already exists.
72
+ - `remove_files_in_dir(path: str)`
73
+ - Removes all files and subdirectories inside a directory.
74
+ - `recursive_dir_copy(source_path: str, target_path: str)`
75
+ - Recursively copies files and subfolders from source to target.
76
+
77
+ ### JSON Utils (`backpack.json_utils`)
78
+
79
+ - `json_load(json_file: str) -> dict`
80
+ - Loads JSON data from file with validation and error handling.
81
+ - `json_save(data: dict, json_file: str) -> bool`
82
+ - Saves a dictionary to JSON file.
83
+
84
+ ### JSON Metadata (`backpack.json_metadata`)
85
+
86
+ - `JsonMetaFile(name: str, path: str)`
87
+ - Manages a metadata JSON file with package/system/time information.
88
+ - Main public methods:
89
+ - `has_file() -> bool`
90
+ - `load() -> None`
91
+ - `insert(key: str, value: Any) -> None`
92
+ - `remove(key: str) -> None`
93
+ - `save() -> None`
94
+ - `load_as_class() -> type`
95
+ - `insert_class(_class: type) -> None`
96
+
97
+ ### JSON User Settings (`backpack.json_user_settings`)
98
+
99
+ - `JsonUserSettings(folder: str, name: str)`
100
+ - Saves and loads JSON settings in the current user's home directory.
101
+ - Main public methods:
102
+ - `save_settings(data: dict | None = None) -> bool | None`
103
+ - `load_settings() -> dict | bool`
104
+
105
+ ### Logger (`backpack.logger`)
106
+
107
+ - `get_logger(name: str) -> logging.Logger`
108
+ - Returns a configured logger with stream handler.
109
+
110
+ ### Patterns (`backpack.patterns`)
111
+
112
+ - `Singleton`
113
+ - Base class implementing singleton behavior via `__new__`.
114
+
115
+ ### Strings (`backpack.strings`)
116
+
117
+ - `normalize_input_string(input_string: str, under_spaces: bool = True, under_hyphen: bool = True, replacer: str = '_') -> str`
118
+ - Keeps alphanumeric/space/hyphen characters and normalizes separators.
119
+ - `begin_or_end_with_numbers(input_string: str) -> bool`
120
+ - Checks whether first or last character is numeric.
121
+ - `begin_with_number(input_string: str) -> bool`
122
+ - Checks whether the first character is numeric.
123
+ - `has_numbers(input_string: str) -> bool`
124
+ - Checks whether any character is numeric.
125
+ - `camelcase_to_snakecase(input_string: str) -> str`
126
+ - Converts CamelCase to snake_case.
127
+ - Handles acronym prefixes, for example `HTTPServer -> http_server`.
128
+
129
+ ### Test Utils (`backpack.test_utils`)
130
+
131
+ - `random_string(length: int = 10) -> str`
132
+ - Generates a random lowercase string.
133
+ - `time_function_decorator(method: type)`
134
+ - Decorator that logs execution time.
135
+
136
+ ## Quick Example
137
+
138
+ ```python
139
+ from backpack.cache import timed_lru_cache
140
+ from backpack.strings import camelcase_to_snakecase, normalize_input_string
141
+ from backpack.json_utils import json_save, json_load
142
+
143
+
144
+ @timed_lru_cache(seconds=60)
145
+ def expensive_call():
146
+ return {'ok': True}
147
+
148
+
149
+ value = camelcase_to_snakecase('HTTPServer')
150
+ clean = normalize_input_string('Blade Runner-2049')
151
+
152
+ json_save({'value': value, 'clean': clean}, 'data.json')
153
+ data = json_load('data.json')
154
+ ```
155
+
@@ -1,17 +1,17 @@
1
1
  backpack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  backpack/cache.py,sha256=NlKyeGSXHaA9-RFLSN9Dblt0s7kL9fKzqQhGPHpgGbM,2508
3
3
  backpack/custom_errors.py,sha256=tkn0AnV-Ihnge9X197nPeRpCFD6Feu9lLntejNTNpik,1358
4
- backpack/file_utils.py,sha256=neJN9PL866H8gNFJMbWe06PqENY9UKO61YQa39ujjgY,2743
4
+ backpack/file_utils.py,sha256=VgwVyZFGHJFpaqp0jkqUCAAFfFKFywoK9LTUngsD3bQ,4478
5
5
  backpack/folder_utils.py,sha256=RxfVHBLDTL2EdU2w_EMOWsdtCQh-f5BHMzGIRo3UEI8,2983
6
6
  backpack/json_metadata.py,sha256=KHsXTCDcrKa68p_HgtQfy_AjXmDCxiA99NIuZfKn2I8,4561
7
7
  backpack/json_user_settings.py,sha256=RwdxIZYD4jkcIrWxMn7ZrlKejaGIYOt2TXTGob7nCUg,2676
8
- backpack/json_utils.py,sha256=ZMl_aGb6oU9sQByOqT5OFTdgAKL2iB-DxsVkVuSCOjA,1324
8
+ backpack/json_utils.py,sha256=wQhGzZVltiob_-W4FN40mmq6sO6lw6KSiL1mOQiokH0,1339
9
9
  backpack/logger.py,sha256=yoo4_4Ok9MAdd3GSTeeSGaIKJ4c-KwdhI6q7lg_39oo,518
10
10
  backpack/patterns.py,sha256=qBwgbpfzMrap4KHtLLsg1CJmsmstGGXfzYLpkuUdbMI,889
11
11
  backpack/strings.py,sha256=boYfBi1wPtfkngpb2uIAxiJC2yo32EaL5wUD_3JjWGo,3811
12
12
  backpack/test_utils.py,sha256=0VqVZB6snc_XM6MsmIanlFGWo5T2zswFq9Cn-HpZntE,1165
13
- backpack/version.py,sha256=WBEIf90Avless1yHQdpQSg-8LGK2ekKoGI1aSbhFXvs,1073
14
- python_backpack-2.0.0.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
15
- python_backpack-2.0.0.dist-info/METADATA,sha256=Tx9wVjs9b5jS_296ngOXGCHkiRdGIxjgUNTGx4B2TbU,518
16
- python_backpack-2.0.0.dist-info/WHEEL,sha256=Vz2fHgx6HFtSwhs8KvkHLqH5Ea4w1_rner5uNVGCeIE,88
17
- python_backpack-2.0.0.dist-info/RECORD,,
13
+ backpack/version.py,sha256=Fq5KuzRZRp4ddDxWlq_4cagPvUSdThBTweQYxzXrPRs,1142
14
+ python_backpack-2.0.2.dist-info/METADATA,sha256=gPzzEs-rVOgn8mlF0Rr7bHKxq4flNSjZkseZ59o4V8g,5736
15
+ python_backpack-2.0.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
16
+ python_backpack-2.0.2.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
17
+ python_backpack-2.0.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.3.2
2
+ Generator: hatchling 1.29.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,12 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: python-backpack
3
- Version: 2.0.0
4
- Summary: A collection of personal scripts for json, File/Folder Operations, String Validation, Custom Errors, Cache and stuff.
5
- License-File: LICENSE
6
- Author: Maximiliano Rocamora
7
- Requires-Python: >=3.11,<4.0
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.11
10
- Classifier: Programming Language :: Python :: 3.12
11
- Classifier: Programming Language :: Python :: 3.13
12
- Classifier: Programming Language :: Python :: 3.14