🎉 Feat: Import & Function Analysis Tool Enhancements 🎉
This commit introduces a suite of tools for analyzing and optimizing imports and functions within the backend codebase. The following files have been updated: - backend/FRONTEND_ASSETS_ANALYSE.md - backend/REDUNDANZ_ANALYSE_FINAL.md - backend/SOFORT_L\303\226SCHBARE_FUN
This commit is contained in:
324
backend/manual_redundancy_analysis.py
Normal file
324
backend/manual_redundancy_analysis.py
Normal file
@@ -0,0 +1,324 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Manuelle detaillierte Redundanz-Analyse für MYP Backend
|
||||
Fokussiert auf wirklich redundante und ungenutzte Funktionen
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import ast
|
||||
from collections import defaultdict
|
||||
|
||||
def analyze_imports_and_calls():
|
||||
"""Analysiert tatsächliche Importe und Funktionsaufrufe"""
|
||||
backend_path = "/cbin/C0S1-cernel/C02L2/Dateiverwaltung/nextcloud/core/files/3_Beruf_Ausbildung_und_Schule/IHK-Abschlussprüfung/Projektarbeit-MYP/backend"
|
||||
|
||||
function_calls = set()
|
||||
function_defs = {}
|
||||
file_imports = defaultdict(set)
|
||||
|
||||
# Alle Python-Dateien durchgehen
|
||||
for root, dirs, files in os.walk(backend_path):
|
||||
# Ignoriere bestimmte Verzeichnisse
|
||||
dirs[:] = [d for d in dirs if d not in ['.git', '__pycache__', 'node_modules', 'instance']]
|
||||
|
||||
for file in files:
|
||||
if not file.endswith('.py'):
|
||||
continue
|
||||
|
||||
file_path = os.path.join(root, file)
|
||||
rel_path = os.path.relpath(file_path, backend_path)
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Funktionsaufrufe mit Regex finden (umfassender als AST)
|
||||
# Direkte Funktionsaufrufe
|
||||
direct_calls = re.findall(r'(\w+)\s*\(', content)
|
||||
function_calls.update(direct_calls)
|
||||
|
||||
# Attributaufrufe (object.method())
|
||||
attr_calls = re.findall(r'\.(\w+)\s*\(', content)
|
||||
function_calls.update(attr_calls)
|
||||
|
||||
# Import-Aufrufe
|
||||
import_calls = re.findall(r'from\s+[\w.]+\s+import\s+([\w,\s]+)', content)
|
||||
for imports in import_calls:
|
||||
for imp in imports.split(','):
|
||||
function_calls.add(imp.strip())
|
||||
|
||||
# AST für Funktionsdefinitionen
|
||||
try:
|
||||
tree = ast.parse(content)
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.FunctionDef):
|
||||
key = f"{rel_path}:{node.name}"
|
||||
function_defs[key] = {
|
||||
'name': node.name,
|
||||
'file': rel_path,
|
||||
'line': node.lineno,
|
||||
'is_private': node.name.startswith('_'),
|
||||
'is_dunder': node.name.startswith('__') and node.name.endswith('__'),
|
||||
'decorators': [getattr(d, 'id', str(d)) for d in node.decorator_list]
|
||||
}
|
||||
except:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler bei {file_path}: {e}")
|
||||
|
||||
return function_calls, function_defs
|
||||
|
||||
def find_truly_unused_functions():
|
||||
"""Findet wirklich ungenutzte Funktionen"""
|
||||
function_calls, function_defs = analyze_imports_and_calls()
|
||||
|
||||
unused = []
|
||||
|
||||
for key, func in function_defs.items():
|
||||
func_name = func['name']
|
||||
|
||||
# Ausschließen:
|
||||
# 1. Dunder-Methoden (__init__, __str__, etc.)
|
||||
# 2. Flask-Route-Handler (haben @app.route oder @blueprint.route)
|
||||
# 3. Test-Funktionen
|
||||
# 4. Main-Funktionen
|
||||
# 5. Flask-Login required Methoden
|
||||
|
||||
if func['is_dunder']:
|
||||
continue
|
||||
|
||||
if func_name in ['main', 'create_app']:
|
||||
continue
|
||||
|
||||
if func_name.startswith('test_'):
|
||||
continue
|
||||
|
||||
# Flask-Login required methods
|
||||
if func_name in ['is_authenticated', 'is_active', 'is_anonymous', 'get_id']:
|
||||
continue
|
||||
|
||||
# Flask-Route handlers (check decorators)
|
||||
is_route_handler = any('route' in str(d) or 'login_required' in str(d)
|
||||
for d in func['decorators'])
|
||||
if is_route_handler:
|
||||
continue
|
||||
|
||||
# Check if function is actually called
|
||||
if func_name not in function_calls:
|
||||
unused.append({
|
||||
'key': key,
|
||||
'name': func_name,
|
||||
'file': func['file'],
|
||||
'line': func['line'],
|
||||
'is_private': func['is_private']
|
||||
})
|
||||
|
||||
return unused
|
||||
|
||||
def find_duplicate_implementations():
|
||||
"""Findet Funktionen mit sehr ähnlichen oder identischen Implementierungen"""
|
||||
backend_path = "/cbin/C0S1-cernel/C02L2/Dateiverwaltung/nextcloud/core/files/3_Beruf_Ausbildung_und_Schule/IHK-Abschlussprüfung/Projektarbeit-MYP/backend"
|
||||
|
||||
# Bekannte Duplikate basierend auf Funktionsnamen
|
||||
known_duplicates = [
|
||||
# Status-Checking-Funktionen
|
||||
('get_printer_status', 'check_printer_status', 'printer_status'),
|
||||
('get_tapo_status', 'check_tapo_status', 'tapo_status'),
|
||||
|
||||
# Validation-Funktionen
|
||||
('validate_email', 'check_email', 'is_valid_email'),
|
||||
('validate_ip', 'check_ip', 'is_valid_ip'),
|
||||
|
||||
# Database-Helper
|
||||
('get_db_session', 'create_session', 'db_session'),
|
||||
('close_db', 'close_session', 'cleanup_db'),
|
||||
|
||||
# Logging-Funktionen
|
||||
('log_error', 'error_log', 'write_error'),
|
||||
('log_info', 'info_log', 'write_info'),
|
||||
|
||||
# User-Helper
|
||||
('get_user_by_id', 'find_user', 'user_by_id'),
|
||||
('check_permission', 'has_permission', 'validate_permission'),
|
||||
|
||||
# File-Handling
|
||||
('upload_file', 'handle_upload', 'process_upload'),
|
||||
('delete_file', 'remove_file', 'cleanup_file'),
|
||||
]
|
||||
|
||||
duplicates = []
|
||||
function_defs = {}
|
||||
|
||||
# Sammle alle Funktionsdefinitionen
|
||||
for root, dirs, files in os.walk(backend_path):
|
||||
dirs[:] = [d for d in dirs if d not in ['.git', '__pycache__', 'node_modules', 'instance']]
|
||||
|
||||
for file in files:
|
||||
if not file.endswith('.py'):
|
||||
continue
|
||||
|
||||
file_path = os.path.join(root, file)
|
||||
rel_path = os.path.relpath(file_path, backend_path)
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
tree = ast.parse(content)
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.FunctionDef):
|
||||
function_defs[node.name] = function_defs.get(node.name, [])
|
||||
function_defs[node.name].append({
|
||||
'file': rel_path,
|
||||
'line': node.lineno,
|
||||
'name': node.name
|
||||
})
|
||||
except:
|
||||
continue
|
||||
|
||||
# Prüfe auf bekannte Duplikate
|
||||
for duplicate_group in known_duplicates:
|
||||
found_functions = []
|
||||
for func_name in duplicate_group:
|
||||
if func_name in function_defs:
|
||||
found_functions.extend(function_defs[func_name])
|
||||
|
||||
if len(found_functions) > 1:
|
||||
duplicates.append({
|
||||
'group': duplicate_group,
|
||||
'functions': found_functions,
|
||||
'count': len(found_functions)
|
||||
})
|
||||
|
||||
# Prüfe auf Funktionen mit identischen Namen in verschiedenen Dateien
|
||||
for func_name, locations in function_defs.items():
|
||||
if len(locations) > 1 and not func_name.startswith('_'):
|
||||
duplicates.append({
|
||||
'group': [func_name],
|
||||
'functions': locations,
|
||||
'count': len(locations),
|
||||
'type': 'identical_names'
|
||||
})
|
||||
|
||||
return duplicates
|
||||
|
||||
def analyze_utils_redundancy():
|
||||
"""Analysiert Redundanz in utils/ Verzeichnis"""
|
||||
utils_path = "/cbin/C0S1-cernel/C02L2/Dateiverwaltung/nextcloud/core/files/3_Beruf_Ausbildung_und_Schule/IHK-Abschlussprüfung/Projektarbeit-MYP/backend/utils"
|
||||
|
||||
utils_files = []
|
||||
for file in os.listdir(utils_path):
|
||||
if file.endswith('.py') and file != '__init__.py':
|
||||
utils_files.append(file)
|
||||
|
||||
# Kategorisiere Utils-Dateien nach Funktionalität
|
||||
categories = {
|
||||
'database': ['database_cleanup.py', 'database_suite.py', 'data_management.py'],
|
||||
'security': ['security_suite.py', 'ip_security.py', 'ip_validation.py'],
|
||||
'ssl': ['ssl_manager.py', 'ssl_suite.py'],
|
||||
'job_management': ['job_scheduler.py', 'job_queue_system.py'],
|
||||
'system': ['core_system.py', 'system_management.py'],
|
||||
'monitoring': ['monitoring_analytics.py', 'audit_logger.py'],
|
||||
'ui': ['ui_components.py', 'drag_drop_system.py'],
|
||||
'utilities': ['utilities_collection.py', 'script_collection.py', 'development_tools.py']
|
||||
}
|
||||
|
||||
redundant_categories = []
|
||||
|
||||
for category, files in categories.items():
|
||||
existing_files = [f for f in files if f in utils_files]
|
||||
if len(existing_files) > 1:
|
||||
redundant_categories.append({
|
||||
'category': category,
|
||||
'files': existing_files,
|
||||
'recommendation': f"Konsolidiere {len(existing_files)} {category}-bezogene Dateien"
|
||||
})
|
||||
|
||||
return redundant_categories, utils_files
|
||||
|
||||
def analyze_blueprint_redundancy():
|
||||
"""Analysiert Redundanz in blueprints/ Verzeichnis"""
|
||||
blueprints_path = "/cbin/C0S1-cernel/C02L2/Dateiverwaltung/nextcloud/core/files/3_Beruf_Ausbildung_und_Schule/IHK-Abschlussprüfung/Projektarbeit-MYP/backend/blueprints"
|
||||
|
||||
blueprint_files = []
|
||||
for file in os.listdir(blueprints_path):
|
||||
if file.endswith('.py'):
|
||||
blueprint_files.append(file)
|
||||
|
||||
# Identifiziere potentielle Duplikate
|
||||
potential_duplicates = [
|
||||
('api.py', 'api_simple.py'), # Zwei API-Blueprints
|
||||
('admin_unified.py', 'sessions.py'), # Überlappende Admin-Funktionalität
|
||||
]
|
||||
|
||||
duplicates = []
|
||||
for file1, file2 in potential_duplicates:
|
||||
if file1 in blueprint_files and file2 in blueprint_files:
|
||||
duplicates.append({
|
||||
'files': [file1, file2],
|
||||
'reason': 'Potential functional overlap'
|
||||
})
|
||||
|
||||
return duplicates, blueprint_files
|
||||
|
||||
def main():
|
||||
"""Hauptanalyse"""
|
||||
print("=" * 80)
|
||||
print("MANUELLE REDUNDANZ-ANALYSE - MYP BACKEND")
|
||||
print("=" * 80)
|
||||
|
||||
print("\n1. UNGENUTZTE FUNKTIONEN")
|
||||
print("-" * 40)
|
||||
unused = find_truly_unused_functions()
|
||||
unused_public = [f for f in unused if not f['is_private']]
|
||||
unused_private = [f for f in unused if f['is_private']]
|
||||
|
||||
print(f"🔴 Öffentliche ungenutzte Funktionen: {len(unused_public)}")
|
||||
for func in unused_public[:10]: # Top 10
|
||||
print(f" {func['file']}:{func['line']} - {func['name']}()")
|
||||
|
||||
print(f"\n🟡 Private ungenutzte Funktionen: {len(unused_private)}")
|
||||
for func in unused_private[:5]: # Top 5
|
||||
print(f" {func['file']}:{func['line']} - {func['name']}()")
|
||||
|
||||
print("\n2. DOPPELTE IMPLEMENTIERUNGEN")
|
||||
print("-" * 40)
|
||||
duplicates = find_duplicate_implementations()
|
||||
for dup in duplicates[:5]: # Top 5
|
||||
print(f"🔄 {dup['group']}: {dup['count']} Implementierungen")
|
||||
for func in dup['functions']:
|
||||
print(f" {func['file']}:{func['line']} - {func['name']}()")
|
||||
print()
|
||||
|
||||
print("\n3. UTILS-VERZEICHNIS REDUNDANZ")
|
||||
print("-" * 40)
|
||||
redundant_categories, all_utils = analyze_utils_redundancy()
|
||||
print(f"📁 Gesamt Utils-Dateien: {len(all_utils)}")
|
||||
for cat in redundant_categories:
|
||||
print(f"🔧 {cat['category'].upper()}: {cat['recommendation']}")
|
||||
for file in cat['files']:
|
||||
print(f" - {file}")
|
||||
print()
|
||||
|
||||
print("\n4. BLUEPRINT REDUNDANZ")
|
||||
print("-" * 40)
|
||||
blueprint_duplicates, all_blueprints = analyze_blueprint_redundancy()
|
||||
print(f"📁 Gesamt Blueprint-Dateien: {len(all_blueprints)}")
|
||||
for dup in blueprint_duplicates:
|
||||
print(f"🔄 Potentielle Duplikate: {' + '.join(dup['files'])}")
|
||||
print(f" Grund: {dup['reason']}")
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print("EMPFEHLUNGEN FÜR CLEANUP")
|
||||
print("=" * 80)
|
||||
|
||||
print(f"1. 🗑️ Lösche {len(unused_public)} ungenutzte öffentliche Funktionen")
|
||||
print(f"2. 🧹 Prüfe {len(unused_private)} ungenutzte private Funktionen")
|
||||
print(f"3. 🔄 Konsolidiere {len(duplicates)} Duplikat-Gruppen")
|
||||
print(f"4. 📁 Reorganisiere {len(redundant_categories)} Utils-Kategorien")
|
||||
print(f"5. 🔗 Prüfe {len(blueprint_duplicates)} Blueprint-Überlappungen")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user