Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #109748 > unrolled thread

Re: UserList - which methods needs to be overriden?

Started byNagy László Zsolt <gandalf@shopzeus.com>
First post2016-06-09 15:55 +0200
Last post2016-06-09 15:55 +0200
Articles 1 — 1 participant

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: UserList - which methods needs to be overriden? Nagy László Zsolt <gandalf@shopzeus.com> - 2016-06-09 15:55 +0200

#109748 — Re: UserList - which methods needs to be overriden?

FromNagy László Zsolt <gandalf@shopzeus.com>
Date2016-06-09 15:55 +0200
SubjectRe: UserList - which methods needs to be overriden?
Message-ID<mailman.115.1465480515.2306.python-list@python.org>
> @wrap_notify('remove', 'clear', 'append', 'insert', 'sort'):
> class ObservableList(ObservableCollection, list):
>     pass
>
> I just can't find out the right syntax.
>
>
All right, this is working.

from contextlib import contextmanager

class ObservableCollection:
    @contextmanager
    def notify(cls):
        print("notify before change")
        yield
        print("notify after change")


def wrap_notify(cls, basecls, method_names):
    for method_name in method_names:
        orig = getattr(basecls, method_name)
        def modified(self, *args, **kwargs):
            with self.notify(): return orig(self,*args,**kwargs)
        setattr(cls, method_name, modified)
    return cls




class ObservableDict(ObservableCollection, dict):
    __slots__ = []
wrap_notify(ObservableDict, dict, ['update', '__delitem__',
'__setitem__']) # many others...

class ObservableList(ObservableCollection, list):
    __slots__ = []
wrap_notify(ObservableList, list, ['append', 'pop']) # many others...


d =  ObservableDict()
d[1] = 2
print(d)


But I'm still not 100% satisfied. wrap_notify is not a class decorator.
Is there a way to make a class decorator that gets the class as its
first parameter? It would be very nice:

def wrap_notify(cls, method_names):
    class Wrapped(cls):
        pass
    for method_name in method_names:
        orig = getattr(Wrapped, method_name)
        def modified(self, *args, **kwargs):
            with self.notify(): return orig(self,*args,**kwargs)
        setattr(cls, method_name, modified)
    return Wrapped


@wrap_notify(['update', '__delitem__', '__setitem__']) # many others...
class ObservableDict(ObservableCollection, dict):
    __slots__ = []

@wrap_notify(['append', 'pop']) # many others...
class ObservableList(ObservableCollection, list):
    __slots__ = []

And finally: is this Pythonic, or a horrible mess? Would it be better to
duplicate the body of each method one by one?

[toc] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web