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
324 lines
12 KiB
Python
324 lines
12 KiB
Python
#!/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() |