hunterMakesPy 0.6.0__tar.gz → 0.7.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.
- {huntermakespy-0.6.0/hunterMakesPy.egg-info → huntermakespy-0.7.0}/PKG-INFO +6 -107
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/README.md +2 -96
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/parseParameters.py +5 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/tests/conftest.py +4 -4
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/tests/test_coping.py +1 -1
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/tests/test_dataStructures.py +12 -19
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/tests/test_filesystemToolkit.py +2 -2
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/tests/test_parseParameters.py +2 -1
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/tests/test_theTypes.py +0 -76
- {huntermakespy-0.6.0 → huntermakespy-0.7.0/hunterMakesPy.egg-info}/PKG-INFO +6 -107
- huntermakespy-0.7.0/hunterMakesPy.egg-info/SOURCES.txt +25 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy.egg-info/requires.txt +0 -4
- huntermakespy-0.7.0/hunterMakesPy.egg-info/top_level.txt +1 -0
- huntermakespy-0.7.0/pyproject.toml +79 -0
- huntermakespy-0.6.0/humpy_cytoolz/Notice_of_Copyright.txt +0 -32
- huntermakespy-0.6.0/humpy_cytoolz/__init__.pxd +0 -19
- huntermakespy-0.6.0/humpy_cytoolz/__init__.py +0 -25
- huntermakespy-0.6.0/humpy_cytoolz/__init__.pyi +0 -24
- huntermakespy-0.6.0/humpy_cytoolz/_signatures.py +0 -12
- huntermakespy-0.6.0/humpy_cytoolz/_signatures.pyi +0 -27
- huntermakespy-0.6.0/humpy_cytoolz/cpython.pxd +0 -11
- huntermakespy-0.6.0/humpy_cytoolz/curried/__init__.py +0 -78
- huntermakespy-0.6.0/humpy_cytoolz/curried/exceptions.py +0 -13
- huntermakespy-0.6.0/humpy_cytoolz/curried/exceptions.pyi +0 -30
- huntermakespy-0.6.0/humpy_cytoolz/curried/operator.py +0 -7
- huntermakespy-0.6.0/humpy_cytoolz/dicttoolz.c +0 -17659
- huntermakespy-0.6.0/humpy_cytoolz/dicttoolz.pxd +0 -51
- huntermakespy-0.6.0/humpy_cytoolz/dicttoolz.pyi +0 -126
- huntermakespy-0.6.0/humpy_cytoolz/dicttoolz.pyx +0 -974
- huntermakespy-0.6.0/humpy_cytoolz/functoolz.c +0 -29204
- huntermakespy-0.6.0/humpy_cytoolz/functoolz.pxd +0 -67
- huntermakespy-0.6.0/humpy_cytoolz/functoolz.pyi +0 -402
- huntermakespy-0.6.0/humpy_cytoolz/functoolz.pyx +0 -919
- huntermakespy-0.6.0/humpy_cytoolz/itertoolz.c +0 -53819
- huntermakespy-0.6.0/humpy_cytoolz/itertoolz.pxd +0 -282
- huntermakespy-0.6.0/humpy_cytoolz/itertoolz.pyi +0 -298
- huntermakespy-0.6.0/humpy_cytoolz/itertoolz.pyx +0 -1864
- huntermakespy-0.6.0/humpy_cytoolz/recipes.c +0 -11453
- huntermakespy-0.6.0/humpy_cytoolz/recipes.pxd +0 -5
- huntermakespy-0.6.0/humpy_cytoolz/recipes.pyi +0 -35
- huntermakespy-0.6.0/humpy_cytoolz/recipes.pyx +0 -67
- huntermakespy-0.6.0/humpy_cytoolz/tests/__init__.py +0 -1
- huntermakespy-0.6.0/humpy_cytoolz/tests/dev_skip_test.py +0 -29
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_curried.py +0 -89
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_curried_toolzlike.py +0 -30
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_dev_skip_test.py +0 -18
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_dicttoolz.py +0 -436
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_docstrings.py +0 -52
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_doctests.py +0 -16
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_embedded_sigs.py +0 -67
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_functoolz.py +0 -627
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_inspect_args.py +0 -439
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_itertoolz.py +0 -415
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_none_safe.py +0 -243
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_recipes.py +0 -16
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_serialization.py +0 -138
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_signatures.py +0 -74
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_stubs.py +0 -0
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_tlz.py +0 -48
- huntermakespy-0.6.0/humpy_cytoolz/tests/test_utils.py +0 -13
- huntermakespy-0.6.0/humpy_cytoolz/utils.c +0 -9069
- huntermakespy-0.6.0/humpy_cytoolz/utils.pxd +0 -1
- huntermakespy-0.6.0/humpy_cytoolz/utils.pyi +0 -11
- huntermakespy-0.6.0/humpy_cytoolz/utils.pyx +0 -60
- huntermakespy-0.6.0/humpy_tlz/__init__.py +0 -9
- huntermakespy-0.6.0/humpy_tlz/_build_tlz.py +0 -82
- huntermakespy-0.6.0/humpy_toolz/Notice_of_Copyright.txt +0 -32
- huntermakespy-0.6.0/humpy_toolz/__init__.py +0 -22
- huntermakespy-0.6.0/humpy_toolz/__init__.pyi +0 -29
- huntermakespy-0.6.0/humpy_toolz/_signatures.py +0 -458
- huntermakespy-0.6.0/humpy_toolz/curried/__init__.py +0 -78
- huntermakespy-0.6.0/humpy_toolz/curried/__init__.pyi +0 -1478
- huntermakespy-0.6.0/humpy_toolz/curried/exceptions.py +0 -13
- huntermakespy-0.6.0/humpy_toolz/curried/exceptions.pyi +0 -91
- huntermakespy-0.6.0/humpy_toolz/curried/operator.py +0 -8
- huntermakespy-0.6.0/humpy_toolz/curried/operator.pyi +0 -248
- huntermakespy-0.6.0/humpy_toolz/dicttoolz.py +0 -865
- huntermakespy-0.6.0/humpy_toolz/functoolz.py +0 -834
- huntermakespy-0.6.0/humpy_toolz/functoolz.pyi +0 -386
- huntermakespy-0.6.0/humpy_toolz/itertoolz.py +0 -1180
- huntermakespy-0.6.0/humpy_toolz/py.typed +0 -0
- huntermakespy-0.6.0/humpy_toolz/recipes.py +0 -43
- huntermakespy-0.6.0/humpy_toolz/recipes.pyi +0 -14
- huntermakespy-0.6.0/humpy_toolz/sandbox/__init__.py +0 -3
- huntermakespy-0.6.0/humpy_toolz/sandbox/__init__.pyi +0 -4
- huntermakespy-0.6.0/humpy_toolz/sandbox/core.py +0 -121
- huntermakespy-0.6.0/humpy_toolz/sandbox/core.pyi +0 -54
- huntermakespy-0.6.0/humpy_toolz/sandbox/parallel.py +0 -70
- huntermakespy-0.6.0/humpy_toolz/sandbox/parallel.pyi +0 -20
- huntermakespy-0.6.0/humpy_toolz/sandbox/tests/__init__.py +0 -1
- huntermakespy-0.6.0/humpy_toolz/sandbox/tests/test_core.py +0 -82
- huntermakespy-0.6.0/humpy_toolz/sandbox/tests/test_parallel.py +0 -22
- huntermakespy-0.6.0/humpy_toolz/tests/__init__.py +0 -1
- huntermakespy-0.6.0/humpy_toolz/tests/test_curried.py +0 -89
- huntermakespy-0.6.0/humpy_toolz/tests/test_curried_doctests.py +0 -10
- huntermakespy-0.6.0/humpy_toolz/tests/test_dicttoolz.py +0 -1077
- huntermakespy-0.6.0/humpy_toolz/tests/test_functoolz.py +0 -620
- huntermakespy-0.6.0/humpy_toolz/tests/test_inspect_args.py +0 -441
- huntermakespy-0.6.0/humpy_toolz/tests/test_itertoolz.py +0 -417
- huntermakespy-0.6.0/humpy_toolz/tests/test_package.py +0 -6
- huntermakespy-0.6.0/humpy_toolz/tests/test_recipes.py +0 -16
- huntermakespy-0.6.0/humpy_toolz/tests/test_serialization.py +0 -139
- huntermakespy-0.6.0/humpy_toolz/tests/test_signatures.py +0 -74
- huntermakespy-0.6.0/humpy_toolz/tests/test_tlz.py +0 -53
- huntermakespy-0.6.0/humpy_toolz/tests/test_utils.py +0 -5
- huntermakespy-0.6.0/humpy_toolz/utils.py +0 -190
- huntermakespy-0.6.0/hunterMakesPy/py.typed +0 -0
- huntermakespy-0.6.0/hunterMakesPy.egg-info/SOURCES.txt +0 -118
- huntermakespy-0.6.0/hunterMakesPy.egg-info/top_level.txt +0 -4
- huntermakespy-0.6.0/pyproject.toml +0 -144
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/LICENSE +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/__init__.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/_theSSOT.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/coping.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/dataStructures.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/filesystemToolkit.py +0 -0
- {huntermakespy-0.6.0/humpy_cytoolz → huntermakespy-0.7.0/hunterMakesPy}/py.typed +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/semiotics.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/tests/__init__.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/theTypes.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy/theTypesCallableFunction.py +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/hunterMakesPy.egg-info/dependency_links.txt +0 -0
- {huntermakespy-0.6.0 → huntermakespy-0.7.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hunterMakesPy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Easy Python functions making making functional Python functions easier.
|
|
5
5
|
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
6
|
License-Expression: CC-BY-NC-4.0
|
|
@@ -9,7 +9,7 @@ Project-URL: Donate, https://www.patreon.com/integrated
|
|
|
9
9
|
Project-URL: Homepage, https://github.com/hunterhogan/hunterMakesPy
|
|
10
10
|
Project-URL: Issues, https://github.com/hunterhogan/hunterMakesPy/issues
|
|
11
11
|
Project-URL: Repository, https://github.com/hunterhogan/hunterMakesPy
|
|
12
|
-
Keywords: attribute loading,
|
|
12
|
+
Keywords: attribute loading,configuration,defensive programming,dictionary merging,dynamic import,file system utilities,input validation,module loading,package settings,parameter validation
|
|
13
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Environment :: Console
|
|
15
15
|
Classifier: Framework :: Pytest
|
|
@@ -19,15 +19,12 @@ Classifier: Intended Audience :: Other Audience
|
|
|
19
19
|
Classifier: Natural Language :: English
|
|
20
20
|
Classifier: Operating System :: OS Independent
|
|
21
21
|
Classifier: Programming Language :: Python
|
|
22
|
-
Classifier: Programming Language :: Python :: 3
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
25
23
|
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
27
24
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
28
25
|
Classifier: Topic :: Utilities
|
|
29
26
|
Classifier: Typing :: Typed
|
|
30
|
-
Requires-Python: >=3.
|
|
27
|
+
Requires-Python: >=3.10
|
|
31
28
|
Description-Content-Type: text/markdown
|
|
32
29
|
License-File: LICENSE
|
|
33
30
|
Requires-Dist: autoflake
|
|
@@ -38,19 +35,15 @@ Requires-Dist: numpy
|
|
|
38
35
|
Requires-Dist: tomli
|
|
39
36
|
Requires-Dist: typing_extensions>=4.10.0
|
|
40
37
|
Provides-Extra: development
|
|
41
|
-
Requires-Dist: astToolkit; extra == "development"
|
|
42
|
-
Requires-Dist: setuptools>=62.3; extra == "development"
|
|
43
38
|
Requires-Dist: pytest-cov; extra == "development"
|
|
44
39
|
Provides-Extra: testing
|
|
45
|
-
Requires-Dist: cython; extra == "testing"
|
|
46
40
|
Requires-Dist: librosa; extra == "testing"
|
|
47
41
|
Requires-Dist: pytest; extra == "testing"
|
|
48
|
-
Requires-Dist: pytest-xdist; extra == "testing"
|
|
49
42
|
Dynamic: license-file
|
|
50
43
|
|
|
51
44
|
# hunterMakesPy
|
|
52
45
|
|
|
53
|
-
Utilities for converting mixed input to integers, calculating CPU limits, handling None values, importing code dynamically, and manipulating nested data.
|
|
46
|
+
Utilities for converting mixed input to integers, calculating CPU limits, handling None values, importing code dynamically, and manipulating nested data.
|
|
54
47
|
|
|
55
48
|
[](https://pypi.org/project/hunterMakesPy/)
|
|
56
49
|
|
|
@@ -129,7 +122,7 @@ Write to `"deep/nested/path/file.txt"` and parent directories are created automa
|
|
|
129
122
|
from hunterMakesPy.filesystemToolkit import writeStringToHere, writePython
|
|
130
123
|
|
|
131
124
|
writeStringToHere("content", "nested/dirs/file.txt") # Creates dirs
|
|
132
|
-
writePython(sourceCode, "output/module.py")
|
|
125
|
+
writePython(sourceCode, "output/module.py") # Formats, then writes
|
|
133
126
|
```
|
|
134
127
|
|
|
135
128
|
## Extract Strings from Arbitrarily Nested Data
|
|
@@ -190,100 +183,6 @@ def test_my_integer_validator(test_name, test_func):
|
|
|
190
183
|
test_func()
|
|
191
184
|
```
|
|
192
185
|
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## `humpy_toolz`: Typed Pure-Python Functional Utilities
|
|
196
|
-
|
|
197
|
-
`humpy_toolz` is a typed fork of [`toolz`](https://github.com/pytoolz/toolz). It provides composable functions for iterators, dictionaries, and function composition with full type stubs and docstrings.
|
|
198
|
-
|
|
199
|
-
### Dictionary Transformations without Mutation
|
|
200
|
-
|
|
201
|
-
Create new mappings by associating, dissociating, filtering, and mapping over keys or values. Nested access is supported through key-path sequences.
|
|
202
|
-
|
|
203
|
-
```python
|
|
204
|
-
from humpy_toolz import merge, valmap, keyfilter, assoc
|
|
205
|
-
|
|
206
|
-
merged = merge({"a": 1}, {"b": 2}) # {"a": 1, "b": 2}
|
|
207
|
-
doubled = valmap(lambda x: x * 2, {"a": 1}) # {"a": 2}
|
|
208
|
-
evens = keyfilter(lambda k: k > 1, {1: "a", 2: "b"}) # {2: "b"}
|
|
209
|
-
updated = assoc({"x": 10}, "y", 20) # {"x": 10, "y": 20}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### Compose, Curry, and Thread Functions
|
|
213
|
-
|
|
214
|
-
Build transformation sequences from left or right, partially apply arguments with `curry`, and thread a value through a series of functions.
|
|
215
|
-
|
|
216
|
-
```python
|
|
217
|
-
from humpy_toolz import compose_left, curry, pipe
|
|
218
|
-
|
|
219
|
-
increment = lambda x: x + 1
|
|
220
|
-
double = lambda x: x * 2
|
|
221
|
-
transform = compose_left(increment, double)
|
|
222
|
-
transform(3) # 8
|
|
223
|
-
|
|
224
|
-
pipe(3, increment, double) # 8
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Slice, Group, and Deduplicate Iterators
|
|
228
|
-
|
|
229
|
-
Lazy operations over iterables: `take`, `drop`, `partition`, `sliding_window`, `unique`, `interleave`, `groupby`, `frequencies`, and more.
|
|
230
|
-
|
|
231
|
-
```python
|
|
232
|
-
from humpy_toolz import take, frequencies, groupby, unique
|
|
233
|
-
|
|
234
|
-
list(take(3, range(100))) # [0, 1, 2]
|
|
235
|
-
frequencies(["a", "b", "a", "c"]) # {"a": 2, "b": 1, "c": 1}
|
|
236
|
-
groupby(len, ["cat", "mouse", "dog"]) # {3: ["cat", "dog"], 5: ["mouse"]}
|
|
237
|
-
list(unique([1, 2, 1, 3])) # [1, 2, 3]
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Curried Namespace for Partial Application
|
|
241
|
-
|
|
242
|
-
Every function in `humpy_toolz.curried` accepts partial arguments and returns a new callable waiting for the rest.
|
|
243
|
-
|
|
244
|
-
```python
|
|
245
|
-
from humpy_toolz.curried import map, filter, get
|
|
246
|
-
|
|
247
|
-
list(map(str.upper, ["hello", "world"])) # ["HELLO", "WORLD"]
|
|
248
|
-
list(filter(lambda x: x > 2, [1, 2, 3, 4])) # [3, 4]
|
|
249
|
-
list(map(get(0), [(1, 2), (3, 4)])) # [1, 3]
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### Sandbox: Parallel Fold and Equality-Based Hashing
|
|
253
|
-
|
|
254
|
-
`humpy_toolz.sandbox` provides `fold` for unordered parallel reductions and `EqualityHashKey` for hashing otherwise-unhashable types.
|
|
255
|
-
|
|
256
|
-
```python
|
|
257
|
-
from humpy_toolz.sandbox import fold, EqualityHashKey
|
|
258
|
-
from operator import add
|
|
259
|
-
|
|
260
|
-
fold(add, range(100), default=0) # 4950
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## `humpy_cytoolz`: Cython-Accelerated Functional Utilities
|
|
266
|
-
|
|
267
|
-
`humpy_cytoolz` is a typed fork of [`cytoolz`](https://github.com/pytoolz/cytoolz). It exposes the same API as `humpy_toolz` but the core modules (`dicttoolz`, `functoolz`, `itertoolz`, `recipes`, `utils`) are compiled as Cython extension modules for lower overhead on hot paths.
|
|
268
|
-
|
|
269
|
-
```python
|
|
270
|
-
from humpy_cytoolz import groupby, curry, merge
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
Install with the `cython` build dependency to compile the extensions. If compilation is unavailable, use `humpy_toolz` directly.
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## `humpy_tlz`: Automatic Cython-or-Pure Dispatch
|
|
278
|
-
|
|
279
|
-
`humpy_tlz` mirrors the `humpy_toolz` API and imports from `humpy_cytoolz` when available, falling back to `humpy_toolz` otherwise. Use `humpy_tlz` in library code so callers benefit from Cython acceleration without requiring it.
|
|
280
|
-
|
|
281
|
-
```python
|
|
282
|
-
from humpy_tlz import pipe, curry, groupby
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
186
|
## My recovery
|
|
288
187
|
|
|
289
188
|
[](https://HunterThinks.com/support)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# hunterMakesPy
|
|
2
2
|
|
|
3
|
-
Utilities for converting mixed input to integers, calculating CPU limits, handling None values, importing code dynamically, and manipulating nested data.
|
|
3
|
+
Utilities for converting mixed input to integers, calculating CPU limits, handling None values, importing code dynamically, and manipulating nested data.
|
|
4
4
|
|
|
5
5
|
[](https://pypi.org/project/hunterMakesPy/)
|
|
6
6
|
|
|
@@ -79,7 +79,7 @@ Write to `"deep/nested/path/file.txt"` and parent directories are created automa
|
|
|
79
79
|
from hunterMakesPy.filesystemToolkit import writeStringToHere, writePython
|
|
80
80
|
|
|
81
81
|
writeStringToHere("content", "nested/dirs/file.txt") # Creates dirs
|
|
82
|
-
writePython(sourceCode, "output/module.py")
|
|
82
|
+
writePython(sourceCode, "output/module.py") # Formats, then writes
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
## Extract Strings from Arbitrarily Nested Data
|
|
@@ -140,100 +140,6 @@ def test_my_integer_validator(test_name, test_func):
|
|
|
140
140
|
test_func()
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
## `humpy_toolz`: Typed Pure-Python Functional Utilities
|
|
146
|
-
|
|
147
|
-
`humpy_toolz` is a typed fork of [`toolz`](https://github.com/pytoolz/toolz). It provides composable functions for iterators, dictionaries, and function composition with full type stubs and docstrings.
|
|
148
|
-
|
|
149
|
-
### Dictionary Transformations without Mutation
|
|
150
|
-
|
|
151
|
-
Create new mappings by associating, dissociating, filtering, and mapping over keys or values. Nested access is supported through key-path sequences.
|
|
152
|
-
|
|
153
|
-
```python
|
|
154
|
-
from humpy_toolz import merge, valmap, keyfilter, assoc
|
|
155
|
-
|
|
156
|
-
merged = merge({"a": 1}, {"b": 2}) # {"a": 1, "b": 2}
|
|
157
|
-
doubled = valmap(lambda x: x * 2, {"a": 1}) # {"a": 2}
|
|
158
|
-
evens = keyfilter(lambda k: k > 1, {1: "a", 2: "b"}) # {2: "b"}
|
|
159
|
-
updated = assoc({"x": 10}, "y", 20) # {"x": 10, "y": 20}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### Compose, Curry, and Thread Functions
|
|
163
|
-
|
|
164
|
-
Build transformation sequences from left or right, partially apply arguments with `curry`, and thread a value through a series of functions.
|
|
165
|
-
|
|
166
|
-
```python
|
|
167
|
-
from humpy_toolz import compose_left, curry, pipe
|
|
168
|
-
|
|
169
|
-
increment = lambda x: x + 1
|
|
170
|
-
double = lambda x: x * 2
|
|
171
|
-
transform = compose_left(increment, double)
|
|
172
|
-
transform(3) # 8
|
|
173
|
-
|
|
174
|
-
pipe(3, increment, double) # 8
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Slice, Group, and Deduplicate Iterators
|
|
178
|
-
|
|
179
|
-
Lazy operations over iterables: `take`, `drop`, `partition`, `sliding_window`, `unique`, `interleave`, `groupby`, `frequencies`, and more.
|
|
180
|
-
|
|
181
|
-
```python
|
|
182
|
-
from humpy_toolz import take, frequencies, groupby, unique
|
|
183
|
-
|
|
184
|
-
list(take(3, range(100))) # [0, 1, 2]
|
|
185
|
-
frequencies(["a", "b", "a", "c"]) # {"a": 2, "b": 1, "c": 1}
|
|
186
|
-
groupby(len, ["cat", "mouse", "dog"]) # {3: ["cat", "dog"], 5: ["mouse"]}
|
|
187
|
-
list(unique([1, 2, 1, 3])) # [1, 2, 3]
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Curried Namespace for Partial Application
|
|
191
|
-
|
|
192
|
-
Every function in `humpy_toolz.curried` accepts partial arguments and returns a new callable waiting for the rest.
|
|
193
|
-
|
|
194
|
-
```python
|
|
195
|
-
from humpy_toolz.curried import map, filter, get
|
|
196
|
-
|
|
197
|
-
list(map(str.upper, ["hello", "world"])) # ["HELLO", "WORLD"]
|
|
198
|
-
list(filter(lambda x: x > 2, [1, 2, 3, 4])) # [3, 4]
|
|
199
|
-
list(map(get(0), [(1, 2), (3, 4)])) # [1, 3]
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### Sandbox: Parallel Fold and Equality-Based Hashing
|
|
203
|
-
|
|
204
|
-
`humpy_toolz.sandbox` provides `fold` for unordered parallel reductions and `EqualityHashKey` for hashing otherwise-unhashable types.
|
|
205
|
-
|
|
206
|
-
```python
|
|
207
|
-
from humpy_toolz.sandbox import fold, EqualityHashKey
|
|
208
|
-
from operator import add
|
|
209
|
-
|
|
210
|
-
fold(add, range(100), default=0) # 4950
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## `humpy_cytoolz`: Cython-Accelerated Functional Utilities
|
|
216
|
-
|
|
217
|
-
`humpy_cytoolz` is a typed fork of [`cytoolz`](https://github.com/pytoolz/cytoolz). It exposes the same API as `humpy_toolz` but the core modules (`dicttoolz`, `functoolz`, `itertoolz`, `recipes`, `utils`) are compiled as Cython extension modules for lower overhead on hot paths.
|
|
218
|
-
|
|
219
|
-
```python
|
|
220
|
-
from humpy_cytoolz import groupby, curry, merge
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
Install with the `cython` build dependency to compile the extensions. If compilation is unavailable, use `humpy_toolz` directly.
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## `humpy_tlz`: Automatic Cython-or-Pure Dispatch
|
|
228
|
-
|
|
229
|
-
`humpy_tlz` mirrors the `humpy_toolz` API and imports from `humpy_cytoolz` when available, falling back to `humpy_toolz` otherwise. Use `humpy_tlz` in library code so callers benefit from Cython acceleration without requiring it.
|
|
230
|
-
|
|
231
|
-
```python
|
|
232
|
-
from humpy_tlz import pipe, curry, groupby
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
143
|
## My recovery
|
|
238
144
|
|
|
239
145
|
[](https://HunterThinks.com/support)
|
|
@@ -116,6 +116,11 @@ def _constructErrorMessage(context: ErrorMessageContext, parameterName: str, par
|
|
|
116
116
|
|
|
117
117
|
# TODO Should I change the function because "On Windows, max_workers must be less than or equal to 61."?
|
|
118
118
|
# https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor
|
|
119
|
+
# autoflake
|
|
120
|
+
# if sys.platform == "win32":
|
|
121
|
+
# # Work around https://bugs.python.org/issue26903
|
|
122
|
+
# worker_count = min(worker_count, 60) # noqa: ERA001
|
|
123
|
+
|
|
119
124
|
def defineConcurrencyLimit(*, limit: bool | float | int | None, cpuTotal: int = multiprocessing.cpu_count()) -> int:
|
|
120
125
|
"""Determine the concurrency limit based on the provided parameter.
|
|
121
126
|
|
|
@@ -41,7 +41,7 @@ def pathTmpTesting(tmp_path: pathlib.Path) -> pathlib.Path:
|
|
|
41
41
|
# Fixture for predictable Python source code samples
|
|
42
42
|
@pytest.fixture
|
|
43
43
|
def dictionaryPythonSourceSamples() -> dict[str, str]:
|
|
44
|
-
"""Provide predictable Python source code samples for testing."""
|
|
44
|
+
"""Provide predictable Python source code samples for testing.""" # noqa: DOC201
|
|
45
45
|
return {
|
|
46
46
|
'functionFibonacci': "def fibonacciNumber():\n return 13\n",
|
|
47
47
|
'functionPrime': "def primeNumber():\n return 17\n",
|
|
@@ -53,19 +53,19 @@ def dictionaryPythonSourceSamples() -> dict[str, str]:
|
|
|
53
53
|
# Fixture for IO stream objects
|
|
54
54
|
@pytest.fixture
|
|
55
55
|
def streamMemoryString() -> io.StringIO:
|
|
56
|
-
"""Provide a StringIO object for testing stream operations."""
|
|
56
|
+
"""Provide a StringIO object for testing stream operations.""" # noqa: DOC201
|
|
57
57
|
return io.StringIO()
|
|
58
58
|
|
|
59
59
|
# Fixture for predictable directory names using cardinal directions
|
|
60
60
|
@pytest.fixture
|
|
61
61
|
def listDirectoryNamesCardinal() -> list[str]:
|
|
62
|
-
"""Provide predictable directory names using cardinal directions."""
|
|
62
|
+
"""Provide predictable directory names using cardinal directions.""" # noqa: DOC201
|
|
63
63
|
return ['north', 'south', 'east', 'west']
|
|
64
64
|
|
|
65
65
|
# Fixture for predictable file content using Fibonacci numbers
|
|
66
66
|
@pytest.fixture
|
|
67
67
|
def listFileContentsFibonacci() -> list[str]:
|
|
68
|
-
"""Provide predictable file contents using Fibonacci sequence."""
|
|
68
|
+
"""Provide predictable file contents using Fibonacci sequence.""" # noqa: DOC201
|
|
69
69
|
return ['fibonacci8', 'fibonacci13', 'fibonacci21', 'fibonacci34']
|
|
70
70
|
|
|
71
71
|
def uniformTestFailureMessage(expected: Any, actual: Any, functionName: str, *arguments: Any, **keywordArguments: Any) -> str:
|
|
@@ -211,7 +211,7 @@ def testPackageSettingsDefaultValues() -> None:
|
|
|
211
211
|
)
|
|
212
212
|
|
|
213
213
|
# identifierPackage should be empty when no fallback provided
|
|
214
|
-
assert packageSettings.identifierPackage
|
|
214
|
+
assert not packageSettings.identifierPackage, uniformTestFailureMessage(
|
|
215
215
|
'', packageSettings.identifierPackage, "PackageSettings default identifierPackage"
|
|
216
216
|
)
|
|
217
217
|
|
|
@@ -147,11 +147,11 @@ def test_updateExtendPolishDictionaryLists(description: str, value_dictionaryLis
|
|
|
147
147
|
],
|
|
148
148
|
)
|
|
149
149
|
def test_autoDecodingRLE(
|
|
150
|
-
description: str
|
|
151
|
-
arrayExpression: str
|
|
152
|
-
expectedWithoutSpaces: str
|
|
153
|
-
expectedWithSpaces: str
|
|
154
|
-
assumeAddSpaces: bool
|
|
150
|
+
description: str
|
|
151
|
+
, arrayExpression: str
|
|
152
|
+
, expectedWithoutSpaces: str
|
|
153
|
+
, expectedWithSpaces: str
|
|
154
|
+
, assumeAddSpaces: bool
|
|
155
155
|
) -> None:
|
|
156
156
|
"""Verify exact output, structural properties, and roundtrip decoding for all RLE cases."""
|
|
157
157
|
expected: str = expectedWithSpaces if assumeAddSpaces else expectedWithoutSpaces
|
|
@@ -169,12 +169,8 @@ def test_autoDecodingRLE(
|
|
|
169
169
|
assert isinstance(resultRLE, str), (
|
|
170
170
|
f"autoDecodingRLE returned {type(resultRLE).__name__}, expected str for {description=} and {assumeAddSpaces=}."
|
|
171
171
|
)
|
|
172
|
-
assert "[" in resultRLE, (
|
|
173
|
-
|
|
174
|
-
)
|
|
175
|
-
assert "]" in resultRLE, (
|
|
176
|
-
f"autoDecodingRLE returned {resultRLE!r}, expected ']' in output for {description=} and {assumeAddSpaces=}."
|
|
177
|
-
)
|
|
172
|
+
assert "[" in resultRLE, (f"autoDecodingRLE returned {resultRLE!r}, expected '[' in output for {description=} and {assumeAddSpaces=}.")
|
|
173
|
+
assert "]" in resultRLE, (f"autoDecodingRLE returned {resultRLE!r}, expected ']' in output for {description=} and {assumeAddSpaces=}.")
|
|
178
174
|
|
|
179
175
|
rawStrLength: int = len(str(value_arrayTarget.tolist()))
|
|
180
176
|
encodedLength: int = len(resultRLE)
|
|
@@ -182,17 +178,14 @@ def test_autoDecodingRLE(
|
|
|
182
178
|
f"autoDecodingRLE produced length {encodedLength}, expected <= {rawStrLength} for {description=} and {assumeAddSpaces=}."
|
|
183
179
|
)
|
|
184
180
|
|
|
185
|
-
assert resultRLE == expected, (
|
|
186
|
-
f"autoDecodingRLE returned {resultRLE!r}, expected {expected!r} for {description=} and {assumeAddSpaces=}."
|
|
187
|
-
)
|
|
181
|
+
assert resultRLE == expected, (f"autoDecodingRLE made {resultRLE!r}, expected {expected!r} for {description=} and {assumeAddSpaces=}.")
|
|
188
182
|
|
|
189
183
|
decodedData = eval(resultRLE) # noqa: S307
|
|
190
184
|
reconstructedArray: NDArray[numpy.integer[Any]] = numpy.array(decodedData)
|
|
191
185
|
numpy.testing.assert_array_equal(
|
|
192
|
-
reconstructedArray
|
|
193
|
-
value_arrayTarget
|
|
194
|
-
err_msg=(
|
|
186
|
+
reconstructedArray
|
|
187
|
+
, value_arrayTarget
|
|
188
|
+
, err_msg=(
|
|
195
189
|
f"autoDecodingRLE roundtrip produced {reconstructedArray.tolist()}, "
|
|
196
190
|
f"expected {value_arrayTarget.tolist()} for {description=} and {assumeAddSpaces=}."
|
|
197
|
-
|
|
198
|
-
)
|
|
191
|
+
))
|
|
@@ -149,7 +149,7 @@ def testMakeDirsSafelyCreatesNestedDirectories(pathTmpTesting: pathlib.Path, lis
|
|
|
149
149
|
"""
|
|
150
150
|
pathDirectoryNested: pathlib.Path = pathTmpTesting
|
|
151
151
|
for directoryComponent in listDirectoryComponents:
|
|
152
|
-
pathDirectoryNested
|
|
152
|
+
pathDirectoryNested /= directoryComponent
|
|
153
153
|
|
|
154
154
|
pathFilenameTarget: pathlib.Path = pathDirectoryNested / filenameTarget
|
|
155
155
|
makeDirectorySafely(pathFilenameTarget)
|
|
@@ -208,7 +208,7 @@ def testWriteStringToHereCreatesFileAndDirectories(pathTmpTesting: pathlib.Path,
|
|
|
208
208
|
"""
|
|
209
209
|
pathDirectoryNested: pathlib.Path = pathTmpTesting
|
|
210
210
|
for directoryComponent in listDirectoryComponents:
|
|
211
|
-
pathDirectoryNested
|
|
211
|
+
pathDirectoryNested /= directoryComponent
|
|
212
212
|
|
|
213
213
|
pathFilenameTarget: pathlib.Path = pathDirectoryNested / filenameTarget
|
|
214
214
|
writeStringToHere(contentTarget, pathFilenameTarget)
|
|
@@ -8,6 +8,7 @@ and string-based boolean parsing.
|
|
|
8
8
|
"""
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
from collections import UserList
|
|
11
12
|
# pyright: standard
|
|
12
13
|
from hunterMakesPy.parseParameters import defineConcurrencyLimit, intInnit, oopsieKwargsie
|
|
13
14
|
from typing import Any, NoReturn, ParamSpec, TYPE_CHECKING, TypeVar
|
|
@@ -230,7 +231,7 @@ def PytestFor_intInnit(callableToTest: Callable[[Iterable[Any], str | None, type
|
|
|
230
231
|
callableToTest(inputData, 'test', None)
|
|
231
232
|
|
|
232
233
|
def testRejectsMutableSequence() -> None:
|
|
233
|
-
class MutableList(
|
|
234
|
+
class MutableList(UserList[int]):
|
|
234
235
|
def __iter__(self) -> Iterator[int]:
|
|
235
236
|
self.append(89)
|
|
236
237
|
return super().__iter__()
|
|
@@ -116,12 +116,6 @@ def testOrdinalsBetweenWorksForInt(floor: int, ceiling: int, comparand: int, exp
|
|
|
116
116
|
Value of `comparand` compared against the bounds.
|
|
117
117
|
expected : bool
|
|
118
118
|
Expected outcome from `between`.
|
|
119
|
-
|
|
120
|
-
Returns
|
|
121
|
-
-------
|
|
122
|
-
unusedReturnValue : None
|
|
123
|
-
Returns `None`.
|
|
124
|
-
|
|
125
119
|
"""
|
|
126
120
|
actual: bool = between(floor, ceiling, comparand)
|
|
127
121
|
assert actual == expected, uniformTestFailureMessage(expected, actual, 'between', floor, ceiling, comparand)
|
|
@@ -141,12 +135,6 @@ def testOrdinalsSortingWorksForInt(values: list[int], expected: list[int]) -> No
|
|
|
141
135
|
Input `values` to sort.
|
|
142
136
|
expected : list[int]
|
|
143
137
|
Expected sorted output for `values`.
|
|
144
|
-
|
|
145
|
-
Returns
|
|
146
|
-
-------
|
|
147
|
-
unusedReturnValue : None
|
|
148
|
-
Returns `None`.
|
|
149
|
-
|
|
150
138
|
"""
|
|
151
139
|
actual: list[int] = sorted(values)
|
|
152
140
|
assert actual == expected, uniformTestFailureMessage(expected, actual, 'sorted', values)
|
|
@@ -170,12 +158,6 @@ def testOrdinalsBetweenWorksForStr(floor: str, ceiling: str, comparand: str, exp
|
|
|
170
158
|
Value of `comparand` compared against the bounds.
|
|
171
159
|
expected : bool
|
|
172
160
|
Expected outcome from `between`.
|
|
173
|
-
|
|
174
|
-
Returns
|
|
175
|
-
-------
|
|
176
|
-
unusedReturnValue : None
|
|
177
|
-
Returns `None`.
|
|
178
|
-
|
|
179
161
|
"""
|
|
180
162
|
actual: bool = between(floor, ceiling, comparand)
|
|
181
163
|
assert actual == expected, uniformTestFailureMessage(expected, actual, 'between', floor, ceiling, comparand)
|
|
@@ -195,12 +177,6 @@ def testOrdinalsSortingWorksForStr(values: list[str], expected: list[str]) -> No
|
|
|
195
177
|
Input `values` to sort.
|
|
196
178
|
expected : list[str]
|
|
197
179
|
Expected sorted output for `values`.
|
|
198
|
-
|
|
199
|
-
Returns
|
|
200
|
-
-------
|
|
201
|
-
unusedReturnValue : None
|
|
202
|
-
Returns `None`.
|
|
203
|
-
|
|
204
180
|
"""
|
|
205
181
|
actual: list[str] = sorted(values)
|
|
206
182
|
assert actual == expected, uniformTestFailureMessage(expected, actual, 'sorted', values)
|
|
@@ -224,12 +200,6 @@ def testOrdinalsBetweenWorksForTuple(floor: tuple[int, int], ceiling: tuple[int,
|
|
|
224
200
|
Value of `comparand` compared against the bounds.
|
|
225
201
|
expected : bool
|
|
226
202
|
Expected outcome from `between`.
|
|
227
|
-
|
|
228
|
-
Returns
|
|
229
|
-
-------
|
|
230
|
-
unusedReturnValue : None
|
|
231
|
-
Returns `None`.
|
|
232
|
-
|
|
233
203
|
"""
|
|
234
204
|
actual: bool = between(floor, ceiling, comparand)
|
|
235
205
|
assert actual == expected, uniformTestFailureMessage(expected, actual, 'between', floor, ceiling, comparand)
|
|
@@ -246,12 +216,6 @@ def testOrdinalsSortingWorksForTuple(values: list[tuple[int, int]], expected: li
|
|
|
246
216
|
Input `values` to sort.
|
|
247
217
|
expected : list[tuple[int, int]]
|
|
248
218
|
Expected sorted output for `values`.
|
|
249
|
-
|
|
250
|
-
Returns
|
|
251
|
-
-------
|
|
252
|
-
unusedReturnValue : None
|
|
253
|
-
Returns `None`.
|
|
254
|
-
|
|
255
219
|
"""
|
|
256
220
|
actual: list[tuple[int, int]] = sorted(values)
|
|
257
221
|
assert actual == expected, uniformTestFailureMessage(expected, actual, 'sorted', values)
|
|
@@ -278,46 +242,6 @@ def testOrdinalsBetweenWorksForCustomComparable(floor: ComparableCardinal, ceili
|
|
|
278
242
|
Value of `comparand` compared against the bounds.
|
|
279
243
|
expected : bool
|
|
280
244
|
Expected outcome from `between`.
|
|
281
|
-
|
|
282
|
-
Returns
|
|
283
|
-
-------
|
|
284
|
-
unusedReturnValue : None
|
|
285
|
-
Returns `None`.
|
|
286
|
-
|
|
287
245
|
"""
|
|
288
246
|
actual: bool = between(floor, ceiling, comparand)
|
|
289
247
|
assert actual == expected, uniformTestFailureMessage(expected, actual, 'between', floor, ceiling, comparand)
|
|
290
|
-
|
|
291
|
-
# TODO validation data must be static.
|
|
292
|
-
# @pytest.mark.parametrize( 'comparisonMethodName' , [ '__le__' , '__lt__' ] )
|
|
293
|
-
# def testOrdinalsComparisonMethodsAcceptOtherOperand(comparisonMethodName: str) -> None:
|
|
294
|
-
# """Validate `Ordinals` comparison method signatures.
|
|
295
|
-
|
|
296
|
-
# (AI generated docstring)
|
|
297
|
-
|
|
298
|
-
# Parameters
|
|
299
|
-
# ----------
|
|
300
|
-
# comparisonMethodName : str
|
|
301
|
-
# Name of the `Ordinals` comparison method to inspect.
|
|
302
|
-
|
|
303
|
-
# Returns
|
|
304
|
-
# -------
|
|
305
|
-
# unusedReturnValue : None
|
|
306
|
-
# Returns `None`.
|
|
307
|
-
|
|
308
|
-
# """
|
|
309
|
-
# comparisonMethod: Callable[[Ordinals, Ordinals], bool] = getattr(Ordinals, comparisonMethodName)
|
|
310
|
-
# signature: inspect.Signature = inspect.signature(comparisonMethod)
|
|
311
|
-
# listParameters: list[inspect.Parameter] = list(signature.parameters.values())
|
|
312
|
-
|
|
313
|
-
# assert len(listParameters) == 2, uniformTestFailureMessage(
|
|
314
|
-
# 2 , len(listParameters) , 'Ordinals comparison parameter count' , comparisonMethodName , signature )
|
|
315
|
-
|
|
316
|
-
# listKinds: list[inspect._ParameterKind] = [parameter.kind for parameter in listParameters]
|
|
317
|
-
# expectedKinds: list[inspect._ParameterKind] = [inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_ONLY]
|
|
318
|
-
# assert listKinds == expectedKinds, uniformTestFailureMessage(
|
|
319
|
-
# expectedKinds , listKinds , 'Ordinals comparison parameter kinds' , comparisonMethodName , signature )
|
|
320
|
-
|
|
321
|
-
# actualReturnAnnotation: object = signature.return_annotation
|
|
322
|
-
# assert actualReturnAnnotation is bool, uniformTestFailureMessage(
|
|
323
|
-
# bool , actualReturnAnnotation , 'Ordinals comparison return annotation' , comparisonMethodName , signature )
|