I think this is a very nice approach. I disagree that that you could decorate a class as @Place.mixin by mistake, In fact i think the decorator actually makes it absolutely clear its purpose. However, the Place.mixin should return the mixin class.
@classmethod def mixin(cls, mixin): """Decorator to add a mixin to the class runtime. """ cls.__bases__ = cls.__bases__ + (mixin,) return mixin This: 1. Allows the class to be mixed-in into other classes if there's need for it 2. Class decorators should return classes, else LinksMixin evaluates to None On 9 October 2014 11:30, kracekumar ramaraju <kracethekingma...@gmail.com> wrote: > On Wed, Oct 8, 2014 at 4:19 PM, Anand Chitipothu <anandol...@gmail.com> > wrote: > > > Hi, > > > > I'm working on a slightly large application and I'm trying to model it > as a > > some kind of plugin architecture so that it modular and I can enable or > > take out features without lot of code changes. > > > > One of the issues I faced was that the wanted to add some methods to a > > class only when a feature/plugin is enabled. > > > > Here is a simplified version of what I have: > > > > class Place(Mixable): > > def __init__(self, name): > > self.name = name > > > > def get_users(self): > > return "users-of-{}".format(self.name) > > > > def get_links(self): > > return "links-of-{}".format(self.name) > > > > There are couple of issues with this. > > > > 1. The logic for computing users or links doesn't really belong to this > > file. I wanted to that in a separate module for modularity. > > > > 2. The Place class will become too large to manage over time. > > > > So, I came up with the following approach to address these issues. > > > > # place.py > > > > class Mixable(object): > > """Magic class to allow adding mixins to the class at run-time. > > """ > > @classmethod > > def mixin(cls, mixin): > > """Decorator to add a mixin to the class runtime. > > """ > > cls.__bases__ = cls.__bases__ + (mixin,) > > > > class Place(Mixable): > > def __init__(self, name): > > self.name = name > > > > # users.py > > @Place.mixin > > class UsersMixin(object): > > def get_users(self): > > return "users-of-{}".format(self.name) > > > > > Is there any specific reason for using decorators ? > > > > > # links.py > > @Place.mixin > > class LinksMixin(object): > > def get_links(self): > > return "links-of-{}".format(self.name) > > > > p = Place('bangalore') > > print(p.get_users()) > > print(p.get_links()) > > > > > > I somehow feel this can lead to unexpected behaviour since Mixable classes > are added at various files. > This pattern looks like global variable argument (global variables are > bad). Say if Idecorate Foo with @Place.mixin by mistake, behaviour of the > Foo will be available in Place class and leads to side effect. > > How about > > #dispatcher.py > # import all the classes > > def get_place_class(): > # Check for features > for cls in classes: > Place.__bases__ = Place.__bases__ + (cls,) > return Place > > > > > With this I was able to split the class into 3 files and now I have > > flexibility of deciding which features enable from a config file. > > > > What do you guys think of this approach? > > > > My only concern base classes are added in different files and difficult to > remember. > > Is this a good practice? > > Are there any know flaws in this approach? > > How did you solve that issue when you faced similar situation? > > > > > Did I understand the problem correctly ? > > > > Anand > > _______________________________________________ > > BangPypers mailing list > > BangPypers@python.org > > https://mail.python.org/mailman/listinfo/bangpypers > > > > > > -- > > *Thanks & Regardskracekumar"Talk is cheap, show me the code" -- Linus > Torvaldshttp://kracekumar.com <http://kracekumar.com>* > _______________________________________________ > BangPypers mailing list > BangPypers@python.org > https://mail.python.org/mailman/listinfo/bangpypers > _______________________________________________ BangPypers mailing list BangPypers@python.org https://mail.python.org/mailman/listinfo/bangpypers