[BangPypers] Adding mixing at run-time

kracekumar ramaraju kracethekingmaker at gmail.com
Thu Oct 9 08:00:37 CEST 2014


On Wed, Oct 8, 2014 at 4:19 PM, Anand Chitipothu <anandology at 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 at 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>*


More information about the BangPypers mailing list