pytilities.delegation.decorators

Package pytilities :: Package delegation :: Module decorators |
[hide private]
[frames] | no frames]

# Source Code for Module pytilities.delegation.decorators

      1  # Copyright (C) 2010 Tim Diels <limyreth@users.sourceforge.net>
      2  #
      3  # This file is part of pytilities.
      4  #
      5  # pytilities is free software: you can redistribute it and/or modify
      6  # it under the terms of the GNU General Public License as published by
      7  # the Free Software Foundation, either version 3 of the License, or
      8  # (at your option) any later version.
      9  #
     10  # pytilities is distributed in the hope that it will be useful,
     11  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  # GNU General Public License for more details.
     14  #
     15  # You should have received a copy of the GNU General Public License
     16  # along with pytilities.  If not, see <http://www.gnu.org/licenses/>.
     17  #
     18
     19  """
     20  Various decorators to ease delegation
     21  """
     22
     23  __docformat__ = 'reStructuredText'
     24
     25  from types import UnboundMethodType
     26  import logging
     27
     28  from . import Profile, DelegatorFactory
     29
     30  # logging stuff
     31  _logger = logging.getLogger("pytilities.delegation")
     32
     33  # Note: we don't care about mangling here, there's no need to. You won't be
     34  # delegating any private vars anyway, or at least you shouldn't.
     35
     36 -def delegator_factory():
     37      """
     38      Makes a `DelegatorFactory` on the class and adds profiles to it.
     39
     40      The factory is stored as a class attribute with name _delegator_factory.
     41      A Delegator method is installed on the class, it is the same as
     42      _delegator_factory.Delegator.
     43
     44      `Profile`s are created based on the annotations left by `delegated`.
     45      """
     46
     47      def _delegator_factory(cls):
     48          # iterate through attributes and generate profiles
     49          # {name: Profile}
     50          profiles = {"default": Profile()}  # there's always a default
     51          for name in cls.__dict__:
     52              attribute = getattr(cls, name)
     53
     54              _logger.debug(name)
     55              if isinstance(attribute, property):
     56                  _logger.debug("prop")
     57                  data_holder = attribute.fget
     58              elif isinstance(attribute, UnboundMethodType):
     59                  _logger.debug("unbound method!")
     60                  data_holder = attribute.im_func
     61              else:
     62                  _logger.debug("I have no clue what this is")
     63                  data_holder = attribute
     64
     65              if hasattr(data_holder, "__pytilities_delegation_profiles"):
     66                  _logger.debug("is delegated!")
     67                  profile_data = data_holder.__pytilities_delegation_profiles
     68                  for profile_name, modifiers in profile_data.iteritems():
     69                      profiles.setdefault(profile_name, Profile())
     70                      profiles[profile_name].add_mappings(modifiers, name)
     71
     72                  del data_holder.__pytilities_delegation_profiles
     73
     74          # make factory with profiles
     75          factory = DelegatorFactory()
     76
     77          for name, profile in profiles.iteritems():
     78              factory.set_profile(name, profile)
     79
     80          # install stuff on cls
     81          setattr(cls, "_delegator_factory", factory)
     82          cls.Delegator = factory.Delegator
     83
     84          return cls
     85
     86      return _delegator_factory
     87
     88 -def delegated(profile_name="default", modifiers="rwd"):
     89      """
     90      Includes the decorated attribute in the specified delegation profile.
     91
     92      Parameters:
     93
     94          `profile_name` :: string
     95              name of the `Profile` to add the attribute to
     96
     97          `modifiers` :: string
     98              the types of access to delegate to the target. Possible modifiers
     99              are combinations of:
    100
    101                  - `r`: read
    102                  - `w`: write
    103                  - `d`: delete
    104      """
    105
    106      def _delegate(attribute):
    107          _logger.debug("%s += %s" % (profile_name, attribute))
    108          if not hasattr(attribute, "__pytilities_delegator_profiles"):
    109              if isinstance(attribute, property):
    110                  # stick data on the getter function, can't set attribs on
    111                  # properties
    112                  data_holder = attribute.fget
    113              else:
    114                  data_holder = attribute
    115
    116              data_holder.__pytilities_delegation_profiles = {}
    117
    118          data_holder.__pytilities_delegation_profiles[profile_name] = modifiers
    119
    120          return attribute
    121
    122      return _delegate
    123