winiutils 1.1.4__tar.gz → 2.3.13__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. winiutils-2.3.13/PKG-INFO +283 -0
  2. winiutils-2.3.13/README.md +263 -0
  3. winiutils-2.3.13/pyproject.toml +120 -0
  4. winiutils-2.3.13/winiutils/dev/tests/fixtures/fixtures.py +32 -0
  5. winiutils-2.3.13/winiutils/main.py +9 -0
  6. winiutils-2.3.13/winiutils/src/__init__.py +4 -0
  7. winiutils-2.3.13/winiutils/src/data/__init__.py +8 -0
  8. winiutils-2.3.13/winiutils/src/data/dataframe/__init__.py +7 -0
  9. winiutils-2.3.13/winiutils/src/data/dataframe/cleaning.py +734 -0
  10. winiutils-2.3.13/winiutils/src/data/structures/__init__.py +8 -0
  11. winiutils-2.3.13/winiutils/src/data/structures/dicts.py +40 -0
  12. winiutils-2.3.13/winiutils/src/data/structures/text/__init__.py +7 -0
  13. winiutils-2.3.13/winiutils/src/data/structures/text/string.py +157 -0
  14. winiutils-2.3.13/winiutils/src/iterating/__init__.py +8 -0
  15. winiutils-2.3.13/winiutils/src/iterating/concurrent/__init__.py +9 -0
  16. winiutils-2.3.13/winiutils/src/iterating/concurrent/concurrent.py +301 -0
  17. winiutils-2.3.13/winiutils/src/iterating/concurrent/multiprocessing.py +186 -0
  18. winiutils-2.3.13/winiutils/src/iterating/concurrent/multithreading.py +132 -0
  19. winiutils-2.3.13/winiutils/src/iterating/iterate.py +45 -0
  20. winiutils-2.3.13/winiutils/src/oop/__init__.py +7 -0
  21. winiutils-2.3.13/winiutils/src/oop/mixins/__init__.py +8 -0
  22. {winiutils-1.1.4 → winiutils-2.3.13}/winiutils/src/oop/mixins/meta.py +71 -25
  23. winiutils-2.3.13/winiutils/src/oop/mixins/mixin.py +58 -0
  24. winiutils-2.3.13/winiutils/src/security/__init__.py +8 -0
  25. winiutils-2.3.13/winiutils/src/security/cryptography.py +100 -0
  26. winiutils-2.3.13/winiutils/src/security/keyring.py +167 -0
  27. winiutils-1.1.4/PKG-INFO +0 -443
  28. winiutils-1.1.4/README.md +0 -422
  29. winiutils-1.1.4/pyproject.toml +0 -74
  30. winiutils-1.1.4/winiutils/dev/artifacts/builder/builder.py +0 -4
  31. winiutils-1.1.4/winiutils/dev/configs/configs.py +0 -4
  32. winiutils-1.1.4/winiutils/main.py +0 -19
  33. winiutils-1.1.4/winiutils/src/__init__.py +0 -1
  34. winiutils-1.1.4/winiutils/src/data/dataframe/cleaning.py +0 -620
  35. winiutils-1.1.4/winiutils/src/data/structures/__init__.py +0 -1
  36. winiutils-1.1.4/winiutils/src/data/structures/dicts.py +0 -16
  37. winiutils-1.1.4/winiutils/src/data/structures/text/__init__.py +0 -1
  38. winiutils-1.1.4/winiutils/src/data/structures/text/string.py +0 -100
  39. winiutils-1.1.4/winiutils/src/iterating/__init__.py +0 -1
  40. winiutils-1.1.4/winiutils/src/iterating/concurrent/__init__.py +0 -1
  41. winiutils-1.1.4/winiutils/src/iterating/concurrent/concurrent.py +0 -251
  42. winiutils-1.1.4/winiutils/src/iterating/concurrent/multiprocessing.py +0 -129
  43. winiutils-1.1.4/winiutils/src/iterating/concurrent/multithreading.py +0 -93
  44. winiutils-1.1.4/winiutils/src/iterating/iterate.py +0 -29
  45. winiutils-1.1.4/winiutils/src/oop/__init__.py +0 -1
  46. winiutils-1.1.4/winiutils/src/oop/mixins/__init__.py +0 -1
  47. winiutils-1.1.4/winiutils/src/oop/mixins/mixin.py +0 -26
  48. winiutils-1.1.4/winiutils/src/resources/__init__.py +0 -1
  49. winiutils-1.1.4/winiutils/src/resources/svgs/__init__.py +0 -1
  50. winiutils-1.1.4/winiutils/src/resources/svgs/delete_garbage_can.svg +0 -2
  51. winiutils-1.1.4/winiutils/src/resources/svgs/download_arrow.svg +0 -3
  52. winiutils-1.1.4/winiutils/src/resources/svgs/exit_fullscreen_icon.svg +0 -7
  53. winiutils-1.1.4/winiutils/src/resources/svgs/fullscreen_icon.svg +0 -4
  54. winiutils-1.1.4/winiutils/src/resources/svgs/menu_icon.svg +0 -4
  55. winiutils-1.1.4/winiutils/src/resources/svgs/pause_icon.svg +0 -4
  56. winiutils-1.1.4/winiutils/src/resources/svgs/play_icon.svg +0 -17
  57. winiutils-1.1.4/winiutils/src/resources/svgs/plus_icon.svg +0 -24
  58. winiutils-1.1.4/winiutils/src/resources/svgs/svg.py +0 -15
  59. winiutils-1.1.4/winiutils/src/security/__init__.py +0 -1
  60. winiutils-1.1.4/winiutils/src/security/cryptography.py +0 -29
  61. winiutils-1.1.4/winiutils/src/security/keyring.py +0 -70
  62. {winiutils-1.1.4 → winiutils-2.3.13}/LICENSE +0 -0
  63. {winiutils-1.1.4 → winiutils-2.3.13}/winiutils/__init__.py +0 -0
  64. {winiutils-1.1.4 → winiutils-2.3.13}/winiutils/dev/__init__.py +0 -0
  65. {winiutils-1.1.4/winiutils/dev/artifacts → winiutils-2.3.13/winiutils/dev/builders}/__init__.py +0 -0
  66. {winiutils-1.1.4/winiutils/dev/artifacts/builder → winiutils-2.3.13/winiutils/dev/cli}/__init__.py +0 -0
  67. {winiutils-1.1.4 → winiutils-2.3.13}/winiutils/dev/cli/subcommands.py +0 -0
  68. {winiutils-1.1.4/winiutils/dev/cli → winiutils-2.3.13/winiutils/dev/configs}/__init__.py +0 -0
  69. {winiutils-1.1.4/winiutils/dev/configs → winiutils-2.3.13/winiutils/dev/tests}/__init__.py +0 -0
  70. {winiutils-1.1.4/winiutils/src/data → winiutils-2.3.13/winiutils/dev/tests/fixtures}/__init__.py +0 -0
  71. {winiutils-1.1.4 → winiutils-2.3.13}/winiutils/py.typed +0 -0
  72. {winiutils-1.1.4/winiutils/src/data/dataframe → winiutils-2.3.13/winiutils/resources}/__init__.py +0 -0
@@ -0,0 +1,283 @@
1
+ Metadata-Version: 2.4
2
+ Name: winiutils
3
+ Version: 2.3.13
4
+ Summary: A utility library for Python development
5
+ Author: Winipedia
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Programming Language :: Python :: 3.12
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Classifier: Programming Language :: Python :: 3.14
11
+ Requires-Dist: cryptography
12
+ Requires-Dist: defusedxml
13
+ Requires-Dist: keyring
14
+ Requires-Dist: keyrings-alt
15
+ Requires-Dist: polars
16
+ Requires-Dist: pyrig
17
+ Requires-Dist: tqdm
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+
21
+ # winiutils
22
+
23
+ <!-- tooling -->
24
+ [![pyrig](https://img.shields.io/badge/built%20with-pyrig-3776AB?logo=buildkite&logoColor=black)](https://github.com/Winipedia/pyrig)
25
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
26
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://pre-commit.com/)
27
+ <!-- code-quality -->
28
+ [![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
29
+ [![ty](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json)](https://github.com/astral-sh/ty)[![mypy](https://img.shields.io/badge/type%20checked-mypy-039dfc.svg)](https://mypy-lang.org/)
30
+ [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
31
+ [![pytest](https://img.shields.io/badge/tested%20with-pytest-46a2f1.svg?logo=pytest)](https://pytest.org/)
32
+ [![codecov](https://codecov.io/gh/Winipedia/winiutils/branch/main/graph/badge.svg)](https://codecov.io/gh/Winipedia/winiutils)
33
+ <!-- package-info -->
34
+ [![PyPI](https://img.shields.io/pypi/v/winiutils?logo=pypi&logoColor=white)](https://pypi.org/project/winiutils/)
35
+ [![Python](https://img.shields.io/badge/python-3.12|3.13|3.14-blue.svg?logo=python&logoColor=white)](https://www.python.org/)
36
+ [![License](https://img.shields.io/github/license/Winipedia/winiutils)](https://github.com/Winipedia/winiutils/blob/main/LICENSE)
37
+ <!-- ci/cd -->
38
+ [![CI](https://img.shields.io/github/actions/workflow/status/Winipedia/winiutils/health_check.yaml?label=CI&logo=github)](https://github.com/Winipedia/winiutils/actions/workflows/health_check.yaml)
39
+ [![CD](https://img.shields.io/github/actions/workflow/status/Winipedia/winiutils/release.yaml?label=CD&logo=github)](https://github.com/Winipedia/winiutils/actions/workflows/release.yaml)
40
+
41
+
42
+ ---
43
+
44
+ > A utility library for Python development
45
+
46
+ ---
47
+
48
+
49
+ ## Table of Contents
50
+
51
+ - [Features](#features)
52
+ - [Installation](#installation)
53
+ - [Quick Start](#quick-start)
54
+ - [Documentation](#documentation)
55
+ - [Modules](#modules)
56
+ - [Development](#development)
57
+ - [License](#license)
58
+
59
+ ---
60
+
61
+ ## Features
62
+
63
+ - **DataFrame Cleaning Pipeline** — Extensible Polars DataFrame cleaning with an 8-step pipeline
64
+ - **Concurrent Processing** — Unified multiprocessing and multithreading with automatic resource optimization
65
+ - **OOP Utilities** — Metaclasses and mixins for automatic method logging and instrumentation
66
+ - **Security Tools** — OS keyring integration and AES-GCM encryption utilities
67
+ - **Type Safety** — Full type hints with strict mypy compliance
68
+ - **Production Ready** — Comprehensive test coverage and logging integration
69
+
70
+ ---
71
+
72
+ ## Installation
73
+
74
+ ### Using uv (recommended)
75
+
76
+ ```bash
77
+ uv add winiutils
78
+ ```
79
+
80
+ ### Using pip
81
+
82
+ ```bash
83
+ pip install winiutils
84
+ ```
85
+
86
+ ### From source
87
+
88
+ ```bash
89
+ git clone https://github.com/Winipedia/winiutils.git
90
+ cd winiutils
91
+ uv sync
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Quick Start
97
+
98
+ ### DataFrame Cleaning
99
+
100
+ ```python
101
+ from winiutils.src.data.dataframe.cleaning import CleaningDF
102
+ import polars as pl
103
+
104
+ class UserDataCleaner(CleaningDF):
105
+ """Clean and standardize user data."""
106
+
107
+ USER_ID = "user_id"
108
+ EMAIL = "email"
109
+ SCORE = "score"
110
+
111
+ @classmethod
112
+ def get_rename_map(cls):
113
+ return {cls.USER_ID: "UserId", cls.EMAIL: "Email", cls.SCORE: "Score"}
114
+
115
+ @classmethod
116
+ def get_col_dtype_map(cls):
117
+ return {cls.USER_ID: pl.Int64, cls.EMAIL: pl.Utf8, cls.SCORE: pl.Float64}
118
+
119
+ # ... implement other abstract methods
120
+
121
+ # Usage
122
+ cleaned = UserDataCleaner(raw_dataframe)
123
+ result = cleaned.df
124
+ ```
125
+
126
+ ### Concurrent Processing
127
+
128
+ ```python
129
+ from winiutils.src.iterating.concurrent.multiprocessing import multiprocess_loop
130
+ from winiutils.src.iterating.concurrent.multithreading import multithread_loop
131
+
132
+ # CPU-bound tasks (multiprocessing)
133
+ def process_chunk(data, config):
134
+ return heavy_computation(data, config)
135
+
136
+ results = multiprocess_loop(
137
+ process_function=process_chunk,
138
+ process_args=[(chunk,) for chunk in data_chunks],
139
+ process_args_static=(config,),
140
+ process_args_len=len(data_chunks),
141
+ )
142
+
143
+ # I/O-bound tasks (multithreading)
144
+ def fetch_url(url, headers):
145
+ return requests.get(url, headers=headers)
146
+
147
+ results = multithread_loop(
148
+ process_function=fetch_url,
149
+ process_args=[(url,) for url in urls],
150
+ process_args_static=(headers,),
151
+ process_args_len=len(urls),
152
+ )
153
+ ```
154
+
155
+ ### Automatic Method Logging
156
+
157
+ ```python
158
+ from winiutils.src.oop.mixins.mixin import ABCLoggingMixin
159
+
160
+ class MyService(ABCLoggingMixin):
161
+ def process_data(self, data: list) -> dict:
162
+ # Automatically logged with timing
163
+ return {"processed": len(data)}
164
+
165
+ # Logs: "MyService - Calling process_data with (...) and {...}"
166
+ # Logs: "MyService - process_data finished with 0.5 seconds -> returning {...}"
167
+ ```
168
+
169
+ ### Encryption with Keyring
170
+
171
+ ```python
172
+ from winiutils.src.security.keyring import get_or_create_aes_gcm
173
+ from winiutils.src.security.cryptography import encrypt_with_aes_gcm, decrypt_with_aes_gcm
174
+
175
+ # Get or create encryption key (stored in OS keyring)
176
+ aes_gcm, key = get_or_create_aes_gcm("my_app", "user@example.com")
177
+
178
+ # Encrypt and decrypt
179
+ encrypted = encrypt_with_aes_gcm(aes_gcm, b"Secret message")
180
+ decrypted = decrypt_with_aes_gcm(aes_gcm, encrypted)
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Documentation
186
+
187
+ Full documentation is available in the [docs](./docs/) folder:
188
+
189
+ - [**Data Processing**](./docs/data.md) — DataFrame cleaning pipeline and data structures
190
+ - [**Iterating & Concurrency**](./docs/iterating.md) — Parallel processing utilities
191
+ - [**OOP Utilities**](./docs/oop.md) — Metaclasses and mixins
192
+ - [**Security**](./docs/security.md) — Encryption and keyring integration
193
+
194
+ ---
195
+
196
+ ## Modules
197
+
198
+ | Module | Description |
199
+ |--------|-------------|
200
+ | [`winiutils.src.data`](./docs/data.md) | DataFrame cleaning pipeline and data structure utilities |
201
+ | [`winiutils.src.iterating`](./docs/iterating.md) | Concurrent processing with multiprocessing and multithreading |
202
+ | [`winiutils.src.oop`](./docs/oop.md) | Metaclasses and mixins for automatic method logging |
203
+ | [`winiutils.src.security`](./docs/security.md) | AES-GCM encryption and OS keyring integration |
204
+
205
+ ---
206
+
207
+ ## Development
208
+
209
+ ### Setup
210
+
211
+ ```bash
212
+ git clone https://github.com/Winipedia/winiutils.git
213
+ cd winiutils
214
+ uv sync --all-groups
215
+ ```
216
+
217
+ ### Running Tests
218
+
219
+ ```bash
220
+ uv run pytest
221
+ ```
222
+
223
+ ### Code Quality
224
+
225
+ ```bash
226
+ # Linting
227
+ uv run ruff check .
228
+
229
+ # Type checking
230
+ uv run mypy .
231
+
232
+ # Security scanning
233
+ uv run bandit -r winiutils/
234
+ ```
235
+
236
+ ### Pre-commit Hooks
237
+
238
+ ```bash
239
+ uv run pre-commit install
240
+ uv run pre-commit run --all-files
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Project Structure
246
+
247
+ ```
248
+ winiutils/
249
+ ├── src/ # Main source code
250
+ │ ├── data/ # Data processing
251
+ │ │ ├── dataframe/ # Polars DataFrame cleaning
252
+ │ │ └── structures/ # Dicts, text utilities
253
+ │ ├── iterating/ # Iteration utilities
254
+ │ │ └── concurrent/ # Multiprocessing & multithreading
255
+ │ ├── oop/ # OOP patterns
256
+ │ │ └── mixins/ # Logging metaclass & mixin
257
+ │ └── security/ # Security utilities
258
+ │ ├── cryptography.py # AES-GCM encryption
259
+ │ └── keyring.py # OS keyring integration
260
+ ├── dev/ # Development tools
261
+ │ ├── cli/ # CLI subcommands
262
+ │ └── tests/fixtures/ # Test fixtures
263
+ ├── docs/ # Documentation
264
+ └── tests/ # Test suite
265
+ ```
266
+
267
+ ---
268
+
269
+ ## License
270
+
271
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
272
+
273
+ ---
274
+
275
+ ## Contributing
276
+
277
+ Contributions are welcome! Please ensure:
278
+
279
+ 1. All tests pass (`uv run pytest`)
280
+ 2. Code passes linting (`uv run ruff check .`)
281
+ 3. Types are correct (`uv run mypy .`)
282
+ 4. New features include tests
283
+ 5. Documentation is updated for API changes
@@ -0,0 +1,263 @@
1
+ # winiutils
2
+
3
+ <!-- tooling -->
4
+ [![pyrig](https://img.shields.io/badge/built%20with-pyrig-3776AB?logo=buildkite&logoColor=black)](https://github.com/Winipedia/pyrig)
5
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
6
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://pre-commit.com/)
7
+ <!-- code-quality -->
8
+ [![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
9
+ [![ty](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json)](https://github.com/astral-sh/ty)[![mypy](https://img.shields.io/badge/type%20checked-mypy-039dfc.svg)](https://mypy-lang.org/)
10
+ [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
11
+ [![pytest](https://img.shields.io/badge/tested%20with-pytest-46a2f1.svg?logo=pytest)](https://pytest.org/)
12
+ [![codecov](https://codecov.io/gh/Winipedia/winiutils/branch/main/graph/badge.svg)](https://codecov.io/gh/Winipedia/winiutils)
13
+ <!-- package-info -->
14
+ [![PyPI](https://img.shields.io/pypi/v/winiutils?logo=pypi&logoColor=white)](https://pypi.org/project/winiutils/)
15
+ [![Python](https://img.shields.io/badge/python-3.12|3.13|3.14-blue.svg?logo=python&logoColor=white)](https://www.python.org/)
16
+ [![License](https://img.shields.io/github/license/Winipedia/winiutils)](https://github.com/Winipedia/winiutils/blob/main/LICENSE)
17
+ <!-- ci/cd -->
18
+ [![CI](https://img.shields.io/github/actions/workflow/status/Winipedia/winiutils/health_check.yaml?label=CI&logo=github)](https://github.com/Winipedia/winiutils/actions/workflows/health_check.yaml)
19
+ [![CD](https://img.shields.io/github/actions/workflow/status/Winipedia/winiutils/release.yaml?label=CD&logo=github)](https://github.com/Winipedia/winiutils/actions/workflows/release.yaml)
20
+
21
+
22
+ ---
23
+
24
+ > A utility library for Python development
25
+
26
+ ---
27
+
28
+
29
+ ## Table of Contents
30
+
31
+ - [Features](#features)
32
+ - [Installation](#installation)
33
+ - [Quick Start](#quick-start)
34
+ - [Documentation](#documentation)
35
+ - [Modules](#modules)
36
+ - [Development](#development)
37
+ - [License](#license)
38
+
39
+ ---
40
+
41
+ ## Features
42
+
43
+ - **DataFrame Cleaning Pipeline** — Extensible Polars DataFrame cleaning with an 8-step pipeline
44
+ - **Concurrent Processing** — Unified multiprocessing and multithreading with automatic resource optimization
45
+ - **OOP Utilities** — Metaclasses and mixins for automatic method logging and instrumentation
46
+ - **Security Tools** — OS keyring integration and AES-GCM encryption utilities
47
+ - **Type Safety** — Full type hints with strict mypy compliance
48
+ - **Production Ready** — Comprehensive test coverage and logging integration
49
+
50
+ ---
51
+
52
+ ## Installation
53
+
54
+ ### Using uv (recommended)
55
+
56
+ ```bash
57
+ uv add winiutils
58
+ ```
59
+
60
+ ### Using pip
61
+
62
+ ```bash
63
+ pip install winiutils
64
+ ```
65
+
66
+ ### From source
67
+
68
+ ```bash
69
+ git clone https://github.com/Winipedia/winiutils.git
70
+ cd winiutils
71
+ uv sync
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Quick Start
77
+
78
+ ### DataFrame Cleaning
79
+
80
+ ```python
81
+ from winiutils.src.data.dataframe.cleaning import CleaningDF
82
+ import polars as pl
83
+
84
+ class UserDataCleaner(CleaningDF):
85
+ """Clean and standardize user data."""
86
+
87
+ USER_ID = "user_id"
88
+ EMAIL = "email"
89
+ SCORE = "score"
90
+
91
+ @classmethod
92
+ def get_rename_map(cls):
93
+ return {cls.USER_ID: "UserId", cls.EMAIL: "Email", cls.SCORE: "Score"}
94
+
95
+ @classmethod
96
+ def get_col_dtype_map(cls):
97
+ return {cls.USER_ID: pl.Int64, cls.EMAIL: pl.Utf8, cls.SCORE: pl.Float64}
98
+
99
+ # ... implement other abstract methods
100
+
101
+ # Usage
102
+ cleaned = UserDataCleaner(raw_dataframe)
103
+ result = cleaned.df
104
+ ```
105
+
106
+ ### Concurrent Processing
107
+
108
+ ```python
109
+ from winiutils.src.iterating.concurrent.multiprocessing import multiprocess_loop
110
+ from winiutils.src.iterating.concurrent.multithreading import multithread_loop
111
+
112
+ # CPU-bound tasks (multiprocessing)
113
+ def process_chunk(data, config):
114
+ return heavy_computation(data, config)
115
+
116
+ results = multiprocess_loop(
117
+ process_function=process_chunk,
118
+ process_args=[(chunk,) for chunk in data_chunks],
119
+ process_args_static=(config,),
120
+ process_args_len=len(data_chunks),
121
+ )
122
+
123
+ # I/O-bound tasks (multithreading)
124
+ def fetch_url(url, headers):
125
+ return requests.get(url, headers=headers)
126
+
127
+ results = multithread_loop(
128
+ process_function=fetch_url,
129
+ process_args=[(url,) for url in urls],
130
+ process_args_static=(headers,),
131
+ process_args_len=len(urls),
132
+ )
133
+ ```
134
+
135
+ ### Automatic Method Logging
136
+
137
+ ```python
138
+ from winiutils.src.oop.mixins.mixin import ABCLoggingMixin
139
+
140
+ class MyService(ABCLoggingMixin):
141
+ def process_data(self, data: list) -> dict:
142
+ # Automatically logged with timing
143
+ return {"processed": len(data)}
144
+
145
+ # Logs: "MyService - Calling process_data with (...) and {...}"
146
+ # Logs: "MyService - process_data finished with 0.5 seconds -> returning {...}"
147
+ ```
148
+
149
+ ### Encryption with Keyring
150
+
151
+ ```python
152
+ from winiutils.src.security.keyring import get_or_create_aes_gcm
153
+ from winiutils.src.security.cryptography import encrypt_with_aes_gcm, decrypt_with_aes_gcm
154
+
155
+ # Get or create encryption key (stored in OS keyring)
156
+ aes_gcm, key = get_or_create_aes_gcm("my_app", "user@example.com")
157
+
158
+ # Encrypt and decrypt
159
+ encrypted = encrypt_with_aes_gcm(aes_gcm, b"Secret message")
160
+ decrypted = decrypt_with_aes_gcm(aes_gcm, encrypted)
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Documentation
166
+
167
+ Full documentation is available in the [docs](./docs/) folder:
168
+
169
+ - [**Data Processing**](./docs/data.md) — DataFrame cleaning pipeline and data structures
170
+ - [**Iterating & Concurrency**](./docs/iterating.md) — Parallel processing utilities
171
+ - [**OOP Utilities**](./docs/oop.md) — Metaclasses and mixins
172
+ - [**Security**](./docs/security.md) — Encryption and keyring integration
173
+
174
+ ---
175
+
176
+ ## Modules
177
+
178
+ | Module | Description |
179
+ |--------|-------------|
180
+ | [`winiutils.src.data`](./docs/data.md) | DataFrame cleaning pipeline and data structure utilities |
181
+ | [`winiutils.src.iterating`](./docs/iterating.md) | Concurrent processing with multiprocessing and multithreading |
182
+ | [`winiutils.src.oop`](./docs/oop.md) | Metaclasses and mixins for automatic method logging |
183
+ | [`winiutils.src.security`](./docs/security.md) | AES-GCM encryption and OS keyring integration |
184
+
185
+ ---
186
+
187
+ ## Development
188
+
189
+ ### Setup
190
+
191
+ ```bash
192
+ git clone https://github.com/Winipedia/winiutils.git
193
+ cd winiutils
194
+ uv sync --all-groups
195
+ ```
196
+
197
+ ### Running Tests
198
+
199
+ ```bash
200
+ uv run pytest
201
+ ```
202
+
203
+ ### Code Quality
204
+
205
+ ```bash
206
+ # Linting
207
+ uv run ruff check .
208
+
209
+ # Type checking
210
+ uv run mypy .
211
+
212
+ # Security scanning
213
+ uv run bandit -r winiutils/
214
+ ```
215
+
216
+ ### Pre-commit Hooks
217
+
218
+ ```bash
219
+ uv run pre-commit install
220
+ uv run pre-commit run --all-files
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Project Structure
226
+
227
+ ```
228
+ winiutils/
229
+ ├── src/ # Main source code
230
+ │ ├── data/ # Data processing
231
+ │ │ ├── dataframe/ # Polars DataFrame cleaning
232
+ │ │ └── structures/ # Dicts, text utilities
233
+ │ ├── iterating/ # Iteration utilities
234
+ │ │ └── concurrent/ # Multiprocessing & multithreading
235
+ │ ├── oop/ # OOP patterns
236
+ │ │ └── mixins/ # Logging metaclass & mixin
237
+ │ └── security/ # Security utilities
238
+ │ ├── cryptography.py # AES-GCM encryption
239
+ │ └── keyring.py # OS keyring integration
240
+ ├── dev/ # Development tools
241
+ │ ├── cli/ # CLI subcommands
242
+ │ └── tests/fixtures/ # Test fixtures
243
+ ├── docs/ # Documentation
244
+ └── tests/ # Test suite
245
+ ```
246
+
247
+ ---
248
+
249
+ ## License
250
+
251
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
252
+
253
+ ---
254
+
255
+ ## Contributing
256
+
257
+ Contributions are welcome! Please ensure:
258
+
259
+ 1. All tests pass (`uv run pytest`)
260
+ 2. Code passes linting (`uv run ruff check .`)
261
+ 3. Types are correct (`uv run mypy .`)
262
+ 4. New features include tests
263
+ 5. Documentation is updated for API changes
@@ -0,0 +1,120 @@
1
+ [project]
2
+ name = "winiutils"
3
+ version = "2.3.13"
4
+ description = "A utility library for Python development"
5
+ license = "MIT"
6
+ requires-python = ">=3.12"
7
+ authors = [
8
+ {name = "Winipedia"},
9
+ ]
10
+ readme = "README.md"
11
+ dependencies = [
12
+ "cryptography",
13
+ "defusedxml",
14
+ "keyring",
15
+ "keyrings-alt",
16
+ "polars",
17
+ "pyrig",
18
+ "tqdm",
19
+ ]
20
+ classifiers = [
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Programming Language :: Python :: 3.14",
24
+ ]
25
+ license-files = [
26
+ "LICENSE",
27
+ ]
28
+
29
+ [project.scripts]
30
+ winipedia-utils = "pyrig.dev.cli.cli:main"
31
+ winiutils = "pyrig.dev.cli.cli:main"
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "bandit",
36
+ "dotenv",
37
+ "mypy",
38
+ "pillow",
39
+ "pre-commit",
40
+ "pygithub",
41
+ "pyinstaller",
42
+ "pytest",
43
+ "pytest-cov",
44
+ "pytest-mock",
45
+ "pyyaml",
46
+ "ruff",
47
+ "setuptools",
48
+ "tenacity",
49
+ "tomlkit",
50
+ "ty",
51
+ "types-defusedxml",
52
+ "types-pyinstaller",
53
+ "types-pyyaml",
54
+ "types-setuptools",
55
+ "types-tqdm",
56
+ ]
57
+
58
+ [build-system]
59
+ requires = [
60
+ "uv_build",
61
+ ]
62
+ build-backend = "uv_build"
63
+
64
+ [tool.uv.build-backend]
65
+ module-name = "winiutils"
66
+ module-root = ""
67
+
68
+ [tool.ruff]
69
+ exclude = [
70
+ ".*",
71
+ "**/migrations/*.py",
72
+ ]
73
+
74
+ [tool.ruff.lint]
75
+ select = [
76
+ "ALL",
77
+ ]
78
+ ignore = [
79
+ "D203",
80
+ "D213",
81
+ "COM812",
82
+ "ANN401",
83
+ ]
84
+ fixable = [
85
+ "ALL",
86
+ ]
87
+
88
+ [tool.ruff.lint.per-file-ignores]
89
+ "tests/**/*.py" = [
90
+ "S101",
91
+ ]
92
+ "**/tests/**/*.py" = [
93
+ "S101",
94
+ ]
95
+
96
+ [tool.ruff.lint.pydocstyle]
97
+ convention = "google"
98
+
99
+ [tool.mypy]
100
+ strict = true
101
+ warn_unreachable = true
102
+ show_error_codes = true
103
+ files = "."
104
+
105
+ [tool.pytest.ini_options]
106
+ testpaths = [
107
+ "tests",
108
+ ]
109
+ addopts = "--cov=winiutils --cov-report=term-missing --cov-fail-under=90"
110
+
111
+ [tool.bandit]
112
+ exclude_dirs = [
113
+ ".*",
114
+ ]
115
+
116
+ [tool.bandit.assert_used]
117
+ skips = [
118
+ "*/tests/*.py",
119
+ "*test_*.py",
120
+ ]
@@ -0,0 +1,32 @@
1
+ """Fixtures for testing.
2
+
3
+ This module provides custom fixtures for pytest that can be pluued into tests
4
+ across the entire test suite.
5
+ All fixtures defined under the fixtures package are auto plugged in automatically
6
+ by pyrig via the pytest_plugins mechanism.
7
+ """
8
+
9
+ from collections.abc import Callable, Iterator
10
+
11
+ import keyring
12
+ import pytest
13
+
14
+
15
+ @pytest.fixture
16
+ def keyring_cleanup() -> Iterator[Callable[[str, str], None]]:
17
+ """Factory fixture to clean up keyring entries after test.
18
+
19
+ Usage:
20
+ def test_something(keyring_cleanup):
21
+ keyring_cleanup("service_name", "username")
22
+ # ... test code that creates keyring entries ...
23
+ """
24
+ entries: list[tuple[str, str]] = []
25
+
26
+ def register(service_name: str, username: str) -> None:
27
+ entries.append((service_name, username))
28
+
29
+ yield register
30
+
31
+ for service_name, username in entries:
32
+ keyring.delete_password(service_name, username)
@@ -0,0 +1,9 @@
1
+ """Main entrypoint for the project."""
2
+
3
+
4
+ def main() -> None:
5
+ """Main entrypoint for the project."""
6
+
7
+
8
+ if __name__ == "__main__":
9
+ main()