winiutils 1.1.4__tar.gz → 2.2.32__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.
- winiutils-2.2.32/PKG-INFO +265 -0
- winiutils-2.2.32/README.md +249 -0
- winiutils-2.2.32/pyproject.toml +98 -0
- winiutils-2.2.32/winiutils/dev/tests/fixtures/fixtures.py +32 -0
- {winiutils-1.1.4 → winiutils-2.2.32}/winiutils/main.py +1 -1
- winiutils-2.2.32/winiutils/src/__init__.py +4 -0
- winiutils-2.2.32/winiutils/src/data/__init__.py +8 -0
- winiutils-2.2.32/winiutils/src/data/dataframe/__init__.py +7 -0
- winiutils-2.2.32/winiutils/src/data/dataframe/cleaning.py +734 -0
- winiutils-2.2.32/winiutils/src/data/structures/__init__.py +8 -0
- winiutils-2.2.32/winiutils/src/data/structures/dicts.py +40 -0
- winiutils-2.2.32/winiutils/src/data/structures/text/__init__.py +7 -0
- winiutils-2.2.32/winiutils/src/data/structures/text/string.py +157 -0
- winiutils-2.2.32/winiutils/src/iterating/__init__.py +8 -0
- winiutils-2.2.32/winiutils/src/iterating/concurrent/__init__.py +9 -0
- winiutils-2.2.32/winiutils/src/iterating/concurrent/concurrent.py +301 -0
- winiutils-2.2.32/winiutils/src/iterating/concurrent/multiprocessing.py +186 -0
- winiutils-2.2.32/winiutils/src/iterating/concurrent/multithreading.py +132 -0
- winiutils-2.2.32/winiutils/src/iterating/iterate.py +45 -0
- winiutils-2.2.32/winiutils/src/oop/__init__.py +7 -0
- winiutils-2.2.32/winiutils/src/oop/mixins/__init__.py +8 -0
- {winiutils-1.1.4 → winiutils-2.2.32}/winiutils/src/oop/mixins/meta.py +67 -22
- winiutils-2.2.32/winiutils/src/oop/mixins/mixin.py +58 -0
- winiutils-2.2.32/winiutils/src/security/__init__.py +8 -0
- winiutils-2.2.32/winiutils/src/security/cryptography.py +100 -0
- winiutils-2.2.32/winiutils/src/security/keyring.py +167 -0
- winiutils-1.1.4/LICENSE +0 -21
- winiutils-1.1.4/PKG-INFO +0 -443
- winiutils-1.1.4/README.md +0 -422
- winiutils-1.1.4/pyproject.toml +0 -74
- winiutils-1.1.4/winiutils/dev/artifacts/builder/builder.py +0 -4
- winiutils-1.1.4/winiutils/dev/configs/configs.py +0 -4
- winiutils-1.1.4/winiutils/src/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/data/dataframe/cleaning.py +0 -620
- winiutils-1.1.4/winiutils/src/data/structures/dicts.py +0 -16
- winiutils-1.1.4/winiutils/src/data/structures/text/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/data/structures/text/string.py +0 -100
- winiutils-1.1.4/winiutils/src/iterating/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/iterating/concurrent/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/iterating/concurrent/concurrent.py +0 -251
- winiutils-1.1.4/winiutils/src/iterating/concurrent/multiprocessing.py +0 -129
- winiutils-1.1.4/winiutils/src/iterating/concurrent/multithreading.py +0 -93
- winiutils-1.1.4/winiutils/src/iterating/iterate.py +0 -29
- winiutils-1.1.4/winiutils/src/oop/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/oop/mixins/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/oop/mixins/mixin.py +0 -26
- winiutils-1.1.4/winiutils/src/resources/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/resources/svgs/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/resources/svgs/delete_garbage_can.svg +0 -2
- winiutils-1.1.4/winiutils/src/resources/svgs/download_arrow.svg +0 -3
- winiutils-1.1.4/winiutils/src/resources/svgs/exit_fullscreen_icon.svg +0 -7
- winiutils-1.1.4/winiutils/src/resources/svgs/fullscreen_icon.svg +0 -4
- winiutils-1.1.4/winiutils/src/resources/svgs/menu_icon.svg +0 -4
- winiutils-1.1.4/winiutils/src/resources/svgs/pause_icon.svg +0 -4
- winiutils-1.1.4/winiutils/src/resources/svgs/play_icon.svg +0 -17
- winiutils-1.1.4/winiutils/src/resources/svgs/plus_icon.svg +0 -24
- winiutils-1.1.4/winiutils/src/resources/svgs/svg.py +0 -15
- winiutils-1.1.4/winiutils/src/security/__init__.py +0 -1
- winiutils-1.1.4/winiutils/src/security/cryptography.py +0 -29
- winiutils-1.1.4/winiutils/src/security/keyring.py +0 -70
- {winiutils-1.1.4 → winiutils-2.2.32}/winiutils/__init__.py +0 -0
- {winiutils-1.1.4 → winiutils-2.2.32}/winiutils/dev/__init__.py +0 -0
- {winiutils-1.1.4 → winiutils-2.2.32}/winiutils/dev/artifacts/__init__.py +0 -0
- {winiutils-1.1.4/winiutils/dev/artifacts/builder → winiutils-2.2.32/winiutils/dev/artifacts/builders}/__init__.py +0 -0
- {winiutils-1.1.4/winiutils/dev/cli → winiutils-2.2.32/winiutils/dev/artifacts/resources}/__init__.py +0 -0
- {winiutils-1.1.4/winiutils/dev/configs → winiutils-2.2.32/winiutils/dev/cli}/__init__.py +0 -0
- {winiutils-1.1.4 → winiutils-2.2.32}/winiutils/dev/cli/subcommands.py +0 -0
- {winiutils-1.1.4/winiutils/src/data → winiutils-2.2.32/winiutils/dev/configs}/__init__.py +0 -0
- {winiutils-1.1.4/winiutils/src/data/dataframe → winiutils-2.2.32/winiutils/dev/tests}/__init__.py +0 -0
- {winiutils-1.1.4/winiutils/src/data/structures → winiutils-2.2.32/winiutils/dev/tests/fixtures}/__init__.py +0 -0
- {winiutils-1.1.4 → winiutils-2.2.32}/winiutils/py.typed +0 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: winiutils
|
|
3
|
+
Version: 2.2.32
|
|
4
|
+
Summary: A package with many utility functions
|
|
5
|
+
Author: Winipedia
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Dist: cryptography
|
|
8
|
+
Requires-Dist: defusedxml
|
|
9
|
+
Requires-Dist: keyring
|
|
10
|
+
Requires-Dist: keyrings-alt
|
|
11
|
+
Requires-Dist: polars
|
|
12
|
+
Requires-Dist: pyrig
|
|
13
|
+
Requires-Dist: tqdm
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# winiutils
|
|
18
|
+
|
|
19
|
+
[](https://github.com/Winipedia/pyrig)
|
|
20
|
+
[](https://www.python.org/downloads/)
|
|
21
|
+
[](https://opensource.org/licenses/MIT)
|
|
22
|
+
[](https://github.com/astral-sh/ruff)
|
|
23
|
+
[](https://mypy-lang.org/)
|
|
24
|
+
|
|
25
|
+
A comprehensive Python utility library providing production-ready tools for data processing, concurrent execution, security, and object-oriented programming patterns.
|
|
26
|
+
|
|
27
|
+
> Built with [pyrig](https://github.com/Winipedia/pyrig)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Table of Contents
|
|
32
|
+
|
|
33
|
+
- [Features](#features)
|
|
34
|
+
- [Installation](#installation)
|
|
35
|
+
- [Quick Start](#quick-start)
|
|
36
|
+
- [Documentation](#documentation)
|
|
37
|
+
- [Modules](#modules)
|
|
38
|
+
- [Development](#development)
|
|
39
|
+
- [License](#license)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- **DataFrame Cleaning Pipeline** — Extensible Polars DataFrame cleaning with an 8-step pipeline
|
|
46
|
+
- **Concurrent Processing** — Unified multiprocessing and multithreading with automatic resource optimization
|
|
47
|
+
- **OOP Utilities** — Metaclasses and mixins for automatic method logging and instrumentation
|
|
48
|
+
- **Security Tools** — OS keyring integration and AES-GCM encryption utilities
|
|
49
|
+
- **Type Safety** — Full type hints with strict mypy compliance
|
|
50
|
+
- **Production Ready** — Comprehensive test coverage and logging integration
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
### Using uv (recommended)
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv add winiutils
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Using pip
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install winiutils
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### From source
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://github.com/Winipedia/winiutils.git
|
|
72
|
+
cd winiutils
|
|
73
|
+
uv sync
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
### DataFrame Cleaning
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from winiutils.src.data.dataframe.cleaning import CleaningDF
|
|
84
|
+
import polars as pl
|
|
85
|
+
|
|
86
|
+
class UserDataCleaner(CleaningDF):
|
|
87
|
+
"""Clean and standardize user data."""
|
|
88
|
+
|
|
89
|
+
USER_ID = "user_id"
|
|
90
|
+
EMAIL = "email"
|
|
91
|
+
SCORE = "score"
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def get_rename_map(cls):
|
|
95
|
+
return {cls.USER_ID: "UserId", cls.EMAIL: "Email", cls.SCORE: "Score"}
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def get_col_dtype_map(cls):
|
|
99
|
+
return {cls.USER_ID: pl.Int64, cls.EMAIL: pl.Utf8, cls.SCORE: pl.Float64}
|
|
100
|
+
|
|
101
|
+
# ... implement other abstract methods
|
|
102
|
+
|
|
103
|
+
# Usage
|
|
104
|
+
cleaned = UserDataCleaner(raw_dataframe)
|
|
105
|
+
result = cleaned.df
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Concurrent Processing
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from winiutils.src.iterating.concurrent.multiprocessing import multiprocess_loop
|
|
112
|
+
from winiutils.src.iterating.concurrent.multithreading import multithread_loop
|
|
113
|
+
|
|
114
|
+
# CPU-bound tasks (multiprocessing)
|
|
115
|
+
def process_chunk(data, config):
|
|
116
|
+
return heavy_computation(data, config)
|
|
117
|
+
|
|
118
|
+
results = multiprocess_loop(
|
|
119
|
+
process_function=process_chunk,
|
|
120
|
+
process_args=[(chunk,) for chunk in data_chunks],
|
|
121
|
+
process_args_static=(config,),
|
|
122
|
+
process_args_len=len(data_chunks),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# I/O-bound tasks (multithreading)
|
|
126
|
+
def fetch_url(url, headers):
|
|
127
|
+
return requests.get(url, headers=headers)
|
|
128
|
+
|
|
129
|
+
results = multithread_loop(
|
|
130
|
+
process_function=fetch_url,
|
|
131
|
+
process_args=[(url,) for url in urls],
|
|
132
|
+
process_args_static=(headers,),
|
|
133
|
+
process_args_len=len(urls),
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Automatic Method Logging
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from winiutils.src.oop.mixins.mixin import ABCLoggingMixin
|
|
141
|
+
|
|
142
|
+
class MyService(ABCLoggingMixin):
|
|
143
|
+
def process_data(self, data: list) -> dict:
|
|
144
|
+
# Automatically logged with timing
|
|
145
|
+
return {"processed": len(data)}
|
|
146
|
+
|
|
147
|
+
# Logs: "MyService - Calling process_data with (...) and {...}"
|
|
148
|
+
# Logs: "MyService - process_data finished with 0.5 seconds -> returning {...}"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Encryption with Keyring
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from winiutils.src.security.keyring import get_or_create_aes_gcm
|
|
155
|
+
from winiutils.src.security.cryptography import encrypt_with_aes_gcm, decrypt_with_aes_gcm
|
|
156
|
+
|
|
157
|
+
# Get or create encryption key (stored in OS keyring)
|
|
158
|
+
aes_gcm, key = get_or_create_aes_gcm("my_app", "user@example.com")
|
|
159
|
+
|
|
160
|
+
# Encrypt and decrypt
|
|
161
|
+
encrypted = encrypt_with_aes_gcm(aes_gcm, b"Secret message")
|
|
162
|
+
decrypted = decrypt_with_aes_gcm(aes_gcm, encrypted)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Documentation
|
|
168
|
+
|
|
169
|
+
Full documentation is available in the [docs](./docs/) folder:
|
|
170
|
+
|
|
171
|
+
- [**Data Processing**](./docs/data.md) — DataFrame cleaning pipeline and data structures
|
|
172
|
+
- [**Iterating & Concurrency**](./docs/iterating.md) — Parallel processing utilities
|
|
173
|
+
- [**OOP Utilities**](./docs/oop.md) — Metaclasses and mixins
|
|
174
|
+
- [**Security**](./docs/security.md) — Encryption and keyring integration
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Modules
|
|
179
|
+
|
|
180
|
+
| Module | Description |
|
|
181
|
+
|--------|-------------|
|
|
182
|
+
| [`winiutils.src.data`](./docs/data.md) | DataFrame cleaning pipeline and data structure utilities |
|
|
183
|
+
| [`winiutils.src.iterating`](./docs/iterating.md) | Concurrent processing with multiprocessing and multithreading |
|
|
184
|
+
| [`winiutils.src.oop`](./docs/oop.md) | Metaclasses and mixins for automatic method logging |
|
|
185
|
+
| [`winiutils.src.security`](./docs/security.md) | AES-GCM encryption and OS keyring integration |
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Development
|
|
190
|
+
|
|
191
|
+
### Setup
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
git clone https://github.com/Winipedia/winiutils.git
|
|
195
|
+
cd winiutils
|
|
196
|
+
uv sync --all-groups
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Running Tests
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
uv run pytest
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Code Quality
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Linting
|
|
209
|
+
uv run ruff check .
|
|
210
|
+
|
|
211
|
+
# Type checking
|
|
212
|
+
uv run mypy .
|
|
213
|
+
|
|
214
|
+
# Security scanning
|
|
215
|
+
uv run bandit -r winiutils/
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Pre-commit Hooks
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
uv run pre-commit install
|
|
222
|
+
uv run pre-commit run --all-files
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Project Structure
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
winiutils/
|
|
231
|
+
├── src/ # Main source code
|
|
232
|
+
│ ├── data/ # Data processing
|
|
233
|
+
│ │ ├── dataframe/ # Polars DataFrame cleaning
|
|
234
|
+
│ │ └── structures/ # Dicts, text utilities
|
|
235
|
+
│ ├── iterating/ # Iteration utilities
|
|
236
|
+
│ │ └── concurrent/ # Multiprocessing & multithreading
|
|
237
|
+
│ ├── oop/ # OOP patterns
|
|
238
|
+
│ │ └── mixins/ # Logging metaclass & mixin
|
|
239
|
+
│ └── security/ # Security utilities
|
|
240
|
+
│ ├── cryptography.py # AES-GCM encryption
|
|
241
|
+
│ └── keyring.py # OS keyring integration
|
|
242
|
+
├── dev/ # Development tools
|
|
243
|
+
│ ├── cli/ # CLI subcommands
|
|
244
|
+
│ └── tests/fixtures/ # Test fixtures
|
|
245
|
+
├── docs/ # Documentation
|
|
246
|
+
└── tests/ # Test suite
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Contributing
|
|
258
|
+
|
|
259
|
+
Contributions are welcome! Please ensure:
|
|
260
|
+
|
|
261
|
+
1. All tests pass (`uv run pytest`)
|
|
262
|
+
2. Code passes linting (`uv run ruff check .`)
|
|
263
|
+
3. Types are correct (`uv run mypy .`)
|
|
264
|
+
4. New features include tests
|
|
265
|
+
5. Documentation is updated for API changes
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# winiutils
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Winipedia/pyrig)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://github.com/astral-sh/ruff)
|
|
7
|
+
[](https://mypy-lang.org/)
|
|
8
|
+
|
|
9
|
+
A comprehensive Python utility library providing production-ready tools for data processing, concurrent execution, security, and object-oriented programming patterns.
|
|
10
|
+
|
|
11
|
+
> Built with [pyrig](https://github.com/Winipedia/pyrig)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
- [Features](#features)
|
|
18
|
+
- [Installation](#installation)
|
|
19
|
+
- [Quick Start](#quick-start)
|
|
20
|
+
- [Documentation](#documentation)
|
|
21
|
+
- [Modules](#modules)
|
|
22
|
+
- [Development](#development)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **DataFrame Cleaning Pipeline** — Extensible Polars DataFrame cleaning with an 8-step pipeline
|
|
30
|
+
- **Concurrent Processing** — Unified multiprocessing and multithreading with automatic resource optimization
|
|
31
|
+
- **OOP Utilities** — Metaclasses and mixins for automatic method logging and instrumentation
|
|
32
|
+
- **Security Tools** — OS keyring integration and AES-GCM encryption utilities
|
|
33
|
+
- **Type Safety** — Full type hints with strict mypy compliance
|
|
34
|
+
- **Production Ready** — Comprehensive test coverage and logging integration
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
### Using uv (recommended)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv add winiutils
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Using pip
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install winiutils
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### From source
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git clone https://github.com/Winipedia/winiutils.git
|
|
56
|
+
cd winiutils
|
|
57
|
+
uv sync
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
### DataFrame Cleaning
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from winiutils.src.data.dataframe.cleaning import CleaningDF
|
|
68
|
+
import polars as pl
|
|
69
|
+
|
|
70
|
+
class UserDataCleaner(CleaningDF):
|
|
71
|
+
"""Clean and standardize user data."""
|
|
72
|
+
|
|
73
|
+
USER_ID = "user_id"
|
|
74
|
+
EMAIL = "email"
|
|
75
|
+
SCORE = "score"
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def get_rename_map(cls):
|
|
79
|
+
return {cls.USER_ID: "UserId", cls.EMAIL: "Email", cls.SCORE: "Score"}
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def get_col_dtype_map(cls):
|
|
83
|
+
return {cls.USER_ID: pl.Int64, cls.EMAIL: pl.Utf8, cls.SCORE: pl.Float64}
|
|
84
|
+
|
|
85
|
+
# ... implement other abstract methods
|
|
86
|
+
|
|
87
|
+
# Usage
|
|
88
|
+
cleaned = UserDataCleaner(raw_dataframe)
|
|
89
|
+
result = cleaned.df
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Concurrent Processing
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from winiutils.src.iterating.concurrent.multiprocessing import multiprocess_loop
|
|
96
|
+
from winiutils.src.iterating.concurrent.multithreading import multithread_loop
|
|
97
|
+
|
|
98
|
+
# CPU-bound tasks (multiprocessing)
|
|
99
|
+
def process_chunk(data, config):
|
|
100
|
+
return heavy_computation(data, config)
|
|
101
|
+
|
|
102
|
+
results = multiprocess_loop(
|
|
103
|
+
process_function=process_chunk,
|
|
104
|
+
process_args=[(chunk,) for chunk in data_chunks],
|
|
105
|
+
process_args_static=(config,),
|
|
106
|
+
process_args_len=len(data_chunks),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# I/O-bound tasks (multithreading)
|
|
110
|
+
def fetch_url(url, headers):
|
|
111
|
+
return requests.get(url, headers=headers)
|
|
112
|
+
|
|
113
|
+
results = multithread_loop(
|
|
114
|
+
process_function=fetch_url,
|
|
115
|
+
process_args=[(url,) for url in urls],
|
|
116
|
+
process_args_static=(headers,),
|
|
117
|
+
process_args_len=len(urls),
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Automatic Method Logging
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from winiutils.src.oop.mixins.mixin import ABCLoggingMixin
|
|
125
|
+
|
|
126
|
+
class MyService(ABCLoggingMixin):
|
|
127
|
+
def process_data(self, data: list) -> dict:
|
|
128
|
+
# Automatically logged with timing
|
|
129
|
+
return {"processed": len(data)}
|
|
130
|
+
|
|
131
|
+
# Logs: "MyService - Calling process_data with (...) and {...}"
|
|
132
|
+
# Logs: "MyService - process_data finished with 0.5 seconds -> returning {...}"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Encryption with Keyring
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from winiutils.src.security.keyring import get_or_create_aes_gcm
|
|
139
|
+
from winiutils.src.security.cryptography import encrypt_with_aes_gcm, decrypt_with_aes_gcm
|
|
140
|
+
|
|
141
|
+
# Get or create encryption key (stored in OS keyring)
|
|
142
|
+
aes_gcm, key = get_or_create_aes_gcm("my_app", "user@example.com")
|
|
143
|
+
|
|
144
|
+
# Encrypt and decrypt
|
|
145
|
+
encrypted = encrypt_with_aes_gcm(aes_gcm, b"Secret message")
|
|
146
|
+
decrypted = decrypt_with_aes_gcm(aes_gcm, encrypted)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Documentation
|
|
152
|
+
|
|
153
|
+
Full documentation is available in the [docs](./docs/) folder:
|
|
154
|
+
|
|
155
|
+
- [**Data Processing**](./docs/data.md) — DataFrame cleaning pipeline and data structures
|
|
156
|
+
- [**Iterating & Concurrency**](./docs/iterating.md) — Parallel processing utilities
|
|
157
|
+
- [**OOP Utilities**](./docs/oop.md) — Metaclasses and mixins
|
|
158
|
+
- [**Security**](./docs/security.md) — Encryption and keyring integration
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Modules
|
|
163
|
+
|
|
164
|
+
| Module | Description |
|
|
165
|
+
|--------|-------------|
|
|
166
|
+
| [`winiutils.src.data`](./docs/data.md) | DataFrame cleaning pipeline and data structure utilities |
|
|
167
|
+
| [`winiutils.src.iterating`](./docs/iterating.md) | Concurrent processing with multiprocessing and multithreading |
|
|
168
|
+
| [`winiutils.src.oop`](./docs/oop.md) | Metaclasses and mixins for automatic method logging |
|
|
169
|
+
| [`winiutils.src.security`](./docs/security.md) | AES-GCM encryption and OS keyring integration |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Development
|
|
174
|
+
|
|
175
|
+
### Setup
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
git clone https://github.com/Winipedia/winiutils.git
|
|
179
|
+
cd winiutils
|
|
180
|
+
uv sync --all-groups
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Running Tests
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
uv run pytest
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Code Quality
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Linting
|
|
193
|
+
uv run ruff check .
|
|
194
|
+
|
|
195
|
+
# Type checking
|
|
196
|
+
uv run mypy .
|
|
197
|
+
|
|
198
|
+
# Security scanning
|
|
199
|
+
uv run bandit -r winiutils/
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Pre-commit Hooks
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
uv run pre-commit install
|
|
206
|
+
uv run pre-commit run --all-files
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Project Structure
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
winiutils/
|
|
215
|
+
├── src/ # Main source code
|
|
216
|
+
│ ├── data/ # Data processing
|
|
217
|
+
│ │ ├── dataframe/ # Polars DataFrame cleaning
|
|
218
|
+
│ │ └── structures/ # Dicts, text utilities
|
|
219
|
+
│ ├── iterating/ # Iteration utilities
|
|
220
|
+
│ │ └── concurrent/ # Multiprocessing & multithreading
|
|
221
|
+
│ ├── oop/ # OOP patterns
|
|
222
|
+
│ │ └── mixins/ # Logging metaclass & mixin
|
|
223
|
+
│ └── security/ # Security utilities
|
|
224
|
+
│ ├── cryptography.py # AES-GCM encryption
|
|
225
|
+
│ └── keyring.py # OS keyring integration
|
|
226
|
+
├── dev/ # Development tools
|
|
227
|
+
│ ├── cli/ # CLI subcommands
|
|
228
|
+
│ └── tests/fixtures/ # Test fixtures
|
|
229
|
+
├── docs/ # Documentation
|
|
230
|
+
└── tests/ # Test suite
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Contributing
|
|
242
|
+
|
|
243
|
+
Contributions are welcome! Please ensure:
|
|
244
|
+
|
|
245
|
+
1. All tests pass (`uv run pytest`)
|
|
246
|
+
2. Code passes linting (`uv run ruff check .`)
|
|
247
|
+
3. Types are correct (`uv run mypy .`)
|
|
248
|
+
4. New features include tests
|
|
249
|
+
5. Documentation is updated for API changes
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "winiutils"
|
|
3
|
+
version = "2.2.32"
|
|
4
|
+
description = "A package with many utility functions"
|
|
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
|
+
|
|
21
|
+
[project.scripts]
|
|
22
|
+
winipedia-utils = "pyrig.dev.cli.cli:main"
|
|
23
|
+
winiutils = "pyrig.dev.cli.cli:main"
|
|
24
|
+
|
|
25
|
+
[dependency-groups]
|
|
26
|
+
dev = [
|
|
27
|
+
"bandit",
|
|
28
|
+
"mypy",
|
|
29
|
+
"pre-commit",
|
|
30
|
+
"pyinstaller",
|
|
31
|
+
"pytest",
|
|
32
|
+
"pytest-mock",
|
|
33
|
+
"ruff",
|
|
34
|
+
"types-defusedxml",
|
|
35
|
+
"types-pyinstaller",
|
|
36
|
+
"types-pyyaml",
|
|
37
|
+
"types-setuptools",
|
|
38
|
+
"types-tqdm",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[build-system]
|
|
42
|
+
requires = [
|
|
43
|
+
"uv_build",
|
|
44
|
+
]
|
|
45
|
+
build-backend = "uv_build"
|
|
46
|
+
|
|
47
|
+
[tool.uv.build-backend]
|
|
48
|
+
module-name = "winiutils"
|
|
49
|
+
module-root = ""
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
exclude = [
|
|
53
|
+
".*",
|
|
54
|
+
"**/migrations/*.py",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
select = [
|
|
59
|
+
"ALL",
|
|
60
|
+
]
|
|
61
|
+
ignore = [
|
|
62
|
+
"D203",
|
|
63
|
+
"D213",
|
|
64
|
+
"COM812",
|
|
65
|
+
"ANN401",
|
|
66
|
+
]
|
|
67
|
+
fixable = [
|
|
68
|
+
"ALL",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[tool.ruff.lint.per-file-ignores]
|
|
72
|
+
"tests/**/*.py" = [
|
|
73
|
+
"S101",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
[tool.ruff.lint.pydocstyle]
|
|
77
|
+
convention = "google"
|
|
78
|
+
|
|
79
|
+
[tool.mypy]
|
|
80
|
+
strict = true
|
|
81
|
+
warn_unreachable = true
|
|
82
|
+
show_error_codes = true
|
|
83
|
+
files = "."
|
|
84
|
+
|
|
85
|
+
[tool.pytest.ini_options]
|
|
86
|
+
testpaths = [
|
|
87
|
+
"tests",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[tool.bandit]
|
|
91
|
+
exclude_dirs = [
|
|
92
|
+
".*",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[tool.bandit.assert_used]
|
|
96
|
+
skips = [
|
|
97
|
+
"*test_*.py",
|
|
98
|
+
]
|
|
@@ -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)
|
|
@@ -8,7 +8,7 @@ def main() -> None:
|
|
|
8
8
|
msg = f"""Add your projects entrypoint code to this function.
|
|
9
9
|
This function is automatically added to your cli by {pyrig.__name__}.
|
|
10
10
|
You can call it with
|
|
11
|
-
`
|
|
11
|
+
`your-pkg-name main`
|
|
12
12
|
or via
|
|
13
13
|
`python -m your-pkg-name`.
|
|
14
14
|
"""
|