aiwaf 0.1.9.1.4__py3-none-any.whl → 0.1.9.1.6__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 +122 -3
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.6.dist-info}/METADATA +23 -3
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.6.dist-info}/RECORD +7 -7
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.6.dist-info}/WHEEL +0 -0
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.6.dist-info}/licenses/LICENSE +0 -0
- {aiwaf-0.1.9.1.4.dist-info → aiwaf-0.1.9.1.6.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:
|
|
@@ -489,7 +498,11 @@ class Command(BaseCommand):
|
|
|
489
498
|
else u['package']['name']
|
|
490
499
|
for u in safe_upgrades
|
|
491
500
|
])
|
|
492
|
-
self.stdout.write(f"
|
|
501
|
+
self.stdout.write(f"Commands that would be executed:")
|
|
502
|
+
self.stdout.write(f" {upgrade_cmd}")
|
|
503
|
+
self.stdout.write(f" pip cache purge # Clear pip cache after upgrades")
|
|
504
|
+
return []
|
|
505
|
+
return []
|
|
493
506
|
else:
|
|
494
507
|
self.stdout.write(self.style.HTTP_INFO("\n🚀 Executing safe upgrades..."))
|
|
495
508
|
success_count = 0
|
|
@@ -510,6 +523,11 @@ class Command(BaseCommand):
|
|
|
510
523
|
if result.returncode == 0:
|
|
511
524
|
self.stdout.write(self.style.SUCCESS(f" ✅ {pkg_name} upgraded successfully"))
|
|
512
525
|
success_count += 1
|
|
526
|
+
upgraded_packages.append({
|
|
527
|
+
'name': pkg_name,
|
|
528
|
+
'old_version': upgrade['package']['installed'],
|
|
529
|
+
'new_version': target_version
|
|
530
|
+
})
|
|
513
531
|
else:
|
|
514
532
|
self.stdout.write(self.style.ERROR(f" ❌ Failed to upgrade {pkg_name}: {result.stderr}"))
|
|
515
533
|
|
|
@@ -521,10 +539,26 @@ class Command(BaseCommand):
|
|
|
521
539
|
self.stdout.write(f"\n🎉 Upgrade complete: {success_count}/{len(safe_upgrades)} packages upgraded successfully")
|
|
522
540
|
|
|
523
541
|
if success_count > 0:
|
|
542
|
+
# Clear pip cache after successful upgrades
|
|
543
|
+
self.stdout.write(self.style.HTTP_INFO("\n🧹 Clearing pip cache..."))
|
|
544
|
+
try:
|
|
545
|
+
cache_result = subprocess.run(['pip', 'cache', 'purge'],
|
|
546
|
+
capture_output=True, text=True, timeout=60)
|
|
547
|
+
if cache_result.returncode == 0:
|
|
548
|
+
self.stdout.write(self.style.SUCCESS(" ✅ Pip cache cleared successfully"))
|
|
549
|
+
else:
|
|
550
|
+
self.stdout.write(self.style.WARNING(f" ⚠️ Cache clear warning: {cache_result.stderr}"))
|
|
551
|
+
except subprocess.TimeoutExpired:
|
|
552
|
+
self.stdout.write(self.style.WARNING(" ⚠️ Pip cache clear timed out"))
|
|
553
|
+
except Exception as e:
|
|
554
|
+
self.stdout.write(self.style.WARNING(f" ⚠️ Could not clear pip cache: {e}"))
|
|
555
|
+
|
|
524
556
|
self.stdout.write(self.style.HTTP_INFO("\n💡 Recommendations after upgrade:"))
|
|
525
557
|
self.stdout.write(" 1. Run tests to ensure everything works correctly")
|
|
526
558
|
self.stdout.write(" 2. Run 'python manage.py check_dependencies' again to verify")
|
|
527
559
|
self.stdout.write(" 3. Consider running 'python manage.py detect_and_train' to retrain with new packages")
|
|
560
|
+
|
|
561
|
+
return upgraded_packages
|
|
528
562
|
|
|
529
563
|
def get_aiwaf_compatibility_constraints(self):
|
|
530
564
|
"""Get AIWAF's compatibility constraints to ensure stability"""
|
|
@@ -692,6 +726,91 @@ class Command(BaseCommand):
|
|
|
692
726
|
|
|
693
727
|
return {'safe': True, 'reason': 'No compatibility issues detected'}
|
|
694
728
|
|
|
729
|
+
def update_requirements_file(self, upgraded_packages):
|
|
730
|
+
"""Update requirements.txt with new package versions"""
|
|
731
|
+
self.stdout.write(self.style.HTTP_INFO("\n📝 Updating requirements.txt..."))
|
|
732
|
+
|
|
733
|
+
requirements_path = os.path.join(settings.BASE_DIR, 'requirements.txt')
|
|
734
|
+
|
|
735
|
+
if not os.path.exists(requirements_path):
|
|
736
|
+
self.stdout.write(self.style.WARNING(f" ⚠️ requirements.txt not found at {requirements_path}"))
|
|
737
|
+
self.stdout.write(" 💡 You can create one manually with updated versions")
|
|
738
|
+
return
|
|
739
|
+
|
|
740
|
+
try:
|
|
741
|
+
# Read current requirements.txt
|
|
742
|
+
with open(requirements_path, 'r') as f:
|
|
743
|
+
lines = f.readlines()
|
|
744
|
+
|
|
745
|
+
# Create backup
|
|
746
|
+
backup_path = requirements_path + '.backup'
|
|
747
|
+
with open(backup_path, 'w') as f:
|
|
748
|
+
f.writelines(lines)
|
|
749
|
+
self.stdout.write(f" 📋 Backup created: {backup_path}")
|
|
750
|
+
|
|
751
|
+
# Update lines with new versions
|
|
752
|
+
updated_lines = []
|
|
753
|
+
updated_count = 0
|
|
754
|
+
|
|
755
|
+
for line in lines:
|
|
756
|
+
original_line = line.strip()
|
|
757
|
+
updated_line = line
|
|
758
|
+
|
|
759
|
+
if original_line and not original_line.startswith('#'):
|
|
760
|
+
# Check if this line contains an upgraded package
|
|
761
|
+
for pkg in upgraded_packages:
|
|
762
|
+
pkg_name = pkg['name']
|
|
763
|
+
new_version = pkg['new_version']
|
|
764
|
+
|
|
765
|
+
# Check various formats: package>=version, package==version, etc.
|
|
766
|
+
if self.line_contains_package(original_line, pkg_name):
|
|
767
|
+
# Update the line with new version
|
|
768
|
+
updated_line = self.update_package_line(original_line, pkg_name, new_version)
|
|
769
|
+
if updated_line != original_line:
|
|
770
|
+
updated_count += 1
|
|
771
|
+
self.stdout.write(f" 📦 {pkg_name}: {original_line} → {updated_line.strip()}")
|
|
772
|
+
break
|
|
773
|
+
|
|
774
|
+
updated_lines.append(updated_line)
|
|
775
|
+
|
|
776
|
+
# Write updated requirements.txt
|
|
777
|
+
with open(requirements_path, 'w') as f:
|
|
778
|
+
f.writelines(updated_lines)
|
|
779
|
+
|
|
780
|
+
if updated_count > 0:
|
|
781
|
+
self.stdout.write(self.style.SUCCESS(f"\n ✅ Updated {updated_count} packages in requirements.txt"))
|
|
782
|
+
self.stdout.write(f" 💾 Original backed up as: {backup_path}")
|
|
783
|
+
else:
|
|
784
|
+
self.stdout.write(self.style.NOTICE(" ℹ️ No package lines found to update in requirements.txt"))
|
|
785
|
+
|
|
786
|
+
except Exception as e:
|
|
787
|
+
self.stdout.write(self.style.ERROR(f" ❌ Error updating requirements.txt: {e}"))
|
|
788
|
+
|
|
789
|
+
def line_contains_package(self, line, package_name):
|
|
790
|
+
"""Check if a requirements line contains the specified package"""
|
|
791
|
+
# Remove comments and whitespace
|
|
792
|
+
line = line.split('#')[0].strip()
|
|
793
|
+
if not line:
|
|
794
|
+
return False
|
|
795
|
+
|
|
796
|
+
# Check if line starts with package name followed by version specifier
|
|
797
|
+
return (line.lower().startswith(package_name.lower()) and
|
|
798
|
+
len(line) > len(package_name) and
|
|
799
|
+
line[len(package_name)] in ['=', '<', '>', '!', '~', ' ', '\t'])
|
|
800
|
+
|
|
801
|
+
def update_package_line(self, line, package_name, new_version):
|
|
802
|
+
"""Update a requirements line with new package version"""
|
|
803
|
+
# Split line into package part and comment part
|
|
804
|
+
parts = line.split('#', 1)
|
|
805
|
+
package_part = parts[0].strip()
|
|
806
|
+
comment_part = f" #{parts[1]}" if len(parts) > 1 else ""
|
|
807
|
+
|
|
808
|
+
# Extract package name and update with new version
|
|
809
|
+
# Use >= to allow for future compatible versions
|
|
810
|
+
updated_package = f"{package_name}>={new_version}"
|
|
811
|
+
|
|
812
|
+
return updated_package + comment_part + '\n'
|
|
813
|
+
|
|
695
814
|
def check_security_vulnerabilities(self, dependencies):
|
|
696
815
|
"""Check for known security vulnerabilities using safety"""
|
|
697
816
|
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.6
|
|
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,8 @@ 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
|
|
252
|
+
- ✅ **Pip cache clearing** to prevent cache-related issues
|
|
248
253
|
|
|
249
254
|
**Safe Upgrade System:**
|
|
250
255
|
|
|
@@ -299,6 +304,18 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
299
304
|
❌ numpy 1.21.0 ✗ 2.0.1
|
|
300
305
|
🚨 NumPy 2.0+ may cause compatibility issues (max safe: 1.99.99)
|
|
301
306
|
|
|
307
|
+
🎉 Upgrade complete: 2/2 packages upgraded successfully
|
|
308
|
+
|
|
309
|
+
🧹 Clearing pip cache...
|
|
310
|
+
✅ Pip cache cleared successfully
|
|
311
|
+
|
|
312
|
+
📝 Updating requirements.txt...
|
|
313
|
+
📋 Backup created: requirements.txt.backup
|
|
314
|
+
📦 pandas: pandas>=1.3 → pandas>=1.5.3
|
|
315
|
+
📦 joblib: joblib>=1.1 → joblib>=1.4.2
|
|
316
|
+
✅ Updated 2 packages in requirements.txt
|
|
317
|
+
💾 Original backed up as: requirements.txt.backup
|
|
318
|
+
|
|
302
319
|
�💡 To update outdated packages, run:
|
|
303
320
|
pip install --upgrade pandas==1.5.3 joblib
|
|
304
321
|
```
|
|
@@ -309,6 +326,8 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
309
326
|
- 📊 **Conservative Constraints**: Avoids known problematic versions
|
|
310
327
|
- 🧪 **Dry Run Mode**: Test upgrade plans before execution
|
|
311
328
|
- ⚠️ **Clear Blocking Reasons**: Explains why upgrades are blocked
|
|
329
|
+
- 📝 **Requirements.txt Updates**: Automatically updates dependency files
|
|
330
|
+
- 🧹 **Cache Management**: Clears pip cache after successful upgrades
|
|
312
331
|
|
|
313
332
|
**Recommended Upgrade Workflow:**
|
|
314
333
|
|
|
@@ -324,7 +343,7 @@ The upgrade system is designed to maintain AIWAF stability while keeping your pa
|
|
|
324
343
|
|
|
325
344
|
3. **Execute safe upgrades:**
|
|
326
345
|
```bash
|
|
327
|
-
python manage.py check_dependencies --upgrade
|
|
346
|
+
python manage.py check_dependencies --upgrade --update-requirements
|
|
328
347
|
```
|
|
329
348
|
|
|
330
349
|
4. **Verify after upgrade:**
|
|
@@ -347,6 +366,7 @@ The system uses a multi-layer decision process:
|
|
|
347
366
|
- **Layer 3**: Analyze cross-package dependencies
|
|
348
367
|
- **Layer 4**: Select highest safe version within constraints
|
|
349
368
|
- **Layer 5**: Execute with error handling and rollback capability
|
|
369
|
+
- **Layer 6**: Clear pip cache and update requirements.txt after success
|
|
350
370
|
|
|
351
371
|
This will ensure the IP is never blocked by AI‑WAF. You can also manage exemptions via the Django admin interface.
|
|
352
372
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
aiwaf/__init__.py,sha256=
|
|
1
|
+
aiwaf/__init__.py,sha256=a8AUvwMuCDX-PCu3FtSH2GKroDDvM1zG6q6KbYyuo6k,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=GOZl00pDwW2cJjDvIaCeB3yWxmeYcJDRTIpmOTLvy2c,37204
|
|
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.6.dist-info/licenses/LICENSE,sha256=Ir8PX4dxgAcdB0wqNPIkw84fzIIRKE75NoUil9RX0QU,1069
|
|
31
|
+
aiwaf-0.1.9.1.6.dist-info/METADATA,sha256=d9OfrFnIC8H5G1l8_hASPjqdF4Fe3nRk9I6YEBN5RnI,22145
|
|
32
|
+
aiwaf-0.1.9.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
33
|
+
aiwaf-0.1.9.1.6.dist-info/top_level.txt,sha256=kU6EyjobT6UPCxuWpI_BvcHDG0I2tMgKaPlWzVxe2xI,6
|
|
34
|
+
aiwaf-0.1.9.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|