summaryrefslogtreecommitdiff
path: root/logilab/common/deprecation.py
diff options
context:
space:
mode:
Diffstat (limited to 'logilab/common/deprecation.py')
-rw-r--r--logilab/common/deprecation.py50
1 files changed, 44 insertions, 6 deletions
diff --git a/logilab/common/deprecation.py b/logilab/common/deprecation.py
index 5dc23f7..ff6dc7c 100644
--- a/logilab/common/deprecation.py
+++ b/logilab/common/deprecation.py
@@ -22,7 +22,45 @@ __docformat__ = "restructuredtext en"
import os
import sys
from warnings import warn
-from functools import wraps
+from functools import WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES, wraps
+
+
+def lazy_wraps(wrapped):
+ """
+ This is the equivalent of the @wraps decorator of functools except it won't
+ try to grabs attributes of the targeted function on decoration but on access.
+
+ This is needed because of logilab.common.modutils.LazyObject.
+
+ Indeed: if you try to decorate a LazyObject with @wraps, wraps will try to
+ access attributes of LazyObject and this will trigger the attempt to import
+ the module decorated by LazyObject which you don't want to do when you just
+ want to mark this LazyObject has been a deprecated objet that you only
+ wants to trigger if the user try to use it.
+
+ Usage: like @wraps()
+
+ >>> @lazy_wraps(function)
+ >>> def wrapper(*args, **kwargs): ...
+ """
+
+ def update_wrapper_attributes(wrapper):
+ def __getattribute__(self, attribute):
+ if attribute in WRAPPER_ASSIGNMENTS:
+ return getattr(wrapped, attribute)
+
+ return super(self.__class__, self).__getattribute__(attribute)
+
+ wrapper.__getattribute__ = __getattribute__
+
+ for attribute in WRAPPER_UPDATES:
+ getattr(wrapper, attribute).update(getattr(wrapped, attribute, {}))
+
+ wrapper.__wrapped__ = wrapped
+
+ return wrapper
+
+ return update_wrapper_attributes
class DeprecationWrapper(object):
@@ -160,12 +198,12 @@ def callable_deprecated(reason=None, version=None, stacklevel=2):
"""
def decorator(func):
- message = reason or 'The function "%s" is deprecated'
- if "%s" in message:
- message %= func.__name__
-
- @wraps(func)
+ @lazy_wraps(func)
def wrapped(*args, **kwargs):
+ message = reason or 'The function "%s" is deprecated'
+ if "%s" in message:
+ message %= func.__name__
+
send_warning(message, version, stacklevel + 1, module_name=func.__module__)
return func(*args, **kwargs)