108 lines
3.7 KiB
Python
108 lines
3.7 KiB
Python
#!/usr/bin/env python3.9
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
JFinal ReflectKit - Reflection Utilities
|
|
"""
|
|
|
|
import inspect
|
|
from typing import Any, Dict, List, Type
|
|
|
|
class ReflectKit:
|
|
"""Reflection utility class"""
|
|
|
|
@staticmethod
|
|
def new_instance(clazz: Type) -> Any:
|
|
"""Create new instance of class"""
|
|
try:
|
|
# Try __new__ first (for immutable types)
|
|
if hasattr(clazz, '__new__'):
|
|
obj = clazz.__new__(clazz)
|
|
if obj is not None and not isinstance(obj, type):
|
|
return obj
|
|
|
|
# Fall back to regular instantiation
|
|
return clazz()
|
|
except Exception as e:
|
|
raise RuntimeError(f"Error creating instance of {clazz}: {e}")
|
|
|
|
@staticmethod
|
|
def get_method_signature(method) -> str:
|
|
"""Get method signature as string"""
|
|
if not callable(method):
|
|
raise ValueError("method must be callable")
|
|
|
|
try:
|
|
# Get function information
|
|
if hasattr(method, '__name__'):
|
|
method_name = method.__name__
|
|
else:
|
|
method_name = str(method)
|
|
|
|
# Get declaring class
|
|
if hasattr(method, '__qualname__'):
|
|
declaring_class = method.__qualname__.rsplit('.', 1)[0] if '.' in method.__qualname__ else ''
|
|
else:
|
|
declaring_class = ''
|
|
|
|
# Get parameters
|
|
try:
|
|
sig = inspect.signature(method)
|
|
params = []
|
|
for param_name, param in sig.parameters.items():
|
|
if param_name != 'self':
|
|
param_type = param.annotation if param.annotation != inspect.Parameter.empty else Any
|
|
params.append(str(param_type.__name__) if hasattr(param_type, '__name__') else str(param_type))
|
|
except (ValueError, TypeError):
|
|
params = []
|
|
|
|
# Build signature
|
|
if declaring_class:
|
|
signature = f"{declaring_class}.{method_name}({', '.join(params)})"
|
|
else:
|
|
signature = f"{method_name}({', '.join(params)})"
|
|
|
|
return signature
|
|
|
|
except Exception as e:
|
|
raise RuntimeError(f"Error getting method signature: {e}")
|
|
|
|
@staticmethod
|
|
def get_class_methods(clazz: Type) -> Dict[str, callable]:
|
|
"""Get all methods of a class"""
|
|
methods = {}
|
|
try:
|
|
for name, method in inspect.getmembers(clazz, predicate=inspect.isfunction):
|
|
if not name.startswith('_'):
|
|
methods[name] = method
|
|
except Exception as e:
|
|
raise RuntimeError(f"Error getting class methods: {e}")
|
|
return methods
|
|
|
|
@staticmethod
|
|
def get_class_attributes(clazz: Type) -> Dict[str, Any]:
|
|
"""Get all class attributes"""
|
|
attributes = {}
|
|
try:
|
|
for name, value in inspect.getmembers(clazz):
|
|
if not name.startswith('_') and not callable(value):
|
|
attributes[name] = value
|
|
except Exception as e:
|
|
raise RuntimeError(f"Error getting class attributes: {e}")
|
|
return attributes
|
|
|
|
@staticmethod
|
|
def is_subclass_of(subclass: Type, superclass: Type) -> bool:
|
|
"""Check if subclass is subclass of superclass"""
|
|
try:
|
|
return issubclass(subclass, superclass)
|
|
except TypeError:
|
|
return False
|
|
|
|
@staticmethod
|
|
def is_instance_of(obj: Any, clazz: Type) -> bool:
|
|
"""Check if object is instance of class"""
|
|
try:
|
|
return isinstance(obj, clazz)
|
|
except TypeError:
|
|
return False
|