Skip to main content

Delegate methods and properties to child objects in a terse, explicit style

Project description

superdelegate

Delegate methods and properties to child objects in a terse, explicit style

Consider the motivating example of a sorted list. In order to encapsulate the list and prevent clients from breaking the sorted order, we want to only allow certain methods through to the underlying list:

import bisect

class SortedList:
    def __init__(self, *args, **kwargs):
        self._lst = list(*args, **kwargs)

    def insert(self, elem):
        bisect.insort(self._lst, elem)

    def __contains__(self, elem):
        ix = bisect.bisect(self._lst, elem)
        return ix != len(self._lst) and self._lst[ix] == elem

    def __getitem__(self, key):
        return self._lst.__getitem__(key)

    def __reversed__(self):
        return self._lst.__reversed__()

    def __len__(self):
        return self._lst.__len__()

    def __iter__(self):
        return self._lst.__iter__()

Much of that code is pretty repetitive. Can we do better? Yes! with superdelegate!

import bisect
from superdelegate import SuperDelegate, delegate_to

class SortedList(SuperDelegate):
    def __init__(self, *args, **kwargs):
        self._lst = list(*args, **kwargs)

    def insert(self, elem):
        bisect.insort(self._lst, elem)

    def __contains__(self, elem):
        ix = bisect.bisect(self._lst, elem)
        return ix != len(self._lst) and self._lst[ix] == elem

    __getitem__ = __reversed__ = __len__ = __iter__ = delegate_to('_lst')

FAQs

Does it work for properties? It does work for properties!

class OnlyGrowsOlder:
    def __init__(self):
        self._age

    @property
    def age(self):
        return self._age
    @age.setter
    def age(self, new_age):
        if new_age > self._age:
            self._age = new_age
        else:
            raise ValueError('Time is like a boy band. It only flows in one direction')

class OlderWrapper(SuperDelegate):
    def __init__(self):
        self._ager

    age = delegate_to('_ager')

Can you have multiple delgatees? You can!

    class SandwichMaker:
        def choose_cheese(self):
            return 'swiss'
    class NavyEngineer:
        def lift_periscope(self):
            return 'done'
    class SubmarineTechnician(SuperDelegate):
        def __init__(self):
            self.sm = SandwichMaker()
            self.ne = NavyEngineer()

        choose_cheese = delegate_to('sm')
        lift_periscope = delegate_to('ne')

Inspiration

This library was inspired by Ruby ActiveSupport's Module#delegate extension.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

superdelegate-0.0.2.tar.gz (4.4 kB view hashes)

Uploaded Source

Built Distribution

superdelegate-0.0.2-py3-none-any.whl (4.9 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page