def test_create_bound_method():
class X(object):
pass
def f(self):
return self
x = X()
b = six.create_bound_method(f, x)
assert isinstance(b, types.MethodType)
assert b() is x
python类create_bound_method()的实例源码
def __get__(self, instance, owner):
if inspect.ismethoddescriptor(self.value) or inspect.isdatadescriptor(self.value):
return self.value.__get__(instance, owner)
if inspect.isfunction(self.value):
if instance is None:
return self
else:
return six.create_bound_method(self.value, instance)
else:
return self.value
#------------------------------------------------[ CheckedInstance ]
def __get__(self, instance, owner):
assert issubclass(owner, Stub), 'stubbed methods belong in Stub classes...'
assert instance, 'implemented for instance methods only'
real_method = getattr(owner.stubbed, self.stub.__name__)
assert isinstance(real_method.im_func, types.FunctionType), 'stubbed methods are for methods...'
real_args = inspect.getargspec(real_method.im_func)
stub_args = inspect.getargspec(self.stub)
assert real_args == stub_args, 'argument specification mismatch'
return six.create_bound_method(self.stub, instance)
def __get__(self, instance, owner):
self.bind_class(owner)
if instance is None:
return self
else:
return six.create_bound_method(self.function, instance)
def test_create_bound_method():
class X(object):
pass
def f(self):
return self
x = X()
b = six.create_bound_method(f, x)
assert isinstance(b, types.MethodType)
assert b() is x
def test_create_bound_method():
class X(object):
pass
def f(self):
return self
x = X()
b = six.create_bound_method(f, x)
assert isinstance(b, types.MethodType)
assert b() is x
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