@@ -1997,129 +1997,6 @@ def _get_attribute_safely(self, value: t.Any, attr_name: str) -> t.Any:
19971997 f"'{ attr_name } '"
19981998 ) from e
19991999
2000- def _create_bound_method (
2001- self , func : t .Any , instance : t .Any , attr_name : str
2002- ) -> t .Callable [..., t .Any ]:
2003- """Create a bound method for a function.
2004-
2005- Args:
2006- func: Function to bind
2007- instance: Instance to bind to
2008- attr_name: Name of the attribute
2009-
2010- Returns:
2011- The bound method
2012- """
2013-
2014- def bound_method (* args , ** kwargs ):
2015- prev_env = self .local_env
2016-
2017- try :
2018- # Check if this is a static method - either by flag or by type
2019- has_static_flag = getattr (
2020- type (instance ), f"__static_{ attr_name } " , False
2021- )
2022- is_static_method = isinstance (func , staticmethod )
2023-
2024- # Check if the method is a function
2025- is_function = isinstance (func , types .FunctionType )
2026-
2027- if has_static_flag or is_static_method :
2028- # For static methods, don't bind to instance
2029- self .local_env = prev_env
2030- if is_static_method :
2031- method = func .__get__ (None , type (instance ))
2032- return method (* args , ** kwargs )
2033- return func (* args , ** kwargs )
2034- elif isinstance (func , classmethod ):
2035- self .local_env = prev_env
2036- method = func .__get__ (type (instance ), type (instance ))
2037- return method (* args , ** kwargs )
2038- elif is_function :
2039- # If it's a function, call it directly
2040- self .local_env = prev_env
2041- return func (* args , ** kwargs )
2042- else :
2043- self .local_env = prev_env
2044- method = func .__get__ (instance , type (instance ))
2045- return method (* args , ** kwargs )
2046- finally :
2047- self .local_env = prev_env
2048-
2049- return bound_method
2050-
2051- def _create_decorated_method (
2052- self , func : t .Any , instance : t .Any , decorator_type : type
2053- ) -> t .Callable [..., t .Any ]:
2054- """Create a method for a decorated function.
2055-
2056- Args:
2057- func: Function to decorate
2058- instance: Instance to bind to
2059- decorator_type: Type of the decorator
2060-
2061- Returns:
2062- The decorated method
2063- """
2064- if isinstance (decorator_type , (classmethod , property )):
2065-
2066- def decorated_method (* args , ** kwargs ):
2067- prev_env = self .local_env
2068- self .local_env = {** prev_env , "self" : instance }
2069- try :
2070- return func (* args , ** kwargs )
2071- finally :
2072- self .local_env = prev_env
2073-
2074- return decorated_method
2075- else :
2076- # For staticmethod, just return the function as is
2077- return func
2078-
2079- def _should_bind_function (
2080- self , func : t .Any , instance : t .Any , attr_name : str
2081- ) -> bool :
2082- """Check if a function should be bound to an instance.
2083-
2084- Args:
2085- func: Function to check
2086- instance: Instance to potentially bind to
2087- attr_name: Name of the attribute
2088-
2089- Returns:
2090- Whether the function should be bound
2091- """
2092- # Check if this is a bound function
2093- if registry .is_bound (func ):
2094- return False
2095-
2096- # Check if this is a static method
2097- if isinstance (instance , type ):
2098- # If accessed on class, check for static marker
2099- if getattr (instance , f"__static_{ attr_name } " , False ):
2100- return False
2101- else :
2102- # If accessed on instance, check the class
2103- if getattr (type (instance ), f"__static_{ attr_name } " , False ):
2104- return False
2105-
2106- # If not a static method, check if it's a module function
2107- if isinstance (instance , types .ModuleType ):
2108- # For module functions, don't bind self
2109- return False
2110-
2111- # Check if the function is in the global environment
2112- for global_value in self .global_env .values ():
2113- if isinstance (global_value , dict ):
2114- # Check nested dictionaries
2115- for nested_value in global_value .values ():
2116- if func is nested_value :
2117- return False
2118- elif func is global_value :
2119- return False
2120-
2121- return True
2122-
21232000 def visit_Attribute (self , node : ast .Attribute ) -> t .Any :
21242001 """Visit an attribute access node.
21252002
@@ -2133,28 +2010,18 @@ def visit_Attribute(self, node: ast.Attribute) -> t.Any:
21332010 AttributeError: If the attribute doesn't exist
21342011 SecurityError: If attribute access is not allowed
21352012 """
2136- # Get the base value
2137- value = self .visit (node .value )
2138-
21392013 # Check if this is a forbidden attribute
21402014 if node .attr in SecurityChecker .FORBIDDEN_ATTRS :
21412015 raise SecurityError (
21422016 f"Access to '{ node .attr } ' attribute is not allowed"
21432017 )
21442018
2019+ # Get the base value
2020+ value = self .visit (node .value )
2021+
21452022 # Get the attribute safely
21462023 attr = self ._get_attribute_safely (value , node .attr )
21472024
2148- # Handle function binding
2149- if isinstance (attr , types .FunctionType ):
2150- if self ._should_bind_function (attr , value , node .attr ):
2151- return self ._create_bound_method (attr , value , node .attr )
2152- return attr
2153- elif isinstance (attr , (classmethod , staticmethod , property )):
2154- # For decorated methods, get the underlying function
2155- func = attr .__get__ (value , type (value ))
2156- return self ._create_decorated_method (func , value , type (attr ))
2157-
21582025 return attr
21592026
21602027 def visit_Subscript (self , node : ast .Subscript ) -> t .Any :
@@ -2319,36 +2186,6 @@ def bound_super_method(name, current_class=next_class):
23192186
23202187 return custom_super
23212188
2322- def _process_class_function (
2323- self , stmt : ast .FunctionDef , namespace : dict [str , t .Any ]
2324- ) -> None :
2325- """Process a function definition within a class.
2326-
2327- Args:
2328- stmt: FunctionDef AST node
2329- namespace: Class namespace dictionary
2330- """
2331- # Handle function definition
2332- self .visit (stmt )
2333-
2334- # Get the function from namespace
2335- func = namespace [stmt .name ]
2336-
2337- # Handle decorators in reverse order
2338- for decorator in reversed (stmt .decorator_list ):
2339- # Evaluate the decorator
2340- decorator_func = self .visit (decorator )
2341- # Apply the decorator
2342- func = decorator_func (func )
2343-
2344- # For static methods, we need to store both the decorator and the
2345- # function
2346- if decorator_func is staticmethod :
2347- namespace [f"__static_{ stmt .name } " ] = True
2348-
2349- # Update the function in namespace
2350- namespace [stmt .name ] = func
2351-
23522189 def _create_class_namespace (self , node : ast .ClassDef ) -> dict [str , t .Any ]:
23532190 """Create and populate the class namespace.
23542191
@@ -2367,10 +2204,7 @@ def _create_class_namespace(self, node: ast.ClassDef) -> dict[str, t.Any]:
23672204 try :
23682205 # Execute the class body
23692206 for stmt in node .body :
2370- if isinstance (stmt , ast .FunctionDef ):
2371- self ._process_class_function (stmt , namespace )
2372- else :
2373- self .visit (stmt )
2207+ self .visit (stmt )
23742208 finally :
23752209 # Restore the environment
23762210 self .local_env = prev_env
0 commit comments