hunterMakesPy 0.1.0__py3-none-any.whl → 0.1.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.
- hunterMakesPy/__init__.py +11 -3
- hunterMakesPy/_theSSOT.py +3 -39
- hunterMakesPy/coping.py +82 -6
- hunterMakesPy/dataStructures.py +12 -12
- hunterMakesPy/filesystemToolkit.py +1 -2
- huntermakespy-0.1.2.dist-info/METADATA +180 -0
- huntermakespy-0.1.2.dist-info/RECORD +20 -0
- tests/test_coping.py +161 -1
- tests/test_filesystemToolkit.py +1 -1
- huntermakespy-0.1.0.dist-info/METADATA +0 -38
- huntermakespy-0.1.0.dist-info/RECORD +0 -20
- {huntermakespy-0.1.0.dist-info → huntermakespy-0.1.2.dist-info}/WHEEL +0 -0
- {huntermakespy-0.1.0.dist-info → huntermakespy-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {huntermakespy-0.1.0.dist-info → huntermakespy-0.1.2.dist-info}/top_level.txt +0 -0
hunterMakesPy/__init__.py
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""A modular toolkit for defensive programming, parameter validation, file system utilities, and data structure manipulation.
|
|
2
|
+
|
|
3
|
+
This package provides:
|
|
4
|
+
- Defensive programming helpers for handling `None` values and error propagation.
|
|
5
|
+
- Parameter and input validation, integer parsing, and concurrency limit utilities.
|
|
6
|
+
- File system and import utilities for safe directory creation and dynamic module/attribute loading.
|
|
7
|
+
- Utilities for string extraction from nested data structures and merging dictionaries of lists.
|
|
8
|
+
|
|
9
|
+
"""
|
|
2
10
|
from hunterMakesPy.theTypes import identifierDotAttribute as identifierDotAttribute
|
|
3
11
|
|
|
4
|
-
from hunterMakesPy.coping import raiseIfNone as raiseIfNone
|
|
12
|
+
from hunterMakesPy.coping import PackageSettings as PackageSettings, raiseIfNone as raiseIfNone
|
|
5
13
|
|
|
6
14
|
from hunterMakesPy.parseParameters import (defineConcurrencyLimit as defineConcurrencyLimit, intInnit as intInnit,
|
|
7
15
|
oopsieKwargsie as oopsieKwargsie)
|
|
8
16
|
|
|
9
17
|
from hunterMakesPy.filesystemToolkit import (importLogicalPath2Identifier as importLogicalPath2Identifier,
|
|
10
18
|
importPathFilename2Identifier as importPathFilename2Identifier, makeDirsSafely as makeDirsSafely,
|
|
11
|
-
|
|
19
|
+
writeStringToHere as writeStringToHere)
|
|
12
20
|
|
|
13
21
|
from hunterMakesPy.dataStructures import (autoDecodingRLE as autoDecodingRLE, stringItUp as stringItUp,
|
|
14
22
|
updateExtendPolishDictionaryLists as updateExtendPolishDictionaryLists)
|
hunterMakesPy/_theSSOT.py
CHANGED
|
@@ -1,40 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Settings for this package."""
|
|
2
|
+
from hunterMakesPy import PackageSettings
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
Tertiary: hardcoded values until I implement a dynamic solution.
|
|
5
|
-
"""
|
|
6
|
-
from importlib.util import find_spec
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from tomli import loads as tomli_loads
|
|
9
|
-
from typing import TYPE_CHECKING
|
|
10
|
-
import dataclasses
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from importlib.machinery import ModuleSpec
|
|
14
|
-
|
|
15
|
-
try:
|
|
16
|
-
identifierPackagePACKAGING: str = tomli_loads(Path("pyproject.toml").read_text())["project"]["name"]
|
|
17
|
-
except Exception: # noqa: BLE001
|
|
18
|
-
identifierPackagePACKAGING = "hunterMakesPy"
|
|
19
|
-
|
|
20
|
-
def getPathPackageINSTALLING() -> Path:
|
|
21
|
-
"""Return the root directory of the installed package."""
|
|
22
|
-
try:
|
|
23
|
-
moduleSpecification: ModuleSpec | None = find_spec(identifierPackagePACKAGING)
|
|
24
|
-
if moduleSpecification and moduleSpecification.origin:
|
|
25
|
-
pathFilename = Path(moduleSpecification.origin)
|
|
26
|
-
return pathFilename.parent if pathFilename.is_file() else pathFilename
|
|
27
|
-
except ModuleNotFoundError:
|
|
28
|
-
pass
|
|
29
|
-
return Path.cwd()
|
|
30
|
-
|
|
31
|
-
@dataclasses.dataclass
|
|
32
|
-
class PackageSettings:
|
|
33
|
-
fileExtension: str = dataclasses.field(default='.py', metadata={'evaluateWhen': 'installing'})
|
|
34
|
-
"""Default file extension for generated code files."""
|
|
35
|
-
identifierPackage: str = dataclasses.field(default = identifierPackagePACKAGING, metadata={'evaluateWhen': 'packaging'})
|
|
36
|
-
"""Name of this package, used for import paths and configuration."""
|
|
37
|
-
pathPackage: Path = dataclasses.field(default_factory=getPathPackageINSTALLING, metadata={'evaluateWhen': 'installing'})
|
|
38
|
-
"""Absolute path to the installed package directory."""
|
|
39
|
-
|
|
40
|
-
settingsPackage = PackageSettings()
|
|
4
|
+
settingsPackage = PackageSettings(identifierPackageFALLBACK="hunterMakesPy")
|
hunterMakesPy/coping.py
CHANGED
|
@@ -1,13 +1,89 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Package configuration and defensive programming utilities for Python projects."""
|
|
2
|
+
from importlib.util import find_spec
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from tomllib import loads as tomllib_loads
|
|
5
|
+
from typing import TYPE_CHECKING, TypeVar
|
|
6
|
+
import dataclasses
|
|
2
7
|
|
|
3
|
-
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from importlib.machinery import ModuleSpec
|
|
4
10
|
|
|
5
|
-
|
|
11
|
+
TypeSansNone = TypeVar('TypeSansNone')
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
from
|
|
13
|
+
def getIdentifierPackagePACKAGING(identifierPackageFALLBACK: str) -> str:
|
|
14
|
+
"""Get package name from pyproject.toml or fallback to provided value."""
|
|
15
|
+
try:
|
|
16
|
+
return tomllib_loads(Path('pyproject.toml').read_text(encoding='utf-8'))['project']['name']
|
|
17
|
+
except Exception: # noqa: BLE001
|
|
18
|
+
return identifierPackageFALLBACK
|
|
19
|
+
|
|
20
|
+
def getPathPackageINSTALLING(identifierPackage: str) -> Path:
|
|
21
|
+
"""Return the root directory of the installed package."""
|
|
22
|
+
try:
|
|
23
|
+
moduleSpecification: ModuleSpec | None = find_spec(identifierPackage)
|
|
24
|
+
if moduleSpecification and moduleSpecification.origin:
|
|
25
|
+
pathFilename = Path(moduleSpecification.origin)
|
|
26
|
+
return pathFilename.parent if pathFilename.is_file() else pathFilename
|
|
27
|
+
except ModuleNotFoundError:
|
|
28
|
+
pass
|
|
29
|
+
return Path.cwd()
|
|
30
|
+
|
|
31
|
+
@dataclasses.dataclass
|
|
32
|
+
class PackageSettings:
|
|
33
|
+
"""Configuration container for Python package metadata and runtime settings.
|
|
34
|
+
|
|
35
|
+
This `class` provides a simple way to store and access basic information about a Python package, It will automatically resolve
|
|
36
|
+
package identifiers and installation paths if they are not passed to the `class` constructor. Python `dataclasses` are easy to
|
|
37
|
+
subtype and extend.
|
|
9
38
|
|
|
10
|
-
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
identifierPackageFALLBACK : str = ''
|
|
42
|
+
Fallback package identifier used only during initialization when automatic discovery fails.
|
|
43
|
+
pathPackage : Path = Path()
|
|
44
|
+
Absolute path to the installed package directory. Automatically resolved from `identifierPackage` if not provided.
|
|
45
|
+
identifierPackage : str = ''
|
|
46
|
+
Canonical name of the package. Automatically extracted from `pyproject.toml`.
|
|
47
|
+
fileExtension : str = '.py'
|
|
48
|
+
Default file extension.
|
|
49
|
+
|
|
50
|
+
Examples
|
|
51
|
+
--------
|
|
52
|
+
Automatic package discovery from development environment:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
settings = PackageSettings(identifierPackageFALLBACK='cobraPy')
|
|
56
|
+
# Automatically discovers package name from pyproject.toml
|
|
57
|
+
# Resolves installation path from package identifier
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Explicit configuration for specific deployment:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
settings = PackageSettings(
|
|
64
|
+
identifierPackage='cobraPy',
|
|
65
|
+
pathPackage=Path('/opt/tenEx/packages/cobraPy'),
|
|
66
|
+
fileExtension='.pyx'
|
|
67
|
+
)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
identifierPackageFALLBACK: dataclasses.InitVar[str] = ''
|
|
73
|
+
"""Fallback package identifier used during initialization only."""
|
|
74
|
+
pathPackage: Path = dataclasses.field(default_factory=Path, metadata={'evaluateWhen': 'installing'})
|
|
75
|
+
"""Absolute path to the installed package."""
|
|
76
|
+
identifierPackage: str = dataclasses.field(default='', metadata={'evaluateWhen': 'packaging'})
|
|
77
|
+
"""Name of this package."""
|
|
78
|
+
fileExtension: str = dataclasses.field(default='.py', metadata={'evaluateWhen': 'installing'})
|
|
79
|
+
"""Default file extension for files."""
|
|
80
|
+
|
|
81
|
+
def __post_init__(self, identifierPackageFALLBACK: str) -> None:
|
|
82
|
+
"""Initialize computed fields after dataclass initialization."""
|
|
83
|
+
if not self.identifierPackage and identifierPackageFALLBACK:
|
|
84
|
+
self.identifierPackage = getIdentifierPackagePACKAGING(identifierPackageFALLBACK)
|
|
85
|
+
if self.pathPackage == Path() and self.identifierPackage:
|
|
86
|
+
self.pathPackage = getPathPackageINSTALLING(self.identifierPackage)
|
|
11
87
|
|
|
12
88
|
def raiseIfNone(returnTarget: TypeSansNone | None, errorMessage: str | None = None) -> TypeSansNone:
|
|
13
89
|
"""Raise a `ValueError` if the target value is `None`, otherwise return the value: tell the type checker that the return value is not `None`.
|
hunterMakesPy/dataStructures.py
CHANGED
|
@@ -46,7 +46,7 @@ def autoDecodingRLE(arrayTarget: NDArray[integer[Any]], *, assumeAddSpaces: bool
|
|
|
46
46
|
"""
|
|
47
47
|
def sliceNDArrayToNestedLists(arraySlice: NDArray[integer[Any]]) -> Any:
|
|
48
48
|
def getLengthOption(optionAsStr: str) -> int:
|
|
49
|
-
|
|
49
|
+
"""`assumeAddSpaces` characters: `,` 1; `]*` 2."""
|
|
50
50
|
return assumeAddSpaces * (optionAsStr.count(',') + optionAsStr.count(']*') * 2) + len(optionAsStr)
|
|
51
51
|
|
|
52
52
|
if arraySlice.ndim > 1:
|
|
@@ -125,29 +125,29 @@ def autoDecodingRLE(arrayTarget: NDArray[integer[Any]], *, assumeAddSpaces: bool
|
|
|
125
125
|
patternRegex = regex.compile(
|
|
126
126
|
"(?<!rang)(?:"
|
|
127
127
|
# Pattern 1: Comma ahead, bracket behind # noqa: ERA001
|
|
128
|
-
"(?P<joinAhead>,)\\((?P<malkovich>\\d+),(?P<
|
|
128
|
+
"(?P<joinAhead>,)\\((?P<malkovich>\\d+),(?P<multiply>\\d+)\\)(?P<bracketBehind>])|"
|
|
129
129
|
# Pattern 2: Bracket or start ahead, comma behind # noqa: ERA001
|
|
130
|
-
"(?P<bracketOrStartAhead>\\[|^.)\\((?P<
|
|
130
|
+
"(?P<bracketOrStartAhead>\\[|^.)\\((?P<malkovichMalkovich>\\d+),(?P<multiplyIDK>\\d+)\\)(?P<joinBehind>,)|"
|
|
131
131
|
# Pattern 3: Bracket ahead, bracket behind # noqa: ERA001
|
|
132
|
-
"(?P<bracketAhead>\\[)\\((?P<
|
|
132
|
+
"(?P<bracketAhead>\\[)\\((?P<malkovichMalkovichMalkovich>\\d+),(?P<multiply_whatever>\\d+)\\)(?P<bracketBehindBracketBehind>])|"
|
|
133
133
|
# Pattern 4: Comma ahead, comma behind # noqa: ERA001
|
|
134
|
-
"(?P<
|
|
134
|
+
"(?P<joinAheadJoinAhead>,)\\((?P<malkovichMalkovichMalkovichMalkovich>\\d+),(?P<multiplyOrSomething>\\d+)\\)(?P<joinBehindJoinBehind>,)"
|
|
135
135
|
")"
|
|
136
136
|
)
|
|
137
137
|
|
|
138
138
|
def replacementByContext(match: regex.Match[str]) -> str:
|
|
139
139
|
"""Generate replacement string based on context patterns."""
|
|
140
|
-
|
|
141
|
-
joinAhead =
|
|
142
|
-
malkovich =
|
|
143
|
-
|
|
144
|
-
joinBehind =
|
|
140
|
+
elephino = match.groupdict()
|
|
141
|
+
joinAhead = elephino.get('joinAhead') or elephino.get('joinAheadJoinAhead')
|
|
142
|
+
malkovich = elephino.get('malkovich') or elephino.get('malkovichMalkovich') or elephino.get('malkovichMalkovichMalkovich') or elephino.get('malkovichMalkovichMalkovichMalkovich')
|
|
143
|
+
multiply = elephino.get('multiply') or elephino.get('multiplyIDK') or elephino.get('multiply_whatever') or elephino.get('multiplyOrSomething')
|
|
144
|
+
joinBehind = elephino.get('joinBehind') or elephino.get('joinBehindJoinBehind')
|
|
145
145
|
|
|
146
146
|
replaceAhead = "]+[" if joinAhead == "," else "["
|
|
147
147
|
|
|
148
148
|
replaceBehind = "+[" if joinBehind == "," else ""
|
|
149
149
|
|
|
150
|
-
return f"{replaceAhead}{malkovich}]*{
|
|
150
|
+
return f"{replaceAhead}{malkovich}]*{multiply}{replaceBehind}"
|
|
151
151
|
|
|
152
152
|
arrayAsStr = patternRegex.sub(replacementByContext, arrayAsStr)
|
|
153
153
|
arrayAsStr = patternRegex.sub(replacementByContext, arrayAsStr)
|
|
@@ -249,7 +249,7 @@ def updateExtendPolishDictionaryLists(*dictionaryLists: Mapping[str, list[Any] |
|
|
|
249
249
|
ImaStr = str(keyName)
|
|
250
250
|
ImaList = list(keyValue)
|
|
251
251
|
ePluribusUnum.setdefault(ImaStr, []).extend(ImaList)
|
|
252
|
-
except TypeError:
|
|
252
|
+
except TypeError:
|
|
253
253
|
if killErroneousDataTypes:
|
|
254
254
|
continue
|
|
255
255
|
else:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""File system and module import utilities.
|
|
2
2
|
|
|
3
|
-
This module provides basic file I/O utilities such as
|
|
4
|
-
callables from modules, and safely creating directories.
|
|
3
|
+
This module provides basic file I/O utilities such as importing callables from modules, and safely creating directories.
|
|
5
4
|
|
|
6
5
|
"""
|
|
7
6
|
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hunterMakesPy
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Easy Python functions making making functional Python functions easier.
|
|
5
|
+
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
|
+
License: CC-BY-NC-4.0
|
|
7
|
+
Project-URL: Donate, https://www.patreon.com/integrated
|
|
8
|
+
Project-URL: Homepage, https://github.com/hunterhogan/
|
|
9
|
+
Project-URL: Issues, https://github.com/hunterhogan/
|
|
10
|
+
Project-URL: Repository, https://github.com/hunterhogan/
|
|
11
|
+
Keywords: attribute loading,concurrency limit,configuration,defensive programming,dictionary merging,directory creation,dynamic import,error propagation,file system utilities,input validation,integer parsing,module loading,nested data structures,package settings,parameter validation,pytest,string extraction,test utilities
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Framework :: Pytest
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
17
|
+
Classifier: Intended Audience :: Other Audience
|
|
18
|
+
Classifier: Natural Language :: English
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
26
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
+
Classifier: Topic :: Utilities
|
|
28
|
+
Classifier: Typing :: Typed
|
|
29
|
+
Requires-Python: >=3.11
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Requires-Dist: charset_normalizer
|
|
33
|
+
Requires-Dist: more_itertools
|
|
34
|
+
Requires-Dist: numpy
|
|
35
|
+
Requires-Dist: python_minifier
|
|
36
|
+
Provides-Extra: development
|
|
37
|
+
Requires-Dist: mypy; extra == "development"
|
|
38
|
+
Requires-Dist: pyupgrade; extra == "development"
|
|
39
|
+
Requires-Dist: setuptools-scm; extra == "development"
|
|
40
|
+
Provides-Extra: testing
|
|
41
|
+
Requires-Dist: pytest; extra == "testing"
|
|
42
|
+
Requires-Dist: pytest-cov; extra == "testing"
|
|
43
|
+
Requires-Dist: pytest-xdist; extra == "testing"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# hunterMakesPy
|
|
47
|
+
|
|
48
|
+
A modular Python toolkit for defensive programming, parameter validation, file system utilities, and flexible data structure manipulation.
|
|
49
|
+
|
|
50
|
+
[](https://pypi.org/project/hunterMakesPy/)
|
|
51
|
+
|
|
52
|
+
## Overview
|
|
53
|
+
|
|
54
|
+
hunterMakesPy provides utilities for safe error handling, flexible input validation, dynamic module and attribute importing, and merging or transforming complex data structures. The package emphasizes clear identifiers, robust type handling, and reusable components for building reliable Python applications.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install hunterMakesPy
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Defensive Programming
|
|
63
|
+
|
|
64
|
+
Utilities for handling `None` values and defensive programming patterns.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from hunterMakesPy import raiseIfNone
|
|
68
|
+
|
|
69
|
+
# Ensure a function result is not None
|
|
70
|
+
def findConfiguration(configName: str) -> dict[str, str] | None:
|
|
71
|
+
# ... search logic ...
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
config = raiseIfNone(
|
|
75
|
+
findConfiguration("database"),
|
|
76
|
+
"Configuration 'database' is required but not found"
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Parameter Validation
|
|
81
|
+
|
|
82
|
+
Parameter validation, integer parsing, and concurrency handling.
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from hunterMakesPy import defineConcurrencyLimit, intInnit, oopsieKwargsie
|
|
86
|
+
|
|
87
|
+
# Smart concurrency limit calculation
|
|
88
|
+
cpuLimit = defineConcurrencyLimit(limit=0.75) # Use 75% of available CPUs
|
|
89
|
+
cpuLimit = defineConcurrencyLimit(limit=True) # Use exactly 1 CPU
|
|
90
|
+
cpuLimit = defineConcurrencyLimit(limit=4) # Use exactly 4 CPUs
|
|
91
|
+
|
|
92
|
+
# Robust integer validation
|
|
93
|
+
validatedIntegers = intInnit([1, "2", 3.0, "4"], "port_numbers")
|
|
94
|
+
|
|
95
|
+
# String-to-boolean conversion for configuration
|
|
96
|
+
userInput = "True"
|
|
97
|
+
booleanValue = oopsieKwargsie(userInput) # Returns True
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## File System Utilities
|
|
101
|
+
|
|
102
|
+
Safe file operations and dynamic module importing.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from hunterMakesPy import (
|
|
106
|
+
importLogicalPath2Identifier,
|
|
107
|
+
importPathFilename2Identifier,
|
|
108
|
+
makeDirsSafely,
|
|
109
|
+
writeStringToHere
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Dynamic imports
|
|
113
|
+
gcdFunction = importLogicalPath2Identifier("math", "gcd")
|
|
114
|
+
customFunction = importPathFilename2Identifier("path/to/module.py", "functionName")
|
|
115
|
+
|
|
116
|
+
# Safe file operations
|
|
117
|
+
pathFilename = Path("deep/nested/directory/file.txt")
|
|
118
|
+
writeStringToHere("content", pathFilename) # Creates directories automatically
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Data Structure Manipulation
|
|
122
|
+
|
|
123
|
+
Utilities for string extraction, data flattening, and array compression.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from hunterMakesPy import stringItUp, updateExtendPolishDictionaryLists, autoDecodingRLE
|
|
127
|
+
import numpy
|
|
128
|
+
|
|
129
|
+
# Extract all strings from nested data structures
|
|
130
|
+
nestedData = {"config": [1, "host", {"port": 8080}], "users": ["alice", "bob"]}
|
|
131
|
+
allStrings = stringItUp(nestedData) # ['config', 'host', 'port', 'users', 'alice', 'bob']
|
|
132
|
+
|
|
133
|
+
# Merge dictionaries containing lists
|
|
134
|
+
dictionaryAlpha = {"servers": ["web1", "web2"], "databases": ["db1"]}
|
|
135
|
+
dictionaryBeta = {"servers": ["web3"], "databases": ["db2", "db3"]}
|
|
136
|
+
merged = updateExtendPolishDictionaryLists(dictionaryAlpha, dictionaryBeta, destroyDuplicates=True)
|
|
137
|
+
|
|
138
|
+
# Compress NumPy arrays with run-length encoding
|
|
139
|
+
arrayData = numpy.array([1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 9])
|
|
140
|
+
compressed = autoDecodingRLE(arrayData) # "[1,*range(2,6)]+[5]*2+[*range(6,10)]"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Testing
|
|
144
|
+
|
|
145
|
+
The package includes comprehensive test suites that you can import and run:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from hunterMakesPy.pytestForYourUse import (
|
|
149
|
+
PytestFor_defineConcurrencyLimit,
|
|
150
|
+
PytestFor_intInnit,
|
|
151
|
+
PytestFor_oopsieKwargsie
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Run tests on the built-in functions
|
|
155
|
+
listOfTests = PytestFor_defineConcurrencyLimit()
|
|
156
|
+
for nameOfTest, callablePytest in listOfTests:
|
|
157
|
+
callablePytest()
|
|
158
|
+
|
|
159
|
+
# Or test your own compatible functions
|
|
160
|
+
@pytest.mark.parametrize("nameOfTest,callablePytest",
|
|
161
|
+
PytestFor_intInnit(callableToTest=myFunction))
|
|
162
|
+
def test_myFunction(nameOfTest, callablePytest):
|
|
163
|
+
callablePytest()
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## My recovery
|
|
167
|
+
|
|
168
|
+
[](https://HunterThinks.com/support)
|
|
169
|
+
[](https://www.youtube.com/@HunterHogan)
|
|
170
|
+
|
|
171
|
+
## How to code
|
|
172
|
+
|
|
173
|
+
Coding One Step at a Time:
|
|
174
|
+
|
|
175
|
+
0. WRITE CODE.
|
|
176
|
+
1. Don't write stupid code that's hard to revise.
|
|
177
|
+
2. Write good code.
|
|
178
|
+
3. When revising, write better code.
|
|
179
|
+
|
|
180
|
+
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
hunterMakesPy/__init__.py,sha256=4gIm--UJmlQEhbLCqpiVFM_JVbyfVpvFFAJyMNFHekk,1329
|
|
2
|
+
hunterMakesPy/_theSSOT.py,sha256=lkLOG3oTIWNKD_ULX55chlUGNqCHgqVIrBvolvK1vbQ,153
|
|
3
|
+
hunterMakesPy/coping.py,sha256=covqNFAwkF9gjafrlAvMdtCO8haFsESQBhO-7s68qSg,5581
|
|
4
|
+
hunterMakesPy/dataStructures.py,sha256=znMEnboo2iNXZtQKdmruRrJDEoeTfqoH4-coUDM75g4,11218
|
|
5
|
+
hunterMakesPy/filesystemToolkit.py,sha256=vDYS0Rc1aP7ETLXHKoO3TfOpuwJQFQW2ybwtJNiIIo4,4305
|
|
6
|
+
hunterMakesPy/parseParameters.py,sha256=plrJ4xR1FQnQR9j-oeMAwB2H9r_8QD8OALnw0OH8Kt0,11947
|
|
7
|
+
hunterMakesPy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
hunterMakesPy/pytestForYourUse.py,sha256=21BI8TXyinf8rMmS6dTsuRMBOOFTcyoG_gD__Gz_e7Q,13288
|
|
9
|
+
hunterMakesPy/theTypes.py,sha256=C2d0uLn1VIx6_2CK41it3IP7iplSQqe51tzWc-RT320,306
|
|
10
|
+
huntermakespy-0.1.2.dist-info/licenses/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
|
|
11
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
tests/conftest.py,sha256=MkNc4Ar6yYrnAok4t1NWsgyOYFDiGo1qwXHyp8ChJf4,1672
|
|
13
|
+
tests/test_coping.py,sha256=MQl0fhdWX2YSFzzjWMThSm_ZSnglE3anSJO2b33typU,9846
|
|
14
|
+
tests/test_dataStructures.py,sha256=VhM3VzG1l8l3Iz1q9sQjpNBQTWSrl4zWbnefsGTccos,16406
|
|
15
|
+
tests/test_filesystemToolkit.py,sha256=jk6Ke0fW6dlHIVyvA1lh7o7_I7DVZr6uMO3s_i43isQ,2445
|
|
16
|
+
tests/test_parseParameters.py,sha256=bHD-O-OyWWwPOx3zvS53pSNPDm3LbFS05N5JcfNCLG4,1137
|
|
17
|
+
huntermakespy-0.1.2.dist-info/METADATA,sha256=b1Xr8jhpu8t-H3BTVQUcCww_gG8q5fcb1REz-8AQbY8,6555
|
|
18
|
+
huntermakespy-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
huntermakespy-0.1.2.dist-info/top_level.txt,sha256=dUy7z3LNO6aqNjPD81tZjE5N9HO70a14Y9lAWjWC2gA,20
|
|
20
|
+
huntermakespy-0.1.2.dist-info/RECORD,,
|
tests/test_coping.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from hunterMakesPy import raiseIfNone
|
|
1
|
+
from hunterMakesPy import PackageSettings, raiseIfNone
|
|
2
|
+
from hunterMakesPy.coping import getIdentifierPackagePACKAGING, getPathPackageINSTALLING
|
|
3
|
+
from pathlib import Path
|
|
2
4
|
from tests.conftest import uniformTestFailureMessage
|
|
3
5
|
import pytest
|
|
4
6
|
|
|
@@ -54,3 +56,161 @@ def testRaiseIfNonePreservesTypeAnnotations() -> None:
|
|
|
54
56
|
|
|
55
57
|
listValue: list[int] = raiseIfNone([29, 31])
|
|
56
58
|
assert isinstance(listValue, list), uniformTestFailureMessage(list, type(listValue), "testRaiseIfNonePreservesTypeAnnotations", listValue)
|
|
59
|
+
|
|
60
|
+
# Tests for PackageSettings dataclass
|
|
61
|
+
@pytest.mark.parametrize(
|
|
62
|
+
"identifierPackageFALLBACK, expectedIdentifierPackage",
|
|
63
|
+
[
|
|
64
|
+
("astToolFactory", "hunterMakesPy"), # Should read from pyproject.toml
|
|
65
|
+
("nonExistentPackage", "hunterMakesPy"), # Should read from pyproject.toml
|
|
66
|
+
("customPackage", "hunterMakesPy"), # Should read from pyproject.toml
|
|
67
|
+
]
|
|
68
|
+
)
|
|
69
|
+
def testPackageSettingsWithFallbackUsesProjectToml(identifierPackageFALLBACK: str, expectedIdentifierPackage: str) -> None:
|
|
70
|
+
"""Test that PackageSettings reads package name from pyproject.toml when using fallback."""
|
|
71
|
+
packageSettings = PackageSettings(identifierPackageFALLBACK)
|
|
72
|
+
assert packageSettings.identifierPackage == expectedIdentifierPackage, uniformTestFailureMessage(
|
|
73
|
+
expectedIdentifierPackage, packageSettings.identifierPackage, "PackageSettings fallback", identifierPackageFALLBACK
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
@pytest.mark.parametrize(
|
|
77
|
+
"explicitIdentifierPackage, expectedIdentifierPackage",
|
|
78
|
+
[
|
|
79
|
+
("customPackageName", "customPackageName"),
|
|
80
|
+
("fibonacci", "fibonacci"),
|
|
81
|
+
("prime", "prime"),
|
|
82
|
+
("astToolFactory", "astToolFactory"),
|
|
83
|
+
]
|
|
84
|
+
)
|
|
85
|
+
def testPackageSettingsWithExplicitIdentifierPackage(explicitIdentifierPackage: str, expectedIdentifierPackage: str) -> None:
|
|
86
|
+
"""Test that PackageSettings respects explicitly provided identifierPackage."""
|
|
87
|
+
packageSettings = PackageSettings(identifierPackage=explicitIdentifierPackage)
|
|
88
|
+
assert packageSettings.identifierPackage == expectedIdentifierPackage, uniformTestFailureMessage(
|
|
89
|
+
expectedIdentifierPackage, packageSettings.identifierPackage, "PackageSettings explicit identifierPackage", explicitIdentifierPackage
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
@pytest.mark.parametrize(
|
|
93
|
+
"explicitPathPackage, expectedPathPackage",
|
|
94
|
+
[
|
|
95
|
+
(Path("C:/fibonacci/path"), Path("C:/fibonacci/path")),
|
|
96
|
+
(Path("C:/prime/directory"), Path("C:/prime/directory")),
|
|
97
|
+
(Path("/usr/local/lib/package"), Path("/usr/local/lib/package")),
|
|
98
|
+
(Path("relative/path"), Path("relative/path")),
|
|
99
|
+
]
|
|
100
|
+
)
|
|
101
|
+
def testPackageSettingsWithExplicitPathPackage(explicitPathPackage: Path, expectedPathPackage: Path) -> None:
|
|
102
|
+
"""Test that PackageSettings respects explicitly provided pathPackage."""
|
|
103
|
+
packageSettings = PackageSettings(pathPackage=explicitPathPackage)
|
|
104
|
+
assert packageSettings.pathPackage == expectedPathPackage, uniformTestFailureMessage(
|
|
105
|
+
expectedPathPackage, packageSettings.pathPackage, "PackageSettings explicit pathPackage", explicitPathPackage
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
@pytest.mark.parametrize(
|
|
109
|
+
"fileExtension, expectedFileExtension",
|
|
110
|
+
[
|
|
111
|
+
(".fibonacci", ".fibonacci"),
|
|
112
|
+
(".prime", ".prime"),
|
|
113
|
+
(".txt", ".txt"),
|
|
114
|
+
(".md", ".md"),
|
|
115
|
+
(".json", ".json"),
|
|
116
|
+
]
|
|
117
|
+
)
|
|
118
|
+
def testPackageSettingsWithCustomFileExtension(fileExtension: str, expectedFileExtension: str) -> None:
|
|
119
|
+
"""Test that PackageSettings respects custom file extensions."""
|
|
120
|
+
packageSettings = PackageSettings(fileExtension=fileExtension)
|
|
121
|
+
assert packageSettings.fileExtension == expectedFileExtension, uniformTestFailureMessage(
|
|
122
|
+
expectedFileExtension, packageSettings.fileExtension, "PackageSettings custom fileExtension", fileExtension
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def testPackageSettingsDefaultValues() -> None:
|
|
126
|
+
"""Test that PackageSettings has correct default values when no arguments provided."""
|
|
127
|
+
packageSettings = PackageSettings()
|
|
128
|
+
|
|
129
|
+
# Should have default file extension
|
|
130
|
+
assert packageSettings.fileExtension == '.py', uniformTestFailureMessage(
|
|
131
|
+
'.py', packageSettings.fileExtension, "PackageSettings default fileExtension"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# identifierPackage should be empty when no fallback provided
|
|
135
|
+
assert packageSettings.identifierPackage == '', uniformTestFailureMessage(
|
|
136
|
+
'', packageSettings.identifierPackage, "PackageSettings default identifierPackage"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# pathPackage should remain as Path() when identifierPackage is empty
|
|
140
|
+
expectedPath = Path()
|
|
141
|
+
assert packageSettings.pathPackage == expectedPath, uniformTestFailureMessage(
|
|
142
|
+
expectedPath, packageSettings.pathPackage, "PackageSettings default pathPackage"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
@pytest.mark.parametrize(
|
|
146
|
+
"identifierPackageFALLBACK, identifierPackage, pathPackage, fileExtension",
|
|
147
|
+
[
|
|
148
|
+
("fallback", "custom", Path("C:/custom/path"), ".txt"),
|
|
149
|
+
("fibonacci", "prime", Path("C:/fibonacci/lib"), ".md"),
|
|
150
|
+
("defaultFallback", "overridePackage", Path("/usr/local/override"), ".json"),
|
|
151
|
+
]
|
|
152
|
+
)
|
|
153
|
+
def testPackageSettingsAllParametersCombined(
|
|
154
|
+
identifierPackageFALLBACK: str,
|
|
155
|
+
identifierPackage: str,
|
|
156
|
+
pathPackage: Path,
|
|
157
|
+
fileExtension: str
|
|
158
|
+
) -> None:
|
|
159
|
+
"""Test PackageSettings with all parameters provided."""
|
|
160
|
+
packageSettings = PackageSettings(
|
|
161
|
+
identifierPackageFALLBACK,
|
|
162
|
+
identifierPackage=identifierPackage,
|
|
163
|
+
pathPackage=pathPackage,
|
|
164
|
+
fileExtension=fileExtension
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
assert packageSettings.identifierPackage == identifierPackage, uniformTestFailureMessage(
|
|
168
|
+
identifierPackage, packageSettings.identifierPackage, "PackageSettings combined identifierPackage"
|
|
169
|
+
)
|
|
170
|
+
assert packageSettings.pathPackage == pathPackage, uniformTestFailureMessage(
|
|
171
|
+
pathPackage, packageSettings.pathPackage, "PackageSettings combined pathPackage"
|
|
172
|
+
)
|
|
173
|
+
assert packageSettings.fileExtension == fileExtension, uniformTestFailureMessage(
|
|
174
|
+
fileExtension, packageSettings.fileExtension, "PackageSettings combined fileExtension"
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
def testPackageSettingsFallbackIgnoredWhenExplicitIdentifierProvided() -> None:
|
|
178
|
+
"""Test that fallback is ignored when explicit identifierPackage is provided."""
|
|
179
|
+
packageSettings = PackageSettings("shouldBeIgnored", identifierPackage="explicit")
|
|
180
|
+
assert packageSettings.identifierPackage == "explicit", uniformTestFailureMessage(
|
|
181
|
+
"explicit", packageSettings.identifierPackage, "PackageSettings fallback ignored"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Tests for helper functions
|
|
185
|
+
@pytest.mark.parametrize(
|
|
186
|
+
"identifierPackageFALLBACK, expectedResult",
|
|
187
|
+
[
|
|
188
|
+
("fibonacci", "hunterMakesPy"), # Should read from pyproject.toml
|
|
189
|
+
("prime", "hunterMakesPy"), # Should read from pyproject.toml
|
|
190
|
+
("nonExistentPackage", "hunterMakesPy"), # Should read from pyproject.toml
|
|
191
|
+
]
|
|
192
|
+
)
|
|
193
|
+
def testGetIdentifierPackagePACKAGING(identifierPackageFALLBACK: str, expectedResult: str) -> None:
|
|
194
|
+
"""Test that getIdentifierPackagePACKAGING reads from pyproject.toml correctly."""
|
|
195
|
+
actual = getIdentifierPackagePACKAGING(identifierPackageFALLBACK)
|
|
196
|
+
assert actual == expectedResult, uniformTestFailureMessage(
|
|
197
|
+
expectedResult, actual, "getIdentifierPackagePACKAGING", identifierPackageFALLBACK
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
@pytest.mark.parametrize(
|
|
201
|
+
"identifierPackage",
|
|
202
|
+
[
|
|
203
|
+
"hunterMakesPy", # This package exists
|
|
204
|
+
"fibonacci", # Non-existent package should fallback to cwd
|
|
205
|
+
"prime", # Non-existent package should fallback to cwd
|
|
206
|
+
]
|
|
207
|
+
)
|
|
208
|
+
def testGetPathPackageINSTALLING(identifierPackage: str) -> None:
|
|
209
|
+
"""Test that getPathPackageINSTALLING returns valid Path objects."""
|
|
210
|
+
actual = getPathPackageINSTALLING(identifierPackage)
|
|
211
|
+
assert isinstance(actual, Path), uniformTestFailureMessage(
|
|
212
|
+
Path, type(actual), "getPathPackageINSTALLING type", identifierPackage
|
|
213
|
+
)
|
|
214
|
+
assert actual.exists() or actual == Path.cwd(), uniformTestFailureMessage(
|
|
215
|
+
"existing path or cwd", actual, "getPathPackageINSTALLING existence", identifierPackage
|
|
216
|
+
)
|
tests/test_filesystemToolkit.py
CHANGED
|
@@ -22,7 +22,7 @@ def testWriteStringToHereCreatesFileAndWritesContent(pathTmpTesting: pathlib.Pat
|
|
|
22
22
|
filePath = nestedDirectory / "test.txt"
|
|
23
23
|
writeStringToHere("hello world", filePath)
|
|
24
24
|
assert filePath.exists(), uniformTestFailureMessage(True, filePath.exists(), "testWriteStringToHereCreatesFileAndWritesContent", filePath)
|
|
25
|
-
assert filePath.read_text() == "hello world", uniformTestFailureMessage("hello world", filePath.read_text(), "testWriteStringToHereCreatesFileAndWritesContent", filePath)
|
|
25
|
+
assert filePath.read_text(encoding="utf-8") == "hello world", uniformTestFailureMessage("hello world", filePath.read_text(encoding="utf-8"), "testWriteStringToHereCreatesFileAndWritesContent", filePath)
|
|
26
26
|
|
|
27
27
|
@pytest.mark.parametrize(
|
|
28
28
|
"moduleName, identifier, expectedType",
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: hunterMakesPy
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
5
|
-
License: CC-BY-NC-4.0
|
|
6
|
-
Project-URL: Donate, https://www.patreon.com/integrated
|
|
7
|
-
Project-URL: Homepage, https://github.com/hunterhogan/
|
|
8
|
-
Project-URL: Issues, https://github.com/hunterhogan/
|
|
9
|
-
Project-URL: Repository, https://github.com/hunterhogan/
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Environment :: Console
|
|
12
|
-
Classifier: Intended Audience :: End Users/Desktop
|
|
13
|
-
Classifier: Intended Audience :: Other Audience
|
|
14
|
-
Classifier: Natural Language :: English
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Classifier: Programming Language :: Python
|
|
17
|
-
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
-
Classifier: Typing :: Typed
|
|
23
|
-
Requires-Python: >=3.10
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
License-File: LICENSE
|
|
26
|
-
Requires-Dist: charset_normalizer
|
|
27
|
-
Requires-Dist: more_itertools
|
|
28
|
-
Requires-Dist: numpy
|
|
29
|
-
Requires-Dist: python_minifier
|
|
30
|
-
Requires-Dist: tomli
|
|
31
|
-
Provides-Extra: testing
|
|
32
|
-
Requires-Dist: mypy; extra == "testing"
|
|
33
|
-
Requires-Dist: pytest; extra == "testing"
|
|
34
|
-
Requires-Dist: pytest-cov; extra == "testing"
|
|
35
|
-
Requires-Dist: pytest-xdist; extra == "testing"
|
|
36
|
-
Requires-Dist: pyupgrade; extra == "testing"
|
|
37
|
-
Requires-Dist: setuptools-scm; extra == "testing"
|
|
38
|
-
Dynamic: license-file
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
hunterMakesPy/__init__.py,sha256=0zTe--KMtLeoBfsKGS5hH_vUEOuOXRQt1nA-K25bMBw,816
|
|
2
|
-
hunterMakesPy/_theSSOT.py,sha256=HiZ_OqaiiHBDdbyKLJPk7aARQujShdX3dpYEpUbpWbM,1631
|
|
3
|
-
hunterMakesPy/coping.py,sha256=AXa3KgAAO0L3KFNUoor8Tjuw7lDGQ2ZIsKUCDV4wR2Y,2529
|
|
4
|
-
hunterMakesPy/dataStructures.py,sha256=2mJDAOxgSstV0gDNcpwA0mHruDbAfeRGIADWTCPXuHY,11397
|
|
5
|
-
hunterMakesPy/filesystemToolkit.py,sha256=OdbMKPuOvverjptsToENU2HNGZ2XzAE7Bm6i0-yJfiU,4372
|
|
6
|
-
hunterMakesPy/parseParameters.py,sha256=plrJ4xR1FQnQR9j-oeMAwB2H9r_8QD8OALnw0OH8Kt0,11947
|
|
7
|
-
hunterMakesPy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
hunterMakesPy/pytestForYourUse.py,sha256=21BI8TXyinf8rMmS6dTsuRMBOOFTcyoG_gD__Gz_e7Q,13288
|
|
9
|
-
hunterMakesPy/theTypes.py,sha256=C2d0uLn1VIx6_2CK41it3IP7iplSQqe51tzWc-RT320,306
|
|
10
|
-
huntermakespy-0.1.0.dist-info/licenses/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
|
|
11
|
-
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
tests/conftest.py,sha256=MkNc4Ar6yYrnAok4t1NWsgyOYFDiGo1qwXHyp8ChJf4,1672
|
|
13
|
-
tests/test_coping.py,sha256=c_rBHU0uoK2CKZhJSWtp7PPnHgdjNtdQEbWpc4P0VkE,2282
|
|
14
|
-
tests/test_dataStructures.py,sha256=VhM3VzG1l8l3Iz1q9sQjpNBQTWSrl4zWbnefsGTccos,16406
|
|
15
|
-
tests/test_filesystemToolkit.py,sha256=aMPyJ-EUCk4XvA08BSC5nDqKPY-YFBM_ePMGRZlSZOo,2413
|
|
16
|
-
tests/test_parseParameters.py,sha256=bHD-O-OyWWwPOx3zvS53pSNPDm3LbFS05N5JcfNCLG4,1137
|
|
17
|
-
huntermakespy-0.1.0.dist-info/METADATA,sha256=YPPLNpMrsIdnhqTuSNdIzEHB3-ckuMsmQEHy5hPSGyc,1474
|
|
18
|
-
huntermakespy-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
-
huntermakespy-0.1.0.dist-info/top_level.txt,sha256=dUy7z3LNO6aqNjPD81tZjE5N9HO70a14Y9lAWjWC2gA,20
|
|
20
|
-
huntermakespy-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|