winipedia-django 0.2.1__py3-none-any.whl → 0.2.5__py3-none-any.whl

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-django might be problematic. Click here for more details.

@@ -0,0 +1,702 @@
1
+ Metadata-Version: 2.4
2
+ Name: winipedia-django
3
+ Version: 0.2.5
4
+ Summary: A utils package for django
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: django (>=5.2.7,<6.0.0)
15
+ Requires-Dist: winipedia-utils (>=0.2.10,<0.3.0)
16
+ Description-Content-Type: text/markdown
17
+
18
+ # winipedia_django
19
+ (Some parts of the README are AI generated, so some parts might not be fully accurate)
20
+
21
+ [![Python Version](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/downloads/)
22
+ [![Django Version](https://img.shields.io/badge/django-5.2%2B-darkgreen)](https://www.djangoproject.com/)
23
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
24
+
25
+ A comprehensive utility package for Django that provides efficient bulk operations, abstract base classes for management commands, and database utilities. Designed to simplify common Django operations while maintaining type safety and performance.
26
+
27
+ ## Table of Contents
28
+
29
+ - [Features](#features)
30
+ - [Installation](#installation)
31
+ - [Quick Start](#quick-start)
32
+ - [Core Modules](#core-modules)
33
+ - [Bulk Operations](#bulk-operations)
34
+ - [Management Commands](#management-commands)
35
+ - [Database Utilities](#database-utilities)
36
+ - [Usage Examples](#usage-examples)
37
+ - [API Reference](#api-reference)
38
+ - [Best Practices](#best-practices)
39
+ - [Contributing](#contributing)
40
+ - [License](#license)
41
+
42
+ ## Features
43
+
44
+ ✨ **Efficient Bulk Operations**
45
+ - Bulk create, update, and delete with automatic chunking
46
+ - Multithreaded processing for improved performance
47
+ - Topological sorting for respecting model dependencies
48
+ - Cascade deletion simulation without database modifications
49
+
50
+ 🎯 **Abstract Base Command**
51
+ - Template method pattern for consistent command structure
52
+ - Automatic logging of command options
53
+ - Pre-configured common arguments (dry-run, batch-size, threads, etc.)
54
+ - Type-safe command implementation
55
+
56
+ 🗄️ **Database Utilities**
57
+ - Model introspection and field extraction
58
+ - Topological sorting of models by dependencies
59
+ - Raw SQL execution with parameter binding
60
+ - Model hashing for comparison operations
61
+ - Abstract BaseModel with timestamps
62
+
63
+ 🔒 **Type Safety**
64
+ - Full type hints throughout the codebase
65
+ - Strict mypy configuration
66
+ - Compatible with modern Python type checking tools
67
+
68
+ ## Installation
69
+
70
+ ### Using pip
71
+
72
+ ```bash
73
+ pip install winipedia-django
74
+ ```
75
+
76
+ ### Using Poetry
77
+
78
+ ```bash
79
+ poetry add winipedia-django
80
+ ```
81
+
82
+ ### Using uv
83
+
84
+ ```bash
85
+ uv pip install winipedia-django
86
+ ```
87
+
88
+ ### Requirements
89
+
90
+ - Python 3.12 or higher
91
+ - Django 5.2 or higher
92
+ - winipedia-utils 0.2.10 or higher
93
+
94
+ ## Quick Start
95
+
96
+ ### Basic Bulk Creation
97
+
98
+ ```python
99
+ from winipedia_django.bulk import bulk_create_in_steps
100
+ from myapp.models import MyModel
101
+
102
+ # Create 10,000 objects efficiently
103
+ objects = [MyModel(name=f"item_{i}") for i in range(10000)]
104
+ created = bulk_create_in_steps(MyModel, objects, step=1000)
105
+ print(f"Created {len(created)} objects")
106
+ ```
107
+
108
+ ### Creating a Management Command
109
+
110
+ ```python
111
+ from argparse import ArgumentParser
112
+ from typing import Any
113
+ from winipedia_django.command import ABCBaseCommand
114
+
115
+ class MyCommand(ABCBaseCommand):
116
+ def add_command_arguments(self, parser: ArgumentParser) -> None:
117
+ parser.add_argument(
118
+ '--input-file',
119
+ type=str,
120
+ required=True,
121
+ help='Path to input file'
122
+ )
123
+
124
+ def handle_command(self, *args: Any, **options: Any) -> None:
125
+ input_file = options['input_file']
126
+ batch_size = options['batch_size']
127
+ dry_run = options['dry_run']
128
+
129
+ if dry_run:
130
+ self.stdout.write('DRY RUN MODE - No changes will be made')
131
+
132
+ # Your command logic here
133
+ self.stdout.write(self.style.SUCCESS('Command completed successfully'))
134
+ ```
135
+
136
+ ### Using Database Utilities
137
+
138
+ ```python
139
+ from winipedia_django.database import (
140
+ get_fields,
141
+ topological_sort_models,
142
+ BaseModel
143
+ )
144
+ from django.db import models
145
+
146
+ # Get all fields from a model
147
+ fields = get_fields(MyModel)
148
+ field_names = [f.name for f in fields if hasattr(f, 'name')]
149
+
150
+ # Sort models by dependencies
151
+ models_to_create = [Book, Author, Publisher]
152
+ sorted_models = topological_sort_models(models_to_create)
153
+ # Result: [Author, Publisher, Book] - dependencies first
154
+
155
+ # Use BaseModel for automatic timestamps
156
+ class Article(BaseModel):
157
+ title = models.CharField(max_length=200)
158
+ content = models.TextField()
159
+
160
+ class Meta:
161
+ app_label = 'blog'
162
+ ```
163
+
164
+ ## Core Modules
165
+
166
+ ### Bulk Operations
167
+
168
+ The `bulk` module provides efficient operations for handling large datasets in Django.
169
+
170
+ #### Key Functions
171
+
172
+ **`bulk_create_in_steps(model, bulk, step=1000)`**
173
+
174
+ Creates model instances in chunks with multithreading support.
175
+
176
+ ```python
177
+ from winipedia_django.bulk import bulk_create_in_steps
178
+
179
+ users = [User(username=f"user_{i}", email=f"user_{i}@example.com")
180
+ for i in range(5000)]
181
+ created_users = bulk_create_in_steps(User, users, step=500)
182
+ ```
183
+
184
+ **`bulk_update_in_steps(model, bulk, update_fields, step=1000)`**
185
+
186
+ Updates model instances efficiently in chunks.
187
+
188
+ ```python
189
+ from winipedia_django.bulk import bulk_update_in_steps
190
+
191
+ users = User.objects.all()[:1000]
192
+ for user in users:
193
+ user.is_active = False
194
+
195
+ updated_count = bulk_update_in_steps(User, users, ['is_active'], step=500)
196
+ print(f"Updated {updated_count} users")
197
+ ```
198
+
199
+ **`bulk_delete_in_steps(model, bulk, step=1000)`**
200
+
201
+ Deletes model instances in chunks, respecting cascade relationships.
202
+
203
+ ```python
204
+ from winipedia_django.bulk import bulk_delete_in_steps
205
+
206
+ users_to_delete = User.objects.filter(is_inactive=True)[:1000]
207
+ total_deleted, deleted_by_model = bulk_delete_in_steps(User, users_to_delete)
208
+ print(f"Deleted {total_deleted} objects total")
209
+ print(f"Breakdown: {deleted_by_model}")
210
+ # Output: Breakdown: {'User': 1000, 'UserProfile': 1000, ...}
211
+ ```
212
+
213
+ **`bulk_create_bulks_in_steps(bulk_by_class, step=1000)`**
214
+
215
+ Creates multiple model types respecting foreign key dependencies.
216
+
217
+ ```python
218
+ from winipedia_django.bulk import bulk_create_bulks_in_steps
219
+
220
+ authors = [Author(name=f"Author {i}") for i in range(100)]
221
+ books = [Book(title=f"Book {i}", author=authors[0]) for i in range(500)]
222
+
223
+ bulk_by_class = {
224
+ Author: authors,
225
+ Book: books,
226
+ }
227
+
228
+ results = bulk_create_bulks_in_steps(bulk_by_class, step=100)
229
+ # Authors are created first, then books (respecting FK dependency)
230
+ print(f"Created {len(results[Author])} authors")
231
+ print(f"Created {len(results[Book])} books")
232
+ ```
233
+
234
+ **`get_differences_between_bulks(bulk1, bulk2, fields)`**
235
+
236
+ Compares two lists of model instances and returns differences.
237
+
238
+ ```python
239
+ from winipedia_django.bulk import get_differences_between_bulks
240
+ from winipedia_django.database import get_fields
241
+
242
+ bulk1 = [User(id=1, name="Alice"), User(id=2, name="Bob")]
243
+ bulk2 = [User(id=1, name="Alice"), User(id=3, name="Charlie")]
244
+
245
+ fields = get_fields(User)
246
+ only_in_1, only_in_2, common_1, common_2 = get_differences_between_bulks(
247
+ bulk1, bulk2, fields
248
+ )
249
+
250
+ print(f"Only in bulk1: {len(only_in_1)}") # Bob
251
+ print(f"Only in bulk2: {len(only_in_2)}") # Charlie
252
+ print(f"In both: {len(common_1)}") # Alice
253
+ ```
254
+
255
+ **`simulate_bulk_deletion(model_class, entries)`**
256
+
257
+ Preview what would be deleted including cascade deletions, without modifying the database.
258
+
259
+ ```python
260
+ from winipedia_django.bulk import simulate_bulk_deletion
261
+
262
+ users_to_delete = User.objects.filter(is_inactive=True)[:100]
263
+ deletion_preview = simulate_bulk_deletion(User, users_to_delete)
264
+
265
+ for model, objects in deletion_preview.items():
266
+ print(f"{model.__name__}: {len(objects)} objects would be deleted")
267
+ ```
268
+
269
+ ### Management Commands
270
+
271
+ The `command` module provides an abstract base class for creating well-structured Django management commands.
272
+
273
+ #### ABCBaseCommand
274
+
275
+ A template method pattern implementation that enforces consistent command structure.
276
+
277
+ **Features:**
278
+ - Automatic logging of all command options
279
+ - Pre-configured common arguments
280
+ - Type-safe implementation
281
+ - Enforced abstract methods
282
+
283
+ **Common Arguments (automatically added):**
284
+ - `--dry-run`: Show what would be done without executing
285
+ - `--size`: Size parameter for operations
286
+ - `--force`: Force an action
287
+ - `--delete`: Enable deletion
288
+ - `--quiet`: Suppress non-error output
289
+ - `--debug`: Print debug output
290
+ - `--yes`: Answer yes to all prompts
291
+ - `--config`: Configuration file or JSON string
292
+ - `--timeout`: Timeout for operations
293
+ - `--batch-size`: Number of items per batch
294
+ - `--no-input`: Do not prompt for user input
295
+ - `--threads`: Number of threads for processing
296
+ - `--processes`: Number of processes for processing
297
+
298
+ **Example Implementation:**
299
+
300
+ ```python
301
+ from argparse import ArgumentParser
302
+ from typing import Any
303
+ from winipedia_django.command import ABCBaseCommand
304
+
305
+ class ImportDataCommand(ABCBaseCommand):
306
+ """Import data from a CSV file."""
307
+
308
+ def add_command_arguments(self, parser: ArgumentParser) -> None:
309
+ """Add command-specific arguments."""
310
+ parser.add_argument(
311
+ '--file',
312
+ type=str,
313
+ required=True,
314
+ help='Path to CSV file to import'
315
+ )
316
+ parser.add_argument(
317
+ '--model',
318
+ type=str,
319
+ required=True,
320
+ choices=['user', 'product', 'order'],
321
+ help='Model to import data into'
322
+ )
323
+
324
+ def handle_command(self, *args: Any, **options: Any) -> None:
325
+ """Execute the import command."""
326
+ file_path = options['file']
327
+ model_name = options['model']
328
+ batch_size = options['batch_size'] or 1000
329
+ dry_run = options['dry_run']
330
+ threads = options['threads'] or 4
331
+
332
+ if not dry_run:
333
+ self.stdout.write(
334
+ self.style.WARNING(f'Importing {model_name} from {file_path}')
335
+ )
336
+ else:
337
+ self.stdout.write(
338
+ self.style.WARNING('DRY RUN - No changes will be made')
339
+ )
340
+
341
+ # Your import logic here
342
+ self.stdout.write(
343
+ self.style.SUCCESS('Import completed successfully')
344
+ )
345
+ ```
346
+
347
+ **Usage:**
348
+
349
+ ```bash
350
+ # Normal execution
351
+ python manage.py import_data --file data.csv --model user --batch-size 500
352
+
353
+ # Dry run
354
+ python manage.py import_data --file data.csv --model user --dry-run
355
+
356
+ # With threading
357
+ python manage.py import_data --file data.csv --model user --threads 8
358
+
359
+ # Quiet mode
360
+ python manage.py import_data --file data.csv --model user --quiet
361
+ ```
362
+
363
+ ### Database Utilities
364
+
365
+ The `database` module provides utilities for working with Django models and the database.
366
+
367
+ #### Model Introspection
368
+
369
+ **`get_model_meta(model)`**
370
+
371
+ Get the Django model metadata options object.
372
+
373
+ ```python
374
+ from winipedia_django.database import get_model_meta
375
+
376
+ meta = get_model_meta(User)
377
+ print(meta.db_table) # 'auth_user'
378
+ print(meta.app_label) # 'auth'
379
+ ```
380
+
381
+ **`get_fields(model)`**
382
+
383
+ Get all fields from a model including relationships.
384
+
385
+ ```python
386
+ from winipedia_django.database import get_fields
387
+
388
+ fields = get_fields(User)
389
+ for field in fields:
390
+ if hasattr(field, 'name'):
391
+ print(f"Field: {field.name}, Type: {type(field).__name__}")
392
+ ```
393
+
394
+ **`get_field_names(fields)`**
395
+
396
+ Extract field names from field objects.
397
+
398
+ ```python
399
+ from winipedia_django.database import get_fields, get_field_names
400
+
401
+ fields = get_fields(User)
402
+ field_names = get_field_names(fields)
403
+ print(field_names) # ['id', 'username', 'email', 'is_active', ...]
404
+ ```
405
+
406
+ #### Model Sorting
407
+
408
+ **`topological_sort_models(models)`**
409
+
410
+ Sort Django models in dependency order using topological sorting.
411
+
412
+ ```python
413
+ from winipedia_django.database import topological_sort_models
414
+
415
+ # Models with dependencies
416
+ models = [Review, Book, Author, Publisher]
417
+ sorted_models = topological_sort_models(models)
418
+ # Result: [Author, Publisher, Book, Review]
419
+ # Dependencies are created before dependents
420
+ ```
421
+
422
+ #### Database Operations
423
+
424
+ **`execute_sql(sql, params=None)`**
425
+
426
+ Execute raw SQL query and return column names with results.
427
+
428
+ ```python
429
+ from winipedia_django.database import execute_sql
430
+
431
+ sql = "SELECT id, username FROM auth_user WHERE is_active = %(active)s"
432
+ params = {"active": True}
433
+ columns, rows = execute_sql(sql, params)
434
+
435
+ for row in rows:
436
+ print(f"ID: {row[0]}, Username: {row[1]}")
437
+ ```
438
+
439
+ #### Model Hashing
440
+
441
+ **`hash_model_instance(instance, fields)`**
442
+
443
+ Hash a model instance based on its field values for comparison.
444
+
445
+ ```python
446
+ from winipedia_django.database import hash_model_instance, get_fields
447
+
448
+ user1 = User(name="Alice", email="alice@example.com")
449
+ user2 = User(name="Alice", email="alice@example.com")
450
+
451
+ fields = get_fields(User)
452
+ hash1 = hash_model_instance(user1, fields)
453
+ hash2 = hash_model_instance(user2, fields)
454
+
455
+ print(hash1 == hash2) # True - same field values
456
+ ```
457
+
458
+ #### BaseModel
459
+
460
+ An abstract base model with automatic timestamp fields.
461
+
462
+ ```python
463
+ from winipedia_django.database import BaseModel
464
+ from django.db import models
465
+
466
+ class Article(BaseModel):
467
+ """Article model with automatic timestamps."""
468
+
469
+ title = models.CharField(max_length=200)
470
+ content = models.TextField()
471
+ author = models.CharField(max_length=100)
472
+
473
+ class Meta:
474
+ app_label = 'blog'
475
+
476
+ def __str__(self) -> str:
477
+ return self.title
478
+
479
+ # Usage
480
+ article = Article(title="My Article", content="...", author="John")
481
+ article.save()
482
+
483
+ print(article.created_at) # Automatically set
484
+ print(article.updated_at) # Automatically set
485
+ print(str(article)) # Article(id=1, created_at=..., updated_at=..., title=My Article, ...)
486
+ ```
487
+
488
+ ## Usage Examples
489
+
490
+ ### Example 1: Bulk Import with Progress Tracking
491
+
492
+ ```python
493
+ from winipedia_django.bulk import bulk_create_in_steps
494
+ from myapp.models import Product
495
+ import csv
496
+
497
+ def import_products(csv_file):
498
+ """Import products from CSV file."""
499
+ products = []
500
+
501
+ with open(csv_file, 'r') as f:
502
+ reader = csv.DictReader(f)
503
+ for row in reader:
504
+ products.append(Product(
505
+ name=row['name'],
506
+ price=float(row['price']),
507
+ description=row['description']
508
+ ))
509
+
510
+ # Create in steps of 500
511
+ created = bulk_create_in_steps(Product, products, step=500)
512
+ print(f"Successfully imported {len(created)} products")
513
+ return created
514
+ ```
515
+
516
+ ### Example 2: Efficient Data Synchronization
517
+
518
+ ```python
519
+ from winipedia_django.bulk import get_differences_between_bulks
520
+ from winipedia_django.database import get_fields
521
+
522
+ def sync_users(remote_users, local_users):
523
+ """Synchronize users between remote and local."""
524
+ fields = get_fields(User)
525
+
526
+ only_remote, only_local, common_remote, common_local = (
527
+ get_differences_between_bulks(remote_users, local_users, fields)
528
+ )
529
+
530
+ # Create new users
531
+ if only_remote:
532
+ bulk_create_in_steps(User, only_remote)
533
+
534
+ # Delete removed users
535
+ if only_local:
536
+ bulk_delete_in_steps(User, only_local)
537
+
538
+ print(f"Created: {len(only_remote)}, Deleted: {len(only_local)}")
539
+ ```
540
+
541
+ ### Example 3: Safe Deletion Preview
542
+
543
+ ```python
544
+ from winipedia_django.bulk import simulate_bulk_deletion
545
+
546
+ def preview_deletion(user_ids):
547
+ """Preview what would be deleted."""
548
+ users = User.objects.filter(id__in=user_ids)
549
+ preview = simulate_bulk_deletion(User, list(users))
550
+
551
+ print("Deletion Preview:")
552
+ for model, objects in preview.items():
553
+ print(f" {model.__name__}: {len(objects)} objects")
554
+
555
+ return preview
556
+ ```
557
+
558
+ ### Example 4: Complex Data Migration
559
+
560
+ ```python
561
+ from winipedia_django.bulk import bulk_create_bulks_in_steps
562
+ from winipedia_django.database import topological_sort_models
563
+
564
+ def migrate_data(source_db):
565
+ """Migrate data from source database."""
566
+ # Fetch data from source
567
+ authors = fetch_authors(source_db)
568
+ publishers = fetch_publishers(source_db)
569
+ books = fetch_books(source_db)
570
+
571
+ # Create in dependency order
572
+ bulk_by_class = {
573
+ Author: authors,
574
+ Publisher: publishers,
575
+ Book: books,
576
+ }
577
+
578
+ results = bulk_create_bulks_in_steps(bulk_by_class, step=1000)
579
+
580
+ for model, instances in results.items():
581
+ print(f"Migrated {len(instances)} {model.__name__} objects")
582
+ ```
583
+
584
+ ## API Reference
585
+
586
+ ### Bulk Module (`winipedia_django.bulk`)
587
+
588
+ | Function | Purpose | Returns |
589
+ |----------|---------|---------|
590
+ | `bulk_create_in_steps()` | Create objects in chunks | `list[Model]` |
591
+ | `bulk_update_in_steps()` | Update objects in chunks | `int` (count) |
592
+ | `bulk_delete_in_steps()` | Delete objects in chunks | `tuple[int, dict]` |
593
+ | `bulk_create_bulks_in_steps()` | Create multiple models respecting dependencies | `dict[type[Model], list[Model]]` |
594
+ | `get_differences_between_bulks()` | Compare two model lists | `tuple[list, list, list, list]` |
595
+ | `simulate_bulk_deletion()` | Preview cascade deletions | `dict[type[Model], set[Model]]` |
596
+ | `multi_simulate_bulk_deletion()` | Preview deletions for multiple models | `dict[type[Model], set[Model]]` |
597
+
598
+ ### Command Module (`winipedia_django.command`)
599
+
600
+ | Class | Purpose |
601
+ |-------|---------|
602
+ | `ABCBaseCommand` | Abstract base class for management commands |
603
+
604
+ ### Database Module (`winipedia_django.database`)
605
+
606
+ | Function | Purpose | Returns |
607
+ |----------|---------|---------|
608
+ | `get_model_meta()` | Get model metadata | `Options[Model]` |
609
+ | `get_fields()` | Get all model fields | `list[Field]` |
610
+ | `get_field_names()` | Extract field names | `list[str]` |
611
+ | `topological_sort_models()` | Sort models by dependencies | `list[type[Model]]` |
612
+ | `execute_sql()` | Execute raw SQL | `tuple[list[str], list[Any]]` |
613
+ | `hash_model_instance()` | Hash model instance | `int` |
614
+
615
+ | Class | Purpose |
616
+ |-------|---------|
617
+ | `BaseModel` | Abstract base model with timestamps |
618
+
619
+ ## Best Practices
620
+
621
+ ### 1. Bulk Operations
622
+
623
+ ✅ **Do:**
624
+ - Use appropriate step sizes (default 1000 is usually good)
625
+ - Use `bulk_create_bulks_in_steps()` for related models
626
+ - Preview deletions with `simulate_bulk_deletion()` before actual deletion
627
+ - Use `--dry-run` flag in commands to test before executing
628
+
629
+ ❌ **Don't:**
630
+ - Use bulk operations inside nested transactions without careful consideration
631
+ - Create very large bulks without chunking
632
+ - Ignore cascade deletion warnings
633
+
634
+ ### 2. Management Commands
635
+
636
+ ✅ **Do:**
637
+ - Use `--dry-run` for destructive operations
638
+ - Provide meaningful `--batch-size` options
639
+ - Use `--quiet` for automation scripts
640
+ - Log important operations
641
+
642
+ ❌ **Don't:**
643
+ - Override `add_arguments()` or `handle()` methods
644
+ - Ignore the template method pattern
645
+ - Skip implementing abstract methods
646
+
647
+ ### 3. Database Operations
648
+
649
+ ✅ **Do:**
650
+ - Use `topological_sort_models()` when creating related models
651
+ - Use `get_fields()` for introspection instead of hardcoding field names
652
+ - Use `execute_sql()` with parameter binding for security
653
+ - Inherit from `BaseModel` for automatic timestamps
654
+
655
+ ❌ **Don't:**
656
+ - Use raw string concatenation in SQL queries
657
+ - Assume field order in models
658
+ - Manually manage created_at/updated_at fields
659
+
660
+ ## Performance Tips
661
+
662
+ 1. **Adjust Step Size**: Larger steps are faster but use more memory
663
+ ```python
664
+ # For large objects, use smaller steps
665
+ bulk_create_in_steps(LargeModel, objects, step=100)
666
+
667
+ # For small objects, use larger steps
668
+ bulk_create_in_steps(SmallModel, objects, step=5000)
669
+ ```
670
+
671
+ 2. **Use Threading**: Leverage multithreading for I/O-bound operations
672
+ ```bash
673
+ python manage.py my_command --threads 8
674
+ ```
675
+
676
+ 3. **Batch Processing**: Process data in batches to reduce memory usage
677
+ ```python
678
+ for batch in get_step_chunks(large_dataset, 1000):
679
+ process_batch(batch)
680
+ ```
681
+
682
+ ## Contributing
683
+
684
+ Contributions are welcome! Please ensure:
685
+
686
+ - Code follows the project's style guide (enforced by ruff)
687
+ - All tests pass: `pytest`
688
+ - Type checking passes: `mypy`
689
+ - Code is documented with docstrings
690
+
691
+ ## License
692
+
693
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
694
+
695
+ ## Support
696
+
697
+ For issues, questions, or suggestions, please open an issue on the project repository.
698
+
699
+ ---
700
+
701
+ **Made with ❤️ by Winipedia**
702
+
@@ -3,7 +3,7 @@ winipedia_django/bulk.py,sha256=PmGJE6g1S7_fqqWOWRGV9uExwMcexb5SeR0Hj0k46z0,1987
3
3
  winipedia_django/command.py,sha256=WS9kO_0uvimH7fnxy5GJZp0mREViPPoodBT_4l8DCzM,13461
4
4
  winipedia_django/database.py,sha256=fvjLy0hrR5SEgJ9inGB2tbXblipvpMhX84tS3yjrdEs,10646
5
5
  winipedia_django/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- winipedia_django-0.2.1.dist-info/METADATA,sha256=fuKtrBKGGEjx4HrIQVrbmI1-RM9yb3YwdUXynTR9Z2E,596
7
- winipedia_django-0.2.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
8
- winipedia_django-0.2.1.dist-info/licenses/LICENSE,sha256=o316mE2gGzd__JT69p7S_zlOmKiHh8YjpImCCcWyTvM,1066
9
- winipedia_django-0.2.1.dist-info/RECORD,,
6
+ winipedia_django-0.2.5.dist-info/METADATA,sha256=tkNkPFgR47Y7tZvEQHwKUu2lDyX-SAdN_qa3NLuDBnY,19976
7
+ winipedia_django-0.2.5.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
8
+ winipedia_django-0.2.5.dist-info/licenses/LICENSE,sha256=o316mE2gGzd__JT69p7S_zlOmKiHh8YjpImCCcWyTvM,1066
9
+ winipedia_django-0.2.5.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: winipedia-django
3
- Version: 0.2.1
4
- Summary: A utils package for django
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: django (>=5.2.7,<6.0.0)
15
- Requires-Dist: winipedia-utils (>=0.2.10,<0.3.0)
16
- Description-Content-Type: text/markdown
17
-
18
- # winipedia_django
19
- A utils package for django.
20
-