Python Snippets



Idioms


 Aliasing Class Methods

Allows you to add aliases to methods in a class.

Aliasing Decorators
class alias(object):
    """
    Alias class that can be used as a decorator for making methods callable
    through other names (or "aliases").
    Note: This decorator must be used inside an @aliased -decorated class.
    For example, if you want to make the method shout() be also callable as
    yell() and scream(), you can use alias like this:

        @alias('yell', 'scream')
        def shout(message):
            # ....
    """

    def __init__(self, *aliases):
        """Constructor."""
        self.aliases = set(aliases)

    def __call__(self, f):
        """
        Method call wrapper. As this decorator has arguments, this method will
        only be called once as a part of the decoration process, receiving only
        one argument: the decorated function ('f'). As a result of this kind of
        decorator, this method must return the callable that will wrap the
        decorated function.
        """
        f._aliases = self.aliases
        return f


def aliased(aliased_class):
    """
    Decorator function that *must* be used in combination with @alias
    decorator. This class will make the magic happen!
    @aliased classes will have their aliased method (via @alias) actually
    aliased.
    This method simply iterates over the member attributes of 'aliased_class'
    seeking for those which have an '_aliases' attribute and then defines new
    members in the class using those aliases as mere pointer functions to the
    original ones.

    Usage:
        @aliased
        class MyClass(object):
            @alias('coolMethod', 'myKinkyMethod')
            def boring_method():
                # ...

        i = MyClass()
        i.coolMethod() # equivalent to i.myKinkyMethod() and i.boring_method()
    """
    original_methods = aliased_class.__dict__.copy()
    for name, method in original_methods.iteritems():
        if hasattr(method, '_aliases'):
            # Add the aliases for 'method', but don't override any
            # previously-defined attribute of 'aliased_class'
            for alias in method._aliases - set(original_methods):
                setattr(aliased_class, alias, method)
    return aliased_class


#
# A very simple example
#

@aliased
class Vehicle(object):
    def __init__(self, brand, model, color):
        """Constructor."""
        self.brand = brand
        self.model = model
        self.color = color

    @alias('modelBrandAndColor', 'getModelBrandAndColour', 'getDescription')
    def model_brand_and_color(self):
        """Get the model and brand of this Vehicle."""
        return '{0} {1} {2}'.format(self.color, self.brand, self.model)

vehicle = Vehicle('Chevrolet', 'Spark', 'black')
# Now your API looks like your users would want.
# Any of the following lines is equivalent to the others:
print vehicle.model_brand_and_color()
print vehicle.getDescription()
print vehicle.modelBrandAndColor()
print vehicle.getModelBrandAndColour()
 Borg Idiom

A variant of the singleton pattern allowing instantiations that reference a single shared storage. Various construction methods are in this blog post. Some more interesting ideas are below:

Borg Class Decorator
def borg(cls):
    cls._state = {}
    orig_init = cls.__init__
    def new_init(self, *args, **kwargs):
        self.__dict__ = cls._state
        orig_init(self, *args, **kwargs)
    cls.__init__ = new_init
    return cls

# Allows you to write this:
@borg
class Foo(object):
    def say_hello(self):
        print "hello, I'm a borg"


Borg Idiom - A Blackboard of Blackboards
class Blackboard(defaultdict):
    """A dict that defaults values to None.
    Blackboards are registered by name. All blackboards with the same
    name have the same contents.
    """
    _name_dict = defaultdict(dict)  # For a twist on the Borg idiom

    def __init__(self, name, **kwargs):
        self.__dict__ = Blackboard._name_dict[name]
        default = lambda: None
        super(Blackboard, self).__init__(default, **kwargs)
 Class Registry

Introspect on a base class to see what classes have inherited from it

Colour Class Registry
class RegisterLeafClasses(type):
    def __init__(cls, name, bases, nmspc):
        super(RegisterLeafClasses, cls).__init__(name, bases, nmspc)
        if not hasattr(cls, 'registry'):
            cls.registry = set()
        cls.registry.add(cls)
        cls.registry -= set(bases) # Remove base classes
    # Metamethods, called on class objects:
    def __iter__(cls):
        return iter(cls.registry)
    def __str__(cls):
        if cls in cls.registry:
            return cls.__name__
        return cls.__name__ + ": " + ", ".join([sc.__name__ for sc in cls])

class Color(object):
    __metaclass__ = RegisterLeafClasses

class Blue(Color): pass
class Red(Color): pass
class Green(Color): pass
class Yellow(Color): pass
print(Color)
class PhthaloBlue(Blue): pass
class CeruleanBlue(Blue): pass
print(Color)
for c in Color: # Iterate over subclasses
    print(c)

class Shape(object):
    __metaclass__ = RegisterLeafClasses

class Round(Shape): pass
class Square(Shape): pass
class Triangular(Shape): pass
class Boxy(Shape): pass
print(Shape)
class Circle(Round): pass
class Ellipse(Round): pass
print(Shape)

""" Output:
Color: Red, Blue, Green, Yellow
Color: Red, CeruleanBlue, Green, PhthaloBlue, Yellow
Red
CeruleanBlue
Green
PhthaloBlue
Yellow
Shape: Square, Round, Boxy, Triangular
Shape: Square, Ellipse, Circle, Boxy, Triangular
"""
 Tarballs - Strip Prefix and Extract


Aliasing Decorators
import tarfile

def strip_leading_drake_prefix(tarball):
    prefix = "drake/"
    offset = len(prefix)
    for tarinfo in tarball.getmembers():
        if tarinfo.name.startswith(prefix):
            tarinfo.name = tarinfo.name[offset:]
            yield tarinfo

tarball = tarfile.open("/tmp/drake.tar.gz")
tarball.extractall("/opt/drake", strip_leading_drake_prefix(tarball))