see whatever…

jump to menu

October 14, 2007

Deprecation decorator

Filed under: CSS,cssutils,Python — see @ 12:55 pm

I was looking for a simple way to “deprecate” methods (in cssutils). For now I use warnings directly but thought a decorator would be easier and clearer (I never really used decorators yet). A bit of googling gave two different options, a simple decorator function which is part of the DecoratorLibrary which is sufficient for most tasks I guess. But I was looking for a deprecation decorator which can handle an individual message which contains information about how to avoid the deprecated method. I found this parameterized decorator example and customized it for my needs:

class Deprecated(object):
    """This is a decorator which can be used to mark functions
    as deprecated. It will result in a warning being emitted
    when the function is used.

    It accepts a single paramter ``msg`` which is shown with the warning.
    It should contain information which function or method to use instead.
    """
    def __init__(self, msg):
        self.msg = msg

    def __call__(self, func):
        def newFunc(*args, **kwargs):
            import warnings
            warnings.warn("Call to deprecated method %r. %s" %
                            (func.__name__, self.msg),
                            category=DeprecationWarning,
                            stacklevel=2)
            return func(*args, **kwargs)
        newFunc.__name__ = func.__name__
        newFunc.__doc__ = func.__doc__
        newFunc.__dict__.update(func.__dict__)
        return newFunc

So it is actually a mixture of both decorator options. A simple class using the decorator may be:

class Calc(object):
    """a simple test calculator

    >>> c = Calc()
    >>> c.add(1, 2)
    3
    >>> c.plus(1, 2) # BTW, is it possible to catch warnings with doctest?
    3
    """

    def add(self, x, y):
        "adds x and y"
        return x+y

    @Deprecated('Use Calc.add() instead.')
    def plus(self, x, y):
        "adds x and y"
        return self.add(x,y)

When used gives the following output

c = Calc()
print c.plus(1,2)
calc.py:75: DeprecationWarning: Call to deprecated method
 'plus'. Use Calc.add() instead.
  print c.plus(1,2)
3

I think this is quite useful and I guess I’ll use this in cssutils. There certainly is something similar out there but it was quite interesting to look a bit into decorators at all.

UPDATE: Please see the comment by Matt (decorator module).

2 Comments »

  1. Very nice, but I’ve got one tiny objection. This decorator changes the signature of the decorated function. You might consider using the decorator module to avoid that. Then you could do something like:


    import warnings
    from decorator import decorator
    def deprecated(msg):
    def _d(f, *args, **kwargs):
    warnings.warn(msg)
    return f(*args, **kwargs)
    return decorator(_d)

    Comment by Matt Wilson — January 20, 2009 @ 9:25 pm

  2. @Matt: True, thanks for the hint.

    In this case not that important I guess as the functions decorated actually should not be used as they are deprecated and so the signature and the whole function will completely “change” (meaning: will be removed in the future) anyway ;)

    Also I did not wanted to add another dependency.

    But generally the decorator module surely is very helpful.

    Comment by admin — February 11, 2009 @ 12:12 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress