winipedia-utils 0.4.29__tar.gz → 0.7.5__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.
Potentially problematic release.
This version of winipedia-utils might be problematic. Click here for more details.
- {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/PKG-INFO +84 -36
- {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/README.md +81 -35
- {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/pyproject.toml +13 -9
- winipedia_utils-0.7.5/winipedia_utils/dev/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/build.py +6 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/builder.py +96 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/builds/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/builds/builder.py +17 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/base/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils/text → winipedia_utils-0.7.5/winipedia_utils/dev/configs/base}/config.py +78 -10
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/builder.py +30 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/configs.py +34 -0
- winipedia_utils-0.4.29/winipedia_utils/git/gitignore/config.py → winipedia_utils-0.7.5/winipedia_utils/dev/configs/gitignore.py +2 -2
- winipedia_utils-0.4.29/winipedia_utils/git/pre_commit/config.py → winipedia_utils-0.7.5/winipedia_utils/dev/configs/pre_commit.py +6 -6
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/pyproject.py +326 -0
- winipedia_utils-0.4.29/winipedia_utils/testing/config.py → winipedia_utils-0.7.5/winipedia_utils/dev/configs/testing.py +7 -56
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/base/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/base/base.py +903 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/health_check.py +69 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/publish.py +51 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/release.py +93 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/git/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/git/github/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/git/github/repo/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/git/github/repo/protect.py +6 -6
- winipedia_utils-0.7.5/winipedia_utils/dev/git/pre_commit/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/git/pre_commit/hooks.py +85 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/git/pre_commit/run_hooks.py +23 -13
- winipedia_utils-0.7.5/winipedia_utils/dev/projects/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/projects/poetry/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/projects/poetry/dev_deps.py +21 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/projects/poetry/poetry.py +248 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/projects/project.py +16 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/testing/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/convention.py +1 -1
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/create_tests.py +14 -14
- winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/fixtures/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/fixture.py +1 -1
- winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/fixtures/scopes/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/class_.py +2 -2
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/module.py +2 -2
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/session.py +10 -10
- winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/utils/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/utils/utils.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/conftest.py +2 -2
- {winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/utils → winipedia_utils-0.7.5/winipedia_utils/dev/testing}/utils.py +7 -47
- {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/winipedia_utils/setup.py +9 -5
- winipedia_utils-0.7.5/winipedia_utils/utils/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/data/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/data/dataframe/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/data/dataframe/cleaning.py +1 -1
- winipedia_utils-0.7.5/winipedia_utils/utils/data/structures/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/data/structures/text/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/data/structures}/text/string.py +36 -3
- winipedia_utils-0.7.5/winipedia_utils/utils/git/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/git/github/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/git/github/github.py +31 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/git/github/repo/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/git/github/repo/repo.py +1 -1
- winipedia_utils-0.7.5/winipedia_utils/utils/git/gitignore/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/git/gitignore/gitignore.py +2 -2
- winipedia_utils-0.7.5/winipedia_utils/utils/iterating/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/iterating/concurrent/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/iterating}/concurrent/concurrent.py +4 -4
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/iterating}/concurrent/multiprocessing.py +2 -2
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/iterating}/concurrent/multithreading.py +1 -1
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/iterating/iterate.py +6 -1
- winipedia_utils-0.7.5/winipedia_utils/utils/logging/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/logging/logger.py +1 -1
- winipedia_utils-0.7.5/winipedia_utils/utils/modules/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/class_.py +15 -8
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/function.py +10 -4
- winipedia_utils-0.7.5/winipedia_utils/utils/modules/inspection.py +56 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/module.py +27 -32
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/package.py +113 -31
- winipedia_utils-0.7.5/winipedia_utils/utils/oop/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/oop/mixins/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/oop/mixins/meta.py +4 -4
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/oop/mixins/mixin.py +2 -2
- winipedia_utils-0.7.5/winipedia_utils/utils/os/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/os/os.py +2 -2
- winipedia_utils-0.7.5/winipedia_utils/utils/resources/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/resources/svgs/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/svg.py +1 -1
- winipedia_utils-0.7.5/winipedia_utils/utils/security/__init__.py +1 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/testing/__init__.py +1 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/testing/assertions.py +18 -0
- winipedia_utils-0.7.5/winipedia_utils/utils/testing/skip.py +19 -0
- winipedia_utils-0.4.29/winipedia_utils/concurrent/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/data/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/data/dataframe/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/data/structures/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/github/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/github/repo/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/base/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/base/base.py +0 -291
- winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/health_check.py +0 -57
- winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/publish.py +0 -49
- winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/release.py +0 -45
- winipedia_utils-0.4.29/winipedia_utils/git/gitignore/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/pre_commit/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/git/pre_commit/hooks.py +0 -147
- winipedia_utils-0.4.29/winipedia_utils/iterating/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/logging/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/modules/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/oop/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/oop/mixins/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/os/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/projects/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/projects/poetry/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/projects/poetry/config.py +0 -166
- winipedia_utils-0.4.29/winipedia_utils/projects/poetry/poetry.py +0 -42
- winipedia_utils-0.4.29/winipedia_utils/projects/project.py +0 -17
- winipedia_utils-0.4.29/winipedia_utils/resources/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/resources/svgs/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/security/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/testing/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/testing/skip.py +0 -10
- winipedia_utils-0.4.29/winipedia_utils/testing/tests/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/fixtures/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/fixtures/scopes/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/utils/__init__.py +0 -1
- winipedia_utils-0.4.29/winipedia_utils/text/__init__.py +0 -1
- {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/LICENSE +0 -0
- {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/winipedia_utils/__init__.py +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/function.py +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/package.py +0 -0
- {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/winipedia_utils/py.typed +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/data/structures/dicts.py +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/logging/ansi.py +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/logging/config.py +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/delete_garbage_can.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/download_arrow.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/exit_fullscreen_icon.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/fullscreen_icon.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/menu_icon.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/pause_icon.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/play_icon.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/plus_icon.svg +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/security/cryptography.py +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/security/keyring.py +0 -0
- {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/testing/fixtures.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: winipedia-utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.5
|
|
4
4
|
Summary: A package with many utility functions
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -15,6 +15,8 @@ Requires-Dist: cryptography
|
|
|
15
15
|
Requires-Dist: defusedxml
|
|
16
16
|
Requires-Dist: dotenv
|
|
17
17
|
Requires-Dist: keyring
|
|
18
|
+
Requires-Dist: networkx
|
|
19
|
+
Requires-Dist: packaging
|
|
18
20
|
Requires-Dist: pathspec
|
|
19
21
|
Requires-Dist: polars
|
|
20
22
|
Requires-Dist: pygithub
|
|
@@ -78,7 +80,8 @@ git clone https://github.com/owner/repo.git
|
|
|
78
80
|
poetry init # or poetry new
|
|
79
81
|
# 4: Poetry will ask you some stuff when you run poetry init.
|
|
80
82
|
# First author name must be equal to the GitHub repository owner (username).
|
|
81
|
-
# The repository name must be equal to the package/project name.
|
|
83
|
+
# The repository name must be equal to the package/project name.
|
|
84
|
+
# (- instead of _ is fine, but only as the project name in pyproject.toml, folder names should all be _)
|
|
82
85
|
|
|
83
86
|
# 5: Add winipedia-utils to your project
|
|
84
87
|
poetry add winipedia-utils
|
|
@@ -103,13 +106,53 @@ The setup creates the following configuration files:
|
|
|
103
106
|
- `.pre-commit-config.yaml` - Pre-commit hook configuration
|
|
104
107
|
- `.gitignore` - Git ignore rules (assumes you added one on GitHub before.)
|
|
105
108
|
- `pyproject.toml` - Project configuration with Poetry settings
|
|
106
|
-
- `.github/workflows/health_check.yaml` - Health check workflow (Runs on every push and pull request)
|
|
109
|
+
- `.github/workflows/health_check.yaml` - Health check workflow (Runs on every push and pull request using a matrix strategy to test across multiple operating systems and Python versions)
|
|
107
110
|
- `.github/workflows/release.yaml` - Release workflow (Creates a release on GitHub when the same actions as in health check pass and commits are pushed to main)
|
|
108
111
|
- `.github/workflows/publish.yaml` - Publishing workflow (Publishes to PyPI when a release is created by the release workflow, if you use this workflow, you need to add a PYPI_TOKEN (named PYPI_TOKEN) to your GitHub secrets that has write access to the package on PyPI.)
|
|
109
112
|
- `py.typed` - PEP 561 marker for type hints
|
|
110
113
|
- `experiment.py` - For experimentation (ignored by git)
|
|
111
114
|
- `test_zero.py` - Test file with one empyt test (so that initial tests pass)
|
|
112
115
|
- `conftest.py` - Pytest configuration file
|
|
116
|
+
- `.python-version` - Python version file for pyenv (if you use pyenv, puts in the lowest supported python version in pyproject.toml opposed to the latest possible python version in workflows)
|
|
117
|
+
|
|
118
|
+
### GitHub Workflows and Matrix Strategy
|
|
119
|
+
|
|
120
|
+
The project uses GitHub Actions workflows with a **matrix strategy** to ensure cross-platform compatibility:
|
|
121
|
+
|
|
122
|
+
#### Matrix Configuration
|
|
123
|
+
|
|
124
|
+
The health check and release workflows test your code across:
|
|
125
|
+
- **Operating Systems**: Ubuntu (latest), Windows (latest), macOS (latest)
|
|
126
|
+
- **Python Versions**: All versions specified in your `pyproject.toml` (e.g., 3.12, 3.13, 3.14)
|
|
127
|
+
|
|
128
|
+
This matrix strategy ensures your code works reliably across different environments before merging or releasing.
|
|
129
|
+
|
|
130
|
+
#### Configuration File Structure
|
|
131
|
+
Config Files are autogenerated via ConfigFile non-abstract subclasses.
|
|
132
|
+
All nonabstract subclasses of ConfigFile are automatically created and managed when you commit or run pytest. winipedia_utils automatically discovers the pkg your_pkg.dev.configs and calls them. This way you can adjust or add some settings by subclassing. It is however important the parent class stays a subset of the child class according to the description in the function `nested_structure_is_subset` in `winipedia_utils.iterating.iterate` bc parents are still initialized and the order is not guaranteed.
|
|
133
|
+
|
|
134
|
+
#### Workflow Structure
|
|
135
|
+
|
|
136
|
+
Worklfows are a type of ConfigFile.
|
|
137
|
+
|
|
138
|
+
The health check workflow consists of two jobs:
|
|
139
|
+
|
|
140
|
+
1. **Matrix Job** (`health_check_matrix`) - Runs all checks in parallel across the matrix of OS and Python versions:
|
|
141
|
+
- Checkout repository
|
|
142
|
+
- Setup Git, Python, and Poetry
|
|
143
|
+
- Add Poetry to PATH (Windows-specific step)
|
|
144
|
+
- Install dependencies
|
|
145
|
+
- Setup CI keyring
|
|
146
|
+
- Protect repository (applies branch protection rules and repository settings)
|
|
147
|
+
- Run pre-commit hooks (linting, formatting, type checking, security, tests)
|
|
148
|
+
|
|
149
|
+
2. **Aggregation Job** (`health_check`) - Aggregates matrix results into a single status check:
|
|
150
|
+
- Required for branch protection compatibility
|
|
151
|
+
- Only runs after all matrix jobs complete successfully
|
|
152
|
+
- Provides a single status check that can be marked as required in branch protection rules
|
|
153
|
+
|
|
154
|
+
The release workflow extends the health check workflow and adds a release job that runs after all health checks pass.
|
|
155
|
+
A build job is added before the release job if a src/dev/artifacts/builds exists with Builder subclasses. This script is created by the setup command and can be modified to create build artifacts for your project. Winipedia Utils automatically discovers all subclasses of Builder (dev.artifacts.builder) and calls them if the artifacts folder contains any files.
|
|
113
156
|
|
|
114
157
|
### Pre-commit Hook Workflow
|
|
115
158
|
|
|
@@ -117,21 +160,21 @@ When you commit code using `git commit`, the following checks run automatically:
|
|
|
117
160
|
|
|
118
161
|
Info: If git commit fails bc of ModuleNotFoundError or smth similar, you need to run `poetry run git commit` instead.
|
|
119
162
|
winipedia_utils hook is a python script that depends on winipedia_utils being installed. Poetry is needed to install winipedia_utils.
|
|
120
|
-
Usually VSCode or other IDEs activates the venv automatically when opening the terminal but if not you need to activate it manually or run `poetry run git commit` instead.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
163
|
+
Usually VSCode or other IDEs activates the venv automatically when opening the terminal but if not you need to activate it manually or run `poetry run git commit` instead. It fails fast, so if one hook in winipedia_utils hook fails, the others don't run bc sys.exit(1) is called.
|
|
164
|
+
|
|
165
|
+
Hooks run in the following order:
|
|
166
|
+
|
|
167
|
+
- Update package manager (poetry self update)
|
|
168
|
+
- Install packages (poetry install --with dev)
|
|
169
|
+
- Update packages (poetry update --with dev (winipedia_utils forces all dependencies with * to be updated to latest compatible version))
|
|
170
|
+
- Lock dependencies (poetry lock)
|
|
171
|
+
- Check package manager configs (poetry check --strict)
|
|
172
|
+
- Create tests (python -m winipedia_utils.dev.testing.create_tests)
|
|
173
|
+
- Lint code (ruff check --fix)
|
|
174
|
+
- Format code (ruff format)
|
|
175
|
+
- Check static types (mypy)
|
|
176
|
+
- Check security (bandit -c pyproject.toml -r .)
|
|
177
|
+
- Run tests (pytest (uses pyproject.toml as config))
|
|
135
178
|
|
|
136
179
|
### Auto-generated Test Structure
|
|
137
180
|
|
|
@@ -151,6 +194,10 @@ my_project/
|
|
|
151
194
|
|
|
152
195
|
For each function, class, and method, skeleton tests are created with `NotImplementedError` placeholders for you to implement.
|
|
153
196
|
|
|
197
|
+
If you have autosuse fixtures just write and add them to the `tests/base/fixtures` directory. They will be automatically discovered, plugged into conftest and used in all tests according to defined scope.
|
|
198
|
+
The filenames in the fixtures folder are just for organisation purposes for your convenience. You still have to
|
|
199
|
+
apply the pytest.fixture decorator to the fixture function and define the scope. So a session scoped function defined on function.py will still run as a session scoped fixture.
|
|
200
|
+
|
|
154
201
|
## Configuration Files
|
|
155
202
|
|
|
156
203
|
Configuration files are managed automatically by the setup system:
|
|
@@ -159,10 +206,11 @@ Configuration files are managed automatically by the setup system:
|
|
|
159
206
|
- **Empty files** - If you want to disable a config file, make it empty. This signals that the file is unwanted and won't be modified
|
|
160
207
|
- **Custom additions** - You can add custom configurations as long as the standard configurations remain intact
|
|
161
208
|
- **Modified standards** - If you modify the standard configurations, they will be restored on the next setup run
|
|
209
|
+
- **Subclasses** - You can create custom config files by subclassing the standard ones. They will be automatically created and managed when you commit or run pytest. winipedia_utils automatically discovers and calls them. This way you can adjust or add some settings. It is however important the parent class stays a subset of the child class according to the description in the function `nested_structure_is_subset` in `winipedia_utils.iterating.iterate`.
|
|
162
210
|
|
|
163
211
|
## Branch Protection
|
|
164
212
|
|
|
165
|
-
As soon as you push to `main` on GitHub (provided the `REPO_TOKEN` secret is set up correctly), the `health_check.yaml` workflow will run and execute `winipedia_utils.git.github.repo.protect`, which uses PyGithub to protect the repository.
|
|
213
|
+
As soon as you push to `main` on GitHub (provided the `REPO_TOKEN` secret is set up correctly), the `health_check.yaml` workflow will run and execute `winipedia_utils.dev.git.github.repo.protect`, which uses PyGithub to protect the repository.
|
|
166
214
|
|
|
167
215
|
### Repository Settings
|
|
168
216
|
|
|
@@ -195,8 +243,8 @@ A ruleset named `main protection` is created for the `main` branch with the foll
|
|
|
195
243
|
- Requires review thread resolution (all comments in reviews must be resolved before merge)
|
|
196
244
|
- Allowed merge methods: `squash` and `rebase` (no merge commits, keeps history clean)
|
|
197
245
|
- **Required Status Checks:**
|
|
198
|
-
- Strict mode enabled (all status checks must pass on the latest commit, not older ones
|
|
199
|
-
- Health check workflow must pass (the
|
|
246
|
+
- Strict mode enabled (all status checks must pass on the latest commit, not older ones)
|
|
247
|
+
- Health check workflow must pass (the aggregated `health_check` job ensures all matrix combinations passed successfully)
|
|
200
248
|
- **Bypass Actors** - Repository admins can bypass all rules (for emergency situations)
|
|
201
249
|
|
|
202
250
|
## Utilities
|
|
@@ -208,8 +256,8 @@ Winipedia Utils provides comprehensive utility modules for common development ta
|
|
|
208
256
|
Unified interface for multiprocessing and multithreading:
|
|
209
257
|
|
|
210
258
|
```python
|
|
211
|
-
from winipedia_utils.concurrent.multiprocessing import multiprocess_loop
|
|
212
|
-
from winipedia_utils.concurrent.multithreading import multithread_loop
|
|
259
|
+
from winipedia_utils.utils.iterating.concurrent.multiprocessing import multiprocess_loop
|
|
260
|
+
from winipedia_utils.utils.iterating.concurrent.multithreading import multithread_loop
|
|
213
261
|
```
|
|
214
262
|
|
|
215
263
|
### Data Cleaning & Handling
|
|
@@ -217,7 +265,7 @@ from winipedia_utils.concurrent.multithreading import multithread_loop
|
|
|
217
265
|
Build data cleaning pipelines using Polars:
|
|
218
266
|
|
|
219
267
|
```python
|
|
220
|
-
from winipedia_utils.data.dataframe.cleaning import CleaningDF
|
|
268
|
+
from winipedia_utils.utils.data.dataframe.cleaning import CleaningDF
|
|
221
269
|
import polars as pl
|
|
222
270
|
```
|
|
223
271
|
|
|
@@ -226,7 +274,7 @@ import polars as pl
|
|
|
226
274
|
Simple, standardized logging setup with automatic method instrumentation:
|
|
227
275
|
|
|
228
276
|
```python
|
|
229
|
-
from winipedia_utils.logging.logger import get_logger
|
|
277
|
+
from winipedia_utils.utils.logging.logger import get_logger
|
|
230
278
|
|
|
231
279
|
logger = get_logger(__name__)
|
|
232
280
|
logger.info("Application started")
|
|
@@ -244,7 +292,7 @@ logger.error("An error occurred")
|
|
|
244
292
|
Advanced metaclasses and mixins for class composition and behavior extension:
|
|
245
293
|
|
|
246
294
|
```python
|
|
247
|
-
from winipedia_utils.oop.mixins.mixin import ABCLoggingMixin, StrictABCLoggingMixin
|
|
295
|
+
from winipedia_utils.utils.oop.mixins.mixin import ABCLoggingMixin, StrictABCLoggingMixin
|
|
248
296
|
```
|
|
249
297
|
|
|
250
298
|
### Security Utilities
|
|
@@ -252,7 +300,7 @@ from winipedia_utils.oop.mixins.mixin import ABCLoggingMixin, StrictABCLoggingMi
|
|
|
252
300
|
Encryption and secure credential storage using keyring:
|
|
253
301
|
|
|
254
302
|
```python
|
|
255
|
-
from winipedia_utils.security.keyring import (
|
|
303
|
+
from winipedia_utils.utils.security.keyring import (
|
|
256
304
|
get_or_create_fernet,
|
|
257
305
|
get_or_create_aes_gcm
|
|
258
306
|
)
|
|
@@ -263,8 +311,8 @@ from winipedia_utils.security.keyring import (
|
|
|
263
311
|
Comprehensive testing framework with automatic test generation:
|
|
264
312
|
|
|
265
313
|
```python
|
|
266
|
-
from winipedia_utils.testing.assertions import assert_with_msg
|
|
267
|
-
from winipedia_utils.testing.convention import (
|
|
314
|
+
from winipedia_utils.utils.testing.assertions import assert_with_msg
|
|
315
|
+
from winipedia_utils.dev.testing.convention import (
|
|
268
316
|
make_test_obj_name,
|
|
269
317
|
get_test_obj_from_obj,
|
|
270
318
|
make_test_obj_importpath_from_obj
|
|
@@ -294,10 +342,10 @@ test_path = make_test_obj_importpath_from_obj(my_function)
|
|
|
294
342
|
Tools for working with Python modules, packages, classes, and functions:
|
|
295
343
|
|
|
296
344
|
```python
|
|
297
|
-
from winipedia_utils.modules.package import find_packages, walk_package
|
|
298
|
-
from winipedia_utils.modules.module import create_module, import_obj_from_importpath
|
|
299
|
-
from winipedia_utils.modules.class_ import get_all_cls_from_module, get_all_methods_from_cls
|
|
300
|
-
from winipedia_utils.modules.function import get_all_functions_from_module
|
|
345
|
+
from winipedia_utils.utils.modules.package import find_packages, walk_package
|
|
346
|
+
from winipedia_utils.utils.modules.module import create_module, import_obj_from_importpath
|
|
347
|
+
from winipedia_utils.utils.modules.class_ import get_all_cls_from_module, get_all_methods_from_cls
|
|
348
|
+
from winipedia_utils.utils.modules.function import get_all_functions_from_module
|
|
301
349
|
```
|
|
302
350
|
|
|
303
351
|
### Text and String Utilities
|
|
@@ -305,7 +353,7 @@ from winipedia_utils.modules.function import get_all_functions_from_module
|
|
|
305
353
|
String manipulation and configuration file handling:
|
|
306
354
|
|
|
307
355
|
```python
|
|
308
|
-
from winipedia_utils.text.string import value_to_truncated_string
|
|
356
|
+
from winipedia_utils.utils.data.structures.text.string import value_to_truncated_string
|
|
309
357
|
```
|
|
310
358
|
|
|
311
359
|
### OS and System Utilities
|
|
@@ -313,7 +361,7 @@ from winipedia_utils.text.string import value_to_truncated_string
|
|
|
313
361
|
Operating system and subprocess utilities:
|
|
314
362
|
|
|
315
363
|
```python
|
|
316
|
-
from winipedia_utils.os.os import run_subprocess
|
|
364
|
+
from winipedia_utils.utils.os.os import run_subprocess
|
|
317
365
|
```
|
|
318
366
|
|
|
319
367
|
### Iteration Utilities
|
|
@@ -321,7 +369,7 @@ from winipedia_utils.os.os import run_subprocess
|
|
|
321
369
|
Utilities for working with iterables and nested structures:
|
|
322
370
|
|
|
323
371
|
```python
|
|
324
|
-
from winipedia_utils.iterating.iterate import get_len_with_default, nested_structure_is_subset
|
|
372
|
+
from winipedia_utils.utils.iterating.iterate import get_len_with_default, nested_structure_is_subset
|
|
325
373
|
```
|
|
326
374
|
|
|
327
375
|
### Philosophy
|
|
@@ -52,7 +52,8 @@ git clone https://github.com/owner/repo.git
|
|
|
52
52
|
poetry init # or poetry new
|
|
53
53
|
# 4: Poetry will ask you some stuff when you run poetry init.
|
|
54
54
|
# First author name must be equal to the GitHub repository owner (username).
|
|
55
|
-
# The repository name must be equal to the package/project name.
|
|
55
|
+
# The repository name must be equal to the package/project name.
|
|
56
|
+
# (- instead of _ is fine, but only as the project name in pyproject.toml, folder names should all be _)
|
|
56
57
|
|
|
57
58
|
# 5: Add winipedia-utils to your project
|
|
58
59
|
poetry add winipedia-utils
|
|
@@ -77,13 +78,53 @@ The setup creates the following configuration files:
|
|
|
77
78
|
- `.pre-commit-config.yaml` - Pre-commit hook configuration
|
|
78
79
|
- `.gitignore` - Git ignore rules (assumes you added one on GitHub before.)
|
|
79
80
|
- `pyproject.toml` - Project configuration with Poetry settings
|
|
80
|
-
- `.github/workflows/health_check.yaml` - Health check workflow (Runs on every push and pull request)
|
|
81
|
+
- `.github/workflows/health_check.yaml` - Health check workflow (Runs on every push and pull request using a matrix strategy to test across multiple operating systems and Python versions)
|
|
81
82
|
- `.github/workflows/release.yaml` - Release workflow (Creates a release on GitHub when the same actions as in health check pass and commits are pushed to main)
|
|
82
83
|
- `.github/workflows/publish.yaml` - Publishing workflow (Publishes to PyPI when a release is created by the release workflow, if you use this workflow, you need to add a PYPI_TOKEN (named PYPI_TOKEN) to your GitHub secrets that has write access to the package on PyPI.)
|
|
83
84
|
- `py.typed` - PEP 561 marker for type hints
|
|
84
85
|
- `experiment.py` - For experimentation (ignored by git)
|
|
85
86
|
- `test_zero.py` - Test file with one empyt test (so that initial tests pass)
|
|
86
87
|
- `conftest.py` - Pytest configuration file
|
|
88
|
+
- `.python-version` - Python version file for pyenv (if you use pyenv, puts in the lowest supported python version in pyproject.toml opposed to the latest possible python version in workflows)
|
|
89
|
+
|
|
90
|
+
### GitHub Workflows and Matrix Strategy
|
|
91
|
+
|
|
92
|
+
The project uses GitHub Actions workflows with a **matrix strategy** to ensure cross-platform compatibility:
|
|
93
|
+
|
|
94
|
+
#### Matrix Configuration
|
|
95
|
+
|
|
96
|
+
The health check and release workflows test your code across:
|
|
97
|
+
- **Operating Systems**: Ubuntu (latest), Windows (latest), macOS (latest)
|
|
98
|
+
- **Python Versions**: All versions specified in your `pyproject.toml` (e.g., 3.12, 3.13, 3.14)
|
|
99
|
+
|
|
100
|
+
This matrix strategy ensures your code works reliably across different environments before merging or releasing.
|
|
101
|
+
|
|
102
|
+
#### Configuration File Structure
|
|
103
|
+
Config Files are autogenerated via ConfigFile non-abstract subclasses.
|
|
104
|
+
All nonabstract subclasses of ConfigFile are automatically created and managed when you commit or run pytest. winipedia_utils automatically discovers the pkg your_pkg.dev.configs and calls them. This way you can adjust or add some settings by subclassing. It is however important the parent class stays a subset of the child class according to the description in the function `nested_structure_is_subset` in `winipedia_utils.iterating.iterate` bc parents are still initialized and the order is not guaranteed.
|
|
105
|
+
|
|
106
|
+
#### Workflow Structure
|
|
107
|
+
|
|
108
|
+
Worklfows are a type of ConfigFile.
|
|
109
|
+
|
|
110
|
+
The health check workflow consists of two jobs:
|
|
111
|
+
|
|
112
|
+
1. **Matrix Job** (`health_check_matrix`) - Runs all checks in parallel across the matrix of OS and Python versions:
|
|
113
|
+
- Checkout repository
|
|
114
|
+
- Setup Git, Python, and Poetry
|
|
115
|
+
- Add Poetry to PATH (Windows-specific step)
|
|
116
|
+
- Install dependencies
|
|
117
|
+
- Setup CI keyring
|
|
118
|
+
- Protect repository (applies branch protection rules and repository settings)
|
|
119
|
+
- Run pre-commit hooks (linting, formatting, type checking, security, tests)
|
|
120
|
+
|
|
121
|
+
2. **Aggregation Job** (`health_check`) - Aggregates matrix results into a single status check:
|
|
122
|
+
- Required for branch protection compatibility
|
|
123
|
+
- Only runs after all matrix jobs complete successfully
|
|
124
|
+
- Provides a single status check that can be marked as required in branch protection rules
|
|
125
|
+
|
|
126
|
+
The release workflow extends the health check workflow and adds a release job that runs after all health checks pass.
|
|
127
|
+
A build job is added before the release job if a src/dev/artifacts/builds exists with Builder subclasses. This script is created by the setup command and can be modified to create build artifacts for your project. Winipedia Utils automatically discovers all subclasses of Builder (dev.artifacts.builder) and calls them if the artifacts folder contains any files.
|
|
87
128
|
|
|
88
129
|
### Pre-commit Hook Workflow
|
|
89
130
|
|
|
@@ -91,21 +132,21 @@ When you commit code using `git commit`, the following checks run automatically:
|
|
|
91
132
|
|
|
92
133
|
Info: If git commit fails bc of ModuleNotFoundError or smth similar, you need to run `poetry run git commit` instead.
|
|
93
134
|
winipedia_utils hook is a python script that depends on winipedia_utils being installed. Poetry is needed to install winipedia_utils.
|
|
94
|
-
Usually VSCode or other IDEs activates the venv automatically when opening the terminal but if not you need to activate it manually or run `poetry run git commit` instead.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
135
|
+
Usually VSCode or other IDEs activates the venv automatically when opening the terminal but if not you need to activate it manually or run `poetry run git commit` instead. It fails fast, so if one hook in winipedia_utils hook fails, the others don't run bc sys.exit(1) is called.
|
|
136
|
+
|
|
137
|
+
Hooks run in the following order:
|
|
138
|
+
|
|
139
|
+
- Update package manager (poetry self update)
|
|
140
|
+
- Install packages (poetry install --with dev)
|
|
141
|
+
- Update packages (poetry update --with dev (winipedia_utils forces all dependencies with * to be updated to latest compatible version))
|
|
142
|
+
- Lock dependencies (poetry lock)
|
|
143
|
+
- Check package manager configs (poetry check --strict)
|
|
144
|
+
- Create tests (python -m winipedia_utils.dev.testing.create_tests)
|
|
145
|
+
- Lint code (ruff check --fix)
|
|
146
|
+
- Format code (ruff format)
|
|
147
|
+
- Check static types (mypy)
|
|
148
|
+
- Check security (bandit -c pyproject.toml -r .)
|
|
149
|
+
- Run tests (pytest (uses pyproject.toml as config))
|
|
109
150
|
|
|
110
151
|
### Auto-generated Test Structure
|
|
111
152
|
|
|
@@ -125,6 +166,10 @@ my_project/
|
|
|
125
166
|
|
|
126
167
|
For each function, class, and method, skeleton tests are created with `NotImplementedError` placeholders for you to implement.
|
|
127
168
|
|
|
169
|
+
If you have autosuse fixtures just write and add them to the `tests/base/fixtures` directory. They will be automatically discovered, plugged into conftest and used in all tests according to defined scope.
|
|
170
|
+
The filenames in the fixtures folder are just for organisation purposes for your convenience. You still have to
|
|
171
|
+
apply the pytest.fixture decorator to the fixture function and define the scope. So a session scoped function defined on function.py will still run as a session scoped fixture.
|
|
172
|
+
|
|
128
173
|
## Configuration Files
|
|
129
174
|
|
|
130
175
|
Configuration files are managed automatically by the setup system:
|
|
@@ -133,10 +178,11 @@ Configuration files are managed automatically by the setup system:
|
|
|
133
178
|
- **Empty files** - If you want to disable a config file, make it empty. This signals that the file is unwanted and won't be modified
|
|
134
179
|
- **Custom additions** - You can add custom configurations as long as the standard configurations remain intact
|
|
135
180
|
- **Modified standards** - If you modify the standard configurations, they will be restored on the next setup run
|
|
181
|
+
- **Subclasses** - You can create custom config files by subclassing the standard ones. They will be automatically created and managed when you commit or run pytest. winipedia_utils automatically discovers and calls them. This way you can adjust or add some settings. It is however important the parent class stays a subset of the child class according to the description in the function `nested_structure_is_subset` in `winipedia_utils.iterating.iterate`.
|
|
136
182
|
|
|
137
183
|
## Branch Protection
|
|
138
184
|
|
|
139
|
-
As soon as you push to `main` on GitHub (provided the `REPO_TOKEN` secret is set up correctly), the `health_check.yaml` workflow will run and execute `winipedia_utils.git.github.repo.protect`, which uses PyGithub to protect the repository.
|
|
185
|
+
As soon as you push to `main` on GitHub (provided the `REPO_TOKEN` secret is set up correctly), the `health_check.yaml` workflow will run and execute `winipedia_utils.dev.git.github.repo.protect`, which uses PyGithub to protect the repository.
|
|
140
186
|
|
|
141
187
|
### Repository Settings
|
|
142
188
|
|
|
@@ -169,8 +215,8 @@ A ruleset named `main protection` is created for the `main` branch with the foll
|
|
|
169
215
|
- Requires review thread resolution (all comments in reviews must be resolved before merge)
|
|
170
216
|
- Allowed merge methods: `squash` and `rebase` (no merge commits, keeps history clean)
|
|
171
217
|
- **Required Status Checks:**
|
|
172
|
-
- Strict mode enabled (all status checks must pass on the latest commit, not older ones
|
|
173
|
-
- Health check workflow must pass (the
|
|
218
|
+
- Strict mode enabled (all status checks must pass on the latest commit, not older ones)
|
|
219
|
+
- Health check workflow must pass (the aggregated `health_check` job ensures all matrix combinations passed successfully)
|
|
174
220
|
- **Bypass Actors** - Repository admins can bypass all rules (for emergency situations)
|
|
175
221
|
|
|
176
222
|
## Utilities
|
|
@@ -182,8 +228,8 @@ Winipedia Utils provides comprehensive utility modules for common development ta
|
|
|
182
228
|
Unified interface for multiprocessing and multithreading:
|
|
183
229
|
|
|
184
230
|
```python
|
|
185
|
-
from winipedia_utils.concurrent.multiprocessing import multiprocess_loop
|
|
186
|
-
from winipedia_utils.concurrent.multithreading import multithread_loop
|
|
231
|
+
from winipedia_utils.utils.iterating.concurrent.multiprocessing import multiprocess_loop
|
|
232
|
+
from winipedia_utils.utils.iterating.concurrent.multithreading import multithread_loop
|
|
187
233
|
```
|
|
188
234
|
|
|
189
235
|
### Data Cleaning & Handling
|
|
@@ -191,7 +237,7 @@ from winipedia_utils.concurrent.multithreading import multithread_loop
|
|
|
191
237
|
Build data cleaning pipelines using Polars:
|
|
192
238
|
|
|
193
239
|
```python
|
|
194
|
-
from winipedia_utils.data.dataframe.cleaning import CleaningDF
|
|
240
|
+
from winipedia_utils.utils.data.dataframe.cleaning import CleaningDF
|
|
195
241
|
import polars as pl
|
|
196
242
|
```
|
|
197
243
|
|
|
@@ -200,7 +246,7 @@ import polars as pl
|
|
|
200
246
|
Simple, standardized logging setup with automatic method instrumentation:
|
|
201
247
|
|
|
202
248
|
```python
|
|
203
|
-
from winipedia_utils.logging.logger import get_logger
|
|
249
|
+
from winipedia_utils.utils.logging.logger import get_logger
|
|
204
250
|
|
|
205
251
|
logger = get_logger(__name__)
|
|
206
252
|
logger.info("Application started")
|
|
@@ -218,7 +264,7 @@ logger.error("An error occurred")
|
|
|
218
264
|
Advanced metaclasses and mixins for class composition and behavior extension:
|
|
219
265
|
|
|
220
266
|
```python
|
|
221
|
-
from winipedia_utils.oop.mixins.mixin import ABCLoggingMixin, StrictABCLoggingMixin
|
|
267
|
+
from winipedia_utils.utils.oop.mixins.mixin import ABCLoggingMixin, StrictABCLoggingMixin
|
|
222
268
|
```
|
|
223
269
|
|
|
224
270
|
### Security Utilities
|
|
@@ -226,7 +272,7 @@ from winipedia_utils.oop.mixins.mixin import ABCLoggingMixin, StrictABCLoggingMi
|
|
|
226
272
|
Encryption and secure credential storage using keyring:
|
|
227
273
|
|
|
228
274
|
```python
|
|
229
|
-
from winipedia_utils.security.keyring import (
|
|
275
|
+
from winipedia_utils.utils.security.keyring import (
|
|
230
276
|
get_or_create_fernet,
|
|
231
277
|
get_or_create_aes_gcm
|
|
232
278
|
)
|
|
@@ -237,8 +283,8 @@ from winipedia_utils.security.keyring import (
|
|
|
237
283
|
Comprehensive testing framework with automatic test generation:
|
|
238
284
|
|
|
239
285
|
```python
|
|
240
|
-
from winipedia_utils.testing.assertions import assert_with_msg
|
|
241
|
-
from winipedia_utils.testing.convention import (
|
|
286
|
+
from winipedia_utils.utils.testing.assertions import assert_with_msg
|
|
287
|
+
from winipedia_utils.dev.testing.convention import (
|
|
242
288
|
make_test_obj_name,
|
|
243
289
|
get_test_obj_from_obj,
|
|
244
290
|
make_test_obj_importpath_from_obj
|
|
@@ -268,10 +314,10 @@ test_path = make_test_obj_importpath_from_obj(my_function)
|
|
|
268
314
|
Tools for working with Python modules, packages, classes, and functions:
|
|
269
315
|
|
|
270
316
|
```python
|
|
271
|
-
from winipedia_utils.modules.package import find_packages, walk_package
|
|
272
|
-
from winipedia_utils.modules.module import create_module, import_obj_from_importpath
|
|
273
|
-
from winipedia_utils.modules.class_ import get_all_cls_from_module, get_all_methods_from_cls
|
|
274
|
-
from winipedia_utils.modules.function import get_all_functions_from_module
|
|
317
|
+
from winipedia_utils.utils.modules.package import find_packages, walk_package
|
|
318
|
+
from winipedia_utils.utils.modules.module import create_module, import_obj_from_importpath
|
|
319
|
+
from winipedia_utils.utils.modules.class_ import get_all_cls_from_module, get_all_methods_from_cls
|
|
320
|
+
from winipedia_utils.utils.modules.function import get_all_functions_from_module
|
|
275
321
|
```
|
|
276
322
|
|
|
277
323
|
### Text and String Utilities
|
|
@@ -279,7 +325,7 @@ from winipedia_utils.modules.function import get_all_functions_from_module
|
|
|
279
325
|
String manipulation and configuration file handling:
|
|
280
326
|
|
|
281
327
|
```python
|
|
282
|
-
from winipedia_utils.text.string import value_to_truncated_string
|
|
328
|
+
from winipedia_utils.utils.data.structures.text.string import value_to_truncated_string
|
|
283
329
|
```
|
|
284
330
|
|
|
285
331
|
### OS and System Utilities
|
|
@@ -287,7 +333,7 @@ from winipedia_utils.text.string import value_to_truncated_string
|
|
|
287
333
|
Operating system and subprocess utilities:
|
|
288
334
|
|
|
289
335
|
```python
|
|
290
|
-
from winipedia_utils.os.os import run_subprocess
|
|
336
|
+
from winipedia_utils.utils.os.os import run_subprocess
|
|
291
337
|
```
|
|
292
338
|
|
|
293
339
|
### Iteration Utilities
|
|
@@ -295,7 +341,7 @@ from winipedia_utils.os.os import run_subprocess
|
|
|
295
341
|
Utilities for working with iterables and nested structures:
|
|
296
342
|
|
|
297
343
|
```python
|
|
298
|
-
from winipedia_utils.iterating.iterate import get_len_with_default, nested_structure_is_subset
|
|
344
|
+
from winipedia_utils.utils.iterating.iterate import get_len_with_default, nested_structure_is_subset
|
|
299
345
|
```
|
|
300
346
|
|
|
301
347
|
### Philosophy
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Project section
|
|
2
2
|
[project]
|
|
3
3
|
name = "winipedia-utils"
|
|
4
|
-
version = "0.
|
|
4
|
+
version = "0.7.5"
|
|
5
5
|
description = "A package with many utility functions"
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
requires-python = ">=3.12"
|
|
8
|
-
dynamic = [ "dependencies",]
|
|
9
8
|
authors = [
|
|
10
9
|
{ name = "Winipedia", email = "win.steveker@gmx.de"}
|
|
11
10
|
]
|
|
12
11
|
license = "MIT"
|
|
12
|
+
dynamic = ["dependencies"]
|
|
13
13
|
|
|
14
|
-
# Build system section
|
|
14
|
+
# Build system section[build-system]
|
|
15
15
|
[build-system]
|
|
16
16
|
requires = [ "poetry-core>=2.0.0,<3.0.0",]
|
|
17
17
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -21,17 +21,19 @@ build-backend = "poetry.core.masonry.api"
|
|
|
21
21
|
include = "winipedia_utils"
|
|
22
22
|
|
|
23
23
|
[tool.poetry.dependencies]
|
|
24
|
-
|
|
24
|
+
networkx = "*"
|
|
25
25
|
setuptools = "*"
|
|
26
|
-
defusedxml = "*"
|
|
27
|
-
tomlkit = "*"
|
|
28
|
-
pathspec = "*"
|
|
29
26
|
pyyaml = "*"
|
|
30
|
-
|
|
31
|
-
cryptography = "*"
|
|
27
|
+
packaging = "*"
|
|
32
28
|
polars = "*"
|
|
29
|
+
tomlkit = "*"
|
|
30
|
+
cryptography = "*"
|
|
31
|
+
tqdm = "*"
|
|
33
32
|
pygithub = "*"
|
|
34
33
|
dotenv = "*"
|
|
34
|
+
pathspec = "*"
|
|
35
|
+
defusedxml = "*"
|
|
36
|
+
keyring = "*"
|
|
35
37
|
|
|
36
38
|
[tool.poetry.group.dev.dependencies]
|
|
37
39
|
ruff = "*"
|
|
@@ -44,6 +46,7 @@ types-tqdm = "*"
|
|
|
44
46
|
types-defusedxml = "*"
|
|
45
47
|
types-pyyaml = "*"
|
|
46
48
|
pytest-mock = "*"
|
|
49
|
+
types-networkx = "*"
|
|
47
50
|
|
|
48
51
|
[tool.ruff]
|
|
49
52
|
exclude = [ ".*", "**/migrations/*.py",]
|
|
@@ -64,3 +67,4 @@ files = "."
|
|
|
64
67
|
testpaths = [ "tests",]
|
|
65
68
|
|
|
66
69
|
[tool.bandit]
|
|
70
|
+
exclude_dirs = ["experiment.py"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""__init__ module."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""__init__ module."""
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Build utilities for creating and managing project builds.
|
|
2
|
+
|
|
3
|
+
This module provides functions for building and managing project artifacts,
|
|
4
|
+
including creating build scripts, configuring build environments, and
|
|
5
|
+
handling build dependencies. These utilities help with the packaging and
|
|
6
|
+
distribution of project code.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import platform
|
|
10
|
+
from abc import abstractmethod
|
|
11
|
+
from importlib import import_module
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from winipedia_utils.dev.configs.builder import BuilderConfigFile
|
|
15
|
+
from winipedia_utils.utils.modules.class_ import (
|
|
16
|
+
get_all_nonabstract_subclasses,
|
|
17
|
+
)
|
|
18
|
+
from winipedia_utils.utils.modules.module import to_module_name, to_path
|
|
19
|
+
from winipedia_utils.utils.oop.mixins.mixin import ABCLoggingMixin
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Builder(ABCLoggingMixin):
|
|
23
|
+
"""Base class for build scripts.
|
|
24
|
+
|
|
25
|
+
Subclass this class and implement the get_artifacts method to create
|
|
26
|
+
a build script for your project. The build method will be called
|
|
27
|
+
automatically when the class is initialized. At the end of the file add
|
|
28
|
+
if __name__ == "__main__":
|
|
29
|
+
YourBuildClass()
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
ARTIFACTS_DIR_NAME = "artifacts"
|
|
33
|
+
ARTIFACTS_PATH = Path(ARTIFACTS_DIR_NAME)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def create_artifacts(cls) -> None:
|
|
38
|
+
"""Build the project.
|
|
39
|
+
|
|
40
|
+
This method should create all artifacts in the ARTIFACTS_PATH folder.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
None
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def __init__(cls) -> None:
|
|
48
|
+
"""Initialize the build script."""
|
|
49
|
+
cls.build()
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def build(cls) -> None:
|
|
53
|
+
"""Build the project.
|
|
54
|
+
|
|
55
|
+
This method is called by the __init__ method.
|
|
56
|
+
It takes all the files and renames them with -platform.system()
|
|
57
|
+
and puts them in the artifacts folder.
|
|
58
|
+
"""
|
|
59
|
+
cls.ARTIFACTS_PATH.mkdir(parents=True, exist_ok=True)
|
|
60
|
+
cls.create_artifacts()
|
|
61
|
+
artifacts = cls.get_artifacts()
|
|
62
|
+
for artifact in artifacts:
|
|
63
|
+
parent = artifact.parent
|
|
64
|
+
if parent != cls.ARTIFACTS_PATH:
|
|
65
|
+
msg = f"You must create {artifact} in {cls.ARTIFACTS_PATH}"
|
|
66
|
+
raise FileNotFoundError(msg)
|
|
67
|
+
|
|
68
|
+
# rename the files with -platform.system()
|
|
69
|
+
new_name = f"{artifact.stem}-{platform.system()}{artifact.suffix}"
|
|
70
|
+
new_path = cls.ARTIFACTS_PATH / new_name
|
|
71
|
+
artifact.rename(new_path)
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def get_artifacts(cls) -> list[Path]:
|
|
75
|
+
"""Get the built artifacts."""
|
|
76
|
+
paths = list(cls.ARTIFACTS_PATH.glob("*"))
|
|
77
|
+
if not paths:
|
|
78
|
+
msg = f"Expected {cls.ARTIFACTS_PATH} to contain files"
|
|
79
|
+
raise FileNotFoundError(msg)
|
|
80
|
+
return paths
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def get_non_abstract_subclasses(cls) -> set[type["Builder"]]:
|
|
84
|
+
"""Get all non-abstract subclasses of Builder."""
|
|
85
|
+
path = BuilderConfigFile.get_parent_path()
|
|
86
|
+
module_name = to_module_name(path)
|
|
87
|
+
if not to_path(module_name, is_package=True).exists():
|
|
88
|
+
return set()
|
|
89
|
+
builds_pkg = import_module(module_name)
|
|
90
|
+
return get_all_nonabstract_subclasses(cls, load_package_before=builds_pkg)
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def init_all_non_abstract_subclasses(cls) -> None:
|
|
94
|
+
"""Build all artifacts."""
|
|
95
|
+
for builder in cls.get_non_abstract_subclasses():
|
|
96
|
+
builder()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""__init__ module."""
|