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
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
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
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
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