knickknacks 0.5.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.
- knickknacks-0.5.0/LICENSE.txt +21 -0
- knickknacks-0.5.0/PKG-INFO +61 -0
- knickknacks-0.5.0/README.md +21 -0
- knickknacks-0.5.0/pyproject.toml +291 -0
- knickknacks-0.5.0/src/knickknacks/__init__.py +37 -0
- knickknacks-0.5.0/src/knickknacks/_version.py +1 -0
- knickknacks-0.5.0/src/knickknacks/backports.py +91 -0
- knickknacks-0.5.0/src/knickknacks/databytes.py +187 -0
- knickknacks-0.5.0/src/knickknacks/iterables.py +101 -0
- knickknacks-0.5.0/src/knickknacks/numbers.py +80 -0
- knickknacks-0.5.0/src/knickknacks/platforms.py +80 -0
- knickknacks-0.5.0/src/knickknacks/py.typed +0 -0
- knickknacks-0.5.0/src/knickknacks/strings.py +242 -0
- knickknacks-0.5.0/src/knickknacks/testing.py +56 -0
- knickknacks-0.5.0/src/knickknacks/typedef.py +73 -0
- knickknacks-0.5.0/src/knickknacks/utils.py +87 -0
- knickknacks-0.5.0/src/knickknacks/xml.py +115 -0
- knickknacks-0.5.0/tests/__init__.py +0 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/.gitignore +2 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/@plugins_snapshot.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/__future__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/__future__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_ast.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_ast.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_codecs.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_codecs.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_collections_abc.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_collections_abc.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_thread.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_thread.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_typeshed/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_typeshed/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_warnings.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_warnings.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_winapi.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/_winapi.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/abc.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/abc.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/builtins.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/builtins.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/codecs.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/codecs.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/collections/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/collections/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/collections/abc.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/collections/abc.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/contextlib.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/contextlib.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/dataclasses.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/dataclasses.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/charset.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/charset.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/contentmanager.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/contentmanager.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/errors.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/errors.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/header.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/header.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/message.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/message.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/policy.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/email/policy.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/enum.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/enum.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/genericpath.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/genericpath.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/abc.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/abc.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/machinery.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/machinery.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/metadata/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/metadata/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/metadata/_meta.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/metadata/_meta.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/readers.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/readers.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/resources/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/resources/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/resources/abc.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/importlib/resources/abc.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/io.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/io.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/logging/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/logging/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/ntpath.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/ntpath.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/os/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/os/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/os/path.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/os/path.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/pathlib.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/pathlib.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/posixpath.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/posixpath.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/re.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/re.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sre_compile.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sre_compile.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sre_constants.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sre_constants.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sre_parse.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sre_parse.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/string.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/string.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/subprocess.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/subprocess.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sys/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sys/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sys/_monitoring.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/sys/_monitoring.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/tests/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/tests/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/tests/knickknacks/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/tests/knickknacks/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/textwrap.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/textwrap.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/threading.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/threading.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/time.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/time.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/types.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/types.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/typing.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/typing.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/typing_extensions.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/typing_extensions.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/__init__.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/__init__.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/_log.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/_log.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/async_case.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/async_case.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/case.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/case.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/loader.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/loader.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/main.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/main.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/mock.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/mock.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/result.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/result.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/runner.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/runner.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/signals.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/signals.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/suite.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/unittest/suite.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/warnings.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/warnings.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/zipfile.data.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/3.12/zipfile.meta.json +1 -0
- knickknacks-0.5.0/tests/knickknacks/.mypy_cache/CACHEDIR.TAG +3 -0
- knickknacks-0.5.0/tests/knickknacks/__init__.py +0 -0
- knickknacks-0.5.0/tests/knickknacks/test_databytes.py +49 -0
- knickknacks-0.5.0/tests/knickknacks/test_iterables.py +68 -0
- knickknacks-0.5.0/tests/knickknacks/test_numbers.py +46 -0
- knickknacks-0.5.0/tests/knickknacks/test_platforms.py +74 -0
- knickknacks-0.5.0/tests/knickknacks/test_strings.py +124 -0
- knickknacks-0.5.0/tests/knickknacks/test_testing.py +55 -0
- knickknacks-0.5.0/tests/knickknacks/test_utils.py +70 -0
- knickknacks-0.5.0/tests/knickknacks/test_xml.py +46 -0
- knickknacks-0.5.0/uv.lock +752 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Nick Stockton
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: knickknacks
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Small, reusable, miscellaneous pieces of code.
|
|
5
|
+
Keywords: utilities,misc,snippets,reusable
|
|
6
|
+
Author-Email: Nick Stockton <nstockton@users.noreply.github.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: Implementation
|
|
20
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
21
|
+
Classifier: Operating System :: MacOS
|
|
22
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
23
|
+
Classifier: Operating System :: Microsoft
|
|
24
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
25
|
+
Classifier: Operating System :: OS Independent
|
|
26
|
+
Classifier: Operating System :: POSIX
|
|
27
|
+
Classifier: Operating System :: POSIX :: BSD
|
|
28
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
29
|
+
Classifier: Operating System :: Unix
|
|
30
|
+
Classifier: Topic :: Software Development
|
|
31
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
32
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
33
|
+
Project-URL: homepage, https://github.com/nstockton/knickknacks
|
|
34
|
+
Project-URL: repository, https://github.com/nstockton/knickknacks
|
|
35
|
+
Project-URL: documentation, https://nstockton.github.io/knickknacks
|
|
36
|
+
Requires-Python: <4.0,>=3.9
|
|
37
|
+
Requires-Dist: backports-strenum<2.0,>=1.3; python_version < "3.11"
|
|
38
|
+
Requires-Dist: typing-extensions<5.0,>=4.8; python_version < "3.12"
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# Knickknacks
|
|
42
|
+
|
|
43
|
+
Small, reusable, miscellaneous pieces of code.
|
|
44
|
+
|
|
45
|
+
## License And Credits
|
|
46
|
+
|
|
47
|
+
Knickknacks is licensed under the terms of the [MIT License.](https://raw.githubusercontent.com/nstockton/knickknacks/master/LICENSE.txt "Knickknacks License")
|
|
48
|
+
|
|
49
|
+
### Running From Source
|
|
50
|
+
|
|
51
|
+
Install the [Python interpreter,](https://python.org "Python Home Page") and make sure it's in your path before running this package.
|
|
52
|
+
|
|
53
|
+
After Python is installed, execute the following commands from the top level directory of this repository to install the module dependencies.
|
|
54
|
+
```
|
|
55
|
+
python -m venv .venv
|
|
56
|
+
source .venv/bin/activate
|
|
57
|
+
pip install --upgrade --require-hashes --requirement requirements-uv.txt
|
|
58
|
+
uv sync
|
|
59
|
+
pre-commit install -t pre-commit
|
|
60
|
+
pre-commit install -t pre-push
|
|
61
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Knickknacks
|
|
2
|
+
|
|
3
|
+
Small, reusable, miscellaneous pieces of code.
|
|
4
|
+
|
|
5
|
+
## License And Credits
|
|
6
|
+
|
|
7
|
+
Knickknacks is licensed under the terms of the [MIT License.](https://raw.githubusercontent.com/nstockton/knickknacks/master/LICENSE.txt "Knickknacks License")
|
|
8
|
+
|
|
9
|
+
### Running From Source
|
|
10
|
+
|
|
11
|
+
Install the [Python interpreter,](https://python.org "Python Home Page") and make sure it's in your path before running this package.
|
|
12
|
+
|
|
13
|
+
After Python is installed, execute the following commands from the top level directory of this repository to install the module dependencies.
|
|
14
|
+
```
|
|
15
|
+
python -m venv .venv
|
|
16
|
+
source .venv/bin/activate
|
|
17
|
+
pip install --upgrade --require-hashes --requirement requirements-uv.txt
|
|
18
|
+
uv sync
|
|
19
|
+
pre-commit install -t pre-commit
|
|
20
|
+
pre-commit install -t pre-push
|
|
21
|
+
```
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"pdm-backend",
|
|
4
|
+
]
|
|
5
|
+
build-backend = "pdm.backend"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "knickknacks"
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Nick Stockton", email = "nstockton@users.noreply.github.com" },
|
|
11
|
+
]
|
|
12
|
+
description = "Small, reusable, miscellaneous pieces of code."
|
|
13
|
+
readme = "README.md"
|
|
14
|
+
requires-python = ">=3.9,<4.0"
|
|
15
|
+
dependencies = [
|
|
16
|
+
"backports-strenum>=1.3,<2.0; python_version < \"3.11\"",
|
|
17
|
+
"typing-extensions>=4.8,<5.0; python_version < \"3.12\"",
|
|
18
|
+
]
|
|
19
|
+
dynamic = []
|
|
20
|
+
keywords = [
|
|
21
|
+
"utilities",
|
|
22
|
+
"misc",
|
|
23
|
+
"snippets",
|
|
24
|
+
"reusable",
|
|
25
|
+
]
|
|
26
|
+
classifiers = [
|
|
27
|
+
"Development Status :: 5 - Production/Stable",
|
|
28
|
+
"Intended Audience :: Developers",
|
|
29
|
+
"License :: OSI Approved :: MIT License",
|
|
30
|
+
"Programming Language :: Python",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
33
|
+
"Programming Language :: Python :: 3.9",
|
|
34
|
+
"Programming Language :: Python :: 3.10",
|
|
35
|
+
"Programming Language :: Python :: 3.11",
|
|
36
|
+
"Programming Language :: Python :: 3.12",
|
|
37
|
+
"Programming Language :: Python :: 3.13",
|
|
38
|
+
"Programming Language :: Python :: Implementation",
|
|
39
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
40
|
+
"Operating System :: MacOS",
|
|
41
|
+
"Operating System :: MacOS :: MacOS X",
|
|
42
|
+
"Operating System :: Microsoft",
|
|
43
|
+
"Operating System :: Microsoft :: Windows",
|
|
44
|
+
"Operating System :: OS Independent",
|
|
45
|
+
"Operating System :: POSIX",
|
|
46
|
+
"Operating System :: POSIX :: BSD",
|
|
47
|
+
"Operating System :: POSIX :: Linux",
|
|
48
|
+
"Operating System :: Unix",
|
|
49
|
+
"Topic :: Software Development",
|
|
50
|
+
"Topic :: Software Development :: Libraries",
|
|
51
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
52
|
+
]
|
|
53
|
+
version = "0.5.0"
|
|
54
|
+
|
|
55
|
+
[project.license]
|
|
56
|
+
text = "MIT"
|
|
57
|
+
|
|
58
|
+
[project.urls]
|
|
59
|
+
homepage = "https://github.com/nstockton/knickknacks"
|
|
60
|
+
repository = "https://github.com/nstockton/knickknacks"
|
|
61
|
+
documentation = "https://nstockton.github.io/knickknacks"
|
|
62
|
+
|
|
63
|
+
[dependency-groups]
|
|
64
|
+
dev = [
|
|
65
|
+
"pre-commit>=3.5,<4.0",
|
|
66
|
+
]
|
|
67
|
+
docs = [
|
|
68
|
+
"jinja2==3.0.3",
|
|
69
|
+
"mkdocs==1.2.3",
|
|
70
|
+
"mkdocs-autorefs==0.3.1",
|
|
71
|
+
"mkdocs-material==8.1.3",
|
|
72
|
+
"mkdocs-material-extensions==1.0.3",
|
|
73
|
+
"mkdocstrings==0.17.0",
|
|
74
|
+
"pytkdocs @ git+https://github.com/nstockton/pytkdocs.git@9991d493b408c403ac5691074e2af2e509f22926",
|
|
75
|
+
]
|
|
76
|
+
lint = [
|
|
77
|
+
"isort>=5.13,<6.0",
|
|
78
|
+
"mypy>=1.14,<2.0",
|
|
79
|
+
"ruff>=0.9,<1.0",
|
|
80
|
+
]
|
|
81
|
+
test = [
|
|
82
|
+
"coverage[toml]>=7.6,<8.0",
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
[tool.pdm.build]
|
|
86
|
+
package-dir = "src"
|
|
87
|
+
includes = [
|
|
88
|
+
"src/knickknacks",
|
|
89
|
+
]
|
|
90
|
+
excludes = []
|
|
91
|
+
source-includes = [
|
|
92
|
+
"tests",
|
|
93
|
+
"uv.lock",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.pdm.version]
|
|
97
|
+
fallback_version = "0.0.0"
|
|
98
|
+
source = "scm"
|
|
99
|
+
tag_filter = "[vV][0-9]*"
|
|
100
|
+
tag_regex = "^(?:[vV])(?P<version>\\d+\\.\\d+\\.\\d+)(?:.*)$"
|
|
101
|
+
write_to = "knickknacks/_version.py"
|
|
102
|
+
write_template = "__version__: str = \"{}\"\r\n"
|
|
103
|
+
|
|
104
|
+
[tool.uv]
|
|
105
|
+
default-groups = [
|
|
106
|
+
"dev",
|
|
107
|
+
"docs",
|
|
108
|
+
"lint",
|
|
109
|
+
"test",
|
|
110
|
+
]
|
|
111
|
+
upgrade-package = [
|
|
112
|
+
"knickknacks",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
[tool.ruff]
|
|
116
|
+
extend-include = [
|
|
117
|
+
"*.pyw",
|
|
118
|
+
]
|
|
119
|
+
force-exclude = true
|
|
120
|
+
line-length = 110
|
|
121
|
+
|
|
122
|
+
[tool.ruff.format]
|
|
123
|
+
docstring-code-format = false
|
|
124
|
+
indent-style = "tab"
|
|
125
|
+
line-ending = "cr-lf"
|
|
126
|
+
|
|
127
|
+
[tool.ruff.lint]
|
|
128
|
+
preview = true
|
|
129
|
+
select = [
|
|
130
|
+
"ALL",
|
|
131
|
+
]
|
|
132
|
+
extend-select = [
|
|
133
|
+
"D213",
|
|
134
|
+
]
|
|
135
|
+
ignore = [
|
|
136
|
+
"ANN",
|
|
137
|
+
"ARG",
|
|
138
|
+
"B019",
|
|
139
|
+
"COM812",
|
|
140
|
+
"D105",
|
|
141
|
+
"D206",
|
|
142
|
+
"D212",
|
|
143
|
+
"EM",
|
|
144
|
+
"G",
|
|
145
|
+
"I",
|
|
146
|
+
"PT",
|
|
147
|
+
"T20",
|
|
148
|
+
"TCH",
|
|
149
|
+
"TRY003",
|
|
150
|
+
"UP007",
|
|
151
|
+
"UP045",
|
|
152
|
+
"W191",
|
|
153
|
+
]
|
|
154
|
+
typing-modules = [
|
|
155
|
+
"knickknacks.typedef",
|
|
156
|
+
]
|
|
157
|
+
unfixable = []
|
|
158
|
+
|
|
159
|
+
[tool.ruff.lint.flake8-builtins]
|
|
160
|
+
builtins-ignorelist = []
|
|
161
|
+
|
|
162
|
+
[tool.ruff.lint.flake8-copyright]
|
|
163
|
+
author = "Nick Stockton"
|
|
164
|
+
min-file-size = 1
|
|
165
|
+
|
|
166
|
+
[tool.ruff.lint.flake8-implicit-str-concat]
|
|
167
|
+
allow-multiline = false
|
|
168
|
+
|
|
169
|
+
[tool.ruff.lint.mccabe]
|
|
170
|
+
max-complexity = 15
|
|
171
|
+
|
|
172
|
+
[tool.ruff.lint.per-file-ignores]
|
|
173
|
+
"**/__init__.py" = [
|
|
174
|
+
"D1",
|
|
175
|
+
]
|
|
176
|
+
"**/_version.py" = [
|
|
177
|
+
"CPY001",
|
|
178
|
+
]
|
|
179
|
+
"./tests/**" = [
|
|
180
|
+
"D1",
|
|
181
|
+
"PLR6301",
|
|
182
|
+
]
|
|
183
|
+
"**/typedef.py" = [
|
|
184
|
+
"F401",
|
|
185
|
+
]
|
|
186
|
+
"./src/knickknacks/backports.py" = [
|
|
187
|
+
"PLR2004",
|
|
188
|
+
]
|
|
189
|
+
"./src/knickknacks/numbers.py" = [
|
|
190
|
+
"A005",
|
|
191
|
+
]
|
|
192
|
+
"./src/knickknacks/testing.py" = [
|
|
193
|
+
"N802",
|
|
194
|
+
"N815",
|
|
195
|
+
]
|
|
196
|
+
"./src/knickknacks/xml.py" = [
|
|
197
|
+
"A005",
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
[tool.ruff.lint.pydocstyle]
|
|
201
|
+
convention = "google"
|
|
202
|
+
ignore-decorators = [
|
|
203
|
+
"typing.overload",
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
[tool.ruff.lint.ruff]
|
|
207
|
+
parenthesize-tuple-in-subscript = true
|
|
208
|
+
|
|
209
|
+
[tool.coverage.report]
|
|
210
|
+
precision = 0
|
|
211
|
+
fail_under = 100.0
|
|
212
|
+
show_missing = true
|
|
213
|
+
skip_covered = true
|
|
214
|
+
sort = "Cover"
|
|
215
|
+
exclude_lines = [
|
|
216
|
+
"\\#\\s*pragma: no cover",
|
|
217
|
+
"^\\s*raise AssertionError\\b",
|
|
218
|
+
"^\\s*raise NotImplementedError\\b",
|
|
219
|
+
"^\\s*def __repr__",
|
|
220
|
+
"^\\s*def __str__",
|
|
221
|
+
"^\\s*if __name__ == .__main__.:",
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
[tool.coverage.run]
|
|
225
|
+
source = [
|
|
226
|
+
"knickknacks",
|
|
227
|
+
]
|
|
228
|
+
omit = [
|
|
229
|
+
"src/knickknacks/backports.py",
|
|
230
|
+
"src/knickknacks/typedef.py",
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
[tool.isort]
|
|
234
|
+
line_length = 110
|
|
235
|
+
color_output = false
|
|
236
|
+
supported_extensions = [
|
|
237
|
+
"py",
|
|
238
|
+
"pyi",
|
|
239
|
+
"pys",
|
|
240
|
+
"pyw",
|
|
241
|
+
]
|
|
242
|
+
extend_skip = []
|
|
243
|
+
indent = "tab"
|
|
244
|
+
atomic = true
|
|
245
|
+
dedup_headings = true
|
|
246
|
+
multi_line_output = 3
|
|
247
|
+
include_trailing_comma = true
|
|
248
|
+
force_grid_wrap = 0
|
|
249
|
+
use_parentheses = true
|
|
250
|
+
ensure_newline_before_comments = true
|
|
251
|
+
indented_import_headings = false
|
|
252
|
+
float_to_top = true
|
|
253
|
+
lines_after_imports = 2
|
|
254
|
+
force_adds = false
|
|
255
|
+
from_first = false
|
|
256
|
+
combine_as_imports = false
|
|
257
|
+
order_by_type = true
|
|
258
|
+
reverse_relative = true
|
|
259
|
+
add_imports = [
|
|
260
|
+
"from __future__ import annotations",
|
|
261
|
+
]
|
|
262
|
+
default_section = "STDLIB"
|
|
263
|
+
import_heading_future = "Future Modules:"
|
|
264
|
+
import_heading_stdlib = "Built-in Modules:"
|
|
265
|
+
import_heading_thirdparty = "Third-party Modules:"
|
|
266
|
+
known_third_party = [
|
|
267
|
+
"backports.strenum",
|
|
268
|
+
"typing_extensions",
|
|
269
|
+
]
|
|
270
|
+
import_heading_firstparty = "Knickknacks Modules:"
|
|
271
|
+
known_first_party = [
|
|
272
|
+
"knickknacks",
|
|
273
|
+
]
|
|
274
|
+
import_heading_localfolder = "Local Modules:"
|
|
275
|
+
|
|
276
|
+
[tool.mypy]
|
|
277
|
+
files = [
|
|
278
|
+
"src/knickknacks",
|
|
279
|
+
"tests",
|
|
280
|
+
]
|
|
281
|
+
exclude = "^$"
|
|
282
|
+
local_partial_types = true
|
|
283
|
+
strict = true
|
|
284
|
+
disallow_any_unimported = true
|
|
285
|
+
disallow_any_decorated = true
|
|
286
|
+
warn_unreachable = true
|
|
287
|
+
show_error_codes = true
|
|
288
|
+
no_color_output = true
|
|
289
|
+
overrides = [
|
|
290
|
+
{ module = "tests.*", disallow_any_decorated = false },
|
|
291
|
+
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Copyright (c) 2025 Nick Stockton
|
|
2
|
+
# -----------------------------------------------------------------------------
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
# -----------------------------------------------------------------------------
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
# copies or substantial portions of the Software.
|
|
12
|
+
# -----------------------------------------------------------------------------
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
# SOFTWARE.
|
|
20
|
+
|
|
21
|
+
# Future Modules:
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
# Built-in Modules:
|
|
25
|
+
from contextlib import suppress
|
|
26
|
+
from typing import TYPE_CHECKING
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__version__: str = "0.0.0"
|
|
30
|
+
if not TYPE_CHECKING:
|
|
31
|
+
with suppress(ImportError):
|
|
32
|
+
from ._version import __version__
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__: list[str] = [
|
|
36
|
+
"__version__",
|
|
37
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__: str = "0.5.0"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Copyright (c) 2025 Nick Stockton
|
|
2
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
|
|
6
|
+
"""Backported classes and functions."""
|
|
7
|
+
|
|
8
|
+
# Future Modules:
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
# Built-in Modules:
|
|
12
|
+
import io
|
|
13
|
+
import pathlib
|
|
14
|
+
import sys
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if sys.version_info >= (3, 11):
|
|
19
|
+
from enum import StrEnum
|
|
20
|
+
else:
|
|
21
|
+
from backports.strenum import StrEnum
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Path(pathlib.Path):
|
|
25
|
+
"""
|
|
26
|
+
Backported pathlib.Path functionality.
|
|
27
|
+
|
|
28
|
+
Currently backports the newline argument From 3.13 read_text, and 3.10 write_text.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def read_text(
|
|
32
|
+
self, encoding: Optional[str] = None, errors: Optional[str] = None, newline: Optional[str] = None
|
|
33
|
+
) -> str:
|
|
34
|
+
"""
|
|
35
|
+
Open the file in text mode, read it, and close the file.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
encoding: The character encoding to use.
|
|
39
|
+
errors: How encoding errors should be handled.
|
|
40
|
+
newline: How newlines should be handled.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
The contents of the file.
|
|
44
|
+
"""
|
|
45
|
+
if sys.version_info >= (3, 13):
|
|
46
|
+
text = super().read_text(encoding, errors, newline)
|
|
47
|
+
else:
|
|
48
|
+
if hasattr(io, "text_encoding"):
|
|
49
|
+
encoding = io.text_encoding(encoding)
|
|
50
|
+
with self.open(mode="r", encoding=encoding, errors=errors, newline=newline) as f:
|
|
51
|
+
text = f.read()
|
|
52
|
+
return text
|
|
53
|
+
|
|
54
|
+
def write_text(
|
|
55
|
+
self,
|
|
56
|
+
data: str,
|
|
57
|
+
encoding: Optional[str] = None,
|
|
58
|
+
errors: Optional[str] = None,
|
|
59
|
+
newline: Optional[str] = None,
|
|
60
|
+
) -> int:
|
|
61
|
+
"""
|
|
62
|
+
Open the file in text mode, write to it, and close the file.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
data: The data to be written.
|
|
66
|
+
encoding: The character encoding to use.
|
|
67
|
+
errors: How encoding errors should be handled.
|
|
68
|
+
newline: How newlines should be handled.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
The number of bytes written.
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
TypeError: Data is not an instance of `str`.
|
|
75
|
+
"""
|
|
76
|
+
if sys.version_info >= (3, 10):
|
|
77
|
+
num_written = super().write_text(data, encoding, errors, newline)
|
|
78
|
+
else:
|
|
79
|
+
if not isinstance(data, str):
|
|
80
|
+
raise TypeError(f"data must be str, not {data.__class__.__name__}")
|
|
81
|
+
if hasattr(io, "text_encoding"):
|
|
82
|
+
encoding = io.text_encoding(encoding)
|
|
83
|
+
with self.open(mode="w", encoding=encoding, errors=errors, newline=newline) as f:
|
|
84
|
+
num_written = f.write(data)
|
|
85
|
+
return num_written
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
__all__: list[str] = [
|
|
89
|
+
"Path",
|
|
90
|
+
"StrEnum",
|
|
91
|
+
]
|