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 CHANGED
@@ -1,6 +1,6 @@
1
1
  default_app_config = "aiwaf.apps.AiwafConfig"
2
2
 
3
- __version__ = "0.1.9.1.4"
3
+ __version__ = "0.1.9.1.6"
4
4
 
5
5
  # Note: Middleware classes are available from aiwaf.middleware
6
6
  # Import them only when needed to avoid circular imports during Django app loading
@@ -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"Command that would be executed:\n {upgrade_cmd}")
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.4
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=vkCOYsWFm0FB3Cys7T_e9fuFbGyXKYgqS4JU9yTnz0I,220
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=dLi3prJjbhzCQzjQND3QLLGzqLJ96XiSLfK8jM0dUpo,31264
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.4.dist-info/licenses/LICENSE,sha256=Ir8PX4dxgAcdB0wqNPIkw84fzIIRKE75NoUil9RX0QU,1069
31
- aiwaf-0.1.9.1.4.dist-info/METADATA,sha256=peKauMlND1kyqP_pYsLTrumQHXoO5Q65VaylYL5_SlM,21231
32
- aiwaf-0.1.9.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- aiwaf-0.1.9.1.4.dist-info/top_level.txt,sha256=kU6EyjobT6UPCxuWpI_BvcHDG0I2tMgKaPlWzVxe2xI,6
34
- aiwaf-0.1.9.1.4.dist-info/RECORD,,
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,,