Bugs Fixed
Bugs Fixed
Bugs Fixed
New Features
Bugs Fixed
Features Changed
Bugs Fixed
Features Changed
Bugs Fixed
Bugs Fixed
When using FunctionWrapper around a method of an existing instance of a class, rather than on the type, then a memory leak could occur in two different scenarios.
The first issue was that wrapping a method on an instance of a class was causing an unwanted reference to the class meaning that if the class type was transient, such as it is being created inside of a function call, the type object would leak.
The second issue was that wrapping a method on an instance of a class and then calling the method was causing an unwanted reference to the instance meaning that if the instance was transient, it would leak.
This was only occuring when the C extension component for the wrapt module was being used.
New Features
When specifying an adapter for a decorator, it is now possible to pass in, in addition to passing in a callable, a tuple of the form which is returned by inspect.getargspec(), or a string of the form which is returned by inspect.formatargspec(). In these two cases the decorator will automatically compile a stub function to use as the adapter. This eliminates the need for a caller to generate the stub function if generating the signature on the fly.
def argspec_factory(wrapped):
argspec = inspect.getargspec(wrapped)
args = argspec.args[1:]
defaults = argspec.defaults and argspec.defaults[-len(argspec.args):]
return inspect.ArgSpec(args, argspec.varargs,
argspec.keywords, defaults)
def session(wrapped):
@wrapt.decorator(adapter=argspec_factory(wrapped))
def _session(wrapped, instance, args, kwargs):
with transaction() as session:
return wrapped(session, *args, **kwargs)
return _session(wrapped)
This mechanism and the original mechanism to pass a function, meant that the adapter function had to be created in advance. If the adapter needed to be generated on demand for the specific function to be wrapped, then it would have been necessary to use a closure around the definition of the decorator as above, such that the generator could be passed in.
As a convenience, instead of using such a closure, it is also now possible to write:
def argspec_factory(wrapped):
argspec = inspect.getargspec(wrapped)
args = argspec.args[1:]
defaults = argspec.defaults and argspec.defaults[-len(argspec.args):]
return inspect.ArgSpec(args, argspec.varargs,
argspec.keywords, defaults)
@wrapt.decorator(adapter=wrapt.adapter_factory(argspec_factory))
def _session(wrapped, instance, args, kwargs):
with transaction() as session:
return wrapped(session, *args, **kwargs)
The result of wrapt.adapter_factory() will be recognised as indicating that the creation of the adapter is to be deferred until the decorator is being applied to a function. The factory function for generating the adapter function or specification on demand will be passed the function being wrapped by the decorator.
If wishing to create a library of routines for generating adapter functions or specifications dynamically, then you can do so by creating classes which derive from wrapt.AdapterFactory as that is the type which is recognised as indicating lazy evaluation of the adapter function. For example, wrapt.adapter_factory() is itself implemented as:
class DelegatedAdapterFactory(wrapt.AdapterFactory):
def __init__(self, factory):
super(DelegatedAdapterFactory, self).__init__()
self.factory = factory
def __call__(self, wrapped):
return self.factory(wrapped)
adapter_factory = DelegatedAdapterFactory
Bugs Fixed
The inspect.signature() function was only added in Python 3.3. Use fallback when doesn’t exist and on Python 3.2 or earlier Python 3 versions.
Note that testing is only performed for Python 3.3+, so it isn’t actually known if the wrapt package works on Python 3.2.
Features Changed
Bugs Fixed
Features Changed
Previously using @wrapt.decorator on a class type didn’t really yield anything which was practically useful. This is now changed and when applied to a class an instance of the class will be automatically created to be used as the decorator wrapper function. The requirement for this is that the __call__() method be specified in the style as would be done for the decorator wrapper function.
@wrapt.decorator
class mydecoratorclass(object):
def __init__(self, arg=None):
self.arg = arg
def __call__(self, wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
@mydecoratorclass
def function():
pass
If the resulting decorator class is to be used with no arguments, the __init__() method of the class must have all default arguments. These arguments can be optionally supplied though, by using keyword arguments to the resulting decorator when applied to the function to be decorated.
@mydecoratorclass(arg=1)
def function():
pass
New Features
Bugs Fixed
Bugs Fixed
The ObjectProxy class would return that the __call__() method existed even though the wrapped object didn’t have one. Similarly, callable() would always return True even if the wrapped object was not callable.
This resulted due to the existance of the __call__() method on the wrapper, required to support the possibility that the wrapped object may be called via the proxy object even if it may not turn out that the wrapped object was callable.
Because checking for the existance of a __call__() method or using callable() can sometimes be used to indirectly infer the type of an object, this could cause issues. To ensure that this now doesn’t occur, the ability to call a wrapped object via the proxy object has been removed from ObjectProxy. Instead, a new class CallableObjectProxy is now provided, with it being necessary to make a conscious choice as to which should be used based on whether the object to be wrapped is in fact callable.
Note that neither before this change, or with the introduction of the class CallableObjectProxy, does the object proxy perform binding. If binding behaviour is required it still needs to be implemented explicitly to match the specific requirements of the use case. Alternatively, the FunctionWrapper class should be used which does implement binding, but also enforces a wrapper mechanism for manipulating what happens at the time of the call.
Bugs Fixed
New Features
Bugs Fixed
Bugs Fixed
Bugs Fixed
New Features
Bugs Fixed
Bugs Fixed
New Features
Bugs Fixed
New Features
Features Changed
Bugs Fixed
New Features
Improvements
Bugs Fixed
Improvements
Bugs Fixed
New Features
Bugs Fixed
Initial release.