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.

Files changed (150) hide show
  1. {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/PKG-INFO +84 -36
  2. {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/README.md +81 -35
  3. {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/pyproject.toml +13 -9
  4. winipedia_utils-0.7.5/winipedia_utils/dev/__init__.py +1 -0
  5. winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/__init__.py +1 -0
  6. winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/build.py +6 -0
  7. winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/builder.py +96 -0
  8. winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/builds/__init__.py +1 -0
  9. winipedia_utils-0.7.5/winipedia_utils/dev/artifacts/builds/builder.py +17 -0
  10. winipedia_utils-0.7.5/winipedia_utils/dev/configs/__init__.py +1 -0
  11. winipedia_utils-0.7.5/winipedia_utils/dev/configs/base/__init__.py +1 -0
  12. {winipedia_utils-0.4.29/winipedia_utils/text → winipedia_utils-0.7.5/winipedia_utils/dev/configs/base}/config.py +78 -10
  13. winipedia_utils-0.7.5/winipedia_utils/dev/configs/builder.py +30 -0
  14. winipedia_utils-0.7.5/winipedia_utils/dev/configs/configs.py +34 -0
  15. winipedia_utils-0.4.29/winipedia_utils/git/gitignore/config.py → winipedia_utils-0.7.5/winipedia_utils/dev/configs/gitignore.py +2 -2
  16. 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
  17. winipedia_utils-0.7.5/winipedia_utils/dev/configs/pyproject.py +326 -0
  18. winipedia_utils-0.4.29/winipedia_utils/testing/config.py → winipedia_utils-0.7.5/winipedia_utils/dev/configs/testing.py +7 -56
  19. winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/__init__.py +1 -0
  20. winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/base/__init__.py +1 -0
  21. winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/base/base.py +903 -0
  22. winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/health_check.py +69 -0
  23. winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/publish.py +51 -0
  24. winipedia_utils-0.7.5/winipedia_utils/dev/configs/workflows/release.py +93 -0
  25. winipedia_utils-0.7.5/winipedia_utils/dev/git/__init__.py +1 -0
  26. winipedia_utils-0.7.5/winipedia_utils/dev/git/github/__init__.py +1 -0
  27. winipedia_utils-0.7.5/winipedia_utils/dev/git/github/repo/__init__.py +1 -0
  28. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/git/github/repo/protect.py +6 -6
  29. winipedia_utils-0.7.5/winipedia_utils/dev/git/pre_commit/__init__.py +1 -0
  30. winipedia_utils-0.7.5/winipedia_utils/dev/git/pre_commit/hooks.py +85 -0
  31. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/git/pre_commit/run_hooks.py +23 -13
  32. winipedia_utils-0.7.5/winipedia_utils/dev/projects/__init__.py +1 -0
  33. winipedia_utils-0.7.5/winipedia_utils/dev/projects/poetry/__init__.py +1 -0
  34. winipedia_utils-0.7.5/winipedia_utils/dev/projects/poetry/dev_deps.py +21 -0
  35. winipedia_utils-0.7.5/winipedia_utils/dev/projects/poetry/poetry.py +248 -0
  36. winipedia_utils-0.7.5/winipedia_utils/dev/projects/project.py +16 -0
  37. winipedia_utils-0.7.5/winipedia_utils/dev/testing/__init__.py +1 -0
  38. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/convention.py +1 -1
  39. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/create_tests.py +14 -14
  40. winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/__init__.py +1 -0
  41. winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/__init__.py +1 -0
  42. winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/fixtures/__init__.py +1 -0
  43. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/fixture.py +1 -1
  44. winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/fixtures/scopes/__init__.py +1 -0
  45. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/class_.py +2 -2
  46. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/module.py +2 -2
  47. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/session.py +10 -10
  48. winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/utils/__init__.py +1 -0
  49. winipedia_utils-0.7.5/winipedia_utils/dev/testing/tests/base/utils/utils.py +1 -0
  50. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/conftest.py +2 -2
  51. {winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/utils → winipedia_utils-0.7.5/winipedia_utils/dev/testing}/utils.py +7 -47
  52. {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/winipedia_utils/setup.py +9 -5
  53. winipedia_utils-0.7.5/winipedia_utils/utils/__init__.py +1 -0
  54. winipedia_utils-0.7.5/winipedia_utils/utils/data/__init__.py +1 -0
  55. winipedia_utils-0.7.5/winipedia_utils/utils/data/dataframe/__init__.py +1 -0
  56. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/data/dataframe/cleaning.py +1 -1
  57. winipedia_utils-0.7.5/winipedia_utils/utils/data/structures/__init__.py +1 -0
  58. winipedia_utils-0.7.5/winipedia_utils/utils/data/structures/text/__init__.py +1 -0
  59. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/data/structures}/text/string.py +36 -3
  60. winipedia_utils-0.7.5/winipedia_utils/utils/git/__init__.py +1 -0
  61. winipedia_utils-0.7.5/winipedia_utils/utils/git/github/__init__.py +1 -0
  62. winipedia_utils-0.7.5/winipedia_utils/utils/git/github/github.py +31 -0
  63. winipedia_utils-0.7.5/winipedia_utils/utils/git/github/repo/__init__.py +1 -0
  64. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/git/github/repo/repo.py +1 -1
  65. winipedia_utils-0.7.5/winipedia_utils/utils/git/gitignore/__init__.py +1 -0
  66. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/git/gitignore/gitignore.py +2 -2
  67. winipedia_utils-0.7.5/winipedia_utils/utils/iterating/__init__.py +1 -0
  68. winipedia_utils-0.7.5/winipedia_utils/utils/iterating/concurrent/__init__.py +1 -0
  69. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/iterating}/concurrent/concurrent.py +4 -4
  70. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/iterating}/concurrent/multiprocessing.py +2 -2
  71. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils/iterating}/concurrent/multithreading.py +1 -1
  72. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/iterating/iterate.py +6 -1
  73. winipedia_utils-0.7.5/winipedia_utils/utils/logging/__init__.py +1 -0
  74. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/logging/logger.py +1 -1
  75. winipedia_utils-0.7.5/winipedia_utils/utils/modules/__init__.py +1 -0
  76. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/class_.py +15 -8
  77. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/function.py +10 -4
  78. winipedia_utils-0.7.5/winipedia_utils/utils/modules/inspection.py +56 -0
  79. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/module.py +27 -32
  80. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/modules/package.py +113 -31
  81. winipedia_utils-0.7.5/winipedia_utils/utils/oop/__init__.py +1 -0
  82. winipedia_utils-0.7.5/winipedia_utils/utils/oop/mixins/__init__.py +1 -0
  83. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/oop/mixins/meta.py +4 -4
  84. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/oop/mixins/mixin.py +2 -2
  85. winipedia_utils-0.7.5/winipedia_utils/utils/os/__init__.py +1 -0
  86. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/os/os.py +2 -2
  87. winipedia_utils-0.7.5/winipedia_utils/utils/resources/__init__.py +1 -0
  88. winipedia_utils-0.7.5/winipedia_utils/utils/resources/svgs/__init__.py +1 -0
  89. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/svg.py +1 -1
  90. winipedia_utils-0.7.5/winipedia_utils/utils/security/__init__.py +1 -0
  91. winipedia_utils-0.7.5/winipedia_utils/utils/testing/__init__.py +1 -0
  92. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/testing/assertions.py +18 -0
  93. winipedia_utils-0.7.5/winipedia_utils/utils/testing/skip.py +19 -0
  94. winipedia_utils-0.4.29/winipedia_utils/concurrent/__init__.py +0 -1
  95. winipedia_utils-0.4.29/winipedia_utils/data/__init__.py +0 -1
  96. winipedia_utils-0.4.29/winipedia_utils/data/dataframe/__init__.py +0 -1
  97. winipedia_utils-0.4.29/winipedia_utils/data/structures/__init__.py +0 -1
  98. winipedia_utils-0.4.29/winipedia_utils/git/__init__.py +0 -1
  99. winipedia_utils-0.4.29/winipedia_utils/git/github/__init__.py +0 -1
  100. winipedia_utils-0.4.29/winipedia_utils/git/github/repo/__init__.py +0 -1
  101. winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/__init__.py +0 -1
  102. winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/base/__init__.py +0 -1
  103. winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/base/base.py +0 -291
  104. winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/health_check.py +0 -57
  105. winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/publish.py +0 -49
  106. winipedia_utils-0.4.29/winipedia_utils/git/github/workflows/release.py +0 -45
  107. winipedia_utils-0.4.29/winipedia_utils/git/gitignore/__init__.py +0 -1
  108. winipedia_utils-0.4.29/winipedia_utils/git/pre_commit/__init__.py +0 -1
  109. winipedia_utils-0.4.29/winipedia_utils/git/pre_commit/hooks.py +0 -147
  110. winipedia_utils-0.4.29/winipedia_utils/iterating/__init__.py +0 -1
  111. winipedia_utils-0.4.29/winipedia_utils/logging/__init__.py +0 -1
  112. winipedia_utils-0.4.29/winipedia_utils/modules/__init__.py +0 -1
  113. winipedia_utils-0.4.29/winipedia_utils/oop/__init__.py +0 -1
  114. winipedia_utils-0.4.29/winipedia_utils/oop/mixins/__init__.py +0 -1
  115. winipedia_utils-0.4.29/winipedia_utils/os/__init__.py +0 -1
  116. winipedia_utils-0.4.29/winipedia_utils/projects/__init__.py +0 -1
  117. winipedia_utils-0.4.29/winipedia_utils/projects/poetry/__init__.py +0 -1
  118. winipedia_utils-0.4.29/winipedia_utils/projects/poetry/config.py +0 -166
  119. winipedia_utils-0.4.29/winipedia_utils/projects/poetry/poetry.py +0 -42
  120. winipedia_utils-0.4.29/winipedia_utils/projects/project.py +0 -17
  121. winipedia_utils-0.4.29/winipedia_utils/resources/__init__.py +0 -1
  122. winipedia_utils-0.4.29/winipedia_utils/resources/svgs/__init__.py +0 -1
  123. winipedia_utils-0.4.29/winipedia_utils/security/__init__.py +0 -1
  124. winipedia_utils-0.4.29/winipedia_utils/testing/__init__.py +0 -1
  125. winipedia_utils-0.4.29/winipedia_utils/testing/skip.py +0 -10
  126. winipedia_utils-0.4.29/winipedia_utils/testing/tests/__init__.py +0 -1
  127. winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/__init__.py +0 -1
  128. winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/fixtures/__init__.py +0 -1
  129. winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/fixtures/scopes/__init__.py +0 -1
  130. winipedia_utils-0.4.29/winipedia_utils/testing/tests/base/utils/__init__.py +0 -1
  131. winipedia_utils-0.4.29/winipedia_utils/text/__init__.py +0 -1
  132. {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/LICENSE +0 -0
  133. {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/winipedia_utils/__init__.py +0 -0
  134. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/function.py +0 -0
  135. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/dev}/testing/tests/base/fixtures/scopes/package.py +0 -0
  136. {winipedia_utils-0.4.29 → winipedia_utils-0.7.5}/winipedia_utils/py.typed +0 -0
  137. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/data/structures/dicts.py +0 -0
  138. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/logging/ansi.py +0 -0
  139. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/logging/config.py +0 -0
  140. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/delete_garbage_can.svg +0 -0
  141. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/download_arrow.svg +0 -0
  142. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/exit_fullscreen_icon.svg +0 -0
  143. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/fullscreen_icon.svg +0 -0
  144. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/menu_icon.svg +0 -0
  145. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/pause_icon.svg +0 -0
  146. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/play_icon.svg +0 -0
  147. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/resources/svgs/plus_icon.svg +0 -0
  148. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/security/cryptography.py +0 -0
  149. {winipedia_utils-0.4.29/winipedia_utils → winipedia_utils-0.7.5/winipedia_utils/utils}/security/keyring.py +0 -0
  150. {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.4.29
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
- 1. Patch version (poetry version patch)
123
- 2. Add version patch to git (git add pyproject.toml)
124
- 3. Update package manager (poetry self update)
125
- 4. Install packages (poetry install --with dev)
126
- 5. Update packages (poetry update --with dev (winipedia_utils forces all dependencies with * to be updated to latest compatible version))
127
- 6. Lock dependencies (poetry lock)
128
- 7. Check package manager configs (poetry check --strict)
129
- 8. Create tests (python -m winipedia_utils.testing.create_tests)
130
- 9. Lint code (ruff check --fix)
131
- 10. Format code (ruff format)
132
- 11. Check static types (mypy)
133
- 12. Check security (bandit -c pyproject.toml -r .)
134
- 13. Run tests (pytest (uses pyproject.toml as config))
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 (sets the health check as required status check))
199
- - Health check workflow must pass (the CI/CD pipeline must complete successfully)
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
- 1. Patch version (poetry version patch)
97
- 2. Add version patch to git (git add pyproject.toml)
98
- 3. Update package manager (poetry self update)
99
- 4. Install packages (poetry install --with dev)
100
- 5. Update packages (poetry update --with dev (winipedia_utils forces all dependencies with * to be updated to latest compatible version))
101
- 6. Lock dependencies (poetry lock)
102
- 7. Check package manager configs (poetry check --strict)
103
- 8. Create tests (python -m winipedia_utils.testing.create_tests)
104
- 9. Lint code (ruff check --fix)
105
- 10. Format code (ruff format)
106
- 11. Check static types (mypy)
107
- 12. Check security (bandit -c pyproject.toml -r .)
108
- 13. Run tests (pytest (uses pyproject.toml as config))
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 (sets the health check as required status check))
173
- - Health check workflow must pass (the CI/CD pipeline must complete successfully)
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.29"
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
- tqdm = "*"
24
+ networkx = "*"
25
25
  setuptools = "*"
26
- defusedxml = "*"
27
- tomlkit = "*"
28
- pathspec = "*"
29
26
  pyyaml = "*"
30
- keyring = "*"
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,6 @@
1
+ """Build artifacts for the project."""
2
+
3
+ from winipedia_utils.dev.artifacts.builder import Builder
4
+
5
+ if __name__ == "__main__":
6
+ Builder.init_all_non_abstract_subclasses()
@@ -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."""