def attrgetter(attr, key=None):
    """
    Looks up ``attr`` on the target value. If the result is a callable, it will be called in place
    without arguments.

    If a ``key`` is given, it may be a function which maps the target value to something else
    before the attribute lookup takes place.

    Examples::

        # Explicitly selecting the sources and then using a processor to allow the model
        # method to organize the data itself, you can still provide all the necessary
        # ORM hints to the column.
        # This is definitely superior to having sources=['get_address'].
        address = columns.TextColumn("Address", sources=['street', 'city', 'state', 'zip'],
                                     processor=attrgetter('get_address'))

    """
    def helper(instance, *args, **kwargs):
        value = instance
        for bit in attr.split('.'):
            value = getattr(value, bit)
            if callable(value):
                value = value()
        return value

    if key:
        helper = keyed_helper(helper)(key=key)
    return helper
Looks up ``attr`` on the target value. If the result is a callable, it will be called in place
    without arguments.

    If a ``key`` is given, it may be a function which maps the target value to something else
    before the attribute lookup takes place.

    Examples::

        # Explicitly selecting the sources and then using a processor to allow the model
        # method to organize the data itself, you can still provide all the necessary
        # ORM hints to the column.
        # This is definitely superior to having sources=['get_address'].
        address = columns.TextColumn("Address", sources=['street', 'city', 'state', 'zip'],
                                     processor=attrgetter('get_address'))