Blog entries by Stéphanie Marcu [1]

logilab-common library contains a lot of utilities which are often unknown. I will write a series of blog entries to explore nice features of this library.

We will begin with the logilab.common.deprecation module which contains utilities to warn users when:

  • a function or a method is deprecated
  • a class has been moved into another module
  • a class has been renamed
  • a callable has been moved to a new module

deprecated

When a function or a method is deprecated, you can use the deprecated decorator. It will print a message to warn the user that the function is deprecated.

The decorator takes two optional arguments:

  • reason: the deprecation message. A good practice is to specify at the beginning of the message, between brackets, the version number from which the function is deprecated. The default message is 'The function "[function name]" is deprecated'.
  • stacklevel: This is the option of the warnings.warn function which is used by the decorator. The default value is 2.

We have a class Person defined in a file person.py. The get_surname method is deprecated, we must use the get_lastname method instead. For that, we use the deprecated decorator on the get_surname method.

from logilab.common.deprecation import deprecated

class Person(object):

    def __init__(self, firstname, lastname):
        self._firstname = firstname
        self._lastname = lastname

    def get_firstname(self):
        return self._firstname

    def get_lastname(self):
        return self._lastname

    @deprecated('[1.2] use get_lastname instead')
    def get_surname(self):
        return self.get_lastname()

def create_user(firstname, lastname):
    return Person(firstname, lastname)

if __name__ == '__main__':
    person = create_user('Paul', 'Smith')
    surname = person.get_surname()

When running person.py we have the message below:

person.py:22: DeprecationWarning: [1.2] use get_lastname instead
surname = person.get_surname()

class_moved

Now we moved the class Person in a new_person.py file. We notice in the person.py file that the class has been moved:

from logilab.common.deprecation import class_moved
import new_person
Person = class_moved(new_person.Person)

if __name__ == '__main__':
    person = Person('Paul', 'Smith')

When we run the person.py file, we have the following message:

person.py:6: DeprecationWarning: class Person is now available as new_person.Person
person = Person('Paul', 'Smith')

The class_moved function takes one mandatory argument and two optional:

  • new_class: this mandatory argument is the new class
  • old_name: this optional argument specify the old class name. By default it is the same name than the new class. This argument is used in the default printed message.
  • message: with this optional argument, you can specify a custom message

class_renamed

The class_renamed function automatically creates a class which fires a DeprecationWarning when instantiated.

The function takes two mandatory arguments and one optional:

  • old_name: a string which contains the old class name
  • new_class: the new class
  • message: an optional message. The default one is '[old class name] is deprecated, use [new class name]'

We now rename the Person class into User class in the new_person.py file. Here is the new person.py file:

from logilab.common.deprecation import class_renamed
from new_person import User

Person = class_renamed('Person', User)

if __name__ == '__main__':
    person = Person('Paul', 'Smith')

When running person.py, we have the following message:

person.py:5: DeprecationWarning: Person is deprecated, use User
person = Person('Paul', 'Smith')

moved

The moved function is used to tell that a callable has been moved to a new module. It returns a callable wrapper, so that when the wrapper is called, a warning is printed telling where the object can be found. Then the import is done (and not before) and the actual object is called.

Note

The usage is somewhat limited on classes since it will fail if the wrapper is used in a class ancestors list: use the class_moved function instead (which has no lazy import feature though).

The moved function takes two mandatory parameters:

  • modpath: a string representing the path to the new module
  • objname: the name of the new callable

We will use in person.py, the create_user function which is now defined in the new_person.py file:

from logilab.common.deprecation import moved

create_user = moved('new_person', 'create_user')

if __name__ == '__main__':
    person = create_user('Paul', 'Smith')

When running person.py, we have the following message:

person.py:4: DeprecationWarning: object create_user has been moved to module new_person
person = create_user('Paul', 'Smith')

blog entry of

Logilab.org - en