hunterMakesPy 0.7.0__tar.gz → 0.7.2__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.
Files changed (27) hide show
  1. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/PKG-INFO +3 -4
  2. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/dataStructures.py +33 -50
  3. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/filesystemToolkit.py +72 -76
  4. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/parseParameters.py +9 -11
  5. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/tests/test_dataStructures.py +0 -1
  6. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/theTypesCallableFunction.py +3 -2
  7. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy.egg-info/PKG-INFO +3 -4
  8. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy.egg-info/requires.txt +1 -0
  9. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/pyproject.toml +4 -11
  10. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/LICENSE +0 -0
  11. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/README.md +0 -0
  12. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/__init__.py +0 -0
  13. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/_theSSOT.py +0 -0
  14. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/coping.py +0 -0
  15. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/py.typed +0 -0
  16. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/semiotics.py +0 -0
  17. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/tests/__init__.py +0 -0
  18. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/tests/conftest.py +0 -0
  19. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/tests/test_coping.py +0 -0
  20. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/tests/test_filesystemToolkit.py +0 -0
  21. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/tests/test_parseParameters.py +0 -0
  22. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/tests/test_theTypes.py +0 -0
  23. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy/theTypes.py +0 -0
  24. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy.egg-info/SOURCES.txt +0 -0
  25. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy.egg-info/dependency_links.txt +0 -0
  26. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/hunterMakesPy.egg-info/top_level.txt +0 -0
  27. {huntermakespy-0.7.0 → huntermakespy-0.7.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hunterMakesPy
3
- Version: 0.7.0
3
+ Version: 0.7.2
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,13 +9,11 @@ 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,configuration,defensive programming,dictionary merging,dynamic import,file system utilities,input validation,module loading,package settings,parameter validation
12
+ Keywords: 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
16
16
  Classifier: Intended Audience :: Developers
17
- Classifier: Intended Audience :: End Users/Desktop
18
- Classifier: Intended Audience :: Other Audience
19
17
  Classifier: Natural Language :: English
20
18
  Classifier: Operating System :: OS Independent
21
19
  Classifier: Programming Language :: Python
@@ -27,6 +25,7 @@ Classifier: Typing :: Typed
27
25
  Requires-Python: >=3.10
28
26
  Description-Content-Type: text/markdown
29
27
  License-File: LICENSE
28
+ Requires-Dist: Z0Z_tools>=2.2.1
30
29
  Requires-Dist: autoflake
31
30
  Requires-Dist: charset_normalizer
32
31
  Requires-Dist: isort
@@ -1,38 +1,27 @@
1
1
  """Manipulate data structures with encoding, extraction, and merging utilities.
2
2
 
3
- (AI generated docstring)
4
-
5
- You can use this module to transform NumPy arrays [1] into compact run-length encoded
6
- strings, extract strings from arbitrarily nested data structures, and merge multiple
7
- dictionaries with list values. The module provides specialized utilities for working with
8
- Cartesian mappings, heterogeneous nested data, and dictionary consolidation operations.
9
-
10
- The run-length encoding function produces self-decoding string representations optimized for
11
- large arrays with repetitive patterns. The string extraction function recursively traverses
12
- nested structures to collect all convertible string values. The dictionary merging function
13
- consolidates multiple dictionaries while offering optional deduplication and sorting.
3
+ You can use this module to transform arrays (in the general sense) into compact run-length encoded
4
+ strings, extract strings from arbitrarily nested data structures, or merge dictionaries of lists.
14
5
 
15
6
  Contents
16
7
  --------
17
8
  Functions
18
9
  autoDecodingRLE
19
- Transform a NumPy array into a compact, self-decoding run-length encoded string representation.
10
+ Transform a NumPy array into a compact, self-decoding run-length encoded string
11
+ representation.
20
12
  stringItUp
21
13
  Convert every element in input data structures to strings.
22
14
  updateExtendPolishDictionaryLists
23
15
  Merge multiple dictionaries with list values into a single dictionary.
24
-
25
- References
26
- ----------
27
- [1] NumPy - Context7
28
- https://numpy.org/doc/stable/reference/index.html
29
-
30
16
  """
31
17
  from __future__ import annotations
32
18
 
33
19
  from charset_normalizer import CharsetMatch
20
+ from collections.abc import Hashable
21
+ from humpy_cytoolz.dicttoolz import valmap
22
+ from humpy_cytoolz.functoolz import compose
34
23
  from types import FunctionType
35
- from typing import Any, cast, TYPE_CHECKING
24
+ from typing import cast, TYPE_CHECKING, TypeVar
36
25
  import charset_normalizer
37
26
  import more_itertools
38
27
  import re as regex
@@ -43,24 +32,23 @@ if TYPE_CHECKING:
43
32
  from hunterMakesPy import 小于
44
33
  from numpy import integer
45
34
  from numpy.typing import NDArray
35
+ from typing import Any
46
36
 
47
37
  def removeExtraWhitespace(string: str) -> str:
48
38
  """Remove extra whitespace from string representation of Python data structures.""" # noqa: DOC201
49
39
  commas: str = regex.sub(r',\s+', ',', string)
50
40
  bracketsOpening: str = regex.sub(r'([\[\(])\s+', r'\1', commas)
51
- # Remove spaces before closing brackets/parentheses.
52
41
  return regex.sub(r'\s+([\]\)])', r'\1', bracketsOpening)
53
42
 
54
43
  def autoDecodingRLE(arrayTarget: NDArray[integer[Any]], *, assumeAddSpaces: bool = False) -> str:
55
44
  """Transform a NumPy array into a compact, self-decoding run-length encoded string representation.
56
45
 
57
46
  Use this function to convert a NumPy array into a string that, when evaluated as Python code,
58
- creates a list or nested lists representing the original array structure, and if used as an
59
- argument to `numpy.array()`, will recreate the original array structure. The RLE (Run-Length
60
- Encoding) string does _not_ need a special decoder function: it is already native Python syntax.
61
- The function employs two encoding strategies:
62
- 1. Python `range` syntax for consecutive integer sequences.
63
- 2. Multiplication syntax for repeated elements.
47
+ creates a list or nested lists representing the original array structure. You can create a NumPy
48
+ array, torch Tensor, or other array-like object with the auto-decoded list of lists. The RLE
49
+ (Run-Length Encoding) string does _not_ need a decoder function: it is native Python syntax. The
50
+ function employs two encoding strategies: 1. Python `range` syntax for consecutive integer
51
+ sequences. 2. Multiplication syntax for repeated elements.
64
52
 
65
53
  The resulting string representation is merely minified Python code, so it is space-efficient and,
66
54
  hypothetically, human-readable.
@@ -71,9 +59,8 @@ def autoDecodingRLE(arrayTarget: NDArray[integer[Any]], *, assumeAddSpaces: bool
71
59
  The NumPy array to be encoded.
72
60
  assumeAddSpaces : bool = False
73
61
  Affects internal length comparison during compression decisions. This parameter doesn't
74
- directly change output format but influences whether `range` or multiplication syntax is
75
- preferred in certain cases. The parameter exists because `ast.unparse()` (Abstract Syntax
76
- Tree) inserts spaces in the RLE string.
62
+ directly change the output: instead, use it to assume that something else will add spaces,
63
+ such as `ast.unparse()` (Abstract Syntax Tree) or a Python formatter.
77
64
 
78
65
  Returns
79
66
  -------
@@ -189,7 +176,7 @@ def autoDecodingRLE(arrayTarget: NDArray[integer[Any]], *, assumeAddSpaces: bool
189
176
  arrayAsStr = patternRegex.sub(replacementByContext, arrayAsStr)
190
177
  arrayAsStr = patternRegex.sub(replacementByContext, arrayAsStr)
191
178
 
192
- # Replace `range(0,stop)` syntax with `range(stop)` syntax.
179
+ # .replace `range(0,stop)` syntax with `range(stop)` syntax.
193
180
  # Add unpack operator `*` for automatic decoding when evaluated.
194
181
  return arrayAsStr.replace('range(0,', 'range(').replace('range', '*range')
195
182
 
@@ -207,7 +194,6 @@ def stringItUp(*scrapPile: Any) -> list[str]:
207
194
  -------
208
195
  listStrungUp : list[str]
209
196
  (list2strung2up) A `list` of string versions of all convertible elements.
210
-
211
197
  """
212
198
  scrap: Any = None
213
199
  listStrungUp: list[str] = []
@@ -256,14 +242,17 @@ def stringItUp(*scrapPile: Any) -> list[str]:
256
242
  listStrungUp.append(repr(scrap))
257
243
  return listStrungUp
258
244
 
259
- def updateExtendPolishDictionaryLists(*dictionaryLists: Mapping[str, list[小于] | set[小于] | tuple[小于, ...]], destroyDuplicates: bool = False, reorderLists: bool = False, killErroneousDataTypes: bool = False) -> dict[str, list[小于]]:
245
+ 文件 = TypeVar('文件', bound=Hashable)
246
+
247
+ # TODO if `reorderLists: bool = False`, the elements do not need to be ordinals, and they should be covariant.
248
+ def updateExtendPolishDictionaryLists(*dictionaryLists: Mapping[文件, list[小于] | set[小于] | tuple[小于, ...]], destroyDuplicates: bool = False, reorderLists: bool = False, killErroneousDataTypes: bool = False) -> dict[文件, list[小于]]:
260
249
  """Merge multiple dictionaries with `list` values into a single dictionary with the `list` values merged.
261
250
 
262
251
  Plus options to destroy duplicates, sort `list` values, and handle erroneous data types.
263
252
 
264
253
  Parameters
265
254
  ----------
266
- *dictionaryLists : Mapping[str, list[Any] | set[Any] | tuple[Any, ...]]
255
+ *dictionaryLists : MutableMapping[文件, list[Any] | set[Any] | tuple[Any, ...]]
267
256
  Variable number of dictionaries to be merged. If only one dictionary is passed, it will be
268
257
  "polished".
269
258
  destroyDuplicates : bool = False
@@ -277,37 +266,31 @@ def updateExtendPolishDictionaryLists(*dictionaryLists: Mapping[str, list[小于
277
266
 
278
267
  Returns
279
268
  -------
280
- ePluribusUnum : dict[str, list[Any]]
269
+ ePluribusUnum : dict[文件, list[Any]]
281
270
  A single dictionary with merged and optionally "polished" `list` values.
282
271
 
283
272
  Notes
284
273
  -----
285
- The returned value, `ePluribusUnum`, is a so-called primitive dictionary (`dict`). Furthermore,
286
- every dictionary key is a so-called primitive string (*cf.* `str()`) and every dictionary value
287
- is a so-called primitive `list` (`list`). If `dictionaryLists` has other data types, the data
288
- types will not be preserved. That could have unexpected consequences. Conversion from the
289
- original data type to a `list`, for example, may not preserve the order even if you want the
290
- order to be preserved.
274
+ The returned value, `ePluribusUnum`, is a dictionary (`dict`). Furthermore, every dictionary value
275
+ is a `list`. If `dictionaryLists` has values that are not data type `list`, the data type will not
276
+ be preserved. That could have unexpected consequences. Conversion from the original data type to a
277
+ `list`, for example, may not preserve the order even if you want the order to be preserved.
291
278
  """ # noqa: DOC501
292
- ePluribusUnum: dict[str, list[小于]] = {}
279
+ ePluribusUnum: dict[文件, list[小于]] = {}
293
280
 
294
281
  for dictionaryListTarget in dictionaryLists:
295
282
  for keyName, keyValue in dictionaryListTarget.items():
296
283
  try:
297
- ImaStr = str(keyName)
298
284
  ImaList: list[小于] = list(keyValue)
299
- ePluribusUnum.setdefault(ImaStr, []).extend(ImaList)
300
- except TypeError: # noqa: PERF203
285
+ ePluribusUnum.setdefault(keyName, []).extend(ImaList)
286
+ except TypeError as error: # noqa: PERF203
301
287
  if killErroneousDataTypes:
302
288
  continue
303
- else:
304
- raise
289
+ raise TypeError from error
305
290
 
306
291
  if destroyDuplicates:
307
- for ImaStr, ImaList in ePluribusUnum.items():
308
- ePluribusUnum[ImaStr] = list(dict.fromkeys(ImaList))
292
+ ePluribusUnum = valmap(compose(list, dict.fromkeys), ePluribusUnum)
309
293
  if reorderLists:
310
- for ImaStr, ImaRichComparisonSupporter in ePluribusUnum.items():
311
- ePluribusUnum[ImaStr] = sorted(ImaRichComparisonSupporter)
294
+ ePluribusUnum = valmap(sorted, ePluribusUnum)
312
295
 
313
296
  return ePluribusUnum
@@ -2,64 +2,65 @@
2
2
 
3
3
  (AI generated docstring)
4
4
 
5
- You can use this module to import `identifier` values from logical module paths or Python
6
- files, create parent directories for output paths, and write text or formatted Python
7
- source to files and text streams. The writing functions can normalize Python imports with
8
- `autoflake` [1] and `isort` [2] before the destination receives the final text.
5
+ You can use this module to import `identifier` values from logical module paths or Python files,
6
+ create parent directories for output paths, and write text or formatted Python source to files and
7
+ text streams. The writing functions can normalize Python imports with `autoflake` [1] and `isort` [2]
8
+ before the destination receives the final text.
9
9
 
10
10
  Contents
11
11
  --------
12
12
  Functions
13
- importLogicalPath2Identifier
14
- Import `identifier` from the module named by `logicalPathModule`.
15
- importPathFilename2Identifier
16
- Import `identifier` from the Python file at `pathFilename`.
17
- makeDirectorySafely
18
- Create parent directories for `pathFilename` when `pathFilename` is a filesystem path.
19
- makeDirsSafely
20
- Temporary alias for `makeDirectorySafely`.
21
- writePython
22
- Format `pythonSource` and write `pythonSource` to `pathFilename`.
23
- writeStringToHere
24
- Write `this` to `pathFilename`.
13
+ importLogicalPath2Identifier
14
+ Import `identifier` from the module named by `logicalPathModule`.
15
+ importPathFilename2Identifier
16
+ Import `identifier` from the Python file at `pathFilename`.
17
+ makeDirectorySafely
18
+ Create parent directories for `pathFilename` when `pathFilename` is a filesystem path.
19
+ makeDirsSafely
20
+ Temporary alias for `makeDirectorySafely`.
21
+ writePython
22
+ Format `pythonSource` and write `pythonSource` to `pathFilename`.
23
+ writeStringToHere
24
+ Write `this` to `pathFilename`.
25
25
 
26
26
  Variables
27
27
  ---------
28
- settings_autoflakeDEFAULT
29
- Default settings dictionary for Python source cleanup.
30
- settings_isortDEFAULT
31
- Default settings dictionary for Python import sorting.
28
+ settings_autoflakeDEFAULT
29
+ Default settings dictionary for Python source cleanup.
30
+ settings_isortDEFAULT
31
+ Default settings dictionary for Python import sorting.
32
32
 
33
33
  References
34
34
  ----------
35
35
  [1] autoflake
36
- https://github.com/PyCQA/autoflake
36
+ https://github.com/PyCQA/autoflake
37
37
  [2] isort
38
- https://pycqa.github.io/isort/
38
+ https://pycqa.github.io/isort/
39
39
  """
40
40
  from __future__ import annotations
41
41
 
42
42
  from autoflake import fix_code as autoflake_fix_code
43
+ from io import IOBase, TextIOBase
43
44
  from isort import code as isort_code
44
45
  from pathlib import Path, PurePath
45
- from typing import Any, overload, TYPE_CHECKING
46
+ from typing import overload, TYPE_CHECKING
46
47
  import contextlib
47
48
  import importlib
48
49
  import importlib.util
49
- import io
50
50
 
51
51
  if TYPE_CHECKING:
52
52
  from hunterMakesPy import identifierDotAttribute
53
53
  from importlib.machinery import ModuleSpec
54
54
  from os import PathLike
55
55
  from types import ModuleType
56
+ from typing import Any
56
57
 
57
58
  def importLogicalPath2Identifier(logicalPathModule: identifierDotAttribute, identifier: str, packageIdentifierIfRelative: str | None = None) -> Any:
58
59
  """Import `identifier` from the module named by `logicalPathModule`.
59
60
 
60
- You can use this function to resolve a function, class, or other attribute from a module
61
- path string. This function imports `logicalPathModule` with `importlib.import_module` [1]
62
- and returns the attribute selected by `identifier`.
61
+ You can use this function to resolve a function, class, or other attribute from a module path
62
+ string. This function imports `logicalPathModule` with `importlib.import_module` [1] and returns
63
+ the attribute selected by `identifier`.
63
64
 
64
65
  Parameters
65
66
  ----------
@@ -83,8 +84,8 @@ def importLogicalPath2Identifier(logicalPathModule: identifierDotAttribute, iden
83
84
  def importPathFilename2Identifier(pathFilename: PathLike[Any] | PurePath, identifier: str, moduleIdentifier: str | None = None) -> Any:
84
85
  """Import `identifier` from the Python file at `pathFilename`.
85
86
 
86
- You can use this function to load a Python source file as a module and retrieve a named
87
- attribute from that module. This function builds a module specification with
87
+ You can use this function to load a Python source file as a module and retrieve a named attribute
88
+ from that module. This function builds a module specification with
88
89
  `importlib.util.spec_from_file_location` [1], executes the loaded module with
89
90
  `importlib.util.module_from_spec` [2], and returns the attribute selected by `identifier`.
90
91
 
@@ -134,79 +135,78 @@ def makeDirectorySafely(pathFilename: Any) -> None:
134
135
 
135
136
  You can use this function to prepare an output location before a later write operation. This
136
137
  function ignores `OSError` from `Path.mkdir` [1] and does nothing when `pathFilename` is an
137
- `io.IOBase` [2] stream.
138
+ `IOBase` [2] stream.
138
139
 
139
140
  Parameters
140
141
  ----------
141
142
  pathFilename : Any
142
- The target path or open stream. When `pathFilename` is not an `io.IOBase` instance, the
143
+ The target path or open stream. When `pathFilename` is not an `IOBase` instance, the
143
144
  function creates the parent directory of `pathFilename`.
144
145
 
145
146
  References
146
147
  ----------
147
148
  [1] `pathlib.Path.mkdir`
148
149
  https://docs.python.org/3/library/pathlib.html#pathlib.Path.mkdir
149
- [2] `io.IOBase`
150
+ [2] `IOBase`
150
151
  https://docs.python.org/3/library/io.html#io.IOBase
151
152
  """
152
- if not isinstance(pathFilename, io.IOBase):
153
+ if not isinstance(pathFilename, IOBase):
153
154
  with contextlib.suppress(OSError):
154
155
  Path(pathFilename).parent.mkdir(parents=True, exist_ok=True)
155
156
  makeDirsSafely = makeDirectorySafely
156
157
  """Alias for `makeDirectorySafely`."""
157
158
 
158
159
  settings_autoflakeDEFAULT: dict[str, list[str] | bool] = {
159
- 'additional_imports': [],
160
- 'expand_star_imports': True,
161
- 'remove_all_unused_imports': True,
162
- 'remove_duplicate_keys': False,
163
- 'remove_unused_variables': False,
160
+ 'additional_imports': []
161
+ , 'expand_star_imports': True
162
+ , 'remove_all_unused_imports': True
163
+ , 'remove_duplicate_keys': False
164
+ , 'remove_unused_variables': False
164
165
  }
165
166
  """Default settings dictionary for Python source cleanup."""
166
167
 
167
168
  settings_isortDEFAULT: dict[str, bool | int | str | list[str]] = {
168
- "combine_as_imports": True,
169
- "force_alphabetical_sort_within_sections": True,
170
- "from_first": True,
171
- "honor_noqa": True,
172
- "indent": "\t",
173
- "line_length": 140,
174
- "lines_after_imports": 1,
175
- "lines_between_types": 0,
176
- "multi_line_output": 4,
177
- "no_sections": True,
178
- "use_parentheses": True,
169
+ "combine_as_imports": True
170
+ , "force_alphabetical_sort_within_sections": True
171
+ , "from_first": True
172
+ , "honor_noqa": True
173
+ , "indent": "\t"
174
+ , "line_length": 140
175
+ , "lines_after_imports": 1
176
+ , "lines_between_types": 0
177
+ , "multi_line_output": 4
178
+ , "no_sections": True
179
+ , "use_parentheses": True
179
180
  }
180
181
  """Default settings dictionary for Python import sorting."""
181
182
 
182
183
  @overload
183
184
  def writePython(pythonSource: str, pathFilename: PathLike[Any] | PurePath, settings: dict[str, dict[str, Any]] | None = None) -> Path: ...
184
185
  @overload
185
- def writePython(pythonSource: str, pathFilename: io.TextIOBase, settings: dict[str, dict[str, Any]] | None = None) -> io.TextIOBase: ...
186
- def writePython(pythonSource: str, pathFilename: PathLike[Any] | PurePath | io.TextIOBase, settings: dict[str, dict[str, Any]] | None = None) -> Path | io.TextIOBase:
186
+ def writePython(pythonSource: str, pathFilename: TextIOBase, settings: dict[str, dict[str, Any]] | None = None) -> TextIOBase: ...
187
+ def writePython(pythonSource: str, pathFilename: PathLike[Any] | PurePath | TextIOBase, settings: dict[str, dict[str, Any]] | None = None) -> Path | TextIOBase:
187
188
  """Format and write Python source code to a file or text stream.
188
189
 
189
190
  (AI generated docstring)
190
191
 
191
- You can use this function to normalize Python imports and then send the resulting source
192
- code to a file path or open text stream. This function applies `autoflake` [1] first,
193
- applies `isort` [2] second, appends a trailing newline, and writes the final text to
194
- `pathFilename`.
192
+ You can use this function to normalize Python imports and then send the resulting source code to a
193
+ file path or open text stream. This function applies `autoflake` [1] first, applies `isort` [2]
194
+ second, appends a trailing newline, and writes the final text to `pathFilename`.
195
195
 
196
196
  Parameters
197
197
  ----------
198
198
  pythonSource : str
199
199
  The Python source code to format and write.
200
- pathFilename : PathLike[Any] | PurePath | io.TextIOBase
200
+ pathFilename : PathLike[Any] | PurePath | TextIOBase
201
201
  The target destination. `pathFilename` can be a filesystem path or an open text stream.
202
202
  settings : dict[str, dict[str, Any]] | None = None
203
- Formatter configuration. The `'autoflake'` key overrides `settings_autoflakeDEFAULT`.
204
- The `'isort'` key overrides `settings_isortDEFAULT`. `None` uses the default settings for
205
- each formatter.
203
+ Formatter configuration. The `'autoflake'` key overrides `settings_autoflakeDEFAULT`. The
204
+ `'isort'` key overrides `settings_isortDEFAULT`. `None` uses the default settings for each
205
+ formatter.
206
206
 
207
207
  Returns
208
208
  -------
209
- destinationWritten : Path | io.TextIOBase
209
+ destinationWritten : Path | TextIOBase
210
210
  The file path or text stream that received the formatted source code.
211
211
 
212
212
  See Also
@@ -235,26 +235,24 @@ def writePython(pythonSource: str, pathFilename: PathLike[Any] | PurePath | io.T
235
235
  @overload
236
236
  def writeStringToHere(this: str, pathFilename: PathLike[Any] | PurePath) -> Path: ...
237
237
  @overload
238
- def writeStringToHere(this: str, pathFilename: io.TextIOBase) -> io.TextIOBase: ...
239
- def writeStringToHere(this: str, pathFilename: PathLike[Any] | PurePath | io.TextIOBase) -> Path | io.TextIOBase:
238
+ def writeStringToHere(this: str, pathFilename: TextIOBase) -> TextIOBase: ...
239
+ def writeStringToHere(this: str, pathFilename: PathLike[Any] | PurePath | TextIOBase) -> Path | TextIOBase:
240
240
  """Write `this` to `pathFilename`.
241
241
 
242
- You can use this function to send text to a filesystem path or an open text stream. This
243
- function creates the parent directory when `pathFilename` is path-like, writes UTF-8 text
244
- with `Path.write_text` [1], or writes and flushes an `io.TextIOBase` [2] stream. The
245
- package-assimilation code in `hunterMakesPy.assimilate.chopShop.transformPackages` [3] uses
246
- this function to persist transformed source files.
242
+ You can use this function to send text to a filesystem path or an open text stream. This function
243
+ creates the parent directory when `pathFilename` is path-like, writes UTF-8 text with
244
+ `Path.write_text` [1], or writes and flushes a `TextIOBase` [2] stream.
247
245
 
248
246
  Parameters
249
247
  ----------
250
248
  this : str
251
249
  The string content to write.
252
- pathFilename : PathLike[Any] | PurePath | io.TextIOBase
250
+ pathFilename : PathLike[Any] | PurePath | TextIOBase
253
251
  The target destination. `pathFilename` can be a filesystem path or an open text stream.
254
252
 
255
253
  Returns
256
254
  -------
257
- destinationWritten : Path | io.TextIOBase
255
+ destinationWritten : Path | TextIOBase
258
256
  The file path or text stream that received `this`.
259
257
 
260
258
  See Also
@@ -266,12 +264,11 @@ def writeStringToHere(this: str, pathFilename: PathLike[Any] | PurePath | io.Tex
266
264
  --------
267
265
  The package-assimilation code writes transformed source text to a destination package path.
268
266
 
269
- ```python
270
- from hunterMakesPy.filesystemToolkit import writeStringToHere
267
+ ```python from hunterMakesPy.filesystemToolkit import writeStringToHere
271
268
 
272
269
  writeStringToHere(
273
- regexChangeImports(pathFilename.read_text()),
274
- settingsFor[humpyPackage].pathPackage / pathFilename.relative_to(pathTransformee),
270
+ regexChangeImports(pathFilename.read_text()), settingsFor[humpyPackage].pathPackage /
271
+ pathFilename.relative_to(pathTransformee)
275
272
  )
276
273
  ```
277
274
 
@@ -279,11 +276,10 @@ def writeStringToHere(this: str, pathFilename: PathLike[Any] | PurePath | io.Tex
279
276
  ----------
280
277
  [1] `pathlib.Path.write_text`
281
278
  https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_text
282
- [2] `io.TextIOBase`
279
+ [2] `TextIOBase`
283
280
  https://docs.python.org/3/library/io.html#io.TextIOBase
284
- [3] `hunterMakesPy.assimilate.chopShop.transformPackages`
285
281
  """
286
- if isinstance(pathFilename, io.TextIOBase):
282
+ if isinstance(pathFilename, TextIOBase):
287
283
  pathFilename.write(str(this))
288
284
  pathFilename.flush()
289
285
  else:
@@ -37,12 +37,14 @@ from __future__ import annotations
37
37
 
38
38
  from collections.abc import Iterable, Sized
39
39
  from dataclasses import dataclass
40
- from typing import Any, TYPE_CHECKING
40
+ from typing import TYPE_CHECKING
41
41
  import charset_normalizer
42
42
  import multiprocessing
43
+ import sys
43
44
 
44
45
  if TYPE_CHECKING:
45
46
  from charset_normalizer.models import CharsetMatch
47
+ from typing import Any
46
48
 
47
49
  @dataclass
48
50
  class ErrorMessageContext:
@@ -114,13 +116,6 @@ def _constructErrorMessage(context: ErrorMessageContext, parameterName: str, par
114
116
 
115
117
  return "".join(messageParts)
116
118
 
117
- # TODO Should I change the function because "On Windows, max_workers must be less than or equal to 61."?
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
-
124
119
  def defineConcurrencyLimit(*, limit: bool | float | int | None, cpuTotal: int = multiprocessing.cpu_count()) -> int:
125
120
  """Determine the concurrency limit based on the provided parameter.
126
121
 
@@ -177,8 +172,6 @@ def defineConcurrencyLimit(*, limit: bool | float | int | None, cpuTotal: int =
177
172
  ```
178
173
 
179
174
  """ # noqa: DOC501
180
- concurrencyLimit: int = cpuTotal
181
-
182
175
  if isinstance(limit, str):
183
176
  limitFromString: bool | str | None = oopsieKwargsie(limit)
184
177
  if isinstance(limitFromString, str):
@@ -191,7 +184,9 @@ def defineConcurrencyLimit(*, limit: bool | float | int | None, cpuTotal: int =
191
184
  limit = limitFromString
192
185
  if isinstance(limit, float) and 1 <= abs(limit):
193
186
  limit = round(limit)
194
- if limit is None or limit is False or limit == 0:
187
+
188
+ concurrencyLimit: int = cpuTotal
189
+ if (limit is None) or (limit is False) or (limit == 0):
195
190
  pass
196
191
  elif limit is True:
197
192
  concurrencyLimit = 1
@@ -204,6 +199,9 @@ def defineConcurrencyLimit(*, limit: bool | float | int | None, cpuTotal: int =
204
199
  elif limit <= -1:
205
200
  concurrencyLimit = cpuTotal - abs(int(limit))
206
201
 
202
+ # https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor
203
+ if sys.platform == "win32":
204
+ concurrencyLimit = min(concurrencyLimit, 61)
207
205
  return max(int(concurrencyLimit), 1)
208
206
 
209
207
  # ruff: noqa: TRY301
@@ -108,7 +108,6 @@ def test_stringItUp(description: str, value_scrapPile: list[Any], expected: list
108
108
  ("Set values", ({'ne': {11, 13}, 'sw': {17}}, {'ne': {19, 23, 13, 29, 11}, 'sw': {31, 17, 37}}), {'destroyDuplicates': True, 'reorderLists': True}, {'ne': [11, 13, 19, 23, 29], 'sw': [17, 31, 37]}),
109
109
  ("NumPy arrays", ({'ne': numpy.array([11, 13]), 'sw': numpy.array([17])}, {'ne': numpy.array([19, 23, 13, 29, 11]), 'sw': numpy.array([31, 17, 37])}), {'destroyDuplicates': False, 'reorderLists': False}, {'ne': [11, 13, 19, 23, 13, 29, 11], 'sw': [17, 31, 17, 37]}),
110
110
  ("Destroy duplicates", ({'fr': [11, 13], 'jp': [17]}, {'fr': [19, 23, 13, 29, 11], 'jp': [31, 17, 37]}), {'destroyDuplicates': True, 'reorderLists': False}, {'fr': [11, 13, 19, 23, 29], 'jp': [17, 31, 37]}),
111
- ("Non-string keys", ({None: [13], True: [17]}, {19: [23], (29, 31): [37]}), {'destroyDuplicates': False, 'reorderLists': False}, {'None': [13], 'True': [17], '19': [23], '(29, 31)': [37]}),
112
111
  ("Reorder lists", ({'fr': [11, 13], 'jp': [17]}, {'fr': [19, 23, 13, 29, 11], 'jp': [31, 17, 37]}), {'destroyDuplicates': False, 'reorderLists': True}, {'fr': [11, 11, 13, 13, 19, 23, 29], 'jp': [17, 17, 31, 37]}),
113
112
  ("Non-iterable values", ({'ne': 13, 'sw': 17}, {'ne': 19, 'nw': 23}), {'destroyDuplicates': False, 'reorderLists': False}, TypeError),
114
113
  ("Skip erroneous types", ({'ne': [11, 13], 'sw': [17, 19]}, {'ne': 23, 'nw': 29}), {'killErroneousDataTypes': True}, {'ne': [11, 13], 'sw': [17, 19]}),
@@ -2,12 +2,13 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  from collections.abc import Callable
5
- from typing import Any, overload, ParamSpec, Protocol, runtime_checkable, TYPE_CHECKING, TypeAlias, TypeVar
6
- from typing_extensions import Self, TypeVarTuple
5
+ from typing import Any, overload, ParamSpec, Protocol, runtime_checkable, TYPE_CHECKING, TypeVar
7
6
  import sys
8
7
 
9
8
  if TYPE_CHECKING:
10
9
  from types import CodeType, MethodType
10
+ from typing import TypeAlias
11
+ from typing_extensions import Self, TypeVarTuple
11
12
 
12
13
  # TODO explore the following
13
14
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hunterMakesPy
3
- Version: 0.7.0
3
+ Version: 0.7.2
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,13 +9,11 @@ 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,configuration,defensive programming,dictionary merging,dynamic import,file system utilities,input validation,module loading,package settings,parameter validation
12
+ Keywords: 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
16
16
  Classifier: Intended Audience :: Developers
17
- Classifier: Intended Audience :: End Users/Desktop
18
- Classifier: Intended Audience :: Other Audience
19
17
  Classifier: Natural Language :: English
20
18
  Classifier: Operating System :: OS Independent
21
19
  Classifier: Programming Language :: Python
@@ -27,6 +25,7 @@ Classifier: Typing :: Typed
27
25
  Requires-Python: >=3.10
28
26
  Description-Content-Type: text/markdown
29
27
  License-File: LICENSE
28
+ Requires-Dist: Z0Z_tools>=2.2.1
30
29
  Requires-Dist: autoflake
31
30
  Requires-Dist: charset_normalizer
32
31
  Requires-Dist: isort
@@ -1,3 +1,4 @@
1
+ Z0Z_tools>=2.2.1
1
2
  autoflake
2
3
  charset_normalizer
3
4
  isort
@@ -1,18 +1,12 @@
1
1
  [project]
2
2
  name = "hunterMakesPy"
3
- version = "0.7.0"
3
+ version = "0.7.2"
4
4
  description = "Easy Python functions making making functional Python functions easier."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
7
7
  license = "CC-BY-NC-4.0"
8
8
  authors = [{ name = "Hunter Hogan", email = "HunterHogan@pm.me" }]
9
9
  keywords = [
10
- "attribute loading",
11
- "configuration",
12
- "defensive programming",
13
- "dictionary merging",
14
- "dynamic import",
15
- "file system utilities",
16
10
  "input validation",
17
11
  "module loading",
18
12
  "package settings",
@@ -23,8 +17,6 @@ classifiers = [
23
17
  "Environment :: Console",
24
18
  "Framework :: Pytest",
25
19
  "Intended Audience :: Developers",
26
- "Intended Audience :: End Users/Desktop",
27
- "Intended Audience :: Other Audience",
28
20
  "Natural Language :: English",
29
21
  "Operating System :: OS Independent",
30
22
  "Programming Language :: Python",
@@ -35,6 +27,7 @@ classifiers = [
35
27
  "Typing :: Typed",
36
28
  ]
37
29
  dependencies = [
30
+ "Z0Z_tools>=2.2.1",
38
31
  "autoflake",
39
32
  "charset_normalizer",
40
33
  "isort",
@@ -45,7 +38,7 @@ dependencies = [
45
38
  ]
46
39
  optional-dependencies = { development = ["pytest-cov"], testing = [
47
40
  "librosa",
48
- "pytest",
41
+ "pytest"
49
42
  ] }
50
43
 
51
44
  [project.urls]
@@ -66,7 +59,7 @@ run = { branch = true, data_file = "hunterMakesPy/tests/coverage/.coverage", omi
66
59
  ], source = ["."] }
67
60
 
68
61
  [tool.pytest]
69
- addopts = ["--color=auto"]
62
+ addopts = ["--color=yes"]
70
63
  log_auto_indent = "On"
71
64
  testpaths = ["hunterMakesPy/tests"]
72
65
 
File without changes
File without changes
File without changes