Exemplo n.º 1
0
    def __init__(cls, name, bases, _dict):
        """class constructor"""
        type.__init__(cls, name, bases, _dict)
       
        # the set of all obs (it is calculated and stored below)
        obs = set()

        # processes now all names in __observables__ 
        conc_props, log_props = type(cls).__get_observables_sets__(cls)

        # processes all concrete properties
        for prop in conc_props:
            val = _dict[prop] # must exist if concrete
            type(cls).__create_conc_prop_accessors__(cls, prop, val)
            obs.add(prop)
            pass

        # processes all logical properties, and adds the actual log
        # properties to the list of all observables
        _getdict = getattr(cls, LOGICAL_GETTERS_MAP_NAME, dict())
        _setdict = getattr(cls, LOGICAL_SETTERS_MAP_NAME, dict())

        real_log_props = type(cls).__create_log_props(cls, log_props, 
                                                      _getdict, _setdict)
        obs |= real_log_props

        # after using the maps, it is time to clear them to make
        # them available to the next class in the mro.
        _getdict.clear()
        _setdict.clear()

        # processes all names in __properties__ (deprecated,
        # overloaded by __observables__)
        props = getattr(cls, PROPS_MAP_NAME, {})      
        if len(props) > 0: 
            import warnings
            warnings.warn("In class %s.%s the use of attribute '%s' in "
                          "models is deprecated."
                          " Use the tuple '%s' instead (see the manual)" \
                              % (cls.__module__, cls.__name__,  
                                 PROPS_MAP_NAME, OBS_TUPLE_NAME), 
                          DeprecationWarning)
            pass
        for prop in (x for x in props.iterkeys() if x not in obs):
            type(cls).__create_conc_prop_accessors__(cls, prop, props[prop])
            obs.add(prop)
            pass

        # generates the list of _all_ properties available for this
        # class (also from bases)
        for base in bases: obs |= getattr(base, ALL_OBS_SET, set())
        setattr(cls, ALL_OBS_SET, frozenset(obs))
        logger.debug("class %s.%s has observables: %s" \
                         % (cls.__module__, cls.__name__, obs))
        return
Exemplo n.º 2
0
    def __init__(cls, name, bases, _dict):
        """class constructor"""
        properties = {}
        type.__init__(cls, name, bases, _dict)

        # the set of all obs (it is calculated and stored below)
        obs = set()

        # processes now all names in __observables__
        for prop in type(cls).__get_observables_array__(cls):
            val = _dict.get(prop, None)
            if val is not None:
                type(cls).__create_prop_accessors__(cls, prop, val)
            # a getter/setter pair or an observable attribute:
            elif not hasattr(cls, prop) or type(getattr(cls, prop)) != property:
                type(cls).__create_prop_accessors__(cls, prop, val)
                pass
            obs.add(prop)
            pass

        # Generates code for all properties (but not for derived props):
        props = getattr(cls, PROPS_MAP_NAME, {})
        if len(props) > 0:
            warnings.warn(
                "In class %s.%s the use of attribute '%s' in models is deprecated."
                " Use the tuple '%s' instead (see the manual)"
                % (cls.__module__, cls.__name__, PROPS_MAP_NAME, OBS_TUPLE_NAME),
                DeprecationWarning,
            )

        # processes all names in __properties__ (deprecated,
        # overloaded by __observables__)
        for prop in (x for x in props.iterkeys() if x not in obs):
            type(cls).__create_prop_accessors__(cls, prop, props[prop])
            obs.add(prop)
            pass

        # generates the list of _all_ properties available for this
        # class (also from bases)
        for base in bases:
            obs |= getattr(base, ALL_OBS_SET, set())
        setattr(cls, ALL_OBS_SET, obs)
        logger.debug("class %s.%s has observables: %s", cls.__module__, cls.__name__, obs)
        return
Exemplo n.º 3
0
    def __create_prop_accessors__(cls, prop_name, default_val):
        """Private method that creates getter and setter, and the
        corresponding property"""
        getter_name = "get_prop_%s" % prop_name
        setter_name = "set_prop_%s" % prop_name

        members_names = cls.__dict__.keys()

        # checks if accessors are already defined:
        if getter_name not in members_names:
            src = type(cls).get_getter_source(cls, getter_name, prop_name)
            func = get_function_from_source(src)
            setattr(cls, getter_name, func)
        else:
            logger.debug("Custom member '%s' overloads generated getter of property '%s'", getter_name, prop_name)
            pass

        if setter_name not in members_names:
            src = type(cls).get_setter_source(cls, setter_name, prop_name)
            func = get_function_from_source(src)
            setattr(cls, setter_name, func)
        else:
            logger.warning("Custom member '%s' overloads generated setter of property '%s'", setter_name, prop_name)
            pass

        prop = property(getattr(cls, getter_name), getattr(cls, setter_name))
        setattr(cls, prop_name, prop)

        has_prop_variable = hasattr(cls, prop_name) or props.has_key(prop_name)
        if has_prop_variable:
            varname = PROP_NAME % {"prop_name": prop_name}
            if not varname in members_names:
                cls.__create_property(varname, default_val)
            else:
                logger.warning(
                    "In class %s.%s automatic property builder found a possible clashing with attribute '%s'",
                    cls.__module__,
                    cls.__name__,
                    varname,
                )
            pass

        return
Exemplo n.º 4
0
    def __create_conc_prop_accessors__(cls, prop_name, default_val):
        """Private method that creates getter and setter, and the
        corresponding property. This is used for concrete
        properties."""
        getter_name = "get_prop_%s" % prop_name
        setter_name = "set_prop_%s" % prop_name

        members_names = cls.__dict__.keys()

        # checks if accessors are already defined:
        if getter_name not in members_names:
            _getter = type(cls).get_getter(cls, prop_name)
            setattr(cls, getter_name, _getter)
        else:
            logger.debug("Custom member '%s' overloads generated getter of property '%s'" \
                             % (getter_name, prop_name))
            pass

        if setter_name not in members_names:
            _setter = type(cls).get_setter(cls, prop_name)
            setattr(cls, setter_name, _setter)
        else:
            logger.warning("Custom member '%s' overloads generated setter of property '%s'" \
                               % (setter_name, prop_name))
            pass

        # creates the property
        prop = property(getattr(cls, getter_name), getattr(cls, setter_name))
        setattr(cls, prop_name, prop)

        # creates the underlaying variable if needed
        varname = PROP_NAME % {'prop_name' : prop_name}
        if varname not in members_names: 
            setattr(cls, varname, cls.create_value(varname, default_val))
            
        else: logger.warning("In class %s.%s automatic property builder found a "
                             "possible clashing with attribute '%s'" \
                                 % (cls.__module__, cls.__name__, varname))        
        return
Exemplo n.º 5
0
    def adapt(self, *args):
        """
        There are four ways to call this:

        .. method:: adapt()
           :noindex:

           Take properties from the model for which ``adapt`` has not yet been
           called, match them to the view by name, and create adapters fitting
           for the respective widget type.
           
           That information comes from :mod:`gtkmvc.adapters.default`.
           See :meth:`_find_widget_match` for name patterns.

           .. versionchanged:: 1.99.1
              Allow incomplete auto-adaption, meaning properties for which no
              widget is found.

        .. method:: adapt(ad)
           :noindex:
        
           Keep track of manually created adapters for future ``adapt()``
           calls.
        
           *ad* is an adapter instance already connected to a widget.

        .. method:: adapt(prop_name)
           :noindex:

           Like ``adapt()`` for a single property.

           *prop_name* is a string.

        .. method:: adapt(prop_name, wid_name)
           :noindex:

           Like ``adapt(prop_name)`` but without widget name matching.
           
           *wid_name* has to exist in the view.
        """
        
        # checks arguments
        n = len(args)
        if n not in range(3): raise TypeError("adapt() takes 0, 1 or 2 arguments (%d given)" % n)

        if n==0:
            adapters = []
            props = self.model.get_properties()
            # matches all properties not previoulsy adapter by the user:
            for prop_name in filter(lambda p: p not in self.__user_props, props):
                try: wid_name = self._find_widget_match(prop_name)
                except TooManyCandidatesError, e:
                    # multiple candidates, gives up
                    raise e
                except ValueError, e: 
                    # no widgets found for given property, continue after emitting a warning
                    if e.args:
                        logger.warn(e[0])
                    else:
                        logger.warn("No widget candidates match property '%s'"
                            % prop_name)
                else:
                    logger.debug("Auto-adapting property %s and widget %s" % \
                                     (prop_name, wid_name))
                    adapters += self.__create_adapters__(prop_name, wid_name)                
                    pass
                pass