aiwaf 0.1.9.1.3__py3-none-any.whl → 0.1.9.1.4__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 +271 -12
- {aiwaf-0.1.9.1.3.dist-info → aiwaf-0.1.9.1.4.dist-info}/METADATA +161 -4
- {aiwaf-0.1.9.1.3.dist-info → aiwaf-0.1.9.1.4.dist-info}/RECORD +7 -7
- {aiwaf-0.1.9.1.3.dist-info → aiwaf-0.1.9.1.4.dist-info}/WHEEL +0 -0
- {aiwaf-0.1.9.1.3.dist-info → aiwaf-0.1.9.1.4.dist-info}/licenses/LICENSE +0 -0
- {aiwaf-0.1.9.1.3.dist-info → aiwaf-0.1.9.1.4.dist-info}/top_level.txt +0 -0
aiwaf/__init__.py
CHANGED
|
@@ -30,6 +30,16 @@ class Command(BaseCommand):
|
|
|
30
30
|
default=True,
|
|
31
31
|
help='Check for package compatibility issues (default: True)'
|
|
32
32
|
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
'--upgrade',
|
|
35
|
+
action='store_true',
|
|
36
|
+
help='Automatically upgrade packages while maintaining stability'
|
|
37
|
+
)
|
|
38
|
+
parser.add_argument(
|
|
39
|
+
'--dry-run',
|
|
40
|
+
action='store_true',
|
|
41
|
+
help='Show what would be upgraded without actually upgrading'
|
|
42
|
+
)
|
|
33
43
|
|
|
34
44
|
def handle(self, *args, **options):
|
|
35
45
|
self.stdout.write(self.style.SUCCESS('🔍 Checking project dependencies...\n'))
|
|
@@ -50,6 +60,9 @@ class Command(BaseCommand):
|
|
|
50
60
|
if options['check_compatibility']:
|
|
51
61
|
self.check_compatibility(results)
|
|
52
62
|
|
|
63
|
+
if options['upgrade']:
|
|
64
|
+
self.perform_safe_upgrade(results, options['dry_run'])
|
|
65
|
+
|
|
53
66
|
if options['check_security']:
|
|
54
67
|
self.check_security_vulnerabilities(dependencies)
|
|
55
68
|
|
|
@@ -338,18 +351,6 @@ class Command(BaseCommand):
|
|
|
338
351
|
'severity': 'error'
|
|
339
352
|
}
|
|
340
353
|
]
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
'package': 'django',
|
|
344
|
-
'conflicts_with': [
|
|
345
|
-
{
|
|
346
|
-
'package': 'pandas',
|
|
347
|
-
'django_versions': '>=4.0',
|
|
348
|
-
'pandas_versions': '<1.3',
|
|
349
|
-
'message': 'Django 4.0+ works better with pandas 1.3+',
|
|
350
|
-
'severity': 'warning'
|
|
351
|
-
}
|
|
352
|
-
]
|
|
353
354
|
}
|
|
354
355
|
]
|
|
355
356
|
|
|
@@ -433,6 +434,264 @@ class Command(BaseCommand):
|
|
|
433
434
|
|
|
434
435
|
return conflicts
|
|
435
436
|
|
|
437
|
+
def perform_safe_upgrade(self, results, dry_run=False):
|
|
438
|
+
"""Perform safe package upgrades while maintaining AIWAF compatibility"""
|
|
439
|
+
self.stdout.write(self.style.HTTP_INFO("\n🔄 Planning safe package upgrades..."))
|
|
440
|
+
|
|
441
|
+
# AIWAF compatibility constraints
|
|
442
|
+
aiwaf_constraints = self.get_aiwaf_compatibility_constraints()
|
|
443
|
+
|
|
444
|
+
# Get packages that can be safely upgraded
|
|
445
|
+
safe_upgrades = []
|
|
446
|
+
blocked_upgrades = []
|
|
447
|
+
|
|
448
|
+
for pkg in results:
|
|
449
|
+
if pkg['status'] == 'outdated' and pkg['name'].lower() != 'aiwaf':
|
|
450
|
+
upgrade_plan = self.plan_safe_upgrade(pkg, aiwaf_constraints, results)
|
|
451
|
+
if upgrade_plan['safe']:
|
|
452
|
+
safe_upgrades.append(upgrade_plan)
|
|
453
|
+
else:
|
|
454
|
+
blocked_upgrades.append(upgrade_plan)
|
|
455
|
+
|
|
456
|
+
# Display upgrade plan
|
|
457
|
+
if safe_upgrades:
|
|
458
|
+
self.stdout.write(self.style.SUCCESS("\n✅ SAFE UPGRADES PLANNED:"))
|
|
459
|
+
self.stdout.write("─" * 80)
|
|
460
|
+
for upgrade in safe_upgrades:
|
|
461
|
+
pkg = upgrade['package']
|
|
462
|
+
target_version = upgrade['target_version']
|
|
463
|
+
self.stdout.write(
|
|
464
|
+
f"📦 {pkg['name']:<20} {pkg['installed']:<12} → {target_version:<12} "
|
|
465
|
+
f"(Latest: {pkg['latest']})"
|
|
466
|
+
)
|
|
467
|
+
if upgrade['reason']:
|
|
468
|
+
self.stdout.write(f" 💡 {upgrade['reason']}")
|
|
469
|
+
|
|
470
|
+
if blocked_upgrades:
|
|
471
|
+
self.stdout.write(self.style.WARNING("\n⚠️ UPGRADES BLOCKED FOR STABILITY:"))
|
|
472
|
+
self.stdout.write("─" * 80)
|
|
473
|
+
for upgrade in blocked_upgrades:
|
|
474
|
+
pkg = upgrade['package']
|
|
475
|
+
self.stdout.write(
|
|
476
|
+
f"❌ {pkg['name']:<20} {pkg['installed']:<12} ✗ {pkg['latest']:<12}"
|
|
477
|
+
)
|
|
478
|
+
self.stdout.write(f" 🚨 {upgrade['reason']}")
|
|
479
|
+
|
|
480
|
+
if not safe_upgrades:
|
|
481
|
+
self.stdout.write(self.style.NOTICE("ℹ️ No safe upgrades available at this time."))
|
|
482
|
+
return
|
|
483
|
+
|
|
484
|
+
# Execute upgrades
|
|
485
|
+
if dry_run:
|
|
486
|
+
self.stdout.write(self.style.NOTICE("\n🏃 DRY RUN MODE - No packages will be upgraded"))
|
|
487
|
+
upgrade_cmd = "pip install --upgrade " + " ".join([
|
|
488
|
+
f"{u['package']['name']}=={u['target_version']}" if u['target_version'] != u['package']['latest']
|
|
489
|
+
else u['package']['name']
|
|
490
|
+
for u in safe_upgrades
|
|
491
|
+
])
|
|
492
|
+
self.stdout.write(f"Command that would be executed:\n {upgrade_cmd}")
|
|
493
|
+
else:
|
|
494
|
+
self.stdout.write(self.style.HTTP_INFO("\n🚀 Executing safe upgrades..."))
|
|
495
|
+
success_count = 0
|
|
496
|
+
|
|
497
|
+
for upgrade in safe_upgrades:
|
|
498
|
+
pkg_name = upgrade['package']['name']
|
|
499
|
+
target_version = upgrade['target_version']
|
|
500
|
+
|
|
501
|
+
try:
|
|
502
|
+
if target_version == upgrade['package']['latest']:
|
|
503
|
+
cmd = ['pip', 'install', '--upgrade', pkg_name]
|
|
504
|
+
else:
|
|
505
|
+
cmd = ['pip', 'install', f"{pkg_name}=={target_version}"]
|
|
506
|
+
|
|
507
|
+
self.stdout.write(f" Upgrading {pkg_name}...")
|
|
508
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
|
|
509
|
+
|
|
510
|
+
if result.returncode == 0:
|
|
511
|
+
self.stdout.write(self.style.SUCCESS(f" ✅ {pkg_name} upgraded successfully"))
|
|
512
|
+
success_count += 1
|
|
513
|
+
else:
|
|
514
|
+
self.stdout.write(self.style.ERROR(f" ❌ Failed to upgrade {pkg_name}: {result.stderr}"))
|
|
515
|
+
|
|
516
|
+
except subprocess.TimeoutExpired:
|
|
517
|
+
self.stdout.write(self.style.ERROR(f" ❌ Timeout upgrading {pkg_name}"))
|
|
518
|
+
except Exception as e:
|
|
519
|
+
self.stdout.write(self.style.ERROR(f" ❌ Error upgrading {pkg_name}: {e}"))
|
|
520
|
+
|
|
521
|
+
self.stdout.write(f"\n🎉 Upgrade complete: {success_count}/{len(safe_upgrades)} packages upgraded successfully")
|
|
522
|
+
|
|
523
|
+
if success_count > 0:
|
|
524
|
+
self.stdout.write(self.style.HTTP_INFO("\n💡 Recommendations after upgrade:"))
|
|
525
|
+
self.stdout.write(" 1. Run tests to ensure everything works correctly")
|
|
526
|
+
self.stdout.write(" 2. Run 'python manage.py check_dependencies' again to verify")
|
|
527
|
+
self.stdout.write(" 3. Consider running 'python manage.py detect_and_train' to retrain with new packages")
|
|
528
|
+
|
|
529
|
+
def get_aiwaf_compatibility_constraints(self):
|
|
530
|
+
"""Get AIWAF's compatibility constraints to ensure stability"""
|
|
531
|
+
return {
|
|
532
|
+
'django': {
|
|
533
|
+
'min_version': '3.2',
|
|
534
|
+
'max_version': '99.0', # AIWAF works with all Django versions
|
|
535
|
+
'reason': 'AIWAF is compatible with Django 3.2+'
|
|
536
|
+
},
|
|
537
|
+
'numpy': {
|
|
538
|
+
'min_version': '1.21',
|
|
539
|
+
'max_version': '1.99.99', # Avoid NumPy 2.0 breaking changes
|
|
540
|
+
'reason': 'NumPy 2.0+ may cause compatibility issues'
|
|
541
|
+
},
|
|
542
|
+
'pandas': {
|
|
543
|
+
'min_version': '1.3',
|
|
544
|
+
'max_version': '2.9.99',
|
|
545
|
+
'reason': 'AIWAF tested with pandas 1.3-2.x series'
|
|
546
|
+
},
|
|
547
|
+
'scikit-learn': {
|
|
548
|
+
'min_version': '1.0',
|
|
549
|
+
'max_version': '1.99.99', # Stay in 1.x series
|
|
550
|
+
'reason': 'AIWAF models trained with scikit-learn 1.x'
|
|
551
|
+
},
|
|
552
|
+
'joblib': {
|
|
553
|
+
'min_version': '1.1',
|
|
554
|
+
'max_version': '1.99.99',
|
|
555
|
+
'reason': 'AIWAF compatible with joblib 1.x series'
|
|
556
|
+
},
|
|
557
|
+
'packaging': {
|
|
558
|
+
'min_version': '21.0',
|
|
559
|
+
'max_version': '99.0',
|
|
560
|
+
'reason': 'Required for dependency checking'
|
|
561
|
+
},
|
|
562
|
+
'requests': {
|
|
563
|
+
'min_version': '2.25.0',
|
|
564
|
+
'max_version': '2.99.99',
|
|
565
|
+
'reason': 'Required for PyPI API access'
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
def plan_safe_upgrade(self, pkg, aiwaf_constraints, all_results):
|
|
570
|
+
"""Plan a safe upgrade for a package considering AIWAF compatibility"""
|
|
571
|
+
pkg_name = pkg['name'].lower()
|
|
572
|
+
current_version = pkg['installed']
|
|
573
|
+
latest_version = pkg['latest']
|
|
574
|
+
|
|
575
|
+
# Skip AIWAF itself
|
|
576
|
+
if pkg_name == 'aiwaf':
|
|
577
|
+
return {
|
|
578
|
+
'package': pkg,
|
|
579
|
+
'safe': False,
|
|
580
|
+
'target_version': None,
|
|
581
|
+
'reason': 'AIWAF should be upgraded separately using pip install --upgrade aiwaf'
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
# Check AIWAF constraints
|
|
585
|
+
if pkg_name in aiwaf_constraints:
|
|
586
|
+
constraint = aiwaf_constraints[pkg_name]
|
|
587
|
+
max_version = constraint['max_version']
|
|
588
|
+
|
|
589
|
+
try:
|
|
590
|
+
if version.parse(latest_version) > version.parse(max_version):
|
|
591
|
+
# Find the highest safe version
|
|
592
|
+
safe_version = self.find_highest_safe_version(pkg_name, max_version)
|
|
593
|
+
if safe_version and version.parse(safe_version) > version.parse(current_version):
|
|
594
|
+
return {
|
|
595
|
+
'package': pkg,
|
|
596
|
+
'safe': True,
|
|
597
|
+
'target_version': safe_version,
|
|
598
|
+
'reason': f'Upgraded to latest safe version (AIWAF constraint: <={max_version})'
|
|
599
|
+
}
|
|
600
|
+
else:
|
|
601
|
+
return {
|
|
602
|
+
'package': pkg,
|
|
603
|
+
'safe': False,
|
|
604
|
+
'target_version': None,
|
|
605
|
+
'reason': f'{constraint["reason"]} (max safe: {max_version})'
|
|
606
|
+
}
|
|
607
|
+
else:
|
|
608
|
+
# Latest version is within AIWAF constraints
|
|
609
|
+
# Check for other compatibility issues
|
|
610
|
+
compatibility_check = self.check_upgrade_compatibility(pkg, latest_version, all_results)
|
|
611
|
+
if compatibility_check['safe']:
|
|
612
|
+
return {
|
|
613
|
+
'package': pkg,
|
|
614
|
+
'safe': True,
|
|
615
|
+
'target_version': latest_version,
|
|
616
|
+
'reason': 'Safe to upgrade to latest version'
|
|
617
|
+
}
|
|
618
|
+
else:
|
|
619
|
+
return {
|
|
620
|
+
'package': pkg,
|
|
621
|
+
'safe': False,
|
|
622
|
+
'target_version': None,
|
|
623
|
+
'reason': compatibility_check['reason']
|
|
624
|
+
}
|
|
625
|
+
except Exception as e:
|
|
626
|
+
return {
|
|
627
|
+
'package': pkg,
|
|
628
|
+
'safe': False,
|
|
629
|
+
'target_version': None,
|
|
630
|
+
'reason': f'Version parsing error: {e}'
|
|
631
|
+
}
|
|
632
|
+
else:
|
|
633
|
+
# No specific AIWAF constraints, check general compatibility
|
|
634
|
+
compatibility_check = self.check_upgrade_compatibility(pkg, latest_version, all_results)
|
|
635
|
+
return {
|
|
636
|
+
'package': pkg,
|
|
637
|
+
'safe': compatibility_check['safe'],
|
|
638
|
+
'target_version': latest_version if compatibility_check['safe'] else None,
|
|
639
|
+
'reason': compatibility_check['reason'] if not compatibility_check['safe'] else 'No known compatibility issues'
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
def find_highest_safe_version(self, package_name, max_version):
|
|
643
|
+
"""Find the highest version that's still within constraints"""
|
|
644
|
+
try:
|
|
645
|
+
response = requests.get(f'https://pypi.org/pypi/{package_name}/json', timeout=10)
|
|
646
|
+
if response.status_code == 200:
|
|
647
|
+
data = response.json()
|
|
648
|
+
releases = data.get('releases', {})
|
|
649
|
+
|
|
650
|
+
safe_versions = []
|
|
651
|
+
for ver in releases.keys():
|
|
652
|
+
try:
|
|
653
|
+
if version.parse(ver) <= version.parse(max_version):
|
|
654
|
+
safe_versions.append(ver)
|
|
655
|
+
except:
|
|
656
|
+
continue
|
|
657
|
+
|
|
658
|
+
if safe_versions:
|
|
659
|
+
# Sort and return the highest safe version
|
|
660
|
+
safe_versions.sort(key=lambda x: version.parse(x), reverse=True)
|
|
661
|
+
return safe_versions[0]
|
|
662
|
+
except Exception:
|
|
663
|
+
pass
|
|
664
|
+
return None
|
|
665
|
+
|
|
666
|
+
def check_upgrade_compatibility(self, pkg, target_version, all_results):
|
|
667
|
+
"""Check if upgrading a package to target version would cause conflicts"""
|
|
668
|
+
pkg_name = pkg['name'].lower()
|
|
669
|
+
|
|
670
|
+
# Known problematic upgrade scenarios
|
|
671
|
+
if pkg_name == 'numpy' and version.parse(target_version) >= version.parse('2.0.0'):
|
|
672
|
+
# Check if pandas is compatible with NumPy 2.0
|
|
673
|
+
pandas_pkg = next((p for p in all_results if p['name'].lower() == 'pandas'), None)
|
|
674
|
+
if pandas_pkg and pandas_pkg['status'] != 'not_installed':
|
|
675
|
+
pandas_version = pandas_pkg['installed']
|
|
676
|
+
if version.parse(pandas_version) < version.parse('2.1.0'):
|
|
677
|
+
return {
|
|
678
|
+
'safe': False,
|
|
679
|
+
'reason': f'NumPy 2.0+ requires pandas 2.1+, but pandas {pandas_version} is installed'
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if pkg_name == 'pandas' and version.parse(target_version) >= version.parse('2.0.0'):
|
|
683
|
+
# Check if NumPy is compatible
|
|
684
|
+
numpy_pkg = next((p for p in all_results if p['name'].lower() == 'numpy'), None)
|
|
685
|
+
if numpy_pkg and numpy_pkg['status'] != 'not_installed':
|
|
686
|
+
numpy_version = numpy_pkg['installed']
|
|
687
|
+
if version.parse(numpy_version) < version.parse('1.22.0'):
|
|
688
|
+
return {
|
|
689
|
+
'safe': False,
|
|
690
|
+
'reason': f'pandas 2.0+ requires NumPy 1.22+, but NumPy {numpy_version} is installed'
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return {'safe': True, 'reason': 'No compatibility issues detected'}
|
|
694
|
+
|
|
436
695
|
def check_security_vulnerabilities(self, dependencies):
|
|
437
696
|
"""Check for known security vulnerabilities using safety"""
|
|
438
697
|
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.4
|
|
4
4
|
Summary: AI-powered Web Application Firewall
|
|
5
5
|
Home-page: https://github.com/aayushgauba/aiwaf
|
|
6
6
|
Author: Aayush Gauba
|
|
@@ -123,6 +123,9 @@ aiwaf/
|
|
|
123
123
|
- **Missing dependency** detection
|
|
124
124
|
- **Security vulnerability** scanning
|
|
125
125
|
- **Smart upgrade suggestions** with compatibility validation
|
|
126
|
+
- **Safe automated upgrades** that preserve AIWAF stability
|
|
127
|
+
- **Dry run mode** for testing upgrade plans
|
|
128
|
+
- **Cross-package dependency** analysis and conflict resolution
|
|
126
129
|
|
|
127
130
|
|
|
128
131
|
**Exempt Path & IP Awareness**
|
|
@@ -222,14 +225,47 @@ python manage.py check_dependencies --format json
|
|
|
222
225
|
|
|
223
226
|
# Include security vulnerability scanning
|
|
224
227
|
python manage.py check_dependencies --check-security
|
|
228
|
+
|
|
229
|
+
# Dry run - show what would be upgraded
|
|
230
|
+
python manage.py check_dependencies --upgrade --dry-run
|
|
231
|
+
|
|
232
|
+
# Actually upgrade packages safely
|
|
233
|
+
python manage.py check_dependencies --upgrade
|
|
234
|
+
|
|
235
|
+
# Full workflow: check, upgrade, and scan for vulnerabilities
|
|
236
|
+
python manage.py check_dependencies --upgrade --check-security
|
|
225
237
|
```
|
|
226
238
|
|
|
227
|
-
**Features:**
|
|
239
|
+
**Core Features:**
|
|
228
240
|
- ✅ **Parses pyproject.toml and requirements.txt**
|
|
229
241
|
- ✅ **Shows current vs latest versions**
|
|
230
242
|
- ✅ **Checks package compatibility** (NumPy 2.0 vs pandas, etc.)
|
|
231
243
|
- ✅ **Detects missing dependencies**
|
|
232
244
|
- ✅ **Security vulnerability scanning** (requires `safety` package)
|
|
245
|
+
- ✅ **Safe package upgrades** (maintains AIWAF stability)
|
|
246
|
+
- ✅ **Dry run mode** for testing upgrade plans
|
|
247
|
+
- ✅ **AIWAF compatibility validation**
|
|
248
|
+
|
|
249
|
+
**Safe Upgrade System:**
|
|
250
|
+
|
|
251
|
+
The upgrade system is designed to maintain AIWAF stability while keeping your packages up to date:
|
|
252
|
+
|
|
253
|
+
| Protection Level | Description | Example |
|
|
254
|
+
|------------------|-------------|---------|
|
|
255
|
+
| 🛡️ **AIWAF Core** | Never upgrades AIWAF itself | Skips `aiwaf` package |
|
|
256
|
+
| 🔒 **Breaking Changes** | Avoids known problematic versions | Blocks NumPy 2.0+ |
|
|
257
|
+
| 🧠 **Smart Constraints** | Respects AIWAF compatibility matrix | pandas ≤ 2.9.99 |
|
|
258
|
+
| 🔍 **Dependency Analysis** | Checks cross-package compatibility | NumPy vs pandas versions |
|
|
259
|
+
|
|
260
|
+
**AIWAF Compatibility Matrix:**
|
|
261
|
+
|
|
262
|
+
| Package | Safe Range | Blocked Versions | Reason |
|
|
263
|
+
|---------|------------|------------------|---------|
|
|
264
|
+
| Django | 3.2+ | None | AIWAF compatible with all Django versions |
|
|
265
|
+
| NumPy | 1.21 - 1.99 | 2.0+ | Avoid breaking changes |
|
|
266
|
+
| pandas | 1.3 - 2.9 | 3.0+ | AIWAF compatibility |
|
|
267
|
+
| scikit-learn | 1.0 - 1.99 | 2.0+ | Model compatibility |
|
|
268
|
+
| joblib | 1.1 - 1.99 | 2.0+ | AIWAF tested range |
|
|
233
269
|
- ✅ **Provides upgrade commands**
|
|
234
270
|
|
|
235
271
|
**Example Output:**
|
|
@@ -249,10 +285,69 @@ python manage.py check_dependencies --check-security
|
|
|
249
285
|
🔍 Checking package compatibility...
|
|
250
286
|
✅ All packages appear to be compatible!
|
|
251
287
|
|
|
252
|
-
|
|
253
|
-
|
|
288
|
+
� Planning safe package upgrades...
|
|
289
|
+
|
|
290
|
+
✅ SAFE UPGRADES PLANNED:
|
|
291
|
+
────────────────────────────────────────
|
|
292
|
+
📦 pandas 1.3.5 → 1.5.3 (Latest: 2.2.2)
|
|
293
|
+
💡 Upgraded to latest safe version (AIWAF constraint: <=1.99.99)
|
|
294
|
+
📦 joblib 1.1.0 → 1.4.2 (Latest: 1.4.2)
|
|
295
|
+
💡 Safe to upgrade to latest version
|
|
296
|
+
|
|
297
|
+
⚠️ UPGRADES BLOCKED FOR STABILITY:
|
|
298
|
+
────────────────────────────────────────
|
|
299
|
+
❌ numpy 1.21.0 ✗ 2.0.1
|
|
300
|
+
🚨 NumPy 2.0+ may cause compatibility issues (max safe: 1.99.99)
|
|
301
|
+
|
|
302
|
+
�💡 To update outdated packages, run:
|
|
303
|
+
pip install --upgrade pandas==1.5.3 joblib
|
|
254
304
|
```
|
|
255
305
|
|
|
306
|
+
**Safe Upgrade System:**
|
|
307
|
+
- 🛡️ **AIWAF Protection**: Never breaks AIWAF functionality
|
|
308
|
+
- 🔍 **Compatibility Validation**: Checks package interdependencies
|
|
309
|
+
- 📊 **Conservative Constraints**: Avoids known problematic versions
|
|
310
|
+
- 🧪 **Dry Run Mode**: Test upgrade plans before execution
|
|
311
|
+
- ⚠️ **Clear Blocking Reasons**: Explains why upgrades are blocked
|
|
312
|
+
|
|
313
|
+
**Recommended Upgrade Workflow:**
|
|
314
|
+
|
|
315
|
+
1. **Check current status:**
|
|
316
|
+
```bash
|
|
317
|
+
python manage.py check_dependencies
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
2. **Preview safe upgrades:**
|
|
321
|
+
```bash
|
|
322
|
+
python manage.py check_dependencies --upgrade --dry-run
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
3. **Execute safe upgrades:**
|
|
326
|
+
```bash
|
|
327
|
+
python manage.py check_dependencies --upgrade
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
4. **Verify after upgrade:**
|
|
331
|
+
```bash
|
|
332
|
+
python manage.py check_dependencies
|
|
333
|
+
python manage.py detect_and_train # Retrain with new packages
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
5. **Test your application:**
|
|
337
|
+
```bash
|
|
338
|
+
python manage.py test # Run your test suite
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Upgrade Decision Logic:**
|
|
342
|
+
|
|
343
|
+
The system uses a multi-layer decision process:
|
|
344
|
+
|
|
345
|
+
- **Layer 1**: Skip AIWAF itself (manual upgrade recommended)
|
|
346
|
+
- **Layer 2**: Check AIWAF compatibility constraints
|
|
347
|
+
- **Layer 3**: Analyze cross-package dependencies
|
|
348
|
+
- **Layer 4**: Select highest safe version within constraints
|
|
349
|
+
- **Layer 5**: Execute with error handling and rollback capability
|
|
350
|
+
|
|
256
351
|
This will ensure the IP is never blocked by AI‑WAF. You can also manage exemptions via the Django admin interface.
|
|
257
352
|
|
|
258
353
|
- **Daily Retraining**
|
|
@@ -444,6 +539,68 @@ MIDDLEWARE = [
|
|
|
444
539
|
- Missing migrations: `python manage.py migrate`
|
|
445
540
|
- Import errors: Check `INSTALLED_APPS` includes `'aiwaf'`
|
|
446
541
|
|
|
542
|
+
### **Dependency Upgrade Troubleshooting**
|
|
543
|
+
|
|
544
|
+
**Common Upgrade Scenarios:**
|
|
545
|
+
|
|
546
|
+
1. **NumPy 2.0 Upgrade Blocked:**
|
|
547
|
+
```bash
|
|
548
|
+
# Check pandas compatibility first
|
|
549
|
+
python manage.py check_dependencies --upgrade --dry-run
|
|
550
|
+
|
|
551
|
+
# If pandas < 2.1, upgrade pandas first
|
|
552
|
+
pip install 'pandas>=2.1,<3.0'
|
|
553
|
+
|
|
554
|
+
# Then allow NumPy upgrade
|
|
555
|
+
python manage.py check_dependencies --upgrade
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
2. **All Upgrades Blocked:**
|
|
559
|
+
```bash
|
|
560
|
+
# Check what's blocking upgrades
|
|
561
|
+
python manage.py check_dependencies --upgrade --dry-run
|
|
562
|
+
|
|
563
|
+
# Manual override (use with caution)
|
|
564
|
+
pip install --upgrade package-name
|
|
565
|
+
|
|
566
|
+
# Verify AIWAF still works
|
|
567
|
+
python manage.py detect_and_train
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
3. **Package Conflict After Upgrade:**
|
|
571
|
+
```bash
|
|
572
|
+
# Check current compatibility
|
|
573
|
+
python manage.py check_dependencies
|
|
574
|
+
|
|
575
|
+
# Downgrade to last known good version
|
|
576
|
+
pip install package-name==previous-version
|
|
577
|
+
|
|
578
|
+
# Find safe upgrade path
|
|
579
|
+
python manage.py check_dependencies --upgrade --dry-run
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
4. **AIWAF Model Issues After Upgrade:**
|
|
583
|
+
```bash
|
|
584
|
+
# Regenerate model with new package versions
|
|
585
|
+
python manage.py regenerate_model
|
|
586
|
+
|
|
587
|
+
# Retrain with current environment
|
|
588
|
+
python manage.py detect_and_train
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**Emergency Rollback:**
|
|
592
|
+
If an upgrade breaks your system:
|
|
593
|
+
```bash
|
|
594
|
+
# Reinstall exact previous versions
|
|
595
|
+
pip install package-name==old-version
|
|
596
|
+
|
|
597
|
+
# Or use requirements.txt backup
|
|
598
|
+
pip install -r requirements.txt.backup
|
|
599
|
+
|
|
600
|
+
# Verify AIWAF functionality
|
|
601
|
+
python manage.py aiwaf_diagnose
|
|
602
|
+
```
|
|
603
|
+
|
|
447
604
|
---
|
|
448
605
|
|
|
449
606
|
## Running Detection & Training
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
aiwaf/__init__.py,sha256=
|
|
1
|
+
aiwaf/__init__.py,sha256=vkCOYsWFm0FB3Cys7T_e9fuFbGyXKYgqS4JU9yTnz0I,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=dLi3prJjbhzCQzjQND3QLLGzqLJ96XiSLfK8jM0dUpo,31264
|
|
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.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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|