#!/usr/bin/env python3.9 # -*- coding: utf-8 -*- """ JFinal ProxyClassLoader - Dynamic Proxy Class Loader """ import importlib import sys from typing import Dict, Optional, Type from .ProxyClass import ProxyClass class ProxyClassLoader: """Dynamic proxy class loader""" def __init__(self): """Initialize proxy class loader""" self._byte_code_map: Dict[str, bytes] = {} def load_proxy_class(self, proxy_class: ProxyClass) -> Type: """ Load proxy class from byte code Args: proxyClass: ProxyClass object with byte code Returns: Loaded proxy class """ # Add byte code to map if proxy_class.byte_code: for class_name, byte_code in proxy_class.byte_code.items(): if class_name not in self._byte_code_map: self._byte_code_map[class_name] = byte_code # Try to load the class class_name = proxy_class.full_name # Check if already loaded if class_name in sys.modules: return sys.modules[class_name] try: # For Python, we'll use dynamic import # In a real implementation, this would use importlib or similar loaded_class = self._dynamic_import(class_name, proxy_class) return loaded_class except (ImportError, AttributeError) as e: raise RuntimeError(f"Error loading proxy class {class_name}: {e}") def _dynamic_import(self, class_name: str, proxy_class: ProxyClass) -> Type: """ Dynamically import and create class from proxy class Args: class_name: Full class name proxyClass: ProxyClass object Returns: Dynamically created class """ # In Python, we can execute the source code and get the class if proxy_class.source_code: # Create a module module_name = proxy_class.pkg module_code = proxy_class.source_code # Execute the code in a new namespace namespace = {} try: exec(module_code, namespace) # Find the class in the namespace for name, obj in namespace.items(): if isinstance(obj, type) and name == proxy_class.name: return obj raise RuntimeError(f"Class {proxy_class.name} not found in generated code") except Exception as e: raise RuntimeError(f"Error executing generated code: {e}") else: raise RuntimeError("No source code available for proxy class") def find_class(self, name: str) -> Optional[bytes]: """ Find class byte code by name Args: name: Full class name Returns: Byte code or None if not found """ return self._byte_code_map.get(name) def add_byte_code(self, name: str, byte_code: bytes): """ Add byte code to the loader Args: name: Full class name byte_code: Class byte code """ self._byte_code_map[name] = byte_code def remove_byte_code(self, name: str) -> Optional[bytes]: """ Remove and return byte code Args: name: Full class name Returns: Removed byte code or None """ return self._byte_code_map.pop(name, None) def clear(self): """Clear all cached byte code""" self._byte_code_map.clear() @property def byte_code_count(self) -> int: """Get number of cached byte codes""" return len(self._byte_code_map)