调整版本并做测试
This commit is contained in:
172
pyenjoy/template/expr/ast/Arith.py
Normal file
172
pyenjoy/template/expr/ast/Arith.py
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal Arith - Arithmetic Expression
|
||||
"""
|
||||
|
||||
from .Expr import Expr
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
|
||||
class Arith(Expr):
|
||||
"""Arithmetic expression"""
|
||||
|
||||
ADD = "+"
|
||||
SUB = "-"
|
||||
MUL = "*"
|
||||
DIV = "/"
|
||||
MOD = "%"
|
||||
|
||||
_rounding_mode = ROUND_HALF_UP
|
||||
|
||||
def __init__(self, left: Expr, operator: str, right: Expr):
|
||||
"""
|
||||
Initialize arithmetic expression
|
||||
|
||||
Args:
|
||||
left: Left expression
|
||||
operator: Arithmetic operator
|
||||
right: Right expression
|
||||
"""
|
||||
self._left = left
|
||||
self._operator = operator
|
||||
self._right = right
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate arithmetic expression"""
|
||||
left_val = self._left.eval(scope)
|
||||
right_val = self._right.eval(scope)
|
||||
|
||||
# Handle None values
|
||||
if left_val is None or right_val is None:
|
||||
return None
|
||||
|
||||
# Convert to appropriate numeric types
|
||||
left_num = self._to_number(left_val)
|
||||
right_num = self._to_number(right_val)
|
||||
|
||||
if left_num is None or right_num is None:
|
||||
return None
|
||||
|
||||
# Perform operation
|
||||
if self._operator == Arith.ADD:
|
||||
return left_num + right_num
|
||||
elif self._operator == Arith.SUB:
|
||||
return left_num - right_num
|
||||
elif self._operator == Arith.MUL:
|
||||
return left_num * right_num
|
||||
elif self._operator == Arith.DIV:
|
||||
if right_num == 0:
|
||||
raise ZeroDivisionError("Division by zero")
|
||||
return self._divide(left_num, right_num)
|
||||
elif self._operator == Arith.MOD:
|
||||
return left_num % right_num
|
||||
else:
|
||||
raise ValueError(f"Unknown operator: {self._operator}")
|
||||
|
||||
def _to_number(self, value):
|
||||
"""Convert value to number"""
|
||||
if isinstance(value, (int, float)):
|
||||
return value
|
||||
if isinstance(value, Decimal):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
if '.' in value:
|
||||
return float(value)
|
||||
else:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return None
|
||||
return None
|
||||
|
||||
def _divide(self, left, right):
|
||||
"""Handle division with proper rounding"""
|
||||
if isinstance(left, Decimal) or isinstance(right, Decimal):
|
||||
result = Decimal(str(left)) / Decimal(str(right))
|
||||
return result.quantize(Decimal('0.00000001'), rounding=self._rounding_mode)
|
||||
else:
|
||||
return left / right
|
||||
|
||||
@classmethod
|
||||
def set_big_decimal_divide_rounding_mode(cls, rounding_mode):
|
||||
"""Set rounding mode for decimal division"""
|
||||
cls._rounding_mode = rounding_mode
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Arith({self._left} {self._operator} {self._right})"
|
||||
|
||||
|
||||
class Unary(Expr):
|
||||
"""Unary expression (positive, negative, increment, decrement)"""
|
||||
|
||||
POSITIVE = "+"
|
||||
NEGATIVE = "-"
|
||||
NOT = "!"
|
||||
|
||||
def __init__(self, operator: str, expr: Expr):
|
||||
"""
|
||||
Initialize unary expression
|
||||
|
||||
Args:
|
||||
operator: Unary operator
|
||||
expr: Expression to operate on
|
||||
"""
|
||||
self._operator = operator
|
||||
self._expr = expr
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate unary expression"""
|
||||
val = self._expr.eval(scope)
|
||||
|
||||
if self._operator == Unary.POSITIVE:
|
||||
return +val if isinstance(val, (int, float)) else val
|
||||
elif self._operator == Unary.NEGATIVE:
|
||||
return -val if isinstance(val, (int, float)) else val
|
||||
elif self._operator == Unary.NOT:
|
||||
return not val
|
||||
else:
|
||||
raise ValueError(f"Unknown operator: {self._operator}")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Unary({self._operator}{self._expr})"
|
||||
|
||||
|
||||
class IncDec(Expr):
|
||||
"""Increment/Decrement expression"""
|
||||
|
||||
INC = "++"
|
||||
DEC = "--"
|
||||
|
||||
def __init__(self, expr: Expr, operator: str, is_prefix: bool = True):
|
||||
"""
|
||||
Initialize increment/decrement
|
||||
|
||||
Args:
|
||||
expr: Expression to increment/decrement
|
||||
operator: INC or DEC
|
||||
is_prefix: Whether this is prefix (++x) or postfix (x++)
|
||||
"""
|
||||
self._expr = expr
|
||||
self._operator = operator
|
||||
self._is_prefix = is_prefix
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate increment/decrement"""
|
||||
# This is a simplified implementation
|
||||
# In a real implementation, this would modify the variable
|
||||
current_val = self._expr.eval(scope)
|
||||
|
||||
if isinstance(current_val, int):
|
||||
if self._operator == IncDec.INC:
|
||||
return current_val + 1
|
||||
else:
|
||||
return current_val - 1
|
||||
|
||||
return current_val
|
||||
|
||||
def __repr__(self) -> str:
|
||||
op_str = self._operator
|
||||
if self._is_prefix:
|
||||
return f"IncDec({op_str}{self._expr})"
|
||||
else:
|
||||
return f"IncDec({self._expr}{op_str})"
|
||||
138
pyenjoy/template/expr/ast/Compare.py
Normal file
138
pyenjoy/template/expr/ast/Compare.py
Normal file
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal Compare - Comparison Expression
|
||||
"""
|
||||
|
||||
from .Expr import Expr
|
||||
|
||||
class Compare(Expr):
|
||||
"""Comparison expression"""
|
||||
|
||||
EQ = "=="
|
||||
NE = "!="
|
||||
GT = ">"
|
||||
GTE = ">="
|
||||
LT = "<"
|
||||
LTE = "<="
|
||||
|
||||
def __init__(self, left: Expr, operator: str, right: Expr):
|
||||
"""
|
||||
Initialize comparison
|
||||
|
||||
Args:
|
||||
left: Left expression
|
||||
operator: Comparison operator
|
||||
right: Right expression
|
||||
"""
|
||||
self._left = left
|
||||
self._operator = operator
|
||||
self._right = right
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate comparison"""
|
||||
left_val = self._left.eval(scope)
|
||||
right_val = self._right.eval(scope)
|
||||
|
||||
# Handle None comparisons
|
||||
if left_val is None and right_val is None:
|
||||
return self._operator == Compare.EQ
|
||||
if left_val is None or right_val is None:
|
||||
return self._operator == Compare.NE
|
||||
|
||||
# Perform comparison based on operator
|
||||
if self._operator == Compare.EQ:
|
||||
return left_val == right_val
|
||||
elif self._operator == Compare.NE:
|
||||
return left_val != right_val
|
||||
elif self._operator == Compare.GT:
|
||||
return left_val > right_val
|
||||
elif self._operator == Compare.GTE:
|
||||
return left_val >= right_val
|
||||
elif self._operator == Compare.LT:
|
||||
return left_val < right_val
|
||||
elif self._operator == Compare.LTE:
|
||||
return left_val <= right_val
|
||||
else:
|
||||
raise ValueError(f"Unknown operator: {self._operator}")
|
||||
|
||||
@property
|
||||
def operator(self) -> str:
|
||||
"""Get operator"""
|
||||
return self._operator
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Compare({self._left} {self._operator} {self._right})"
|
||||
|
||||
|
||||
class Logic(Expr):
|
||||
"""Logical expression (and, or, not)"""
|
||||
|
||||
AND = "&&"
|
||||
OR = "||"
|
||||
NOT = "!"
|
||||
|
||||
def __init__(self, operator: str, *expressions: Expr):
|
||||
"""
|
||||
Initialize logical expression
|
||||
|
||||
Args:
|
||||
operator: Logical operator
|
||||
expressions: Expressions to operate on
|
||||
"""
|
||||
self._operator = operator
|
||||
self._expressions = expressions
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate logical expression"""
|
||||
if self._operator == Logic.NOT:
|
||||
# Unary NOT
|
||||
if not self._expressions:
|
||||
return True
|
||||
return not self._expressions[0].eval(scope)
|
||||
else:
|
||||
# Binary AND/OR
|
||||
results = [expr.eval(scope) for expr in self._expressions]
|
||||
|
||||
if self._operator == Logic.AND:
|
||||
return all(results)
|
||||
elif self._operator == Logic.OR:
|
||||
return any(results)
|
||||
else:
|
||||
raise ValueError(f"Unknown operator: {self._operator}")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
expr_str = f" {self._operator} ".join(str(expr) for expr in self._expressions)
|
||||
if self._operator == Logic.NOT:
|
||||
return f"NOT({expr_str})"
|
||||
return f"({expr_str})"
|
||||
|
||||
|
||||
class Ternary(Expr):
|
||||
"""Ternary conditional expression (condition ? true_val : false_val)"""
|
||||
|
||||
def __init__(self, condition: Expr, true_expr: Expr, false_expr: Expr):
|
||||
"""
|
||||
Initialize ternary expression
|
||||
|
||||
Args:
|
||||
condition: Condition expression
|
||||
true_expr: Expression when condition is true
|
||||
false_expr: Expression when condition is false
|
||||
"""
|
||||
self._condition = condition
|
||||
self._true_expr = true_expr
|
||||
self._false_expr = false_expr
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate ternary expression"""
|
||||
cond_val = self._condition.eval(scope)
|
||||
|
||||
# Convert to boolean (handle None, 0, empty strings, etc.)
|
||||
if cond_val:
|
||||
return self._true_expr.eval(scope)
|
||||
else:
|
||||
return self._false_expr.eval(scope)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Ternary({self._condition} ? {self._true_expr} : {self._false_expr})"
|
||||
151
pyenjoy/template/expr/ast/Const.py
Normal file
151
pyenjoy/template/expr/ast/Const.py
Normal file
@@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal Const - Constant Expression
|
||||
"""
|
||||
|
||||
from .Expr import Expr
|
||||
|
||||
class Const(Expr):
|
||||
"""Constant value expression"""
|
||||
|
||||
def __init__(self, value):
|
||||
"""
|
||||
Initialize constant
|
||||
|
||||
Args:
|
||||
value: Constant value
|
||||
"""
|
||||
self._value = value
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate and return constant value"""
|
||||
return self._value
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Const({self._value})"
|
||||
|
||||
|
||||
class NullExpr(Expr):
|
||||
"""Null expression"""
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate and return None"""
|
||||
return None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "NullExpr()"
|
||||
|
||||
|
||||
class Id(Expr):
|
||||
"""Identifier expression (variable reference)"""
|
||||
|
||||
def __init__(self, name: str):
|
||||
"""
|
||||
Initialize identifier
|
||||
|
||||
Args:
|
||||
name: Variable name
|
||||
"""
|
||||
self._name = name
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate and return variable value"""
|
||||
return scope.get(self._name)
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Get identifier name"""
|
||||
return self._name
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Id({self._name})"
|
||||
|
||||
|
||||
class Map(Expr):
|
||||
"""Map/dictionary expression"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize empty map"""
|
||||
self._entries = []
|
||||
|
||||
def add_entry(self, key_expr: Expr, value_expr: Expr):
|
||||
"""
|
||||
Add map entry
|
||||
|
||||
Args:
|
||||
key_expr: Key expression
|
||||
value_expr: Value expression
|
||||
"""
|
||||
self._entries.append((key_expr, value_expr))
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate and return map"""
|
||||
result = {}
|
||||
for key_expr, value_expr in self._entries:
|
||||
key = key_expr.eval(scope)
|
||||
value = value_expr.eval(scope)
|
||||
if key is not None:
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Map({len(self._entries)} entries)"
|
||||
|
||||
|
||||
class Array(Expr):
|
||||
"""Array/list expression"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize empty array"""
|
||||
self._elements = []
|
||||
|
||||
def add_element(self, element_expr: Expr):
|
||||
"""
|
||||
Add array element
|
||||
|
||||
Args:
|
||||
element_expr: Element expression
|
||||
"""
|
||||
self._elements.append(element_expr)
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate and return array"""
|
||||
return [expr.eval(scope) for expr in self._elements]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Array({len(self._elements)} elements)"
|
||||
|
||||
|
||||
class RangeArray(Expr):
|
||||
"""Range array expression (e.g., 1..10)"""
|
||||
|
||||
def __init__(self, start_expr: Expr, end_expr: Expr, inclusive: bool = True):
|
||||
"""
|
||||
Initialize range array
|
||||
|
||||
Args:
|
||||
start_expr: Start expression
|
||||
end_expr: End expression
|
||||
inclusive: Whether end is inclusive
|
||||
"""
|
||||
self._start_expr = start_expr
|
||||
self._end_expr = end_expr
|
||||
self._inclusive = inclusive
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate and return range array"""
|
||||
start = self._start_expr.eval(scope)
|
||||
end = self._end_expr.eval(scope)
|
||||
|
||||
if isinstance(start, int) and isinstance(end, int):
|
||||
if self._inclusive:
|
||||
return list(range(start, end + 1))
|
||||
else:
|
||||
return list(range(start, end))
|
||||
|
||||
# For non-integer ranges, return empty list
|
||||
return []
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"RangeArray({self._start_expr}, {self._end_expr}, inclusive={self._inclusive})"
|
||||
100
pyenjoy/template/expr/ast/Expr.py
Normal file
100
pyenjoy/template/expr/ast/Expr.py
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal Expr - Expression Evaluation Base Class
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
from ...stat.Scope import Scope
|
||||
from ...Env import Env
|
||||
|
||||
class Expr:
|
||||
"""Base class for expression AST nodes"""
|
||||
|
||||
def eval(self, scope: Scope) -> Any:
|
||||
"""
|
||||
Evaluate expression
|
||||
|
||||
Args:
|
||||
scope: Execution scope
|
||||
|
||||
Returns:
|
||||
Expression result
|
||||
"""
|
||||
raise NotImplementedError("Expr.eval() must be implemented by subclasses")
|
||||
|
||||
def eval_expr_list(self, scope: Scope) -> list:
|
||||
"""
|
||||
Evaluate as expression list
|
||||
|
||||
Args:
|
||||
scope: Execution scope
|
||||
|
||||
Returns:
|
||||
List of expression results
|
||||
"""
|
||||
return [self.eval(scope)]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Expr({self.__class__.__name__})"
|
||||
|
||||
|
||||
class ExprList(Expr):
|
||||
"""Expression list containing multiple expressions"""
|
||||
|
||||
def __init__(self, expressions: list = None):
|
||||
"""
|
||||
Initialize expression list
|
||||
|
||||
Args:
|
||||
expressions: List of expressions
|
||||
"""
|
||||
self._expressions = expressions or []
|
||||
|
||||
def add_expr(self, expr: Expr):
|
||||
"""
|
||||
Add expression to list
|
||||
|
||||
Args:
|
||||
expr: Expression to add
|
||||
"""
|
||||
if expr:
|
||||
self._expressions.append(expr)
|
||||
|
||||
def eval(self, scope: Scope) -> Any:
|
||||
"""
|
||||
Evaluate all expressions and return last result
|
||||
|
||||
Args:
|
||||
scope: Execution scope
|
||||
|
||||
Returns:
|
||||
Last expression result
|
||||
"""
|
||||
result = None
|
||||
for expr in self._expressions:
|
||||
result = expr.eval(scope)
|
||||
return result
|
||||
|
||||
def eval_expr_list(self, scope: Scope) -> list:
|
||||
"""
|
||||
Evaluate all expressions and return list of results
|
||||
|
||||
Args:
|
||||
scope: Execution scope
|
||||
|
||||
Returns:
|
||||
List of results
|
||||
"""
|
||||
return [expr.eval(scope) for expr in self._expressions]
|
||||
|
||||
def get_expressions(self) -> list:
|
||||
"""Get all expressions"""
|
||||
return self._expressions.copy()
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Get number of expressions"""
|
||||
return len(self._expressions)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"ExprList({len(self._expressions)} expressions)"
|
||||
27
pyenjoy/template/expr/ast/FieldKeyBuilder.py
Normal file
27
pyenjoy/template/expr/ast/FieldKeyBuilder.py
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal FieldKeyBuilder - Field Key Builder
|
||||
"""
|
||||
|
||||
class FieldKeyBuilder:
|
||||
"""Field key builder for field access"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize field key builder"""
|
||||
pass
|
||||
|
||||
def build_field_key(self, field_name: str) -> str:
|
||||
"""
|
||||
Build field key
|
||||
|
||||
Args:
|
||||
field_name: Field name
|
||||
|
||||
Returns:
|
||||
Field key
|
||||
"""
|
||||
return field_name
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "FieldKeyBuilder()"
|
||||
64
pyenjoy/template/expr/ast/FieldKit.py
Normal file
64
pyenjoy/template/expr/ast/FieldKit.py
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal FieldKit - Field Access Utilities
|
||||
"""
|
||||
|
||||
class FieldKit:
|
||||
"""Field access utilities"""
|
||||
|
||||
@staticmethod
|
||||
def get_field(obj, field_name: str):
|
||||
"""
|
||||
Get field value from object
|
||||
|
||||
Args:
|
||||
obj: Object to get field from
|
||||
field_name: Field name
|
||||
|
||||
Returns:
|
||||
Field value or None
|
||||
"""
|
||||
if obj is None:
|
||||
return None
|
||||
|
||||
# Try attribute access
|
||||
if hasattr(obj, field_name):
|
||||
return getattr(obj, field_name)
|
||||
|
||||
# Try dictionary access
|
||||
if isinstance(obj, dict) and field_name in obj:
|
||||
return obj[field_name]
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def set_field(obj, field_name: str, value):
|
||||
"""
|
||||
Set field value on object
|
||||
|
||||
Args:
|
||||
obj: Object to set field on
|
||||
field_name: Field name
|
||||
value: Value to set
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
if obj is None:
|
||||
return False
|
||||
|
||||
# Try attribute access
|
||||
if hasattr(obj, field_name):
|
||||
setattr(obj, field_name, value)
|
||||
return True
|
||||
|
||||
# Try dictionary access
|
||||
if isinstance(obj, dict):
|
||||
obj[field_name] = value
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "FieldKit()"
|
||||
56
pyenjoy/template/expr/ast/MethodKit.py
Normal file
56
pyenjoy/template/expr/ast/MethodKit.py
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal MethodKit - Method Access Utilities
|
||||
"""
|
||||
|
||||
class MethodKit:
|
||||
"""Method access utilities"""
|
||||
|
||||
@staticmethod
|
||||
def get_method(obj, method_name: str, *args):
|
||||
"""
|
||||
Get method from object
|
||||
|
||||
Args:
|
||||
obj: Object to get method from
|
||||
method_name: Method name
|
||||
args: Method arguments
|
||||
|
||||
Returns:
|
||||
Method or None
|
||||
"""
|
||||
if obj is None:
|
||||
return None
|
||||
|
||||
# Try attribute access
|
||||
if hasattr(obj, method_name):
|
||||
method = getattr(obj, method_name)
|
||||
if callable(method):
|
||||
return method
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def invoke_method(obj, method_name: str, *args):
|
||||
"""
|
||||
Invoke method on object
|
||||
|
||||
Args:
|
||||
obj: Object to invoke method on
|
||||
method_name: Method name
|
||||
args: Method arguments
|
||||
|
||||
Returns:
|
||||
Method result or None
|
||||
"""
|
||||
method = MethodKit.get_method(obj, method_name)
|
||||
if method:
|
||||
try:
|
||||
return method(*args)
|
||||
except:
|
||||
return None
|
||||
return None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "MethodKit()"
|
||||
121
pyenjoy/template/expr/ast/SharedMethodKit.py
Normal file
121
pyenjoy/template/expr/ast/SharedMethodKit.py
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal SharedMethodKit - Shared Method Kit
|
||||
"""
|
||||
|
||||
from typing import Dict, List, Any, Optional
|
||||
|
||||
class SharedMethodKit:
|
||||
"""Shared method kit for template functions"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize shared method kit"""
|
||||
self._shared_methods: Dict[str, List[Any]] = {}
|
||||
|
||||
def add_shared_method(self, obj: Any):
|
||||
"""
|
||||
Add shared methods from object
|
||||
|
||||
Args:
|
||||
obj: Object with methods to add
|
||||
"""
|
||||
if obj is None:
|
||||
return
|
||||
|
||||
# Get all methods from object
|
||||
import inspect
|
||||
for name, method in inspect.getmembers(obj, predicate=inspect.ismethod):
|
||||
if not name.startswith('_'):
|
||||
if name not in self._shared_methods:
|
||||
self._shared_methods[name] = []
|
||||
self._shared_methods[name].append(method)
|
||||
|
||||
def add_shared_method_from_class(self, clazz):
|
||||
"""
|
||||
Add shared methods from class
|
||||
|
||||
Args:
|
||||
clazz: Class with methods to add
|
||||
"""
|
||||
if clazz is None:
|
||||
return
|
||||
|
||||
# Get all methods from class
|
||||
import inspect
|
||||
for name, method in inspect.getmembers(clazz, predicate=inspect.isfunction):
|
||||
if not name.startswith('_'):
|
||||
if name not in self._shared_methods:
|
||||
self._shared_methods[name] = []
|
||||
self._shared_methods[name].append(method)
|
||||
|
||||
def add_shared_static_method(self, clazz):
|
||||
"""
|
||||
Add shared static methods from class
|
||||
|
||||
Args:
|
||||
clazz: Class with static methods to add
|
||||
"""
|
||||
if clazz is None:
|
||||
return
|
||||
|
||||
# Get all static methods from class
|
||||
import inspect
|
||||
for name, method in inspect.getmembers(clazz, predicate=inspect.isfunction):
|
||||
if not name.startswith('_'):
|
||||
if name not in self._shared_methods:
|
||||
self._shared_methods[name] = []
|
||||
self._shared_methods[name].append(method)
|
||||
|
||||
def remove_shared_method(self, method_name: str):
|
||||
"""
|
||||
Remove shared method by name
|
||||
|
||||
Args:
|
||||
method_name: Method name to remove
|
||||
"""
|
||||
if method_name in self._shared_methods:
|
||||
del self._shared_methods[method_name]
|
||||
|
||||
def get_shared_method(self, method_name: str) -> Optional[Any]:
|
||||
"""
|
||||
Get shared method by name
|
||||
|
||||
Args:
|
||||
method_name: Method name to get
|
||||
|
||||
Returns:
|
||||
Shared method or None
|
||||
"""
|
||||
if method_name in self._shared_methods:
|
||||
methods = self._shared_methods[method_name]
|
||||
if methods:
|
||||
return methods[0]
|
||||
return None
|
||||
|
||||
def get_shared_methods(self, method_name: str) -> List[Any]:
|
||||
"""
|
||||
Get all shared methods with given name
|
||||
|
||||
Args:
|
||||
method_name: Method name
|
||||
|
||||
Returns:
|
||||
List of shared methods
|
||||
"""
|
||||
return self._shared_methods.get(method_name, [])
|
||||
|
||||
def has_shared_method(self, method_name: str) -> bool:
|
||||
"""
|
||||
Check if shared method exists
|
||||
|
||||
Args:
|
||||
method_name: Method name
|
||||
|
||||
Returns:
|
||||
True if method exists, False otherwise
|
||||
"""
|
||||
return method_name in self._shared_methods and self._shared_methods[method_name]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"SharedMethodKit({len(self._shared_methods)} methods)"
|
||||
20
pyenjoy/template/expr/ast/__init__.py
Normal file
20
pyenjoy/template/expr/ast/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Export expression AST classes
|
||||
from .Expr import Expr, ExprList
|
||||
from .Const import Const, NullExpr, Id, Map, Array, RangeArray
|
||||
from .Compare import Compare, Logic, Ternary
|
||||
from .Arith import Arith, Unary, IncDec
|
||||
from .SharedMethodKit import SharedMethodKit
|
||||
from .FieldKit import FieldKit
|
||||
from .FieldKeyBuilder import FieldKeyBuilder
|
||||
from .MethodKit import MethodKit
|
||||
|
||||
__all__ = [
|
||||
'Expr', 'ExprList',
|
||||
'Const', 'NullExpr', 'Id', 'Map', 'Array', 'RangeArray',
|
||||
'Compare', 'Logic', 'Ternary',
|
||||
'Arith', 'Unary', 'IncDec',
|
||||
'SharedMethodKit',
|
||||
'FieldKit',
|
||||
'FieldKeyBuilder',
|
||||
'MethodKit'
|
||||
]
|
||||
Reference in New Issue
Block a user