winiutils 1.1.4__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 (47) hide show
  1. winiutils-1.1.4/LICENSE +21 -0
  2. winiutils-1.1.4/PKG-INFO +443 -0
  3. winiutils-1.1.4/README.md +422 -0
  4. winiutils-1.1.4/pyproject.toml +74 -0
  5. winiutils-1.1.4/winiutils/__init__.py +1 -0
  6. winiutils-1.1.4/winiutils/dev/__init__.py +1 -0
  7. winiutils-1.1.4/winiutils/dev/artifacts/__init__.py +1 -0
  8. winiutils-1.1.4/winiutils/dev/artifacts/builder/__init__.py +1 -0
  9. winiutils-1.1.4/winiutils/dev/artifacts/builder/builder.py +4 -0
  10. winiutils-1.1.4/winiutils/dev/cli/__init__.py +1 -0
  11. winiutils-1.1.4/winiutils/dev/cli/subcommands.py +6 -0
  12. winiutils-1.1.4/winiutils/dev/configs/__init__.py +1 -0
  13. winiutils-1.1.4/winiutils/dev/configs/configs.py +4 -0
  14. winiutils-1.1.4/winiutils/main.py +19 -0
  15. winiutils-1.1.4/winiutils/py.typed +0 -0
  16. winiutils-1.1.4/winiutils/src/__init__.py +1 -0
  17. winiutils-1.1.4/winiutils/src/data/__init__.py +1 -0
  18. winiutils-1.1.4/winiutils/src/data/dataframe/__init__.py +1 -0
  19. winiutils-1.1.4/winiutils/src/data/dataframe/cleaning.py +620 -0
  20. winiutils-1.1.4/winiutils/src/data/structures/__init__.py +1 -0
  21. winiutils-1.1.4/winiutils/src/data/structures/dicts.py +16 -0
  22. winiutils-1.1.4/winiutils/src/data/structures/text/__init__.py +1 -0
  23. winiutils-1.1.4/winiutils/src/data/structures/text/string.py +100 -0
  24. winiutils-1.1.4/winiutils/src/iterating/__init__.py +1 -0
  25. winiutils-1.1.4/winiutils/src/iterating/concurrent/__init__.py +1 -0
  26. winiutils-1.1.4/winiutils/src/iterating/concurrent/concurrent.py +251 -0
  27. winiutils-1.1.4/winiutils/src/iterating/concurrent/multiprocessing.py +129 -0
  28. winiutils-1.1.4/winiutils/src/iterating/concurrent/multithreading.py +93 -0
  29. winiutils-1.1.4/winiutils/src/iterating/iterate.py +29 -0
  30. winiutils-1.1.4/winiutils/src/oop/__init__.py +1 -0
  31. winiutils-1.1.4/winiutils/src/oop/mixins/__init__.py +1 -0
  32. winiutils-1.1.4/winiutils/src/oop/mixins/meta.py +171 -0
  33. winiutils-1.1.4/winiutils/src/oop/mixins/mixin.py +26 -0
  34. winiutils-1.1.4/winiutils/src/resources/__init__.py +1 -0
  35. winiutils-1.1.4/winiutils/src/resources/svgs/__init__.py +1 -0
  36. winiutils-1.1.4/winiutils/src/resources/svgs/delete_garbage_can.svg +2 -0
  37. winiutils-1.1.4/winiutils/src/resources/svgs/download_arrow.svg +3 -0
  38. winiutils-1.1.4/winiutils/src/resources/svgs/exit_fullscreen_icon.svg +7 -0
  39. winiutils-1.1.4/winiutils/src/resources/svgs/fullscreen_icon.svg +4 -0
  40. winiutils-1.1.4/winiutils/src/resources/svgs/menu_icon.svg +4 -0
  41. winiutils-1.1.4/winiutils/src/resources/svgs/pause_icon.svg +4 -0
  42. winiutils-1.1.4/winiutils/src/resources/svgs/play_icon.svg +17 -0
  43. winiutils-1.1.4/winiutils/src/resources/svgs/plus_icon.svg +24 -0
  44. winiutils-1.1.4/winiutils/src/resources/svgs/svg.py +15 -0
  45. winiutils-1.1.4/winiutils/src/security/__init__.py +1 -0
  46. winiutils-1.1.4/winiutils/src/security/cryptography.py +29 -0
  47. winiutils-1.1.4/winiutils/src/security/keyring.py +70 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Winipedia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,443 @@
1
+ Metadata-Version: 2.4
2
+ Name: winiutils
3
+ Version: 1.1.4
4
+ Summary: A package with many utility functions
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Author: Winipedia
8
+ Author-email: win.steveker@gmx.de
9
+ Requires-Python: >=3.12
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: cryptography
15
+ Requires-Dist: defusedxml
16
+ Requires-Dist: keyring
17
+ Requires-Dist: polars
18
+ Requires-Dist: pyrig
19
+ Requires-Dist: tqdm
20
+ Description-Content-Type: text/markdown
21
+
22
+ # winiutils
23
+
24
+ (This project uses [pyrig](https://github.com/Winipedia/pyrig))
25
+
26
+ ## Overview
27
+
28
+ **winiutils** is a comprehensive Python utility library providing production-ready tools for data processing, concurrent execution, security, and object-oriented programming patterns. Built with strict type safety and code quality standards, it offers reusable components for common development tasks.
29
+
30
+ ## Features
31
+
32
+ ### DataFrame Cleaning Pipeline
33
+
34
+ The `CleaningDF` abstract base class provides a production-ready, extensible framework for cleaning and standardizing Polars DataFrames. It implements a comprehensive 8-step cleaning pipeline:
35
+
36
+ **Pipeline Stages:**
37
+ 1. **Column Renaming** - Standardize column names from raw input
38
+ 2. **Column Dropping** - Remove columns not in schema
39
+ 3. **Null Filling** - Fill null values with configurable defaults
40
+ 4. **Type Conversion** - Convert to correct data types with custom transformations
41
+ 5. **Null Subset Dropping** - Remove rows where specified column groups are all null
42
+ 6. **Duplicate Handling** - Aggregate duplicate rows and sum specified columns
43
+ 7. **Sorting** - Multi-column sorting with per-column direction control
44
+ 8. **Validation** - Enforce data quality (correct dtypes, no nulls in required columns, no NaN values)
45
+
46
+ **Key Features:**
47
+ - **Abstract Configuration**: 10 abstract methods for complete customization
48
+ - `get_rename_map()` - Column name standardization
49
+ - `get_col_dtype_map()` - Type schema definition
50
+ - `get_fill_null_map()` - Null value defaults
51
+ - `get_col_converter_map()` - Custom column transformations
52
+ - `get_drop_null_subsets()` - Row deletion rules
53
+ - `get_unique_subsets()` - Duplicate detection criteria
54
+ - `get_add_on_duplicate_cols()` - Columns to aggregate on duplicates
55
+ - `get_sort_cols()` - Sort order specification
56
+ - `get_no_null_cols()` - Required non-null columns
57
+ - `get_col_precision_map()` - Float rounding precision
58
+
59
+ - **Advanced Features**:
60
+ - **Kahan Summation**: Compensated rounding for floats to prevent accumulation errors
61
+ - **Automatic Logging**: Built-in method logging via `ABCLoggingMixin`
62
+ - **Type Safety**: Full Polars type enforcement with validation
63
+ - **NaN Handling**: Automatic NaN to null conversion
64
+ - **Duplicate Aggregation**: Sum values when merging duplicate rows
65
+ - **Standard Conversions**: Auto-strip strings, auto-round floats
66
+
67
+ **Usage Pattern:**
68
+ ```python
69
+ class MyDataCleaner(CleaningDF):
70
+ # Define column constants
71
+ USER_ID = "user_id"
72
+ EMAIL = "email"
73
+
74
+ @classmethod
75
+ def get_rename_map(cls) -> dict[str, str]:
76
+ return {cls.USER_ID: "UserId", cls.EMAIL: "Email_Address"}
77
+
78
+ @classmethod
79
+ def get_col_dtype_map(cls) -> dict[str, type[pl.DataType]]:
80
+ return {cls.USER_ID: pl.Int64, cls.EMAIL: pl.Utf8}
81
+
82
+ # ... implement other abstract methods
83
+
84
+ # Use it
85
+ cleaned_data = MyDataCleaner(raw_dataframe)
86
+ result_df = cleaned_data.df
87
+ ```
88
+
89
+ **Best For:**
90
+ - ETL pipelines requiring consistent data quality
91
+ - Data standardization before database loading
92
+ - Building composable data cleaning workflows
93
+ - Projects requiring audit trails (automatic logging)
94
+
95
+ ### Concurrent Processing
96
+
97
+ A unified, intelligent framework for parallel execution supporting both multiprocessing (CPU-bound) and multithreading (I/O-bound) tasks with automatic resource optimization.
98
+
99
+ **Core Functions:**
100
+
101
+ **`multiprocess_loop()`** - CPU-bound parallel processing
102
+ - Uses `multiprocessing.Pool` with spawn context for true parallelism
103
+ - Bypasses Python's GIL for CPU-intensive tasks
104
+ - Automatic process pool sizing based on CPU count and active processes
105
+ - Deep-copy support for mutable static arguments
106
+
107
+ **`multithread_loop()`** - I/O-bound parallel processing
108
+ - Uses `ThreadPoolExecutor` for concurrent I/O operations
109
+ - Efficient for network requests, file I/O, database queries
110
+ - Automatic thread pool sizing (CPU count × 4)
111
+ - Safe for mutable objects (shared memory)
112
+
113
+ **`cancel_on_timeout()`** - Timeout enforcement
114
+ - Decorator/wrapper for functions that may hang
115
+ - Uses multiprocessing to forcefully terminate on timeout
116
+ - Proper cleanup with process termination and joining
117
+ - Works with pickle-able functions
118
+
119
+ **Key Features:**
120
+
121
+ - **Automatic Worker Optimization**: Calculates optimal pool size based on:
122
+ - Available CPU cores
123
+ - Currently active processes/threads
124
+ - Number of tasks to process
125
+ - Ensures at least 1 worker, prevents oversubscription
126
+
127
+ - **Progress Tracking**: Built-in tqdm integration
128
+ - Real-time progress bars for all parallel operations
129
+ - Descriptive labels showing function name and worker type
130
+ - Accurate task counting
131
+
132
+ - **Order Preservation**: Results returned in original input order
133
+ - Uses internal ordering system with `imap_unordered`
134
+ - Efficient unordered processing with ordered output
135
+ - No manual result sorting required
136
+
137
+ - **Flexible Argument Handling**:
138
+ - `process_args`: Variable arguments per task (iterable of iterables)
139
+ - `process_args_static`: Shared arguments across all tasks
140
+ - `deepcopy_static_args`: Arguments deep-copied per process (for mutables)
141
+ - `process_args_len`: Optional length hint for optimization
142
+
143
+ - **Smart Execution**: Single unified `concurrent_loop()` backend
144
+ - Automatically selects map/imap_unordered based on task count
145
+ - Handles both Pool and ThreadPoolExecutor transparently
146
+ - Consistent API regardless of concurrency type
147
+
148
+ **Usage Examples:**
149
+
150
+ ```python
151
+ from winiutils.src.iterating.concurrent.multiprocessing import multiprocess_loop
152
+ from winiutils.src.iterating.concurrent.multithreading import multithread_loop
153
+ from winiutils.src.iterating.concurrent.multiprocessing import cancel_on_timeout
154
+
155
+ # CPU-bound: Process large datasets in parallel
156
+ def process_data(data_chunk, config):
157
+ # Heavy computation
158
+ return analyzed_data
159
+
160
+ results = multiprocess_loop(
161
+ process_function=process_data,
162
+ process_args=[(chunk,) for chunk in data_chunks],
163
+ process_args_static=(config,),
164
+ process_args_len=len(data_chunks)
165
+ )
166
+
167
+ # I/O-bound: Fetch multiple URLs concurrently
168
+ def fetch_url(url, headers):
169
+ return requests.get(url, headers=headers)
170
+
171
+ responses = multithread_loop(
172
+ process_function=fetch_url,
173
+ process_args=[(url,) for url in urls],
174
+ process_args_static=(headers,),
175
+ process_args_len=len(urls)
176
+ )
177
+
178
+ # Timeout enforcement for blocking operations
179
+ @cancel_on_timeout(seconds=5, message="User input timeout")
180
+ def get_user_input():
181
+ return input("Enter value: ")
182
+
183
+ try:
184
+ user_value = get_user_input()
185
+ except multiprocessing.TimeoutError:
186
+ user_value = "default"
187
+ ```
188
+
189
+ **Architecture Highlights:**
190
+
191
+ - **Spawn Context**: Uses `spawn` instead of `fork` for safer multiprocessing
192
+ - **Context Managers**: Proper resource cleanup with `with` statements
193
+ - **Type Safety**: Full type hints for all functions and parameters
194
+ - **Logging**: Integrated logging for pool size decisions and execution flow
195
+ - **Error Handling**: Graceful handling of timeouts and process failures
196
+
197
+ **Best For:**
198
+ - Parallel data processing pipelines
199
+ - Batch API requests or database queries
200
+ - CPU-intensive computations (image processing, ML inference)
201
+ - Operations requiring timeout enforcement
202
+ - Applications needing automatic resource management
203
+
204
+ ### Object-Oriented Programming Utilities
205
+
206
+ Advanced metaclasses and mixins for automatic method instrumentation and class composition using the mixin pattern.
207
+
208
+ **Core Components:**
209
+
210
+ **`ABCLoggingMeta`** - Metaclass for automatic method logging
211
+ - Extends `ABCMeta` to combine abstract class enforcement with logging
212
+ - Automatically wraps all non-magic methods with logging decorators
213
+ - Supports `classmethod`, `staticmethod`, and instance methods
214
+ - Zero boilerplate - just use as metaclass
215
+
216
+ **`ABCLoggingMixin`** - Ready-to-use mixin class
217
+ - Pre-configured with `ABCLoggingMeta` metaclass
218
+ - Inherit to add automatic logging to any class
219
+ - Combines well with other mixins and base classes
220
+
221
+ **Logging Features:**
222
+
223
+ - **Automatic Instrumentation**: All methods automatically logged without decorators
224
+ - **Performance Tracking**: Measures and logs execution time for each method call
225
+ - **Argument Logging**: Captures and logs method arguments (truncated for readability)
226
+ - **Return Value Logging**: Logs method return values (truncated)
227
+ - **Rate Limiting**: Intelligent throttling to prevent log spam
228
+ - Only logs if >1 second since last call to same method
229
+ - Prevents flooding logs in tight loops
230
+ - Per-method tracking (not global)
231
+ - **Truncation**: Arguments and returns truncated to 20 characters max
232
+ - **Magic Method Exclusion**: Skips `__init__`, `__str__`, etc. to avoid noise
233
+
234
+ **How It Works:**
235
+
236
+ The metaclass intercepts class creation and wraps methods at definition time:
237
+ 1. Iterates through all class attributes during `__new__`
238
+ 2. Identifies callable, non-magic methods
239
+ 3. Wraps each with a logging decorator that:
240
+ - Tracks call times per method
241
+ - Logs method name, class name, arguments, kwargs
242
+ - Executes the original method
243
+ - Logs execution duration and return value
244
+ - Updates last call time for rate limiting
245
+
246
+ **Usage Examples:**
247
+
248
+ ```python
249
+ from winiutils.src.oop.mixins.mixin import ABCLoggingMixin
250
+ from abc import abstractmethod
251
+
252
+ # Option 1: Use the mixin
253
+ class MyService(ABCLoggingMixin):
254
+ def process_data(self, data: list) -> dict:
255
+ # Automatically logged with timing
256
+ return {"processed": len(data)}
257
+
258
+ @classmethod
259
+ def validate(cls, value: str) -> bool:
260
+ # Classmethods also logged
261
+ return len(value) > 0
262
+
263
+ # Option 2: Use the metaclass directly
264
+ from winiutils.src.oop.mixins.meta import ABCLoggingMeta
265
+
266
+ class MyAbstractService(metaclass=ABCLoggingMeta):
267
+ @abstractmethod
268
+ def execute(self) -> None:
269
+ pass
270
+
271
+ class ConcreteService(MyAbstractService):
272
+ def execute(self) -> None:
273
+ # Automatically logged
274
+ print("Executing...")
275
+
276
+ # Usage - logging happens automatically
277
+ service = MyService()
278
+ result = service.process_data([1, 2, 3])
279
+ # Logs: "MyService - Calling process_data with ([1, 2, 3],) and {}"
280
+ # Logs: "MyService - process_data finished with 0.001 seconds -> returning {'processed': 3}"
281
+ ```
282
+
283
+ **Log Output Example:**
284
+ ```
285
+ INFO - MyService - Calling process_data with ([1, 2, 3],) and {}
286
+ INFO - MyService - process_data finished with 0.001234 seconds -> returning {'processed': 3}
287
+ INFO - MyService - Calling validate with ('test',) and {}
288
+ INFO - MyService - validate finished with 0.000123 seconds -> returning True
289
+ ```
290
+
291
+ **Technical Details:**
292
+
293
+ - **Metaclass Inheritance**: Properly extends `ABCMeta` for abstract class support
294
+ - **Decorator Preservation**: Uses `@wraps` to maintain function metadata
295
+ - **Performance**: Minimal overhead - caches `time.time` function reference
296
+ - **Thread Safety**: Each method has independent call time tracking
297
+ - **Memory Efficient**: Call times stored in closure, not instance attributes
298
+
299
+ **Integration with Other Utilities:**
300
+
301
+ The `CleaningDF` class uses `ABCLoggingMixin` to automatically log all cleaning operations:
302
+ ```python
303
+ class CleaningDF(ABCLoggingMixin):
304
+ # All methods (rename_cols, fill_nulls, etc.) automatically logged
305
+ # Provides audit trail of data cleaning pipeline
306
+ pass
307
+ ```
308
+
309
+ **Best For:**
310
+ - Debugging complex class hierarchies
311
+ - Performance profiling during development
312
+ - Audit trails for data processing pipelines
313
+ - Monitoring service method execution
314
+ - Classes with abstract methods requiring implementation tracking
315
+ - Reducing logging boilerplate in large codebases
316
+
317
+ ### Security Utilities
318
+
319
+ Production-ready cryptography and secure credential storage utilities built on industry-standard libraries (`cryptography` and `keyring`).
320
+
321
+ **Cryptography Module** (`winiutils.src.security.cryptography`)
322
+
323
+ **AES-GCM Encryption/Decryption** - Authenticated encryption with proper IV handling
324
+
325
+ **`encrypt_with_aes_gcm(aes_gcm, data, aad=None)`**
326
+ - Encrypts data using AES-GCM (Galois/Counter Mode)
327
+ - Generates random 12-byte IV for each encryption
328
+ - Prepends IV to ciphertext for easy decryption
329
+ - Optional Additional Authenticated Data (AAD) support
330
+ - Returns: `IV + encrypted_data` as single bytes object
331
+
332
+ **`decrypt_with_aes_gcm(aes_gcm, data, aad=None)`**
333
+ - Decrypts AES-GCM encrypted data
334
+ - Automatically extracts IV from first 12 bytes
335
+ - Validates authentication tag (prevents tampering)
336
+ - Optional AAD support (must match encryption AAD)
337
+ - Returns: Original plaintext as bytes
338
+
339
+ **Key Features:**
340
+ - **Authenticated Encryption**: AES-GCM provides both confidentiality and integrity
341
+ - **Random IVs**: Each encryption uses a unique, cryptographically random IV
342
+ - **No IV Management**: IV automatically prepended/extracted - no separate storage needed
343
+ - **AAD Support**: Authenticate additional data without encrypting it
344
+ - **Standard Compliance**: Uses `cryptography` library's AEAD implementation
345
+
346
+ **Keyring Module** (`winiutils.src.security.keyring`)
347
+
348
+ **Secure Key Storage** - System keyring integration for credential management
349
+
350
+ **`get_or_create_fernet(service_name, username)`**
351
+ - Retrieves or generates Fernet symmetric encryption key
352
+ - Stores key securely in system keyring (OS-level security)
353
+ - Returns: `(Fernet instance, raw_key_bytes)` tuple
354
+ - Automatic base64 encoding for keyring storage
355
+
356
+ **`get_or_create_aes_gcm(service_name, username)`**
357
+ - Retrieves or generates 256-bit AES-GCM key
358
+ - Stores key securely in system keyring
359
+ - Returns: `(AESGCM instance, raw_key_bytes)` tuple
360
+ - Uses `AESGCM.generate_key(bit_length=256)`
361
+
362
+ **`get_or_create_key(service_name, username, key_class, generate_key_func)`**
363
+ - Generic key retrieval/creation function
364
+ - Supports any key type with custom generation function
365
+ - Service name automatically modified with key class name
366
+ - Base64 encoding for safe string storage
367
+ - Type-safe with generic type parameter
368
+
369
+ **Key Features:**
370
+ - **System Keyring**: Uses OS-native credential storage (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux)
371
+ - **Automatic Generation**: Creates keys on first use if not found
372
+ - **Type Safety**: Generic type parameters for key class
373
+ - **Service Namespacing**: Prevents key collisions with class-based naming
374
+ - **Base64 Encoding**: Safe storage of binary keys as strings
375
+ - **Lazy Initialization**: Keys only generated when needed
376
+
377
+ **Usage Examples:**
378
+
379
+ ```python
380
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
381
+ from winiutils.src.security.keyring import get_or_create_aes_gcm
382
+ from winiutils.src.security.cryptography import encrypt_with_aes_gcm, decrypt_with_aes_gcm
383
+
384
+ # Get or create encryption key (stored in system keyring)
385
+ aes_gcm, raw_key = get_or_create_aes_gcm(
386
+ service_name="my_app",
387
+ username="user@example.com"
388
+ )
389
+
390
+ # Encrypt sensitive data
391
+ plaintext = b"Secret message"
392
+ aad = b"metadata" # Optional authenticated data
393
+ encrypted = encrypt_with_aes_gcm(aes_gcm, plaintext, aad)
394
+
395
+ # Decrypt data
396
+ decrypted = decrypt_with_aes_gcm(aes_gcm, encrypted, aad)
397
+ assert decrypted == plaintext
398
+
399
+ # Using Fernet (simpler, includes timestamp)
400
+ from cryptography.fernet import Fernet
401
+ from winiutils.src.security.keyring import get_or_create_fernet
402
+
403
+ fernet, key = get_or_create_fernet("my_app", "user@example.com")
404
+ token = fernet.encrypt(b"Secret data")
405
+ original = fernet.decrypt(token)
406
+
407
+ # Custom key type
408
+ from winiutils.src.security.keyring import get_or_create_key
409
+
410
+ custom_cipher, key = get_or_create_key(
411
+ service_name="my_app",
412
+ username="admin",
413
+ key_class=AESGCM,
414
+ generate_key_func=lambda: AESGCM.generate_key(bit_length=128)
415
+ )
416
+ ```
417
+
418
+ **Security Best Practices:**
419
+
420
+ - **Key Storage**: Never hardcode keys - always use keyring
421
+ - **IV Uniqueness**: Never reuse IVs with the same key (handled automatically)
422
+ - **AAD Usage**: Use AAD for context binding (e.g., user ID, timestamp)
423
+ - **Key Rotation**: Periodically regenerate keys and re-encrypt data
424
+ - **Access Control**: Limit keyring access to authorized users only
425
+
426
+ **Architecture Highlights:**
427
+
428
+ - **Service Name Modification**: Appends key class name to prevent collisions
429
+ - `"my_app"` + `Fernet` → `"my_app_Fernet"`
430
+ - `"my_app"` + `AESGCM` → `"my_app_AESGCM"`
431
+ - **Idempotent**: Multiple calls return same key (no regeneration)
432
+ - **Cross-Platform**: Works on Windows, macOS, Linux via `keyring` library
433
+ - **No Database**: Keys stored in OS credential manager, not files
434
+ - **Separation of Concerns**: Cryptography operations separate from key management
435
+
436
+ **Best For:**
437
+ - Encrypting sensitive application data (passwords, tokens, PII)
438
+ - Secure configuration file encryption
439
+ - Database credential protection
440
+ - API key storage and retrieval
441
+ - Multi-user applications requiring per-user encryption
442
+ - Applications requiring OS-level security integration
443
+ - Compliance with data protection regulations (GDPR, HIPAA)