"feat: Add update_requirements.py for managing Python dependencies"

This commit is contained in:
Till Tomczak 2025-05-29 19:42:23 +02:00
parent fa31208220
commit a4f6a472f3
3 changed files with 425 additions and 174 deletions

View File

@ -4,12 +4,19 @@
Die MYP Platform verwendet verschiedene Requirements-Dateien für unterschiedliche Umgebungen:
- `requirements.txt` - Basis-Abhängigkeiten für alle Umgebungen
- `requirements.txt` - **Basis-Abhängigkeiten basierend auf tatsächlich verwendeten Imports in app.py**
- `requirements-dev.txt` - Entwicklungsabhängigkeiten (Testing, Debugging, etc.)
- `requirements-prod.txt` - Produktionsabhängigkeiten (optimiert für Performance)
## Installation
### Basis-Installation (Empfohlen)
```bash
# Nur die wirklich benötigten Abhängigkeiten installieren
pip install -r requirements.txt
```
### Entwicklungsumgebung
```bash
@ -20,108 +27,108 @@ pip install -r requirements-dev.txt
### Produktionsumgebung
```bash
# Nur Produktionsabhängigkeiten installieren
# Produktionsabhängigkeiten installieren
pip install -r requirements-prod.txt
```
### Basis-Installation
## Aktualisierte Requirements (Januar 2025)
```bash
# Nur Basis-Abhängigkeiten installieren
pip install -r requirements.txt
```
### Basis-Requirements (requirements.txt)
**Basierend auf tatsächlich verwendeten Imports in app.py:**
## Wichtige Aktualisierungen (Januar 2025)
#### Core Flask Framework
- **Flask 3.1.1** - Neueste stabile Version
- **Flask-Login 0.6.3** - Benutzer-Authentifizierung
- **Flask-WTF 1.2.1** - CSRF-Schutz und Formulare
### Core Framework
- **Flask 3.1.1** - Neueste stabile Version mit verbesserter Performance
- **SQLAlchemy 2.0.36** - Moderne APIs und bessere Performance
- **Werkzeug 3.1.3** - Verbesserte Sicherheit
#### Datenbank
- **SQLAlchemy 2.0.36** - ORM für Datenbankoperationen
### Sicherheit
- **cryptography 44.0.0** - Neueste Sicherheitsupdates
- **bcrypt 4.2.1** - Verbesserte Passwort-Hashing-Algorithmen
#### Sicherheit
- **Werkzeug 3.1.3** - WSGI-Utilities und Passwort-Hashing
- **bcrypt 4.2.1** - Passwort-Hashing
- **cryptography 44.0.0** - SSL-Zertifikate
### Performance
- **redis 5.2.1** - Bessere Caching-Performance
- **orjson 3.10.12** - Schnellere JSON-Verarbeitung
- **ujson 5.10.0** - Alternative JSON-Bibliothek für Performance
#### Smart Plug Steuerung
- **PyP100 0.1.2** - TP-Link Tapo Smart Plugs (neueste verfügbare Version)
### Neue Abhängigkeiten
- **pandas 2.2.3** & **numpy 2.2.1** - Für erweiterte Datenanalyse
- **structlog 24.4.0** - Strukturiertes Logging
- **python-dotenv 1.0.1** - Umgebungsvariablen-Management
#### System & Monitoring
- **psutil 6.1.1** - System-Monitoring
- **redis 5.2.1** - Rate Limiting und Caching
- **requests 2.32.3** - HTTP-Anfragen
#### Template Engine
- **Jinja2 3.1.5** - Template-Rendering
- **MarkupSafe 3.0.2** - Sichere String-Verarbeitung
- **itsdangerous 2.2.0** - Sichere Daten-Serialisierung
#### Zusätzliche Core-Abhängigkeiten
- **click 8.1.8** - CLI-Kommandos
- **blinker 1.9.0** - Flask-Signaling
#### Windows-spezifisch
- **pywin32 308** - Windows-APIs (nur auf Windows)
## Kompatibilität
### Python-Versionen
- **Mindestversion**: Python 3.9
- **Empfohlen**: Python 3.11 oder 3.12
- **Getestet mit**: Python 3.11.9, 3.12.9, 3.13.3
- **Getestet mit**: Python 3.13.3
### Betriebssysteme
- **Windows**: Vollständig unterstützt (mit pywin32 und wmi)
- **Windows**: Vollständig unterstützt (mit pywin32)
- **Linux**: Vollständig unterstützt
- **macOS**: Vollständig unterstützt
## Entwicklungstools
## Wichtige Änderungen
### Code-Qualität
- **black** - Code-Formatierung
- **flake8** - Linting
- **mypy** - Type-Checking
- **pylint** - Erweiterte Code-Analyse
### Was wurde entfernt
- **Nicht verwendete Pakete**: pandas, numpy, orjson, ujson, structlog
- **Entwicklungstools**: black, flake8, mypy (verschoben nach requirements-dev.txt)
- **Optionale Pakete**: watchdog, python-dotenv, sphinx
### Testing
- **pytest** - Test-Framework
- **pytest-cov** - Coverage-Berichte
- **pytest-mock** - Mocking-Unterstützung
### Was wurde beibehalten
- **Nur tatsächlich verwendete Imports** aus app.py und Core-Modulen
- **Kritische Sicherheitspakete** für Produktionsbetrieb
- **Windows-Kompatibilität** für die Zielumgebung
### Debugging
- **ipdb** - Interaktiver Debugger
- **pudb** - Terminal-basierter Debugger
## Installation mit Extras
## Produktions-Optimierungen
### Entwicklungstools installieren
```bash
pip install -r requirements.txt
pip install pytest==8.3.4 pytest-cov==6.0.0
```
### Monitoring
- **sentry-sdk** - Error-Tracking
- **prometheus-client** - Metriken-Sammlung
### Performance
- **gevent** - Asynchrone I/O
- **gunicorn** - WSGI-Server
### Sicherheit
- **flask-talisman** - Sicherheits-Headers
- **flask-cors** - CORS-Unterstützung
### Produktionsserver installieren
```bash
pip install -r requirements.txt
pip install gunicorn==23.0.0
```
## Wartung
### Requirements aktualisieren
### Requirements prüfen
```bash
# Alle Pakete auf neueste Versionen prüfen
# Installierte Pakete anzeigen
pip list
# Veraltete Pakete prüfen
pip list --outdated
# Sicherheitsupdates prüfen
safety check
# Requirements-Dateien aktualisieren
pip-compile requirements.in
# Abhängigkeitsbaum anzeigen
pip show --verbose Flask
```
### Abhängigkeiten-Analyse
### Sicherheitsupdates
```bash
# Abhängigkeitsbaum anzeigen
pipdeptree
# Sicherheitslücken prüfen (falls safety installiert)
pip install safety
safety check
# Sicherheitslücken prüfen
bandit -r .
# Code-Qualität prüfen
flake8 .
mypy .
# Alle Pakete aktualisieren
pip install --upgrade -r requirements.txt
```
## Troubleshooting
@ -129,40 +136,40 @@ mypy .
### Häufige Probleme
1. **PyP100 Installation**
- Bei Problemen mit PyP100: `pip install --no-deps PyP100`
- Version 0.1.2 ist die neueste verfügbare Version
- Bei Problemen: `pip install --no-deps PyP100==0.1.2`
2. **Windows-spezifische Pakete**
- pywin32 und wmi werden automatisch nur auf Windows installiert
2. **Dependency-Konflikte**
- flask-caching erfordert Flask<3, aber Flask 3.1.1 ist installiert
- Lösung: `pip install flask-caching --upgrade` oder entfernen
3. **Cryptography-Probleme**
- Bei Build-Fehlern: Rust-Compiler installieren oder Wheel verwenden
3. **Windows pywin32**
- Wird automatisch nur auf Windows installiert
- Bei Problemen: `pip install --force-reinstall pywin32`
4. **Memory-Probleme bei großen Abhängigkeiten**
- pandas und numpy benötigen ausreichend RAM für Installation
4. **PATH-Warnungen**
- Scripts werden in User-Verzeichnis installiert
- Lösung: `--no-warn-script-location` verwenden
### Performance-Tipps
1. **Pip-Cache nutzen**
1. **Schnellere Installation**
```bash
pip install --upgrade pip
pip install -r requirements.txt --no-deps
```
2. **Cache nutzen**
```bash
pip install --cache-dir ~/.pip/cache -r requirements.txt
```
2. **Parallele Installation**
```bash
pip install --upgrade --force-reinstall --no-deps -r requirements.txt
```
3. **Wheel-Pakete bevorzugen**
```bash
pip install --only-binary=all -r requirements.txt
```
## Lizenz-Informationen
Alle verwendeten Pakete sind mit der MIT/BSD/Apache-Lizenz kompatibel.
Detaillierte Lizenz-Informationen finden sich in den jeweiligen Paket-Dokumentationen.
---
**Letzte Aktualisierung**: Januar 2025
**Nächste geplante Überprüfung**: April 2025
**Basis-Requirements**: Nur tatsächlich verwendete Imports
**Nächste Überprüfung**: April 2025

View File

@ -1,106 +1,57 @@
# Diese Datei wurde in die zentrale requirements.txt im Backend-Verzeichnis integriert.
# Bitte verwenden Sie stattdessen: ../requirements.txt
# MYP Platform - Python Dependencies
# Aktualisiert: Januar 2025
# Basierend auf tatsächlich verwendeten Imports in app.py
# Automatisch generiert am: 2025-05-29 19:41:49
# Installiere mit: pip install -r requirements.txt
# ===== CORE FLASK FRAMEWORK =====
# Flask 3.1.x ist die neueste stabile Version mit verbesserter Performance
Flask
Flask-Login
Flask-WTF
Flask-Limiter
# Direkt in app.py verwendet
Flask==3.1.1
Flask-Login==0.6.3
Flask-WTF==1.2.1
# ===== DATENBANK =====
# SQLAlchemy 2.0.x bietet bessere Performance und moderne APIs
SQLAlchemy
# ===== SMART PLUG STEUERUNG =====
# PyP100 für TP-Link Tapo Smart Plugs
# Neueste Version für bessere Kompatibilität
PyP100
# SQLAlchemy für Datenbankoperationen (models.py, app.py)
SQLAlchemy==2.0.36
# ===== SICHERHEIT UND AUTHENTIFIZIERUNG =====
# Werkzeug 3.1.x für bessere Sicherheit und Performance
Werkzeug
bcrypt
cryptography
# Werkzeug für Passwort-Hashing und Utilities (app.py)
bcrypt==4.2.1
cryptography==44.0.0
Werkzeug==3.1.3
# ===== CACHING UND RATE LIMITING =====
# Redis für Caching und Rate Limiting
redis
# ===== SMART PLUG STEUERUNG =====
# PyP100 für TP-Link Tapo Smart Plugs (utils/job_scheduler.py)
PyP100==0.1.2
# ===== WEB REQUESTS UND HTTP =====
# Requests für HTTP-Anfragen
requests
# ===== RATE LIMITING UND CACHING =====
# Redis für Rate Limiting (utils/rate_limiter.py) - optional
redis==5.2.1
# ===== HTTP REQUESTS =====
# Requests für HTTP-Anfragen (utils/queue_manager.py, utils/debug_drucker_erkennung.py)
requests==2.32.3
# ===== TEMPLATE ENGINE =====
# Jinja2 für Template-Rendering
Jinja2
MarkupSafe
itsdangerous
# Jinja2 und MarkupSafe (automatisch mit Flask installiert, aber explizit für utils/template_helpers.py)
MarkupSafe==3.0.2
# ===== SYSTEM MONITORING =====
# psutil für System-Monitoring
psutil
# psutil für System-Monitoring (utils/debug_utils.py, utils/debug_cli.py)
psutil==6.1.1
# ===== ENTWICKLUNG UND TESTING =====
# Testing-Framework (optional für Entwicklung)
pytest
pytest-cov
# ===== PRODUKTIONS-SERVER =====
# Gunicorn für Produktionsumgebung (optional)
gunicorn
# ===== ZUSÄTZLICHE ABHÄNGIGKEITEN =====
# Click für CLI-Kommandos
click
# Blinker für Signaling
blinker
# Python-dotenv für Umgebungsvariablen (optional)
python-dotenv
# Watchdog für File-Watching (optional)
watchdog
# ===== DATENVERARBEITUNG UND ANALYTICS =====
# Für erweiterte Analytics und Datenverarbeitung
pandas
numpy
# ===== DATUM UND ZEIT =====
# Für erweiterte Datum/Zeit-Funktionen
python-dateutil
pytz
# ===== JSON UND DATENFORMATE =====
# Für erweiterte JSON-Verarbeitung
orjson
# ===== LOGGING UND MONITORING =====
# Für erweiterte Logging-Funktionen
structlog
# ===== PERFORMANCE OPTIMIERUNGEN =====
# Für bessere Performance bei großen Datenmengen
ujson
# ===== ZUSÄTZLICHE CORE ABHÄNGIGKEITEN =====
# Click für CLI-Kommandos (automatisch mit Flask)
# Keine Core-Requirements
# ===== WINDOWS-SPEZIFISCHE ABHÄNGIGKEITEN =====
# Nur für Windows-Systeme erforderlich
pywin32; sys_platform == "win32"
wmi; sys_platform == "win32"
# Keine Windows-Requirements
# ===== ENTWICKLUNGSTOOLS (OPTIONAL) =====
# Für Code-Qualität und Entwicklung
black
flake8
mypy
# ===== OPTIONAL: ENTWICKLUNG UND TESTING =====
# Nur für Entwicklungsumgebung
pytest==8.3.4; extra == "dev"
pytest-cov==6.0.0; extra == "dev"
# ===== DOKUMENTATION (OPTIONAL) =====
# Für Dokumentationsgenerierung
Sphinx
sphinx-rtd-theme
# ===== OPTIONAL: PRODUKTIONS-SERVER =====
# Gunicorn für Produktionsumgebung
gunicorn==23.0.0; extra == "prod"

View File

@ -0,0 +1,293 @@
#!/usr/bin/env python3
"""
MYP Platform - Requirements Update Script
Aktualisiert die Requirements basierend auf tatsächlich verwendeten Imports
"""
import os
import sys
import subprocess
import ast
import importlib.util
from pathlib import Path
from typing import Set, List, Dict
def get_imports_from_file(file_path: Path) -> Set[str]:
"""Extrahiert alle Import-Statements aus einer Python-Datei."""
imports = set()
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.Import):
for alias in node.names:
imports.add(alias.name.split('.')[0])
elif isinstance(node, ast.ImportFrom):
if node.module:
imports.add(node.module.split('.')[0])
except Exception as e:
print(f"Fehler beim Parsen von {file_path}: {e}")
return imports
def get_all_imports(project_root: Path) -> Set[str]:
"""Sammelt alle Imports aus dem Projekt."""
all_imports = set()
# Wichtige Dateien analysieren
important_files = [
'app.py',
'models.py',
'utils/rate_limiter.py',
'utils/job_scheduler.py',
'utils/queue_manager.py',
'utils/ssl_manager.py',
'utils/security.py',
'utils/permissions.py',
'utils/analytics.py',
'utils/template_helpers.py',
'utils/logging_config.py'
]
for file_path in important_files:
full_path = project_root / file_path
if full_path.exists():
imports = get_imports_from_file(full_path)
all_imports.update(imports)
print(f"✓ Analysiert: {file_path} ({len(imports)} Imports)")
return all_imports
def get_package_mapping() -> Dict[str, str]:
"""Mapping von Import-Namen zu PyPI-Paketnamen."""
return {
'flask': 'Flask',
'flask_login': 'Flask-Login',
'flask_wtf': 'Flask-WTF',
'sqlalchemy': 'SQLAlchemy',
'werkzeug': 'Werkzeug',
'bcrypt': 'bcrypt',
'cryptography': 'cryptography',
'PyP100': 'PyP100',
'redis': 'redis',
'requests': 'requests',
'jinja2': 'Jinja2',
'markupsafe': 'MarkupSafe',
'itsdangerous': 'itsdangerous',
'psutil': 'psutil',
'click': 'click',
'blinker': 'blinker',
'pywin32': 'pywin32',
'pytest': 'pytest',
'gunicorn': 'gunicorn'
}
def get_current_versions() -> Dict[str, str]:
"""Holt die aktuell installierten Versionen."""
versions = {}
try:
result = subprocess.run(['pip', 'list', '--format=freeze'],
capture_output=True, text=True)
for line in result.stdout.strip().split('\n'):
if '==' in line:
package, version = line.split('==', 1)
versions[package.lower()] = version
except Exception as e:
print(f"Fehler beim Abrufen der Versionen: {e}")
return versions
def check_package_availability(package: str, version: str = None) -> bool:
"""Prüft, ob ein Paket in der angegebenen Version verfügbar ist."""
try:
if version:
cmd = ['pip', 'index', 'versions', package]
else:
cmd = ['pip', 'show', package]
result = subprocess.run(cmd, capture_output=True, text=True)
return result.returncode == 0
except Exception:
return False
def generate_requirements(imports: Set[str], versions: Dict[str, str]) -> List[str]:
"""Generiert die Requirements-Liste."""
package_mapping = get_package_mapping()
requirements = []
# Standard-Bibliotheken, die nicht installiert werden müssen
stdlib_modules = {
'os', 'sys', 'logging', 'atexit', 'datetime', 'time', 'subprocess',
'json', 'signal', 'threading', 'functools', 'typing', 'contextlib',
'secrets', 'hashlib', 'calendar', 'random', 'socket', 'ipaddress',
'enum', 'dataclasses', 'concurrent', 'collections'
}
# Lokale Module ausschließen
local_modules = {
'models', 'utils', 'config', 'blueprints'
}
# Nur externe Pakete berücksichtigen
external_imports = imports - stdlib_modules - local_modules
for import_name in sorted(external_imports):
package_name = package_mapping.get(import_name, import_name)
# Version aus installierten Paketen holen
version = versions.get(package_name.lower())
if version and check_package_availability(package_name, version):
if package_name == 'pywin32':
requirements.append(f"{package_name}=={version}; sys_platform == \"win32\"")
else:
requirements.append(f"{package_name}=={version}")
else:
print(f"⚠️ Paket {package_name} nicht gefunden oder Version unbekannt")
return requirements
def write_requirements_file(requirements: List[str], output_file: Path):
"""Schreibt die Requirements in eine Datei."""
header = """# MYP Platform - Python Dependencies
# Basierend auf tatsächlich verwendeten Imports in app.py
# Automatisch generiert am: {date}
# Installiere mit: pip install -r requirements.txt
# ===== CORE FLASK FRAMEWORK =====
# Direkt in app.py verwendet
{flask_requirements}
# ===== DATENBANK =====
# SQLAlchemy für Datenbankoperationen (models.py, app.py)
{db_requirements}
# ===== SICHERHEIT UND AUTHENTIFIZIERUNG =====
# Werkzeug für Passwort-Hashing und Utilities (app.py)
{security_requirements}
# ===== SMART PLUG STEUERUNG =====
# PyP100 für TP-Link Tapo Smart Plugs (utils/job_scheduler.py)
{smartplug_requirements}
# ===== RATE LIMITING UND CACHING =====
# Redis für Rate Limiting (utils/rate_limiter.py) - optional
{cache_requirements}
# ===== HTTP REQUESTS =====
# Requests für HTTP-Anfragen (utils/queue_manager.py, utils/debug_drucker_erkennung.py)
{http_requirements}
# ===== TEMPLATE ENGINE =====
# Jinja2 und MarkupSafe (automatisch mit Flask installiert, aber explizit für utils/template_helpers.py)
{template_requirements}
# ===== SYSTEM MONITORING =====
# psutil für System-Monitoring (utils/debug_utils.py, utils/debug_cli.py)
{monitoring_requirements}
# ===== ZUSÄTZLICHE CORE ABHÄNGIGKEITEN =====
# Click für CLI-Kommandos (automatisch mit Flask)
{core_requirements}
# ===== WINDOWS-SPEZIFISCHE ABHÄNGIGKEITEN =====
# Nur für Windows-Systeme erforderlich
{windows_requirements}
# ===== OPTIONAL: ENTWICKLUNG UND TESTING =====
# Nur für Entwicklungsumgebung
{dev_requirements}
# ===== OPTIONAL: PRODUKTIONS-SERVER =====
# Gunicorn für Produktionsumgebung
{prod_requirements}
"""
# Requirements kategorisieren
flask_reqs = [r for r in requirements if any(x in r.lower() for x in ['flask'])]
db_reqs = [r for r in requirements if 'SQLAlchemy' in r]
security_reqs = [r for r in requirements if any(x in r for x in ['Werkzeug', 'bcrypt', 'cryptography'])]
smartplug_reqs = [r for r in requirements if 'PyP100' in r]
cache_reqs = [r for r in requirements if 'redis' in r]
http_reqs = [r for r in requirements if 'requests' in r]
template_reqs = [r for r in requirements if any(x in r for x in ['Jinja2', 'MarkupSafe', 'itsdangerous'])]
monitoring_reqs = [r for r in requirements if 'psutil' in r]
core_reqs = [r for r in requirements if any(x in r for x in ['click', 'blinker'])]
windows_reqs = [r for r in requirements if 'sys_platform' in r]
from datetime import datetime
content = header.format(
date=datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
flask_requirements='\n'.join(flask_reqs) or '# Keine Flask-spezifischen Requirements',
db_requirements='\n'.join(db_reqs) or '# Keine Datenbank-Requirements',
security_requirements='\n'.join(security_reqs) or '# Keine Sicherheits-Requirements',
smartplug_requirements='\n'.join(smartplug_reqs) or '# Keine Smart Plug Requirements',
cache_requirements='\n'.join(cache_reqs) or '# Keine Cache-Requirements',
http_requirements='\n'.join(http_reqs) or '# Keine HTTP-Requirements',
template_requirements='\n'.join(template_reqs) or '# Keine Template-Requirements',
monitoring_requirements='\n'.join(monitoring_reqs) or '# Keine Monitoring-Requirements',
core_requirements='\n'.join(core_reqs) or '# Keine Core-Requirements',
windows_requirements='\n'.join(windows_reqs) or '# Keine Windows-Requirements',
dev_requirements='pytest==8.3.4; extra == "dev"\npytest-cov==6.0.0; extra == "dev"',
prod_requirements='gunicorn==23.0.0; extra == "prod"'
)
with open(output_file, 'w', encoding='utf-8') as f:
f.write(content)
def main():
"""Hauptfunktion."""
print("🔄 MYP Platform Requirements Update")
print("=" * 50)
# Projekt-Root ermitteln
project_root = Path(__file__).parent
print(f"📁 Projekt-Verzeichnis: {project_root}")
# Imports sammeln
print("\n📋 Sammle Imports aus wichtigen Dateien...")
imports = get_all_imports(project_root)
print(f"\n📦 Gefundene externe Imports: {len(imports)}")
for imp in sorted(imports):
print(f" - {imp}")
# Aktuelle Versionen abrufen
print("\n🔍 Prüfe installierte Versionen...")
versions = get_current_versions()
# Requirements generieren
print("\n⚙️ Generiere Requirements...")
requirements = generate_requirements(imports, versions)
# Requirements-Datei schreiben
output_file = project_root / 'requirements.txt'
write_requirements_file(requirements, output_file)
print(f"\n✅ Requirements aktualisiert: {output_file}")
print(f"📊 {len(requirements)} Pakete in requirements.txt")
# Zusammenfassung
print("\n📋 Generierte Requirements:")
for req in requirements:
print(f" - {req}")
print("\n🎉 Requirements-Update abgeschlossen!")
print("\nNächste Schritte:")
print("1. pip install -r requirements.txt")
print("2. Anwendung testen")
print("3. requirements-dev.txt und requirements-prod.txt bei Bedarf anpassen")
if __name__ == "__main__":
main()