Release Notes
=============

Version 2.2.1
-------------

**Bugs Fixed**

* Reverted the change in 2.2.0 which had aligned the C implementation of
  ``FunctionWrapper.__get__`` with the pure Python implementation by
  substituting ``Py_None`` for ``NULL`` before invoking the wrapped
  descriptor's ``__get__`` slot. The change was based on a misreading of
  what the pure Python path does once it crosses back into C. The pure
  Python path calls ``self.__wrapped__.__get__(None, owner)`` from Python,
  and for any built-in descriptor that call is dispatched through the
  ``__get__`` slot wrapper inside CPython, which converts ``Py_None`` back
  to ``NULL`` before the wrapped descriptor's ``tp_descr_get`` is invoked.
  The pre 2.2.0 C path called ``tp_descr_get`` directly with ``obj`` as
  received, which is ``NULL`` on class access, so it was already producing
  the same value the Python path produces after the slot wrapper's
  ``Py_None`` to ``NULL`` conversion. Substituting ``Py_None`` for ``NULL``
  before ``tp_descr_get`` was called caused the wrapped descriptor to see
  a value it would never see during ordinary class attribute lookup.
  Native CPython descriptors other than ``func_descr_get`` fast path on
  ``obj == NULL`` and return the descriptor unchanged. With ``Py_None``
  substituted in they fall through to a type check against the owner type
  of the descriptor, and ``NoneType`` does not satisfy that check, so a
  ``TypeError`` is raised. This broke class attribute access for any
  built-in or C extension descriptor (``method_descriptor``,
  ``wrapper_descriptor``, ``getset_descriptor``, ``member_descriptor``)
  wrapped by ``@wrapt.decorator`` or ``@wrapt.function_wrapper``. The
  failure mode is most likely to show up in instrumentation libraries that
  monkey patch built-in methods onto classes and where some inspection or
  binding step then accesses the wrapped attribute through the class. The
  existing test suite did not catch the regression because all wrappers in
  the test suite are applied to pure Python functions, whose
  ``func_descr_get`` slot treats ``NULL`` and ``Py_None`` equivalently. A
  new regression test has been added which wraps a ``method_descriptor``
  and exercises class attribute access, so the missing coverage of
  non-function descriptors is now in place. With thanks to
  `brettlangdon <https://github.com/brettlangdon>`_ for reporting the
  regression and identifying the underlying cause.

Version 2.2.0
-------------

A special thanks to `devdanzin <https://github.com/devdanzin>`_ for providing
an extremely useful analysis of issues in the wrapt C extension. Their
analysis led to the majority of the fixes and updates in this release and
their help is much appreciated.

**New Features**

* Added ``bind_state_to_wrapper`` (also available as ``StateBindingWrapper``),
  a descriptor decorator for automatically binding state to a wrapper. When
  applied on top of a method decorated with ``function_wrapper`` or
  ``decorator``, it intercepts descriptor binding so that when the method is
  accessed through an instance, the owner instance is automatically stored on
  the resulting wrapper as a named attribute. This eliminates the need for
  manual setup in decorator factory functions and makes it straightforward to
  build stateful decorators where the state is accessible through the decorated
  function. See the "Tracking Call State" section of :doc:`examples` for usage.

* Added ``lru_cache``, a drop-in replacement for ``functools.lru_cache`` that
  works correctly with instance methods. Unlike ``functools.lru_cache``, which
  includes ``self`` as a cache key — causing cache pollution across instances,
  preventing garbage collection of instances, and requiring instances to be
  hashable — ``wrapt.lru_cache`` maintains a separate per-instance cache stored
  as an attribute on the instance itself. This means each instance gets its own
  full ``maxsize`` budget, instances do not need to be hashable, and caches are
  automatically cleaned up when the instance is garbage collected. For plain
  functions, class methods, and static methods, a single shared cache is used.
  The ``cache_info()``, ``cache_clear()``, and ``cache_parameters()`` methods
  are available directly on the decorated function. See the "LRU Cache"
  section of :doc:`bundled` for details.

* Added support for deferred patching in ``wrap_function_wrapper`` and
  ``patch_function_wrapper``. When the target module name is passed as a
  string with a trailing ``?`` (e.g., ``"requests?"``) and the module has
  not yet been imported, a post import hook will be registered so that the
  wrapping is applied automatically when the module is eventually imported.
  If the module is already imported, the wrapping is applied immediately.
  This avoids eagerly importing modules solely for the purpose of monkey
  patching them.

* Added ``__self_dict__`` to ``ObjectProxy`` to allow introspection of the
  proxy's own instance dictionary. Because ``ObjectProxy`` replaces
  ``__dict__`` with a property that delegates to the wrapped object,
  ``vars(proxy)`` returns the wrapped object's attributes rather than the
  proxy's, which previously made it impossible to see what ``_self_``
  attributes were stored on the proxy itself. ``__self_dict__`` returns
  the live instance dictionary of the proxy, so mutations to it are
  reflected on the proxy. The metaclass used by the pure Python
  ``ObjectProxy`` was also updated to preserve a custom ``__dict__``
  property defined on a subclass rather than overwriting it with the
  default delegating property, allowing subclasses to provide their own
  combined view if desired. See the "Introspecting the ObjectProxy
  instance __dict__" section of :doc:`issues` for details.

* Extended ``synchronized`` to support async functions and async locks.
  When applied to an ``async def`` function or method, the wrapper now
  awaits an ``asyncio.Lock`` created per context rather than acquiring a
  ``threading.RLock``. When an object with coroutine ``acquire``/``release``
  methods (such as an ``asyncio.Lock``) is supplied directly, the returned
  decorator and context manager use it via the async protocol. The object
  returned by ``synchronized`` now also exposes ``__aenter__`` and
  ``__aexit__`` so it can be used with ``async with`` to synchronise a
  block of code using an independent per-context ``asyncio.Lock``. Note
  that ``asyncio.Lock`` is not reentrant, which is a known difference from
  the threading case; users requiring reentrant semantics can pass their
  own task-reentrant async lock via the explicit-lock form. See the "Thread
  Synchronization" section of :doc:`bundled` for details.

* Added ``mark_as_sync``, ``mark_as_async``, ``async_to_sync`` and
  ``sync_to_async`` decorators for declaring or bridging the calling
  convention of a decorated callable. ``mark_as_sync`` and ``mark_as_async``
  are pass-through wrappers that adjust ``__code__.co_flags`` so that
  ``inspect.iscoroutinefunction()`` reports the intended convention,
  letting ``synchronized`` auto-select the correct sync or async wrapping
  behaviour even when an upstream decorator has changed the effective
  calling convention. Both markers take an optional ``generator`` keyword
  (tri-state: ``None`` / ``True`` / ``False``) controlling the reported
  generator bit, so all four callable kinds (plain function, sync
  generator, coroutine function, async generator) can be asserted.
  ``async_to_sync`` runs an async callable to completion via
  ``asyncio.run()``, and ``sync_to_async`` dispatches a sync callable
  onto the default executor via ``loop.run_in_executor()``; both
  self-mark so they integrate with ``synchronized`` without needing an
  additional marker decorator. The naming of ``async_to_sync`` and
  ``sync_to_async`` follows the convention used by ``asgiref``. See the
  "Calling Convention Markers and Adapters" section of :doc:`bundled` for
  details.

* Added ``with_signature``, a decorator for overriding the signature that
  introspection tools see for a wrapped callable without mutating the wrapped
  function itself. The signature can be supplied as a prototype callable, a
  prebuilt ``inspect.Signature`` object, or a factory callable that derives
  the signature from the wrapped function at decoration time. Annotations,
  defaults, keyword defaults, and argument-related attributes of ``__code__``
  are all derived from the supplied signature so that tools which read those
  attributes directly stay consistent with ``inspect.signature()``. The
  override propagates correctly through outer wrapt decorators stacked on
  top, and is handled correctly for instance methods, class methods, and
  static methods. ``with_signature`` replaces the need for the ``adapter``
  argument of ``wrapt.decorator``, which is planned for deprecation in a
  future release. See the "Signature Override" section of :doc:`bundled`
  for details.

**Features Changed**

* Improved attribute access on ``BoundFunctionWrapper`` to delegate lookups to
  the parent ``FunctionWrapper`` before falling back to the wrapped function.
  Custom ``_self_``-prefixed attributes set on a ``BoundFunctionWrapper`` are
  now automatically persisted on the parent ``FunctionWrapper`` rather than
  being lost when the transient bound instance is discarded. These changes make
  it easier to store and access decorator state on wrapped methods when accessed
  through class instances.

* Reworked module initialisation in the C extension to use multi-phase
  initialisation (PEP 489) with per-interpreter module state. The six
  proxy and function-wrapper types are now heap types created via
  ``PyType_FromModuleAndSpec`` rather than static ``PyTypeObject``
  definitions, and the previously process-wide cached interned strings
  are now stored in per-interpreter module state and populated eagerly
  during module execution. As a result the C extension now declares
  ``Py_mod_multiple_interpreters = Py_MOD_PER_INTERPRETER_GIL_SUPPORTED``
  on Python 3.12+ (so it can be loaded into sub-interpreters that own
  their own GIL, per PEP 684) and continues to declare
  ``Py_mod_gil = Py_MOD_GIL_NOT_USED`` on Python 3.13+ for free-threaded
  builds, with that declaration now sound because there is no remaining
  lazy initialisation of shared Python objects to race on. See the
  "Free-threaded Python (PEP 703)" section of :doc:`issues` for the
  current limitations on shared-mutation use cases.

* Aligned the error raised when attempting to delete ``__wrapped__`` on a
  proxy object. Both the C and Python implementations now raise
  ``TypeError("can't delete __wrapped__ attribute")``, matching the
  convention used by CPython for non-deletable attributes.

* Changed ``WrapperNotInitializedError`` to inherit from ``ValueError`` only,
  removing the ``AttributeError`` base class. The dual inheritance was
  originally added so that IDEs such as PyCharm, which introspect objects
  between ``__new__`` and ``__init__``, would not fail when encountering an
  unset ``__wrapped__``. However, inheriting from ``AttributeError`` caused
  ``hasattr``/``getattr``/``except AttributeError`` patterns throughout the
  codebase to silently swallow genuine errors. The proxy now tracks whether
  ``__init__`` has been called: before ``__init__``, accessing ``__wrapped__``
  raises a plain ``AttributeError`` (satisfying IDE introspection); after
  ``__init__``, it raises ``WrapperNotInitializedError`` (a ``ValueError``)
  which will not be silently ignored.

* Added ``__instancecheck__`` and ``__subclasscheck__`` to ``ObjectProxy``
  so that ``isinstance()`` and ``issubclass()`` work correctly when a proxied
  type appears on the right-hand side of the check. Previously these methods
  were only available on ``FunctionWrapper``. See the "Using issubclass() and
  isinstance() with proxied types" section of :doc:`issues` for remaining
  limitations when the proxy appears on the left-hand side.

* Removed the ``__reduce_ex__`` override from the object proxy base classes.
  Previously both ``__reduce__`` and ``__reduce_ex__`` were overridden to
  raise ``NotImplementedError``, which forced proxy subclasses wanting to
  support pickling to override both methods, with ``__reduce_ex__`` typically
  just delegating to ``__reduce__``. Because the default ``__reduce_ex__``
  inherited from ``object`` already delegates to ``__reduce__`` whenever a
  subclass has overridden it, the extra override was unnecessary and
  actively prevented the standard pickle contract from working as expected.
  Proxy subclasses now only need to override ``__reduce__`` to be
  pickleable. See the "Serialising an Object Proxy" section of :doc:`examples`
  for a worked example. Note that code which needs to remain compatible
  with versions of **wrapt** prior to 2.2.0 should continue to define both
  ``__reduce__`` and ``__reduce_ex__``, as defining ``__reduce_ex__`` in
  addition to ``__reduce__`` is harmless on newer versions.

**Bugs Fixed**

* Fixed a ``Py_DECREF(NULL)`` crash in the C implementation of all inplace
  operators (``+=``, ``-=``, ``*=``, ``%=``, ``**=``, ``<<=``, ``>>=``, ``&=``,
  ``^=``, ``|=``, ``//=``, ``/=``, ``@=``) on ``ObjectProxy``. When a subclass
  overrode ``__object_proxy__`` with a descriptor that raised an exception,
  the error path dereferenced a ``NULL`` pointer (and leaked the intermediate
  result). The exception raised by ``__object_proxy__`` is now propagated
  cleanly.

* Fixed a number of optional attribute lookups in the C implementation of
  ``ObjectProxy`` and ``FunctionWrapper`` that were silently swallowing any
  exception raised during the lookup, instead of only ignoring
  ``AttributeError``. As a result, exceptions such as ``MemoryError``,
  ``KeyboardInterrupt``, ``SystemExit``, and user exceptions raised from
  ``__getattribute__``, properties, or descriptors on wrapped objects or
  proxy subclasses were being lost. These lookups now propagate any
  non-``AttributeError`` exception to the caller, matching the behaviour
  of the pure-Python implementation.

* Fixed an error in the C implementation of ``FunctionWrapper`` where if the
  ``enabled`` argument (or the value returned from a callable ``enabled``)
  raised an exception when its truthiness was evaluated, the exception was
  silently swallowed, the wrapper was bypassed, and the wrapped function was
  called directly with a pending Python exception. The exception raised from
  ``__bool__`` is now propagated to the caller and the wrapped function is
  not invoked, matching the behaviour of the pure-Python implementation.

* Fixed a reference leak in the C implementation of ``__round__`` on
  ``ObjectProxy``. Each call to ``round()`` on a proxy was leaking one
  reference to the ``builtins.round`` function due to a spurious
  ``Py_INCREF`` that was not balanced by a matching ``Py_DECREF``.

* Fixed a reference leak in the C implementation of ``FunctionWrapper``
  when wrapping another ``FunctionWrapperBase`` instance. The new reference
  returned by the internal ``_self_binding`` attribute lookup was never
  released, leaking one reference to the binding string object on every
  such construction. The same code path also failed to check for a ``NULL``
  return from the attribute lookup, so any non-``AttributeError`` exception
  raised during the lookup was silently swallowed; such exceptions are now
  propagated to the caller.

* Fixed an unchecked ``PyDict_New()`` allocation in the C implementation of
  ``ObjectProxy.__new__``. If the dict allocation failed, the proxy object
  was still returned to the caller with a ``NULL`` instance dict and a
  pending ``MemoryError``, violating the C-API contract and causing a crash
  on the next attribute write. The constructor now releases the partially
  constructed proxy and propagates the ``MemoryError`` to the caller.

* Fixed unchecked ``PyTuple_New()`` and ``PyDict_New()`` allocations in the
  C implementation of ``PartialCallableObjectProxy.__call__``. If either
  allocation failed under low-memory conditions, the function would
  dereference a ``NULL`` pointer (via ``PyTuple_SetItem`` or ``PyDict_Update``)
  and crash the interpreter. Both allocations are now checked and the
  ``MemoryError`` is propagated cleanly to the caller.

* Fixed error suppression in the C implementation of ``FunctionWrapper`` and
  ``BoundFunctionWrapper`` where ``PyObject_RichCompareBool()`` calls used
  in ``binding`` dispatch were checked with ``== 1``, conflating the error
  return ``-1`` with the false return ``0``. If a comparison raised, the
  exception was silently swallowed, subsequent comparisons in the same
  ``||``-chain overwrote the pending error indicator, and control fell
  through to a downstream call that executed with a stale exception set,
  typically surfacing as a confusing ``SystemError`` instead of the
  original exception. The two surviving ``PyObject_RichCompareBool()``
  comparisons (against the ``"builtin"`` and ``"class"`` binding values
  in ``FunctionWrapper.__get__``) now distinguish ``-1`` from ``0`` and
  propagate any exception to the caller, matching the behaviour of the
  pure-Python implementation. The remaining ``binding`` dispatch sites in
  ``FunctionWrapper.__call__``, ``FunctionWrapper.__get__``, and
  ``BoundFunctionWrapper.__call__`` have been further simplified to
  compare ``self->binding`` directly against fixed ASCII literals using
  ``PyUnicode_CompareWithASCIIString()``, a primitive that allocates
  nothing and cannot raise, so the swallowed-exception failure mode
  cannot reoccur at those sites.

* Fixed a leaked module reference and unchecked ``PyModule_AddObject()``
  calls in the C extension's module initialisation. If any ``PyType_Ready()``
  call failed, the freshly created module object was leaked. Each subsequent
  ``PyModule_AddObject()`` call was also unchecked, so on failure the
  preceding ``Py_INCREF`` leaked a type reference and initialisation
  continued with a pending exception, ultimately returning the module
  with an exception set in violation of the C-API contract. All failures
  are now checked and routed through a single cleanup path that releases
  the module before returning ``NULL``.

* Fixed a use-after-free reentrancy window in the C implementation of
  ``ObjectProxy``, ``PartialCallableObjectProxy`` and ``FunctionWrapper``
  when replacing instance fields such as ``__wrapped__``. Code decremented
  the old value's refcount before overwriting the field, leaving the field
  briefly pointing at a freed object while the old object's ``__del__`` ran.
  Any reentrant access to the proxy from that finalizer (or from a weakref
  callback, triggered GC pass, or audit hook) would observe the dangling
  pointer.

* Fixed unchecked ``PyObject_IsInstance()`` error returns in the C
  implementation of ``FunctionWrapper.__init__`` and
  ``BoundFunctionWrapper.__call__``. The cascade in ``__init__`` that
  selects the ``binding`` ("function", "classmethod", "class",
  "staticmethod", "instancemethod", ...) used bare
  ``else if (PyObject_IsInstance(...))``, and because ``-1`` is truthy in
  C, an exception raised from a metaclass's ``__instancecheck__`` was
  silently treated as a positive match: the wrong binding was recorded
  and a Python exception was left set on the thread state, surfacing
  later as a spurious failure in unrelated code. The shifted-argument
  branch in ``BoundFunctionWrapper.__call__`` had the related ``== 1``
  variant, which avoided the truthy trap but still silently swallowed
  the ``-1`` error case. Both sites now distinguish ``-1`` from ``0``
  and propagate any exception to the caller.

* Fixed unchecked ``PyDict_New()`` allocations in the C implementation of
  ``FunctionWrapper.__call__`` and ``BoundFunctionWrapper.__call__`` used
  to synthesize an empty kwargs dict when the caller did not supply one.
  If the allocation failed, the resulting ``NULL`` was passed as the
  ``kwds`` argument to ``PyObject_CallFunctionObjArgs()``, whose variadic
  argument list is ``NULL``-terminated. This truncated the call, masked
  the original ``MemoryError``, and surfaced as a confusing ``TypeError``
  from the wrapper signature mismatch instead. All three sites now check
  for allocation failure, release any locally owned references, and
  propagate the ``MemoryError`` to the caller.

* Fixed eager evaluation of ``__annotations__`` in the pure-Python
  implementation of ``ObjectProxy.__init__`` on Python 3.14+. Python 3.14
  defers annotation evaluation (PEP 649/749) via the ``__annotate__``
  descriptor, but ``ObjectProxy`` was accessing ``wrapped.__annotations__``
  at construction time, which forced immediate evaluation and raised
  ``TypeError`` when names referenced in annotations had been shadowed in
  the local scope. The proxy now copies ``__annotate__`` instead of
  ``__annotations__`` on Python 3.14+, matching the approach taken by
  ``functools.wraps`` in the standard library. The C extension was not
  affected as it already delegates ``__annotations__`` to the wrapped
  object lazily on each access.

* Fixed type-level access to ``__module__`` and ``__doc__`` on proxy and
  wrapper classes (e.g. ``ObjectProxy.__module__``) returning a descriptor
  object instead of a string. CPython's ``type.__module__`` getter performs
  a raw dict lookup on the type's ``__dict__`` without invoking the
  descriptor protocol, so the proxying descriptors placed there to delegate
  instance-level access to the wrapped object were returned as-is. This
  caused tools such as pylint/astroid to crash with ``AttributeError:
  'property' object has no attribute 'split'`` when introspecting wrapt
  types. The pure-Python implementation has always had this bug but it was
  not previously reported because the C extension was the default code path
  and static types were unaffected. The C extension became affected after
  the conversion to heap types in this release, since heap types store
  ``__module__`` in ``tp_dict`` rather than deriving it from ``tp_name``.
  The fix moves ``__module__`` and ``__doc__`` proxying out of the type-level
  descriptor slots and into the instance-level attribute access machinery
  (``tp_getattro``/``tp_setattro`` in C, metaclass properties in Python),
  ensuring that type-level access returns the real string while instance-level
  access continues to delegate to the wrapped object.

* Fixed missing NULL guards in the C implementation of
  ``FunctionWrapper.__call__``, ``FunctionWrapper.__get__``, and
  ``BoundFunctionWrapper.__call__``. If a wrapper object was constructed via
  ``__new__`` without calling ``__init__``, invoking or accessing the
  descriptor on the uninitialized object would dereference NULL pointers and
  crash the interpreter (SIGSEGV) instead of raising
  ``WrapperNotInitializedError``. The same ``if (!self->wrapped)`` guard
  already used throughout the rest of the C extension has been added to these
  three functions.

* Fixed missing NULL guards for the ``other`` operand in the C implementation
  of all thirteen inplace numeric operators (``+=``, ``-=``, ``*=``, ``%=``,
  ``**=``, ``<<=``, ``>>=``, ``&=``, ``^=``, ``|=``, ``//=``, ``/=``, ``@=``)
  on ``ObjectProxy``. When ``other`` was itself a proxy whose wrapped attribute
  had not been set, the code unwrapped it to ``NULL`` and passed that to the
  corresponding ``PyNumber_InPlace*`` function, crashing the interpreter
  (SIGSEGV). The non-inplace binary operators already had the correct guard;
  the inplace variants now check for ``NULL`` and raise the same uninitialised
  wrapper error.

* Replaced all thirteen uses of the deprecated ``PyObject_HasAttrString()``
  C-API function in the inplace numeric operators of ``ObjectProxy`` with
  ``PyObject_GetOptionalAttrString()`` (backfilled for Python < 3.13).
  ``PyObject_HasAttrString()`` catches all exceptions and returns false,
  silently swallowing ``KeyboardInterrupt``, ``SystemExit``, or any
  exception raised by ``__getattr__``/``__getattribute__`` on the wrapped
  object. The replacement only suppresses ``AttributeError``, matching the
  behaviour of Python's ``hasattr()`` and the pure-Python implementation.

* Fixed a behaviour divergence in the pure-Python implementation of
  ``BoundFunctionWrapper.__call__`` when ``binding`` is ``"callable"`` and
  ``instance`` is ``None``. This situation arises when a callable descriptor
  wrapped via ``FunctionWrapper`` is assigned as a class attribute and then
  accessed via the class rather than an instance. The pure-Python
  ``"callable"`` path unconditionally required a positional argument (raising
  ``TypeError`` if none was provided) and extracted the first argument as the
  instance without checking whether it was actually an instance of the owner
  class. The C extension had already been updated in an earlier rework to
  align the ``"callable"`` path with the ``"function"`` path, adding an
  ``isinstance`` guard and falling through gracefully when no arguments are
  provided, but the corresponding Python code was not updated at the time.
  The pure-Python implementation now matches the C extension: it only extracts
  the first argument as the instance when it passes the ``isinstance`` check
  against the owner class, and calls the wrapper with ``instance=None`` when
  no arguments are provided rather than raising ``TypeError``.

* Fixed a crash (SIGSEGV) in the C implementation of ``ObjectProxy.__pow__``
  when a proxy was passed as the modulo argument to the ternary form of the
  builtin ``pow()``. The ``nb_power`` slot unwrapped the first two arguments
  but not modulo before calling ``PyNumber_Power``, so CPython's ternary
  operator fallback recursed back into the same slot indefinitely and
  overflowed the C stack. The slot now returns ``NotImplemented`` when modulo
  is a proxy, causing ``TypeError`` to be raised instead, matching the
  behaviour of the pure-Python and PyPy implementations which do not unwrap
  modulo either. See the "Ternary ``pow()`` with ObjectProxy" section of
  :doc:`issues` for the resulting calling convention.

* Aligned the C implementation of ``FunctionWrapper.__get__`` with the pure
  Python implementation when a wrapped descriptor is accessed from a class
  rather than an instance. The C path was passing ``NULL`` through to the
  wrapped descriptor's ``__get__`` slot in this case, whereas the pure
  Python path always passes ``None``. Native CPython descriptors treat the
  two equivalently so no user visible difference has been observed in
  practice, but a third party C descriptor which branched on ``NULL``
  versus ``Py_None`` could have seen the two implementations behave
  differently. The C path now substitutes ``Py_None`` for ``NULL`` before
  invoking the wrapped descriptor, so both implementations behave the
  same regardless of descriptor origin.

Version 2.1.2
-------------

**Bugs Fixed**

* Building of Python wheels for riscv64 Linux platform had been accidentally
  removed from the build configuration. This has now been added back in.

* When a weak function proxy was created for a bound method and the instance
  it was bound to was garbage collected, calling the proxy would silently
  call the function as unbound instead of raising a ``ReferenceError``.

* When deleting an attribute named ``__annotations__`` on an object proxy, the
  attribute was only being deleted from the proxy and not also from the wrapped
  object.

Version 2.1.1
-------------

**Bugs Fixed**

* Search field for documentation hosted on Read the Docs wasn't working
  correctly due to JavaScript error.

* Missing ``tox.ini`` from source distribution package has been added.

Version 2.1.0
-------------

**Features Changed**

* Drop support for Python 3.8. Python version 3.9 or later is now required.

**Bugs Fixed**

* Improved type hints so that ``mypy`` and ``ty`` work better for methods of
  classes when using ``wrapt.decorator`` and ``wrapt.function_wrapper``. Note
  that applying these to static methods still does not work correctly due to
  possibly limitations in those type checkers. The ``pyrefly`` tool still does
  not work correctly with ``wrapt.decorator`` and ``wrapt.function_wrapper``
  applied to any methods of classes. Overall ``pyright`` provides the best
  experience when using ``wrapt`` with type checking.

Version 2.0.1
-------------

**Bugs Fixed**

* The ``wrapt.lazy_import()`` function wasn't included in the
  ``__all__`` attribute of the ``wrapt`` module, meaning that it wasn't
  accessible when using ``from wrapt import *`` and type checkers such as
  ``mypy`` or ``pylance`` may not see it as part of the public API.

* When using ``wrapt.lazy_import()`` to lazily import a function of a module,
  the resulting proxy object wasn't marked as callable until something triggered
  the import of the module via the proxy. This meant a ``callable()`` check
  on the proxy would return ``False`` until the module was actually imported.
  Further, calling the proxy before the module was imported would raise
  ``TypeError: 'LazyObjectProxy' object is not callable`` rather than
  importing the module and calling the function as expected. In order to
  address this issue, an additional keyword argument ``interface`` has been
  added to ``wrapt.lazy_import()`` which can be used to specify the expected
  interface type of the wrapped object. This will default to ``Callable``
  when an attribute name is supplied, and to ``ModuleType`` when no attribute
  name is supplied. If using ``wrapt.lazy_import()`` and supplying an
  ``attribute`` argument, and you expect the wrapped object to be something
  other than a callable, you should now also supply ``interface=...`` with the
  appropriate type from ``collections.abc`` to ensure the proxy behaves correctly
  prior to the module being imported. This should only be necessary where the
  wrapped object has special dunder methods on its type which need to exist on
  the proxy prior to the module being imported.

Version 2.0.0
-------------

There have been subtle changes in various corner cases of the behaviour of the
``ObjectProxy`` class, which although not expected to cause problems, still has
the potential for causing issues if code was for some reason dependent on prior
behaviour. All existing code related to Python 2.X has also been removed.
Finally it has also been a while since the last significant release. For all
these reasons a major version bump is being made.

**New Features**

* Added ``__all__`` attribute to ``wrapt`` module to expose the public API.

* The ``wrapt.PartialCallableObjectProxy`` class can now be created via the
  convenience function ``wrapt.partial``, for users who are used to using
  ``functools.partial`` and want to use the ``wrapt`` version of it.

* Type hints have been added to the ``wrapt`` module. The type hints are
  available when using Python 3.10 or later, and can be used with static type
  checkers such as ``pylance`` or ``mypy``. Note that due to limitations in
  Python's type hinting system, type checking is not always able to be applied
  or details such as default values may not be available. See the documentation
  for more details on limitations and workarounds.

* Added ``wrapt.BaseObjectProxy`` class which is the base class for all object
  proxy classes. This class is either the pure Python or C extension variant of
  the object proxy depending on whether the C extension is available. This used
  to be the ``ObjectProxy`` class, but has been renamed to ``BaseObjectProxy``
  to better reflect its role as the foundational class for all object proxies.
  This variant does though no longer provide a proxy implementation for the
  ``__iter__()`` special method as it was originally a mistake to include it
  in the ``ObjectProxy`` class as its presence could cause issues when the
  wrapped object is not iterable. A ``wrapt.ObjectProxy`` class is still
  provided but this is now a pure Python subclass of ``BaseObjectProxy`` which
  adds a proxy implementation for the ``__iter__()`` special method. This is
  done for backwards compatibility reasons as ``ObjectProxy`` with the
  ``__iter__()`` special method has been part of the public API for a long time.

* Added ``wrapt.AutoObjectProxy`` class which is a pure Python subclass of
  ``BaseObjectProxy`` which overrides the ``__new__()`` method to dynamically
  generate a custom subclass which includes methods for callable, descriptor and
  iterator protocols, as well as other select special methods. This is done using
  a dynamically generated subclass as the special methods for these protocols
  must be defined on the class itself and not on the instance. Because
  ``AutoObjectProxy`` dynamically generates a custom subclass for each instance,
  it has a notable memory overhead for every instance created, and thus should
  only be used where you know you will not be needing many instances of it.
  If you know what additional special methods you need, it is preferable to use
  ``BaseObjectProxy`` directly and add them to a subclass as needed. If you only
  need ``__iter__()`` support for backwards compatibility then use ``ObjectProxy``
  instead.

* Added ``wrapt.LazyObjectProxy`` class which is a variant of ``AutoObjectProxy``
  which takes a callable which returns the object to be wrapped. The callable is
  only invoked the first time an attribute of the wrapped object is accessed.
  This can be useful for deferring creation of expensive objects until they are
  actually needed. Note that the callable is only invoked once and protection
  is in place to ensure that if multiple threads try to access the wrapped object
  at the same time, only one thread will invoke the callable and the other
  threads will wait for the result. Because ``LazyObjectProxy`` is a subclass of
  ``AutoObjectProxy``, it has the same memory overhead considerations as
  ``AutoObjectProxy`` and should only be used where you know you will not be
  needing many instances of it.

* Added ``wrapt.lazy_import()`` function which takes a module name and returns a
  ``LazyObjectProxy`` which will import the module when it is first needed.
  This can be useful for deferring import of modules until they are actually
  needed. If the module name is a dotted name, then the full dotted name is
  imported and the last component returned. An optional ``attribute`` argument
  can be supplied which is the name of an attribute of the module to return
  instead of the module itself.

**Features Changed**

* Code related to Python 2.X and workarounds for older Python 3.X versions has
  been removed.

* Dependency at runtime on ``setuptools`` for calculating package entry points
  has been removed. Instead the ``importlib.metadata`` module is now used for
  this purpose. The ``wrapt`` package no longer requires ``setuptools`` to be
  installed at runtime. It is still required for building and installing the
  package from source, but not for installation using Python wheels, and not
  for using it.

* For reasons to do with backward/forward compatibility the ``wrapt`` module
  included references to ``getcallargs()`` and ``formatargspec()`` functions which
  were part of the ``inspect`` module at one time or another. These were provided
  as convenience for users of the ``wrapt`` module, but were not actually part of
  the public API. They have now been removed from the ``wrapt`` module and are
  no longer available. If you need these functions, you should use the
  ``inspect`` module directly.

* The ``enabled``, ``adapter`` and ``proxy`` arguments to the ``@decorator``
  decorator had to be keyword parameters, and the initial ``wrapped`` argument
  had to be positional only. Because though Python 2.X was still being supported
  it was not possible to use appropriate syntax to mark them as such. These
  arguments are now marked as positional and keyword only parameters in the
  function signature as appropriate.

* The object proxy classes now raise a ``WrapperNotInitializedError`` exception
  rather than Python builtin ``ValueError`` exception when an attempt is made
  to access an attribute of the wrapped object before the wrapper has been
  initialized. The ``WrapperNotInitializedError`` exception inherits from both
  ``ValueError`` and ``AttributeError`` so that it can be caught by code which
  wants to handle both cases. This is being done to allow IDEs such as PyCharm
  to give a live view of Python objects and their attributes. Previously a
  ``ValueError`` exception was being raised, which was problematic because
  PyCharm would see it as an actual error and fail. By using a custom exception
  that also inherits from ``AttributeError`` it is hoped the IDE will see it as
  a normal attribute access error rather than an actual error and so just not
  attempt to show the attribute within the IDE.

**Bugs Fixed**

* Reference count was not being incremented on type object for C implementation
  of the partial callable object proxy when module was initialized. If ``wrapt``
  was being used in Python sub interpreters which were deleted it could lead
  to the process crashing. Note that this change was also back ported and
  included in version 1.17.3 and 1.14.2 releases.

* Wasn't chaining ``__mro_entries__()`` calls when the wrapped object was not a
  type (class) and itself had a ``__mro_entries__()`` method. This meant that if
  using the object proxy as a base class for a generic class, the generic
  parameters were being ignored.

* When an object proxy wrapped an immutable type, such as an integer, and the
  object proxy had been assigned to a second variable, the result of an
  in-place operation on the second variable was also affecting the first
  variable, when instead the lifetime of the two variables should have been
  independent to reflect what occurs for normal immutable types.

Version 1.17.3
--------------

**Bugs Fixed**

* Reference count was not being incremented on type object for C implementation
  of the partial callable object proxy when module was initialized. If wrapt was
  being used in Python sub interpreters which were deleted it could lead to the
  process crashing.

Version 1.17.2
--------------

**New Features**

* Added universal binary wheels for macOS. That is, contains both x86_64 and
  arm64 architectures in the same wheel.

Version 1.17.1
--------------

**Bugs Fixed**

* Due to GitHub actions changes, binary wheels were missing for macOS Intel.

* Not implemented error for ``__reduce__()`` on ``ObjectProxy`` was incorrectly
  displaying the error as being on ``__reduce_ex__()``.

Version 1.17.0
--------------

Note that version 1.17.0 drops support for Python 3.6 and 3.7. Python version
3.8 or later is required.

**New Features**

* Add ``__format__()`` method to ``ObjectProxy`` class to allow formatting of
  wrapped object.

* Added C extension internal flag to indicate that ``wrapt`` should be safe for
  Python 3.13 free threading mode. Releases will include free threading variants
  of Python wheels. Note that as free threading is new, one should be cautious
  about using it in production until it has been more widely tested.

**Bugs Fixed**

* When a normal function or builtin function which had ``wrapt.decorator`` or a
  function wrapper applied, was assigned as a class attribute, and the function
  attribute called via the class or an instance of the class, an additional
  argument was being passed, inserted as the first argument, which was the class
  or instance. This was not the correct behaviour and the class or instance
  should not have been passed as the first argument.

* When an instance of a callable class object was wrapped which didn't not have
  a ``__get__()`` method for binding, and it was called in context where binding
  would be attempted, it would fail with error that ``__get__()`` did not exist
  when instead it should have been called directly, ignoring that binding was
  not possible.

* The ``__round__`` hook for the object proxy didn't accept ``ndigits`` argument.

Version 1.16.0
--------------

Note that version 1.16.0 drops support for Python 2.7 and 3.5. Python version
3.6 or later is required.

**New Features**

* The ``patch_function_wrapper()`` decorator now accepts an ``enabled``
  argument, which can be a literal boolean value, object that evaluates as
  boolean, or a callable object which returns a boolean. In the case of a
  callable, determination of whether the wrapper is invoked will be left until
  the point of the call. In the other cases, the wrapper will not be applied if
  the value evaluates false at the point of applying the wrapper.

**Features Changed**

* The import hook loader and finder objects are now implemented as transparent
  object proxies so they properly proxy pass access to attributes/functions of
  the wrapped loader or finder.

* Code files in the implementation have been reorganized such that the pure
  Python version of the ``ObjectProxy`` class is directly available even if the
  C extension variant is being used. This is to allow the pure Python variant to
  be used in exceptional cases where the C extension variant is not fully
  compatible with the pure Python implementation and the behaviour of the pure
  Python variant is what is required. This should only be relied upon if have
  absolutely no choice. The pure Python variant is not as performant as the C
  extension.

  To access the pure Python variant use ``from wrapt.wrappers import ObjectProxy``
  instead of just ``from wrapt import ObjectProxy``. Note that prior to this
  version if you had used ``from wrapt.wrappers import ObjectProxy`` you would
  have got the C extension variant of the class rather than the pure Python
  version if the C extension variant was available.

**Bugs Fixed**

* It was not possible to update the ``__class__`` attribute through the
  transparent object proxy when relying on the C implementation.

Version 1.15.0
--------------

**Bugs Fixed**

* When the C extension for wrapt was being used, and a property was used on an
  object proxy wrapping another object to intercept access to an attribute of
  the same name on the wrapped object, if the function implementing the property
  raised an exception, then the exception was ignored and not propagated back to
  the caller. What happened instead was that the original value of the attribute
  from the wrapped object was returned, thus silently suppressing that an
  exception had occurred in the wrapper. This behaviour was not happening when
  the pure Python version of wrapt was being used, with it raising the
  exception. The pure Python and C extension implementations thus did not behave
  the same.

  Note that in the specific case that the exception raised is AttributeError it
  still wouldn't be raised. This is the case for both Python and C extension
  implementations. If a wrapper for an attribute internally raises an
  AttributeError for some reason, the wrapper should if necessary catch the
  exception and deal with it, or propagate it as a different exception type if
  it is important that an exception still be passed back.

* Address issue where the post import hook mechanism of wrapt wasn't transparent
  and left the ``__loader__`` and ``__spec__.loader`` attributes of a module as
  the wrapt import hook loader and not the original loader. That the original
  loader wasn't preserved could interfere with code which needed access to the
  original loader.

* Address issues where a thread deadlock could occur within the wrapt module
  import handler, when code executed from a post import hook created a new
  thread and code executed in the context of the new thread itself tried to
  register a post import hook, or imported a new module.

* When using ``CallableObjectProxy`` as a wrapper for a type or function and
  calling the wrapped object, it was not possible to pass a keyword argument
  named ``self``. This only occurred when using the pure Python version of wrapt
  and did not occur when using the C extension based implementation.

* When using ``PartialCallableObjectProxy`` as a wrapper for a type or function,
  when constructing the partial object and when calling the partial object, it
  was not possible to pass a keyword argument named ``self``. This only occurred
  when using the pure Python version of wrapt and did not occur when using the C
  extension based implementation.

* When using ``FunctionWrapper`` as a wrapper for a type or function and calling
  the wrapped object, it was not possible to pass a keyword argument named
  ``self``. Because ``FunctionWrapper`` is also used by decorators, this also
  affected decorators on functions and class types. A similar issue also arose
  when these were applied to class and instance methods where binding occurred
  when the method was accessed. In that case it was in ``BoundFunctionWrapper``
  that the problem could arise. These all only occurred when using the pure
  Python version of wrapt and did not occur when using the C extension based
  implementation.

* When using ``WeakFunctionProxy`` as a wrapper for a function, when calling the
  function via the proxy object, it was not possible to pass a keyword argument
  named ``self``.

Version 1.14.2
--------------

**Bugs Fixed**

* Reference count was not being incremented on type object for C implementation
  of the partial callable object proxy when module was initialized. If wrapt was
  being used in Python sub interpreters which were deleted it could lead to the
  process crashing.

Version 1.14.1
--------------

**Bugs Fixed**

* When the post import hooks mechanism was being used, and a Python package with
  its own custom module importer was used, importing modules could fail if the
  custom module importer didn't use the latest Python import hook finder/loader
  APIs and instead used the deprecated API. This was actually occurring with the
  ``zipimporter`` in Python itself, which was not updated to use the newer
  Python APIs until Python 3.10.

Version 1.14.0
--------------

**Bugs Fixed**

* Python 3.11 dropped ``inspect.formatargspec()`` which was used in creating
  signature changing decorators. Now bundling a version of this function
  which uses ``Parameter`` and ``Signature`` from ``inspect`` module when
  available. The replacement function is exposed as ``wrapt.formatargspec()``
  if need it for your own code.

* When using a decorator on a class, ``isinstance()`` checks wouldn't previously
  work as expected and you had to manually use ``Type.__wrapped__`` to access
  the real type when doing instance checks. The ``__instancecheck__`` hook is
  now implemented such that you don't have to use ``Type.__wrapped__`` instead
  of ``Type`` as last argument to ``isinstance()``.

* Eliminated deprecation warnings related to Python module import system, which
  would have turned into broken code in Python 3.12. This was used by the post
  import hook mechanism.

**New Features**

* Binary wheels provided on PyPi for ``aarch64`` Linux systems and macOS
  native silicon where supported by Python when using ``pypa/cibuildwheel``.

Version 1.13.3
--------------

**New Features**

* Adds wheels for Python 3.10 on PyPi and where possible also now
  generating binary wheels for ``musllinux``.

Version 1.13.2
--------------

**Features Changed**

* On the Windows platform when using Python 2.7, by default the C extension
  will not be installed and the pure Python implementation will be used.
  This is because too often on Windows when using Python 2.7, there is no
  working compiler available. Prior to version 1.13.0, when installing the
  package it would fallback to using the pure Python implementation
  automatically but that relied on a workaround to do it when there was
  no working compiler. With the changes in 1.13.0 to use the builtin
  mechanism of Python to not fail when a C extension cannot be compiled,
  this fallback doesn't work when the compiler doesn't exist, as the
  builtin mechanism in Python regards lack of a compiler as fatal and not
  a condition for which it is okay to ignore the fact that the extension
  could not be compiled.

  If you are using Python 2.7 on Windows, have a working compiler, and
  still want to attempt to install the C extension, you can do so by
  setting the ``WRAPT_INSTALL_EXTENSIONS`` environment variable to ``true``
  when installing the ``wrapt`` package.

  Note that the next significant release of ``wrapt`` will drop support for
  Python 2.7 and Python 3.5. The change described here is to ensure that
  ``wrapt`` can be used with Python 2.7 on Windows for just a little bit
  longer. If using Python 2.7 on non Windows platforms, it will still
  attempt to install the C extension.

Version 1.13.1
--------------

**Bugs Fixed**

* Fix Python version constraint so PyPi classifier for ``pip`` requires
  Python 2.7 or Python 3.5+.

Version 1.13.0
--------------

**Bugs Fixed**

* When a reference to a class method was taken out of a class, and then
  wrapped in a function wrapper, and called, the class type was not being
  passed as the instance argument, but as the first argument in args,
  with the instance being ``None``. The class type should have been passed
  as the instance argument.

* If supplying an adapter function for a signature changing decorator
  using input in the form of a function argument specification, name lookup
  exceptions would occur where the adaptor function had annotations which
  referenced non builtin Python types. Although the issues have been
  addressed where using input data in the format usually returned by
  ``inspect.getfullargspec()`` to pass the function argument specification,
  you can still have problems when supplying a function signature as
  string. In the latter case only Python builtin types can be referenced
  in annotations.

* When a decorator was applied on top of a data/non-data descriptor in a
  class definition, the call to the special method ``__set_name__()`` to
  notify the descriptor of the variable name was not being propagated. Note
  that this issue has been addressed in the ``FunctionWrapper`` used by
  ``@wrapt.decorator`` but has not been applied to the generic
  ``ObjectProxy`` class. If using ``ObjectProxy`` directly to construct a
  custom wrapper which is applied to a descriptor, you will need to
  propagate the ``__set_name__()`` call yourself if required.

* The ``issubclass()`` builtin method would give incorrect results when used
  with a class which had a decorator applied to it. Note that this has only
  been able to be fixed for Python 3.7+. Also, due to what is arguably a
  bug (https://bugs.python.org/issue44847) in the Python standard library,
  you will still have problems when the class hierarchy uses a base class
  which has the ``abc.ABCMeta`` metaclass. In this later case an exception
  will be raised of ``TypeError: issubclass() arg 1 must be a class``.

Version 1.12.1
--------------

**Bugs Fixed**

* Applying a function wrapper to a static method of a class using the
  ``wrap_function_wrapper()`` function, or wrapper for the same, wasn't
  being done correctly when the static method was the immediate child of
  the target object. It was working when the name path had multiple name
  components. A failure would subsequently occur when the static method
  was called via an instance of the class, rather than the class.

Version 1.12.0
--------------

**Features Changed**

* Provided that you only want to support Python 3.7, when deriving from
  a base class which has a decorator applied to it, you no longer need
  to access the true type of the base class using ``__wrapped__`` in
  the inherited class list of the derived class.

**Bugs Fixed**

* When using the ``synchronized`` decorator on instance methods of a
  class, if the class declared special methods to override the result for
  when the class instance was tested as a boolean so that it returned
  ``False`` all the time, the synchronized method would fail when called.

* When using an adapter function to change the signature of the decorated
  function, ``inspect.signature()`` was returning the wrong signature
  when an instance method was inspected by accessing the method via the
  class type.

Version 1.11.2
--------------

**Bugs Fixed**

* Fix possible crash when garbage collection kicks in when invoking a
  destructor of wrapped object.

Version 1.11.1
--------------

**Bugs Fixed**

* Fixed memory leak in C extension variant of ``PartialCallableObjectProxy``
  class introduced in 1.11.0, when it was being used to perform binding,
  when a call of an instance method was made through the class type, and
  the self object passed explicitly as first argument.

* The C extension variant of the ``PartialCallableObjectProxy`` class
  introduced in 1.11.0, which is a version of ``functools.partial``
  which correctly handles binding when applied to methods of classes,
  couldn't be used when no positional arguments were supplied.

* When the C extension variant of ``PartialCallableObjectProxy`` was
  used and multiple positional arguments were supplied, the first
  argument would be replicated and used to all arguments, instead of
  correct values, when the partial was called.

* When the C extension variant of ``PartialCallableObjectProxy`` was
  used and keyword arguments were supplied, it would fail as was
  incorrectly using the positional arguments where the keyword arguments
  should have been used.

Version 1.11.0
--------------

**Bugs Fixed**

* When using arithmetic operations through a proxy object, checks about
  the types of arguments were not being performed correctly, which could
  result in an exception being raised to indicate that a proxy object had
  not been initialised when in fact the argument wasn't even an instance
  of a proxy object.

  Because an incorrect cast in C level code was being performed and
  an attribute in memory checked on the basis of it being a type different
  to what it actually was, technically it may have resulted in a process
  crash if the size of the object was smaller than the type being casted
  to.

* The ``__complex__()`` special method wasn't implemented and using
  ``complex()`` on a proxy object would give wrong results or fail.

* When using the C extension, if an exception was raised when using inplace
  or, ie., ``|=``, the error condition wasn't being correctly propagated
  back which would result in an exception showing up as wrong location
  in subsequent code.

* Type of ``long`` was used instead of ``Py_hash_t`` for Python 3.3+. This
  caused compiler warnings on Windows, which depending on what locale was
  set to, would cause pip to fail when installing the package.

* If calling ``Class.instancemethod`` and passing ``self`` explicitly, the
  ability to access ``__name__`` and ``__module__`` on the final bound
  method were not preserved. This was due to a ``partial`` being used for
  this special case, and it doesn't preserve introspection.

* Fixed typo in the getter property of ``ObjectProxy`` for accessing
  ``__annotations__``. Appeared that it was still working as would fall back
  to using generic ``__getattr__()`` to access attribute on wrapped object.

**Features Changed**

* Dropped support for Python 2.6 and 3.3.

* If ``copy.copy()`` or ``copy.deepcopy()`` is used on an instance of the
  ``ObjectProxy`` class, a ``NotImplementedError`` exception is raised, with
  a message indicating that the object proxy must implement the
  ``__copy__()`` or ``__deepcopy__()`` method. This is in place of the
  default ``TypeError`` exception with message indicating a pickle error.

* If ``pickle.dump()`` or ``pickle.dumps()`` is used on an instance of the
  ``ObjectProxy`` class, a ``NotImplementedError`` exception is raised, with
  a message indicating that the object proxy must implement the
  ``__reduce_ex__()`` method. This is in place of the default ``TypeError``
  exception with message indicating a pickle error.

Version 1.10.11
---------------

**Bugs Fixed**

* When wrapping a ``@classmethod`` in a class used as a base class, when
  the method was called via the derived class type, the base class type was
  being passed for the ``cls`` argument instead of the derived class type
  through which the call was made.

**New Features**

* The C extension can be disabled at runtime by setting the environment
  variable ``WRAPT_DISABLE_EXTENSIONS``. This may be necessary where there
  is currently a difference in behaviour between pure Python implementation
  and C extension and the C extension isn't having the desired result.

Version 1.10.10
---------------

**Features Changed**

* Added back missing description and categorisations when releasing to PyPi.

Version 1.10.9
--------------

**Bugs Fixed**

* Code for ``inspect.getargspec()`` when using Python 2.6 was missing
  import of ``sys`` module.

Version 1.10.8
--------------

**Bugs Fixed**

* Ensure that ``inspect.getargspec()`` is only used with Python 2.6 where
  required, as function has been removed in Python 3.6.

Version 1.10.7
--------------

**Bugs Fixed**

* The mod operator '%' was being incorrectly proxied in Python variant of
  object proxy to the xor operator '^'.

Version 1.10.6
--------------

**Bugs Fixed**

* Registration of post import hook would fail with an exception if
  registered after another import hook for the same target module had been
  registered and the target module also imported.

**New Features**

* Support for testing with Travis CI added to repository.

Version 1.10.5
--------------

**Bugs Fixed**

* Post import hook discovery was not working correctly where multiple
  target modules were registered in the same entry point list. Only the
  callback for the last would be called regardless of the target module.

* If a ``WeakFunctionProxy`` wrapper was used around a method of a class
  which was decorated using a wrapt decorator, the decorator wasn't being
  invoked when the method was called via the weakref proxy.

**Features Changed**

* The ``register_post_import_hook()`` function, modelled after the
  function of the same name in PEP-369 has been extended to allow a string
  name to be supplied for the import hook. This needs to be of the form
  ``module::function`` and will result in an import hook proxy being used
  which will only load and call the function of the specified module when
  the import hook is required. This avoids needing to load the code needed
  to operate on the target module unless required.

Version 1.10.4
--------------

**Bugs Fixed**

* Fixup botched package version number from 1.10.3 release.

Version 1.10.3
--------------

**Bugs Fixed**

* Post import hook discovery from third party modules declared via
  ``setuptools`` entry points was failing due to typo in temporary variable
  name. Also added the ``discover_post_import_hooks()`` to the public API
  as was missing.

**Features Changed**

* To ensure parity between pure Python and C extension variants of the
  ``ObjectProxy`` class, allow the ``__wrapped__`` attribute to be set
  in a derived class when the ``ObjectProxy.__init__()`` method hasn't
  been called.

Version 1.10.2
--------------

**Bugs Fixed**

* When creating a derived ``ObjectProxy``, if the base class ``__init__()``
  method wasn't called and the ``__wrapped__`` attribute was accessed,
  in the pure Python implementation a recursive call of ``__getattr__()``
  would occur and the maximum stack depth would be reached and an exception
  raised.

* When creating a derived ``ObjectProxy``, if the base class ``__init__()``
  method wasn't called, in the C extension implementation, if that instance
  was then used in a binary arithmetic operation the process would crash.

Version 1.10.1
--------------

**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 occurring when the C extension component for the
  ``wrapt`` module was being used.

Version 1.10.0
--------------

**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.

Version 1.9.0
-------------

**Features Changed**

* When using ``wrapt.wrap_object()``, it is now possible to pass an
  arbitrary object in addition to a module object, or a string name
  identifying a module. Similar for underlying ``wrapt.resolve_path()``
  function.

**Bugs Fixed**

* It is necessary to proxy the special ``__weakref__`` attribute in the
  pure Python object proxy else using ``inspect.getmembers()`` on a
  decorator class will fail.

* The ``FunctionWrapper`` class was not passing through the instance
  correctly to the wrapper function when it was applied to a method of an
  existing instance of a class.

* The ``FunctionWrapper`` was not always working when applied around a
  method of a class type by accessing the method to be wrapped using
  ``getattr()``. Instead it is necessary to access the original unbound
  method from the class ``__dict__``. Updated the ``FunctionWrapper`` to
  work better in such situations, but also modify ``resolve_path()`` to
  always grab the class method from the class ``__dict__`` when wrapping
  methods using ``wrapt.wrap_object()`` so wrapping is more predictable.
  When doing monkey patching ``wrapt.wrap_object()`` should always be
  used to ensure correct operation.

* The ``AttributeWrapper`` class used internally to the function
  ``wrap_object_attribute()`` had wrongly named the ``__delete__`` method
  for the descriptor as ``__del__``.

Version 1.8.0
-------------

**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:
          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

Version 1.7.0
-------------

**New Features**

* Provide ``wrapt.getcallargs()`` for determining how arguments mapped to a
  wrapped function. For Python 2.7 this is actually ``inspect.getcallargs()``
  with a local copy being used in the case of Python 2.6.

* Added ``wrapt.wrap_object_attribute()`` as a way of wrapping or otherwise
  modifying the result of trying to access the attribute of an object
  instance. It works by adding a data descriptor with the same name as
  the attribute, to the class type, allowing reading of the attribute
  to be intercepted. It does not affect updates to or deletion of the
  attribute.

**Bugs Fixed**

* Need to explicitly proxy special methods ``__bytes__()``, ``__reversed__()``
  and ``__round__()`` as they are only looked up on the class type and not
  the instance, so can't rely on ``__getattr__()`` fallback.

* Raise more appropriate ``TypeError``, with corresponding message, rather
  than ``IndexError``, when a decorated instance or class method is called via
  the class but the required 1st argument of the instance or class is not
  supplied.

Version 1.6.0
-------------

**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 existence 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 existence 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.

Version 1.5.1
-------------

**Bugs Fixed**

* Instance method locking for the ``synchronized`` decorator was not correctly
  locking on the instance but the class, if a synchronized class method
  had been called prior to the synchronized instance method.

Version 1.5.0
-------------

**New Features**

* Enhanced ``@wrapt.transient_function_wrapper`` so it can be applied to
  instance methods and class methods with the ``self``/``cls`` argument being
  supplied correctly. This allows instance and class methods to be used for
  this type of decorator, with the instance or class type being able to
  be used to hold any state required for the decorator.

**Bugs Fixed**

* If the wrong details for a function to be patched was given to the
  decorator ``@wrapt.transient_function_wrapper``, the exception indicating
  this was being incorrectly swallowed up and mutating to a different
  more obscure error about local variable being access before being set.

Version 1.4.2
-------------

**Bugs Fixed**

* A process could crash if the C extension module was used and when using
  the ``ObjectProxy`` class a reference count cycle was created that required
  the Python garbage collector to kick in to break the cycle. This was
  occurring as the C extension had not implemented GC support in the
  ``ObjectProxy`` class correctly.

Version 1.4.1
-------------

**Bugs Fixed**

* Overriding ``__wrapped__`` attribute directly on any wrapper more than once
  could cause corruption of memory due to incorrect reference count
  decrement.

Version 1.4.0
-------------

**New Features**

* Enhanced ``@wrapt.decorator`` and ``@wrapt.function_wrapper`` so they can be
  applied to instance methods and class methods with the ``self``/``cls`` argument
  being supplied correctly. This allows instance and class methods to be
  used as decorators, with the instance or class type being able to be used
  to hold any state required for the decorator.

**Bugs Fixed**

* Fixed process crash in extension when the wrapped object passed as first
  argument to FunctionWrapper did not have a ``tp_descr_get`` callback for the
  type at C code level. Now raised an ``AttributeError`` exception in line with
  what Python implementation does.

Version 1.3.1
-------------

**Bugs Fixed**

* The ``discover_post_import_hooks()`` function had not been added to the
  top level wrapt module.

Version 1.3.0
-------------

**New Features**

* Added a ``@transient_function_wrapper`` decorator for applying a wrapper
  function around a target function only for the life of a single function
  call. The decorator is useful for performing mocking or pass through
  data validation/modification when doing unit testing of packages.

Version 1.2.1
-------------

**Bugs Fixed**

* In C implementation, not dealing with unbound method type creation
  properly which would cause later problems when calling instance method
  via the class type in certain circumstances. Introduced problem in 1.2.0.

* Eliminated compiler warnings due to missing casts in C implementation.

Version 1.2.0
-------------

**New Features**

* Added an ``enabled`` option to ``@decorator`` and ``FunctionWrapper`` which can
  be provided a boolean, or a function returning a boolean to allow the
  work of the decorator to be disabled dynamically. When a boolean, is
  used for ``@decorator``, the wrapper will not even be applied if ``enabled``
  is ``False``. If a function, then will be called prior to wrapper being
  called and if returns ``False``, then original wrapped function called
  directly rather than the wrapper being called.

* Added in an implementation of a post import hook mechanism in line with
  that described in PEP 369.

* Added in helper functions specifically designed to assist in performing
  monkey patching of existing code.

**Features Changed**

* Collapsed functionality of ``_BoundMethodWrapper`` into ``_BoundFunctionWrapper``
  and renamed the latter to ``BoundFunctionWrapper``. If deriving from the
  ``FunctionWrapper`` class and needing to override the type of the bound
  wrapper, the class attribute ``__bound_function_wrapper__`` should be set
  in the derived ``FunctionWrapper`` class to the replacement type.

**Bugs Fixed**

* When creating a custom proxy by deriving from ``ObjectProxy`` and the custom
  proxy needed to override ``__getattr__()``, it was not possible to called the
  base class ``ObjectProxy.__getattr__()`` when the C implementation of
  ObjectProxy was being used. The derived class ``__getattr__()`` could also
  get ignored.

* Using ``inspect.getargspec()`` now works correctly on bound methods when an
  adapter function can be provided to ``@decorator``.

Version 1.1.3
-------------

**New Features**

* Added a ``_self_parent`` attribute to ``FunctionWrapper`` and bound variants.
  For the ``FunctionWrapper`` the value will always be ``None``. In the case of the
  bound variants of the function wrapper, the attribute will refer back
  to the unbound ``FunctionWrapper`` instance. This can be used to get a back
  reference to the parent to access or cache data against the persistent
  function wrapper, the bound wrappers often being transient and only
  existing for the single call.

**Improvements**

* Use interned strings to optimise name comparisons in the setattro()
  method of the C implementation of the object proxy.

**Bugs Fixed**

* The pypy interpreter is missing ``operator.__index__()`` so proxying of that
  method in the object proxy would fail. This is a bug in pypy which is
  being addressed. Use ``operator.index()`` instead which pypy does provide
  and which also exists for CPython.

* The pure Python implementation allowed the ``__wrapped__`` attribute to be
  deleted which could cause problems. Now raise a TypeError exception.

* The C implementation of the object proxy would crash if an attempt was
  made to delete the ``__wrapped__`` attribute from the object proxy. Now raise a
  TypeError exception.

Version 1.1.2
-------------

**Improvements**

* Reduced performance overhead from previous versions. Most notable in the
  C implementation. Benchmark figures have been updated in documentation.

Version 1.1.1
-------------

**Bugs Fixed**

* Python object memory leak was occurring due to incorrect increment of
  object reference count in C implementation of object proxy when an
  instance method was called via the class and the instance passed in
  explicitly.

* In place operators in pure Python object proxy for ``__idiv__`` and
  ``__itruediv__`` were not replacing the wrapped object with the result
  of the operation on the wrapped object.

* In place operators in C implementation of Python object proxy were
  not replacing the wrapped object with the result of the operation on the
  wrapped object.

Version 1.1.0
-------------

**New Features**

* Added a synchronized decorator for performing thread mutex locking on
  functions, object instances or classes. This is the same decorator as
  covered as an example in the wrapt documentation.

* Added a ``WeakFunctionProxy`` class which can wrap references to instance
  methods as well as normal functions.

* Exposed from the C extension the classes ``_FunctionWrapperBase``,
  ``_BoundFunctionWrapper`` and ``_BoundMethodWrapper`` so that it is possible to
  create new variants of ``FunctionWrapper`` in pure Python code.

**Bugs Fixed**

* When deriving from ``ObjectProxy``, and the C extension variant
  was being used, if a derived class overrode ``__new__()`` and tried to access
  attributes of the ObjectProxy created using the base class ``__new__()``
  before ``__init__()`` was called, then an exception would be raised
  indicating that the 'wrapper has not been initialised'.

* When deriving from ``ObjectProxy``, and the C extension variant
  was being used, if a derived class ``__init__()`` attempted to update
  attributes, even the special ``_self_`` attributed before calling the base
  class ``__init__()`` method, then an exception would be raised indicating
  that the 'wrapper has not been initialised'.

Version 1.0.0
-------------

Initial release.
