aiwaf 0.1.9.1.4__py3-none-any.whl → 0.1.9.1.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 aiwaf might be problematic. Click here for more details.
- aiwaf/__init__.py +1 -1
- aiwaf/management/commands/check_dependencies.py +105 -2
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.5.dist-info}/METADATA +17 -3
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.5.dist-info}/RECORD +7 -7
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.5.dist-info}/WHEEL +0 -0
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.5.dist-info}/licenses/LICENSE +0 -0
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.5.dist-info}/top_level.txt +0 -0
aiwaf/__init__.py
CHANGED
|
@@ -40,6 +40,11 @@ class Command(BaseCommand):
|
|
|
40
40
|
action='store_true',
|
|
41
41
|
help='Show what would be upgraded without actually upgrading'
|
|
42
42
|
)
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
'--update-requirements',
|
|
45
|
+
action='store_true',
|
|
46
|
+
help='Update requirements.txt with upgraded package versions'
|
|
47
|
+
)
|
|
43
48
|
|
|
44
49
|
def handle(self, *args, **options):
|
|
45
50
|
self.stdout.write(self.style.SUCCESS('🔍 Checking project dependencies...\n'))
|
|
@@ -61,7 +66,10 @@ class Command(BaseCommand):
|
|
|
61
66
|
self.check_compatibility(results)
|
|
62
67
|
|
|
63
68
|
if options['upgrade']:
|
|
64
|
-
self.perform_safe_upgrade(results, options['dry_run'])
|
|
69
|
+
upgraded_packages = self.perform_safe_upgrade(results, options['dry_run'])
|
|
70
|
+
|
|
71
|
+
if options['update_requirements'] and upgraded_packages and not options['dry_run']:
|
|
72
|
+
self.update_requirements_file(upgraded_packages)
|
|
65
73
|
|
|
66
74
|
if options['check_security']:
|
|
67
75
|
self.check_security_vulnerabilities(dependencies)
|
|
@@ -444,6 +452,7 @@ class Command(BaseCommand):
|
|
|
444
452
|
# Get packages that can be safely upgraded
|
|
445
453
|
safe_upgrades = []
|
|
446
454
|
blocked_upgrades = []
|
|
455
|
+
upgraded_packages = [] # Track successfully upgraded packages
|
|
447
456
|
|
|
448
457
|
for pkg in results:
|
|
449
458
|
if pkg['status'] == 'outdated' and pkg['name'].lower() != 'aiwaf':
|
|
@@ -479,7 +488,7 @@ class Command(BaseCommand):
|
|
|
479
488
|
|
|
480
489
|
if not safe_upgrades:
|
|
481
490
|
self.stdout.write(self.style.NOTICE("ℹ️ No safe upgrades available at this time."))
|
|
482
|
-
return
|
|
491
|
+
return []
|
|
483
492
|
|
|
484
493
|
# Execute upgrades
|
|
485
494
|
if dry_run:
|
|
@@ -490,6 +499,8 @@ class Command(BaseCommand):
|
|
|
490
499
|
for u in safe_upgrades
|
|
491
500
|
])
|
|
492
501
|
self.stdout.write(f"Command that would be executed:\n {upgrade_cmd}")
|
|
502
|
+
return []
|
|
503
|
+
return []
|
|
493
504
|
else:
|
|
494
505
|
self.stdout.write(self.style.HTTP_INFO("\n🚀 Executing safe upgrades..."))
|
|
495
506
|
success_count = 0
|
|
@@ -510,6 +521,11 @@ class Command(BaseCommand):
|
|
|
510
521
|
if result.returncode == 0:
|
|
511
522
|
self.stdout.write(self.style.SUCCESS(f" ✅ {pkg_name} upgraded successfully"))
|
|
512
523
|
success_count += 1
|
|
524
|
+
upgraded_packages.append({
|
|
525
|
+
'name': pkg_name,
|
|
526
|
+
'old_version': upgrade['package']['installed'],
|
|
527
|
+
'new_version': target_version
|
|
528
|
+
})
|
|
513
529
|
else:
|
|
514
530
|
self.stdout.write(self.style.ERROR(f" ❌ Failed to upgrade {pkg_name}: {result.stderr}"))
|
|
515
531
|
|
|
@@ -525,6 +541,8 @@ class Command(BaseCommand):
|
|
|
525
541
|
self.stdout.write(" 1. Run tests to ensure everything works correctly")
|
|
526
542
|
self.stdout.write(" 2. Run 'python manage.py check_dependencies' again to verify")
|
|
527
543
|
self.stdout.write(" 3. Consider running 'python manage.py detect_and_train' to retrain with new packages")
|
|
544
|
+
|
|
545
|
+
return upgraded_packages
|
|
528
546
|
|
|
529
547
|
def get_aiwaf_compatibility_constraints(self):
|
|
530
548
|
"""Get AIWAF's compatibility constraints to ensure stability"""
|
|
@@ -692,6 +710,91 @@ class Command(BaseCommand):
|
|
|
692
710
|
|
|
693
711
|
return {'safe': True, 'reason': 'No compatibility issues detected'}
|
|
694
712
|
|
|
713
|
+
def update_requirements_file(self, upgraded_packages):
|
|
714
|
+
"""Update requirements.txt with new package versions"""
|
|
715
|
+
self.stdout.write(self.style.HTTP_INFO("\n📝 Updating requirements.txt..."))
|
|
716
|
+
|
|
717
|
+
requirements_path = os.path.join(settings.BASE_DIR, 'requirements.txt')
|
|
718
|
+
|
|
719
|
+
if not os.path.exists(requirements_path):
|
|
720
|
+
self.stdout.write(self.style.WARNING(f" ⚠️ requirements.txt not found at {requirements_path}"))
|
|
721
|
+
self.stdout.write(" 💡 You can create one manually with updated versions")
|
|
722
|
+
return
|
|
723
|
+
|
|
724
|
+
try:
|
|
725
|
+
# Read current requirements.txt
|
|
726
|
+
with open(requirements_path, 'r') as f:
|
|
727
|
+
lines = f.readlines()
|
|
728
|
+
|
|
729
|
+
# Create backup
|
|
730
|
+
backup_path = requirements_path + '.backup'
|
|
731
|
+
with open(backup_path, 'w') as f:
|
|
732
|
+
f.writelines(lines)
|
|
733
|
+
self.stdout.write(f" 📋 Backup created: {backup_path}")
|
|
734
|
+
|
|
735
|
+
# Update lines with new versions
|
|
736
|
+
updated_lines = []
|
|
737
|
+
updated_count = 0
|
|
738
|
+
|
|
739
|
+
for line in lines:
|
|
740
|
+
original_line = line.strip()
|
|
741
|
+
updated_line = line
|
|
742
|
+
|
|
743
|
+
if original_line and not original_line.startswith('#'):
|
|
744
|
+
# Check if this line contains an upgraded package
|
|
745
|
+
for pkg in upgraded_packages:
|
|
746
|
+
pkg_name = pkg['name']
|
|
747
|
+
new_version = pkg['new_version']
|
|
748
|
+
|
|
749
|
+
# Check various formats: package>=version, package==version, etc.
|
|
750
|
+
if self.line_contains_package(original_line, pkg_name):
|
|
751
|
+
# Update the line with new version
|
|
752
|
+
updated_line = self.update_package_line(original_line, pkg_name, new_version)
|
|
753
|
+
if updated_line != original_line:
|
|
754
|
+
updated_count += 1
|
|
755
|
+
self.stdout.write(f" 📦 {pkg_name}: {original_line} → {updated_line.strip()}")
|
|
756
|
+
break
|
|
757
|
+
|
|
758
|
+
updated_lines.append(updated_line)
|
|
759
|
+
|
|
760
|
+
# Write updated requirements.txt
|
|
761
|
+
with open(requirements_path, 'w') as f:
|
|
762
|
+
f.writelines(updated_lines)
|
|
763
|
+
|
|
764
|
+
if updated_count > 0:
|
|
765
|
+
self.stdout.write(self.style.SUCCESS(f"\n ✅ Updated {updated_count} packages in requirements.txt"))
|
|
766
|
+
self.stdout.write(f" 💾 Original backed up as: {backup_path}")
|
|
767
|
+
else:
|
|
768
|
+
self.stdout.write(self.style.NOTICE(" ℹ️ No package lines found to update in requirements.txt"))
|
|
769
|
+
|
|
770
|
+
except Exception as e:
|
|
771
|
+
self.stdout.write(self.style.ERROR(f" ❌ Error updating requirements.txt: {e}"))
|
|
772
|
+
|
|
773
|
+
def line_contains_package(self, line, package_name):
|
|
774
|
+
"""Check if a requirements line contains the specified package"""
|
|
775
|
+
# Remove comments and whitespace
|
|
776
|
+
line = line.split('#')[0].strip()
|
|
777
|
+
if not line:
|
|
778
|
+
return False
|
|
779
|
+
|
|
780
|
+
# Check if line starts with package name followed by version specifier
|
|
781
|
+
return (line.lower().startswith(package_name.lower()) and
|
|
782
|
+
len(line) > len(package_name) and
|
|
783
|
+
line[len(package_name)] in ['=', '<', '>', '!', '~', ' ', '\t'])
|
|
784
|
+
|
|
785
|
+
def update_package_line(self, line, package_name, new_version):
|
|
786
|
+
"""Update a requirements line with new package version"""
|
|
787
|
+
# Split line into package part and comment part
|
|
788
|
+
parts = line.split('#', 1)
|
|
789
|
+
package_part = parts[0].strip()
|
|
790
|
+
comment_part = f" #{parts[1]}" if len(parts) > 1 else ""
|
|
791
|
+
|
|
792
|
+
# Extract package name and update with new version
|
|
793
|
+
# Use >= to allow for future compatible versions
|
|
794
|
+
updated_package = f"{package_name}>={new_version}"
|
|
795
|
+
|
|
796
|
+
return updated_package + comment_part + '\n'
|
|
797
|
+
|
|
695
798
|
def check_security_vulnerabilities(self, dependencies):
|
|
696
799
|
"""Check for known security vulnerabilities using safety"""
|
|
697
800
|
self.stdout.write(self.style.HTTP_INFO("\n🔒 Checking for security vulnerabilities..."))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiwaf
|
|
3
|
-
Version: 0.1.9.1.
|
|
3
|
+
Version: 0.1.9.1.5
|
|
4
4
|
Summary: AI-powered Web Application Firewall
|
|
5
5
|
Home-page: https://github.com/aayushgauba/aiwaf
|
|
6
6
|
Author: Aayush Gauba
|
|
@@ -232,8 +232,11 @@ python manage.py check_dependencies --upgrade --dry-run
|
|
|
232
232
|
# Actually upgrade packages safely
|
|
233
233
|
python manage.py check_dependencies --upgrade
|
|
234
234
|
|
|
235
|
+
# Upgrade packages and update requirements.txt
|
|
236
|
+
python manage.py check_dependencies --upgrade --update-requirements
|
|
237
|
+
|
|
235
238
|
# Full workflow: check, upgrade, and scan for vulnerabilities
|
|
236
|
-
python manage.py check_dependencies --upgrade --check-security
|
|
239
|
+
python manage.py check_dependencies --upgrade --check-security --update-requirements
|
|
237
240
|
```
|
|
238
241
|
|
|
239
242
|
**Core Features:**
|
|
@@ -245,6 +248,7 @@ python manage.py check_dependencies --upgrade --check-security
|
|
|
245
248
|
- ✅ **Safe package upgrades** (maintains AIWAF stability)
|
|
246
249
|
- ✅ **Dry run mode** for testing upgrade plans
|
|
247
250
|
- ✅ **AIWAF compatibility validation**
|
|
251
|
+
- ✅ **Automatic requirements.txt updates** after successful upgrades
|
|
248
252
|
|
|
249
253
|
**Safe Upgrade System:**
|
|
250
254
|
|
|
@@ -299,6 +303,15 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
299
303
|
❌ numpy 1.21.0 ✗ 2.0.1
|
|
300
304
|
🚨 NumPy 2.0+ may cause compatibility issues (max safe: 1.99.99)
|
|
301
305
|
|
|
306
|
+
🎉 Upgrade complete: 2/2 packages upgraded successfully
|
|
307
|
+
|
|
308
|
+
📝 Updating requirements.txt...
|
|
309
|
+
📋 Backup created: requirements.txt.backup
|
|
310
|
+
📦 pandas: pandas>=1.3 → pandas>=1.5.3
|
|
311
|
+
📦 joblib: joblib>=1.1 → joblib>=1.4.2
|
|
312
|
+
✅ Updated 2 packages in requirements.txt
|
|
313
|
+
💾 Original backed up as: requirements.txt.backup
|
|
314
|
+
|
|
302
315
|
�💡 To update outdated packages, run:
|
|
303
316
|
pip install --upgrade pandas==1.5.3 joblib
|
|
304
317
|
```
|
|
@@ -309,6 +322,7 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
309
322
|
- 📊 **Conservative Constraints**: Avoids known problematic versions
|
|
310
323
|
- 🧪 **Dry Run Mode**: Test upgrade plans before execution
|
|
311
324
|
- ⚠️ **Clear Blocking Reasons**: Explains why upgrades are blocked
|
|
325
|
+
- 📝 **Requirements.txt Updates**: Automatically updates dependency files
|
|
312
326
|
|
|
313
327
|
**Recommended Upgrade Workflow:**
|
|
314
328
|
|
|
@@ -324,7 +338,7 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
324
338
|
|
|
325
339
|
3. **Execute safe upgrades:**
|
|
326
340
|
```bash
|
|
327
|
-
python manage.py check_dependencies --upgrade
|
|
341
|
+
python manage.py check_dependencies --upgrade --update-requirements
|
|
328
342
|
```
|
|
329
343
|
|
|
330
344
|
4. **Verify after upgrade:**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
aiwaf/__init__.py,sha256=
|
|
1
|
+
aiwaf/__init__.py,sha256=XpqePdxlyW-5RJkAUTNtlGeSUYFl7vaRQ6JrnHU1W-Y,220
|
|
2
2
|
aiwaf/apps.py,sha256=nCez-Ptlv2kaEk5HenA8b1pATz1VfhrHP1344gwcY1A,142
|
|
3
3
|
aiwaf/blacklist_manager.py,sha256=LYCeKFB-7e_C6Bg2WeFJWFIIQlrfRMPuGp30ivrnhQY,1196
|
|
4
4
|
aiwaf/decorators.py,sha256=IUKOdM_gdroffImRZep1g1wT6gNqD10zGwcp28hsJCs,825
|
|
@@ -15,7 +15,7 @@ aiwaf/management/commands/add_ipexemption.py,sha256=sSf3d9hGK9RqqlBYkCrnrd8KZWGT
|
|
|
15
15
|
aiwaf/management/commands/aiwaf_diagnose.py,sha256=nXFRhq66N4QC3e4scYJ2sUngJce-0yDxtBO3R2BllRM,6134
|
|
16
16
|
aiwaf/management/commands/aiwaf_logging.py,sha256=FCIqULn2tii2vD9VxL7vk3PV4k4vr7kaA00KyaCExYY,7692
|
|
17
17
|
aiwaf/management/commands/aiwaf_reset.py,sha256=0FIBqpZS8xgFFvAKJ-0zAC_-QNQwRkOHpXb8N-OdFr8,3740
|
|
18
|
-
aiwaf/management/commands/check_dependencies.py,sha256=
|
|
18
|
+
aiwaf/management/commands/check_dependencies.py,sha256=pxON6cFrBTWtNRzPOzB_S4Jdld1G6q1O_ds3xtbjq8Y,36134
|
|
19
19
|
aiwaf/management/commands/clear_cache.py,sha256=cdnuTgxkhKLqT_6k6yTcEBlREovNRQxAE51ceXlGYMA,647
|
|
20
20
|
aiwaf/management/commands/debug_csv.py,sha256=Lddqp37mIn0zdvHf4GbuNTWYyJ5h8bumDcGmFSAioi0,6801
|
|
21
21
|
aiwaf/management/commands/detect_and_train.py,sha256=-o-LZ7QZ5GeJPCekryox1DGXKMmFEkwwrcDsiM166K0,269
|
|
@@ -27,8 +27,8 @@ aiwaf/management/commands/test_exemption_fix.py,sha256=ngyGaHUCmQQ6y--6j4q1viZJt
|
|
|
27
27
|
aiwaf/resources/model.pkl,sha256=5t6h9BX8yoh2xct85MXOO60jdlWyg1APskUOW0jZE1Y,1288265
|
|
28
28
|
aiwaf/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
29
|
aiwaf/templatetags/aiwaf_tags.py,sha256=XXfb7Tl4DjU3Sc40GbqdaqOEtKTUKELBEk58u83wBNw,357
|
|
30
|
-
aiwaf-0.1.9.1.
|
|
31
|
-
aiwaf-0.1.9.1.
|
|
32
|
-
aiwaf-0.1.9.1.
|
|
33
|
-
aiwaf-0.1.9.1.
|
|
34
|
-
aiwaf-0.1.9.1.
|
|
30
|
+
aiwaf-0.1.9.1.5.dist-info/licenses/LICENSE,sha256=Ir8PX4dxgAcdB0wqNPIkw84fzIIRKE75NoUil9RX0QU,1069
|
|
31
|
+
aiwaf-0.1.9.1.5.dist-info/METADATA,sha256=7hXUI5PEFAGOTugMBbECEz1SgMHbb8NEnYt_Alg4yFM,21873
|
|
32
|
+
aiwaf-0.1.9.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
33
|
+
aiwaf-0.1.9.1.5.dist-info/top_level.txt,sha256=kU6EyjobT6UPCxuWpI_BvcHDG0I2tMgKaPlWzVxe2xI,6
|
|
34
|
+
aiwaf-0.1.9.1.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|