#!/usr/bin/env python3.9 # -*- coding: utf-8 -*- """ JFinal ProxyCompiler - Dynamic Proxy Compiler """ import os import tempfile import subprocess import hashlib from typing import Dict, Optional, List, Tuple from .ProxyClass import ProxyClass from .ProxyClassLoader import ProxyClassLoader class ProxyCompiler: """Dynamic proxy compiler""" def __init__(self): """Initialize proxy compiler""" self._class_loader = ProxyClassLoader() self._compile_options: List[str] = [] def compile(self, proxy_class: ProxyClass): """ Compile proxy class source code to byte code Args: proxyClass: ProxyClass object with source code """ if not proxy_class.source_code: raise ValueError("Proxy class source code is not set") try: # Generate byte code by compiling Python source byte_code = self._compile_python_source(proxy_class) # Set the byte code proxy_class.byte_code = { proxy_class.full_name: byte_code } except Exception as e: raise RuntimeError(f"Error compiling proxy class: {e}") def _compile_python_source(self, proxy_class: ProxyClass) -> bytes: """ Compile Python source code to bytecode Args: proxyClass: ProxyClass with source code Returns: Compiled bytecode """ # Method 1: Use compile() and exec() try: # Compile the source code compiled = compile(proxy_class.source_code, proxy_class.name, 'exec') # Create a namespace and execute namespace = {} exec(compiled, namespace) # For Python, bytecode is already loaded in the namespace # Return dummy byte code since Python doesn't have traditional bytecode like Java return b'PYTHON_PROXY_CLASS' except SyntaxError as e: raise RuntimeError(f"Syntax error in generated code: {e}") except Exception as e: raise RuntimeError(f"Error compiling Python source: {e}") def set_compile_options(self, options: List[str]) -> 'ProxyCompiler': """ Set compile options Args: options: List of compiler options Returns: Self for chaining """ self._compile_options = options.copy() return self def add_compile_option(self, option: str) -> 'ProxyCompiler': """ Add single compile option Args: option: Compiler option Returns: Self for chaining """ if option: self._compile_options.append(option) return self def get_class_loader(self) -> ProxyClassLoader: """Get associated class loader""" return self._class_loader def compile_and_load(self, proxy_class: ProxyClass) -> type: """ Compile proxy class and load the resulting class Args: proxyClass: ProxyClass with source code Returns: Loaded proxy class """ # Compile self.compile(proxy_class) # Load return self._class_loader.load_proxy_class(proxy_class) class JavaProxyCompiler: """Compiler for Java proxy classes (for Jython compatibility)""" def __init__(self): """Initialize Java proxy compiler""" self._options: List[str] = [] def compile(self, proxy_class: ProxyClass): """Compile Java proxy class""" # This would use javax.tools.JavaCompiler in Java version # For Python, we provide a stub implementation pass def set_options(self, options: List[str]) -> 'JavaProxyCompiler': """Set compiler options""" self._options = options.copy() return self def add_option(self, option: str) -> 'JavaProxyCompiler': """Add compiler option""" if option: self._options.append(option) return self