# -*- coding: utf-8 -*- """ Kompressor-Registry. Zentrale Verwaltung von Komprimierungsalgorithmen. """ from __future__ import annotations from typing import Type from trixy_core.network.compression.compressor import ( Compressor, CompressionLevel, ) from trixy_core.network.compression.zlib import ZlibCompressor, GzipCompressor class CompressionRegistry: """ Registry für Komprimierungsalgorithmen. Verwaltet verfügbare Kompressoren und ermöglicht die Auswahl basierend auf Namen oder Content-Type. Beispiel: registry = get_default_registry() # Nach Namen compressor = registry.get("zlib") # Nach Content-Type compressor = registry.get_by_content_type("application/gzip") """ def __init__(self) -> None: """Initialisiert die Registry.""" self._compressors: dict[str, Type[Compressor]] = {} self._content_types: dict[str, str] = {} def register( self, name: str, compressor_class: Type[Compressor], content_type: str | None = None, ) -> None: """ Registriert einen Kompressor. Args: name: Name des Kompressors compressor_class: Kompressor-Klasse content_type: Optional: Content-Type Mapping """ self._compressors[name.lower()] = compressor_class if content_type: self._content_types[content_type.lower()] = name.lower() def unregister(self, name: str) -> bool: """ Entfernt einen Kompressor. Args: name: Name des Kompressors Returns: True wenn entfernt """ name = name.lower() if name in self._compressors: del self._compressors[name] # Content-Type Mapping entfernen to_remove = [ ct for ct, n in self._content_types.items() if n == name ] for ct in to_remove: del self._content_types[ct] return True return False def get( self, name: str, level: CompressionLevel = CompressionLevel.DEFAULT, ) -> Compressor | None: """ Holt Kompressor nach Namen. Args: name: Name des Kompressors level: Komprimierungsstufe Returns: Kompressor-Instanz oder None """ compressor_class = self._compressors.get(name.lower()) if compressor_class: return compressor_class(level=level) return None def get_by_content_type( self, content_type: str, level: CompressionLevel = CompressionLevel.DEFAULT, ) -> Compressor | None: """ Holt Kompressor nach Content-Type. Args: content_type: Content-Type (z.B. "application/gzip") level: Komprimierungsstufe Returns: Kompressor-Instanz oder None """ name = self._content_types.get(content_type.lower()) if name: return self.get(name, level) return None def list_available(self) -> list[str]: """Listet alle verfügbaren Kompressoren.""" return list(self._compressors.keys()) def is_available(self, name: str) -> bool: """Prüft ob Kompressor verfügbar ist.""" return name.lower() in self._compressors def __contains__(self, name: str) -> bool: return self.is_available(name) def __len__(self) -> int: return len(self._compressors) # Globale Default-Registry _default_registry: CompressionRegistry | None = None def get_default_registry() -> CompressionRegistry: """ Holt die globale Standard-Registry. Enthält vorregistrierte Standard-Kompressoren. Returns: CompressionRegistry-Instanz """ global _default_registry if _default_registry is None: _default_registry = CompressionRegistry() # Zlib registrieren (immer verfügbar) _default_registry.register( "zlib", ZlibCompressor, "application/zlib" ) # Gzip registrieren _default_registry.register( "gzip", GzipCompressor, "application/gzip" ) # Content-Type Aliase _default_registry._content_types["application/x-gzip"] = "gzip" _default_registry._content_types["application/deflate"] = "zlib" # LZ4 wenn verfügbar try: from trixy_core.network.compression.lz4 import ( LZ4Compressor, LZ4HCCompressor, ) _default_registry.register( "lz4", LZ4Compressor, "application/x-lz4" ) _default_registry.register( "lz4hc", LZ4HCCompressor, "application/x-lz4hc" ) except ImportError: pass return _default_registry def get_compressor( name: str, level: CompressionLevel = CompressionLevel.DEFAULT, ) -> Compressor | None: """ Convenience-Funktion zum Holen eines Kompressors. Args: name: Name des Kompressors level: Komprimierungsstufe Returns: Kompressor-Instanz oder None """ return get_default_registry().get(name, level)