# deprecation.py - Module providing classes and functions for deprecation. # # Copyright (c) 2009 Julian Andres Klode # Copyright (c) 2009 Ben Finney # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA """Classes and functions for deprecating features. This is used for internal purposes only and not part of the official API. Do not use it for anything outside the apt package. """ import re import operator import warnings import apt_pkg __all__ = [] class AttributeDeprecatedBy(object): """Property acting as a proxy for a new attribute. When accessed, the property issues a DeprecationWarning and (on get) calls attrgetter() for the attribute 'attribute' on the current object or (on set) uses setattr to set the value of the wrapped attribute. """ def __init__(self, attribute): """Initialize the property.""" self.attribute = attribute self.__doc__ = 'Deprecated, please use \'%s\' instead' % attribute self.getter = operator.attrgetter(attribute) def __get__(self, obj, type_=None): """Issue a DeprecationWarning and return the requested value.""" if obj is None: return getattr(type_, self.attribute, self) warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2) return self.getter(obj or type_) def __set__(self, obj, value): """Issue a DeprecationWarning and set the requested value.""" warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2) setattr(obj, self.attribute, value) def function_deprecated_by(func, convert_names=True): """Return a function that warns it is deprecated by another function. Returns a new function that warns it is deprecated by function 'func', then acts as a pass-through wrapper for 'func'. This function also converts all keyword argument names from mixedCase to lowercase_with_underscores, but only if 'convert_names' is True (default). """ warning = 'Deprecated, please use \'%s()\' instead' % func.__name__ def deprecated_function(*args, **kwds): """Wrapper around a deprecated function.""" warnings.warn(warning, DeprecationWarning, stacklevel=2) if convert_names: for key in kwds.keys(): kwds[re.sub('([A-Z])', '_\\1', key).lower()] = kwds.pop(key) return func(*args, **kwds) return deprecated_function def deprecated_args(func): """A function with deprecated arguments. Similar to function_deprecated_by() but warns on every deprecated argument instead of function calls. """ if not apt_pkg._COMPAT_0_7: return func def deprecated_function(*args, **kwds): """Wrapper around a function with deprecated arguments.""" for key in kwds.keys(): new_key = re.sub('([A-Z])', '_\\1', key).lower() if new_key != key: warnings.warn("Deprecated parameter %r" % key) kwds[new_key] = kwds.pop(key) return func(*args, **kwds) # Wrap the function completely (same as functools.wraps) # pylint: disable-msg=W0622 deprecated_function.__name__ = func.__name__ deprecated_function.__doc__ = func.__doc__ deprecated_function.__module__ = func.__module__ deprecated_function.__dict__.update(func.__dict__) return deprecated_function