我们从Python开源项目中,提取了以下18个代码示例,用于说明如何使用six.get_method_function()。
def test_monitor(): """A CallMonitor records each call to a method, and its arguments.""" class SomethingElse(object): def foo(self, n, y=None): self.n = n return y s = SomethingElse() original_method = six.get_method_function(s.foo) with CallMonitor(s.foo) as monitor: assert s.foo(1, y='a') == 'a' assert s.foo(2) == None assert six.get_method_function(s.foo) is original_method assert s.n == 2 assert monitor.times_called == 2 assert monitor.calls[0].args == (1,) assert monitor.calls[0].kwargs == {'y':'a'} assert monitor.calls[0].return_value == 'a' assert monitor.calls[1].args == (2,) assert monitor.calls[1].kwargs == {} assert monitor.calls[1].return_value == None
def _get_abc_interface_props_and_funcs(cls): properties = set() function_sigs = {} if not hasattr(cls, '__abstractmethods__'): return properties, function_sigs for name in cls.__abstractmethods__: if _builtin_attrs(name): pass # shortcut value = getattr(cls, name) if isinstance(value, (staticmethod, classmethod, types.MethodType)): func = six.get_method_function(value) function_sigs[name] = _get_function_signature(func) elif isinstance(value, types.FunctionType): function_sigs[name] = _get_function_signature(value) elif isinstance(value, property): properties.add(name) return properties, function_sigs
def call_unlogged(method, *args, **kwargs): """Calls the original method without logging when ``logged`` is applied. In case you pass in an ordinary method that was not decorated, it will work as usual. Args: method: The method object from the object. *args: Args to pass to the method. **kwargs: Keyword arguments to pass to the method. Returns: Whatever that method returns. """ try: f = method.original_function except AttributeError: f = get_method_function(method) return f(get_method_self(method), *args, **kwargs)
def __getattr__(self, attr): """Route all other attribute requests into the parent object's browser. Black magic included Here is the explanation: If you call ``.elements`` on this object directly, it will correctly inject the parent locator. But if you call eg. ``element``, what will happen is that it will invoke the original method from underlying browser and that method's ``self`` is the underlying browser and not this wrapper. Therefore ``element`` would call the original ``elements`` without injecting the parent. What this getter does is that if you pull out a method, it detects that, unbinds the pure function and rebinds it to this wrapper. The method that came from the browser object is now executed not against the browser, but against this wrapper, enabling us to intercept every single ``elements`` call. """ value = getattr(self._browser, attr) if inspect.ismethod(value): function = six.get_method_function(value) # Bind the function like it was defined on this class value = function.__get__(self, BrowserParentWrapper) return value
def test_get_method_function(): class X(object): def m(self): pass x = X() assert six.get_method_function(x.m) is X.__dict__["m"] py.test.raises(AttributeError, six.get_method_function, hasattr)
def get_op_handler(operation): """ Import and load the operation handler """ # Patch the unversioned sdk path to include the appropriate API version for the # resource type in question. from azure.cli.core._profile import CLOUD import types for rt in ResourceType: if operation.startswith(rt.import_prefix + ".operations."): subs = operation[len(rt.import_prefix + ".operations."):] operation_group = subs[:subs.index('_operations')] operation = operation.replace( rt.import_prefix, get_versioned_sdk_path(CLOUD.profile, rt, operation_group=operation_group)) elif operation.startswith(rt.import_prefix): operation = operation.replace(rt.import_prefix, get_versioned_sdk_path(CLOUD.profile, rt)) try: mod_to_import, attr_path = operation.split('#') op = import_module(mod_to_import) for part in attr_path.split('.'): op = getattr(op, part) if isinstance(op, types.FunctionType): return op return six.get_method_function(op) except (ValueError, AttributeError): raise ValueError("The operation '{}' is invalid.".format(operation))
def replaced(method, replacement, on=None): """A context manager which replaces the method passed in as `method` with the callable in `replacement` for the duration of the managed context. .. code-block:: python class SomethingElse(object): def foo(self, n, y='yyy'): assert None, 'This should never be reached in this test' s = SomethingElse() def replacement(n, y=None): return y with replaced(s.foo, replacement): assert s.foo(1, y='a') == 'a' assert s.foo(2) == None assert s.foo(2) == 'yyy' """ StubClass.signatures_match(method, replacement, ignore_self=True) is_unbound_method = six.PY2 and inspect.ismethod(method) and not method.im_self if (not inspect.ismethod(method) or is_unbound_method) and not on: raise ValueError('You have to supply a on= when stubbing an unbound method') target = on or six.get_method_self(method) if inspect.isfunction(method) or inspect.isbuiltin(method): method_name = method.__name__ else: method_name = six.get_method_function(method).__name__ saved_method = getattr(target, method_name) try: setattr(target, method_name, replacement) yield finally: setattr(target, method_name, saved_method)
def _is_empty_function(func, unwrap=False): """ Return True if func is considered empty. All functions with no return statement have an implicit return None - this is explicit in the code object. """ if isinstance(func, (staticmethod, classmethod, types.MethodType)): func = six.get_method_function(func) if isinstance(func, property): func = property.fget if unwrap: func = _unwrap_function(func) try: code_obj = six.get_function_code(func) except AttributeError: # This callable is something else - assume it is OK. return True # quick check if code_obj.co_code == b'd\x00\x00S' and code_obj.co_consts[0] is None: return True if code_obj.co_code == b'd\x01\x00S' and code_obj.co_consts[1] is None: return True # convert bytes to instructions instructions = _get_instructions(code_obj) if len(instructions) < 2: return True # this never happens as there is always the implicit return None which is 2 instructions assert instructions[-1].opname == 'RETURN_VALUE' # returns TOS (top of stack) instruction = instructions[-2] if not (instruction.opname == 'LOAD_CONST' and code_obj.co_consts[instruction.arg] is None): # TOS is None return False # return is not None instructions = instructions[:-2] if len(instructions) == 0: return True # look for raise NotImplementedError if instructions[-1].opname == 'RAISE_VARARGS': # the thing we are raising should be the result of __call__ (instantiating exception object) if instructions[-2].opname == 'CALL_FUNCTION': for instr in instructions[:-2]: if instr.opname == 'LOAD_GLOBAL' and code_obj.co_names[instr.arg] == 'NotImplementedError': return True return False
def _find_method(obj, func): if obj: try: func_self = six.get_method_self(func) except AttributeError: # func has no __self__ pass else: if func_self is obj: return six.get_method_function(func).__name__ raise ValueError("Function %s is not a method of: %s" % (func, obj))
def _get_op_handler(operation): """ Import and load the operation handler """ try: mod_to_import, attr_path = operation.split('#') op = import_module(mod_to_import) for part in attr_path.split('.'): op = getattr(op, part) if isinstance(op, types.FunctionType): return op return six.get_method_function(op) except (ValueError, AttributeError): raise ValueError("The operation '{}' is invalid.".format(operation))
def _getobj(self): # Regular object-making first obj = super(SpecInstance, self)._getobj() # Then decorate it with our parent's extra attributes, allowing nested # test classes to appear as an aggregate of parents' "scopes". # NOTE: need parent.parent due to instance->class hierarchy # NOTE: of course, skipping if we've gone out the top into a module etc if ( not hasattr(self, 'parent') or not hasattr(self.parent, 'parent') or not isinstance(self.parent.parent, SpecInstance) ): return obj parent_obj = self.parent.parent.obj # Obtain parent attributes, etc not found on our obj (serves as both a # useful identifier of "stuff added to an outer class" and a way of # ensuring that we can override such attrs), and set them on obj delta = set(dir(parent_obj)).difference(set(dir(obj))) for name in delta: value = getattr(parent_obj, name) # Classes get skipped; they'd always just be other 'inner' classes # that we don't want to copy elsewhere. if isinstance(value, six.class_types): continue # Functions (methods) may get skipped, or not, depending: if isinstance(value, types.MethodType): # If they look like tests, they get skipped; don't want to copy # tests around! if istestfunction(name): continue # Non-test == they're probably lifecycle methods # (setup/teardown) or helpers (_do_thing). Rebind them to the # target instance, otherwise the 'self' in the setup/helper is # not the same 'self' as that in the actual test method it runs # around or within! # TODO: arguably, all setup or helper methods should become # autouse class fixtures (see e.g. pytest docs under 'xunit # setup on steroids') func = six.get_method_function(value) setattr(obj, name, six.create_bound_method(func, obj)) # Anything else should be some data-type attribute, which is copied # verbatim / by-value. else: setattr(obj, name, value) return obj
def test_replace(): """Replaced methods replace the original one, but are restored after the with.""" class SomethingElse(object): def foo(self, n, y=None): assert None, 'This should never be reached in this test' # Case: bound method s = SomethingElse() def replacement(n, y=None): return y original_method = six.get_method_function(s.foo) with replaced(s.foo, replacement): assert s.foo(1, y='a') == 'a' assert s.foo(2) == None assert six.get_method_function(s.foo) is original_method # Case: unbound method """Python 3 does not support the concept of unbound methods, they are just plain functions without an im_class pointing back to their class. See https://docs.python.org/3/whatsnew/3.0.html#operators-and-special-methods, and https://mail.python.org/pipermail/python-dev/2005-January/050625.html for the rationale. To be able to support them under Python3, on= is mandatory. """ s = SomethingElse() def replacement(self, n, y=None): return y original_method = six.get_unbound_function(SomethingElse.foo) with replaced(SomethingElse.foo, replacement, on=SomethingElse): assert s.foo(1, y='a') == 'a' assert s.foo(2) == None restored_method = six.get_unbound_function(SomethingElse.foo) assert restored_method is original_method # Case: unbound method (no on= given) s = SomethingElse() def replacement(self, n, y=None): return y with pytest.raises(ValueError, message='You have to supply a on= when stubbing an unbound method'): with replaced(SomethingElse.foo, replacement): pass
def object_build(self, node, obj): """recursive method which create a partial ast from real objects (only function, class, and method are handled) """ if obj in self._done: return self._done[obj] self._done[obj] = node for name in dir(obj): try: member = getattr(obj, name) except AttributeError: # damned ExtensionClass.Base, I know you're there ! attach_dummy_node(node, name) continue if ismethod(member): member = six.get_method_function(member) if isfunction(member): # verify this is not an imported function filename = getattr(six.get_function_code(member), 'co_filename', None) if filename is None: assert isinstance(member, object) object_build_methoddescriptor(node, member, name) elif filename != getattr(self._module, '__file__', None): attach_dummy_node(node, name, member) else: object_build_function(node, member, name) elif isbuiltin(member): if (not _io_discrepancy(member) and self.imported_member(node, member, name)): continue object_build_methoddescriptor(node, member, name) elif isclass(member): if self.imported_member(node, member, name): continue if member in self._done: class_node = self._done[member] if not class_node in node.locals.get(name, ()): node.add_local_node(class_node, name) else: class_node = object_build_class(node, member, name) # recursion self.object_build(class_node, member) if name == '__class__' and class_node.parent is None: class_node.parent = self._done[self._module] elif ismethoddescriptor(member): assert isinstance(member, object) object_build_methoddescriptor(node, member, name) elif isdatadescriptor(member): assert isinstance(member, object) object_build_datadescriptor(node, member, name) elif type(member) in _CONSTANTS: attach_const_node(node, name, member) else: # create an empty node so that the name is actually defined attach_dummy_node(node, name, member)