def _rename_compilable_function(self, node): assert anno.hasanno(node.func, 'live_val') assert anno.hasanno(node.func, 'fqn') target_entity = anno.getanno(node.func, 'live_val') target_fqn = anno.getanno(node.func, 'fqn') if not self._should_compile(node, target_fqn): return node if anno.hasanno(node, 'is_constructor'): new_name = self.context.namer.compiled_class_name( target_fqn, live_entity=target_entity) do_rename = True else: if anno.hasanno(node.func, 'parent_type'): owner_type = anno.getanno(node.func, 'parent_type') else: # Fallback - not reliable. owner_type = inspect_utils.getmethodclass(target_entity) new_name, do_rename = self.context.namer.compiled_function_name( target_fqn, live_entity=target_entity, owner_type=owner_type) if do_rename: if target_entity is not None: if tf_inspect.ismethod(target_entity): # The renaming process will transform it into a regular function. # TODO(mdan): Is this complete? How does it work with nested members? node.args = [node.func.value] + node.args node.func = templates.replace('func_name', func_name=new_name)[0] return node
def _rename_compilable_function(self, node): assert anno.hasanno(node.func, 'live_val') assert anno.hasanno(node.func, 'fqn') target_entity = anno.getanno(node.func, 'live_val') target_fqn = anno.getanno(node.func, 'fqn') if not self._should_compile(node, target_fqn): return node if anno.hasanno(node, 'is_constructor'): new_name = self.ctx.namer.compiled_class_name( target_fqn, live_entity=target_entity) do_rename = True else: if anno.hasanno(node.func, 'parent_type'): owner_type = anno.getanno(node.func, 'parent_type') else: # Fallback - not reliable. owner_type = inspect_utils.getmethodclass(target_entity) new_name, do_rename = self.ctx.namer.compiled_function_name( target_fqn, live_entity=target_entity, owner_type=owner_type) if do_rename: if target_entity is not None: if tf_inspect.ismethod(target_entity): # The renaming process will transform it into a regular function. # TODO(mdan): Is this complete? How does it work with nested members? node.args = [node.func.value] + node.args node.func = templates.replace('func_name', func_name=new_name)[0] return node
def test_getmethodclass_callables(self): class TestCallable(object): def __call__(self): pass c = TestCallable() self.assertEqual(inspect_utils.getmethodclass(c), TestCallable)
def test_getmethodclass_callables(self): class TestCallable(object): def __call__(self): pass c = TestCallable() self.assertEqual(inspect_utils.getmethodclass(c), TestCallable)
def test_getmethodclass_locals(self): def local_function(): pass class LocalClass(object): def member_function(self): pass @decorator def decorated_member(self): pass @function_decorator() def fn_decorated_member(self): pass @wrapping_decorator() def wrap_decorated_member(self): pass self.assertEqual( inspect_utils.getmethodclass(local_function), None) self.assertEqual( inspect_utils.getmethodclass(LocalClass.member_function), LocalClass) self.assertEqual( inspect_utils.getmethodclass(LocalClass.decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(LocalClass.fn_decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(LocalClass.wrap_decorated_member), LocalClass) test_obj = LocalClass() self.assertEqual( inspect_utils.getmethodclass(test_obj.member_function), LocalClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.fn_decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.wrap_decorated_member), LocalClass)
def test_getmethodclass_locals(self): def local_function(): pass class LocalClass(object): def member_function(self): pass @decorator def decorated_member(self): pass @function_decorator() def fn_decorated_member(self): pass @wrapping_decorator() def wrap_decorated_member(self): pass self.assertEqual( inspect_utils.getmethodclass(local_function), None) self.assertEqual( inspect_utils.getmethodclass(LocalClass.member_function), LocalClass) self.assertEqual( inspect_utils.getmethodclass(LocalClass.decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(LocalClass.fn_decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(LocalClass.wrap_decorated_member), LocalClass) test_obj = LocalClass() self.assertEqual( inspect_utils.getmethodclass(test_obj.member_function), LocalClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.fn_decorated_member), LocalClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.wrap_decorated_member), LocalClass)
def converted_call(f, recursive, verbose, arg_types, *args, **kwargs): """Compiles a function call inline.""" # TODO(mdan): This needs cleanup. # In particular, we may want to avoid renaming functions altogether. if conversion.is_whitelisted_for_graph(f): return f(*args, **kwargs) unknown_arg_value = object() # Sentinel for arguments of unknown value if inspect_utils.isbuiltin(f): return builtins.dynamic_builtin(f, *args, **kwargs) if tf_inspect.isfunction(f) or tf_inspect.ismethod(f): # Regular functions target_entity = f arg_map_target = f effective_args = args f_class = inspect_utils.getmethodclass(f) if f_class is not None: partial_types = (f_class,) else: partial_types = () elif tf_inspect.isclass(f): # Constructors target_entity = f arg_map_target = f.__init__ effective_args = args partial_types = () elif hasattr(f, '__call__') and hasattr(f, '__class__'): # Callable objects target_entity = f.__call__ arg_map_target = f.__call__ effective_args = (f,) + args partial_types = (f.__class__,) else: NotImplementedError('unknown callable type "%s"' % type(f)) arg_values = tf_inspect.getcallargs(arg_map_target, *args, **kwargs) for name, arg in arg_values.items(): if arg is unknown_arg_value: continue arg_class = arg.__class__ # If arg_value_hints specifies any name, use that instead. if name not in arg_types: arg_types[name] = (arg_class.__name__, arg_class) # When called from within a decorator, this is the only indication that # the function is a method - it appears that the decorator is applied # before the method is bound. if not partial_types: if 'self' in arg_values: if tf_inspect.isclass(arg_values['self'].__class__): partial_types = (arg_values['self'].__class__,) elif 'cls' in arg_values: if tf_inspect.isclass(arg_values['cls']): partial_types = (arg_values['cls'],) converted_f = to_graph( target_entity, recursive=recursive, verbose=verbose, arg_values=arg_values, arg_types=arg_types, partial_types=partial_types) return converted_f(*effective_args, **kwargs)
def converted_call(f, recursive, verbose, arg_types, *args, **kwargs): """Compiles a function call inline.""" # TODO(mdan): This needs cleanup. # In particular, we may want to avoid renaming functions altogether. if conversion.is_whitelisted_for_graph(f): return f(*args, **kwargs) unknown_arg_value = object() # Sentinel for arguments of unknown value if inspect_utils.isbuiltin(f): return builtins.dynamic_builtin(f, *args, **kwargs) if tf_inspect.isfunction(f) or tf_inspect.ismethod(f): # Regular functions target_entity = f arg_map_target = f effective_args = args f_class = inspect_utils.getmethodclass(f) if f_class is not None: partial_types = (f_class,) else: partial_types = () elif tf_inspect.isclass(f): # Constructors target_entity = f arg_map_target = f.__init__ effective_args = args partial_types = () elif hasattr(f, '__call__') and hasattr(f, '__class__'): # Callable objects target_entity = f.__call__ arg_map_target = f.__call__ effective_args = (f,) + args partial_types = (f.__class__,) else: NotImplementedError('unknown callable type "%s"' % type(f)) arg_values = tf_inspect.getcallargs(arg_map_target, *args, **kwargs) for name, arg in arg_values.items(): if arg is unknown_arg_value: continue arg_class = arg.__class__ # If arg_value_hints specifies any name, use that instead. if name not in arg_types: arg_types[name] = (arg_class.__name__, arg_class) # When called from within a decorator, this is the only indication that # the function is a method - it appears that the decorator is applied # before the method is bound. if not partial_types: if 'self' in arg_values: if tf_inspect.isclass(arg_values['self'].__class__): partial_types = (arg_values['self'].__class__,) elif 'cls' in arg_values: if tf_inspect.isclass(arg_values['cls']): partial_types = (arg_values['cls'],) converted_f = to_graph( target_entity, recursive=recursive, verbose=verbose, arg_values=arg_values, arg_types=arg_types, partial_types=partial_types) return converted_f(*effective_args, **kwargs)
def test_getmethodclass(self): self.assertEqual(inspect_utils.getmethodclass(free_function), None) self.assertEqual(inspect_utils.getmethodclass(free_factory()), None) self.assertEqual( inspect_utils.getmethodclass(TestClass.member_function), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.fn_decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.wrap_decorated_member), TestClass) self.assertEqual(inspect_utils.getmethodclass(TestClass.static_method), TestClass) self.assertEqual(inspect_utils.getmethodclass(TestClass.class_method), TestClass) test_obj = TestClass() self.assertEqual( inspect_utils.getmethodclass(test_obj.member_function), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.fn_decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.wrap_decorated_member), TestClass) self.assertEqual(inspect_utils.getmethodclass(test_obj.static_method), TestClass) self.assertEqual(inspect_utils.getmethodclass(test_obj.class_method), TestClass)
def test_getmethodclass(self): self.assertEqual( inspect_utils.getmethodclass(free_function), None) self.assertEqual( inspect_utils.getmethodclass(free_factory()), None) self.assertEqual( inspect_utils.getmethodclass(TestClass.member_function), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.fn_decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.wrap_decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.static_method), TestClass) self.assertEqual( inspect_utils.getmethodclass(TestClass.class_method), TestClass) test_obj = TestClass() self.assertEqual( inspect_utils.getmethodclass(test_obj.member_function), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.fn_decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.wrap_decorated_member), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.static_method), TestClass) self.assertEqual( inspect_utils.getmethodclass(test_obj.class_method), TestClass)