refactor property handling to avoid name conflicts
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 13 Aug 2009 10:20:57 +0200
changeset 2799 b703639614e7
parent 2798 9c650701cb17
child 2801 7ef4c1c9266b
refactor property handling to avoid name conflicts
appobject.py
devtools/devctl.py
view.py
web/action.py
web/box.py
web/component.py
web/facet.py
web/views/ajaxedit.py
web/views/basecomponents.py
--- a/appobject.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/appobject.py	Thu Aug 13 10:20:57 2009 +0200
@@ -277,38 +277,18 @@
         """
         cls.build___select__()
         cls.vreg = registry.vreg
-        cls.register_properties()
+        pdefs = getattr(cls, 'cw_property_defs', {})
+        for propid, pdef in pdefs:
+            pdef = pdef.copy() # may be shared
+            pdef['default'] = getattr(cls, propid, pdef['default'])
+            pdef['sitewide'] = getattr(cls, 'site_wide', pdef.get('sitewide'))
+            registry.vreg.register_property(cls._cwpropkey(propid), **pdef)
         return cls
 
     @classmethod
     def vreg_initialization_completed(cls):
         pass
 
-    # properties definition:
-    # key: id of the property (the actual CWProperty key is build using
-    #      <registry name>.<obj id>.<property id>
-    # value: tuple (property type, vocabfunc, default value, property description)
-    #        possible types are those used by `logilab.common.configuration`
-    #
-    # notice that when it exists multiple objects with the same id (adaptation,
-    # overriding) only the first encountered definition is considered, so those
-    # objects can't try to have different default values for instance.
-
-    property_defs = {}
-
-    @classmethod
-    def register_properties(cls):
-        for propid, pdef in cls.property_defs.items():
-            pdef = pdef.copy() # may be shared
-            pdef['default'] = getattr(cls, propid, pdef['default'])
-            pdef['sitewide'] = getattr(cls, 'site_wide', pdef.get('sitewide'))
-            cls.vreg.register_property(cls.propkey(propid), **pdef)
-
-    @classmethod
-    def propkey(cls, propid):
-        return '%s.%s.%s' % (cls.__registry__, cls.id, propid)
-
-
     def __init__(self, req=None, rset=None, row=None, col=None, **extra):
         super(AppObject, self).__init__()
         self.req = req
@@ -317,16 +297,43 @@
         self.col = col
         self.extra_kwargs = extra
 
-    def propval(self, propid):
-        assert self.req
-        return self.req.property_value(self.propkey(propid))
-
     def view(self, __vid, rset=None, __fallback_oid=None, __registry='views',
              **kwargs):
         """shortcut to self.vreg.view method avoiding to pass self.req"""
         return self.vreg[__registry].render(__vid, self.req, __fallback_oid,
                                             rset=rset, **kwargs)
 
+    # persistent class properties ##############################################
+    #
+    # optional `cw_property_defs` dict on a class defines available persistent
+    # properties for this class:
+    #
+    # * key: id of the property (the actual CWProperty key is build using
+    #        <registry name>.<obj id>.<property id>
+    # * value: tuple (property type, vocabfunc, default value, property description)
+    #         possible types are those used by `logilab.common.configuration`
+    #
+    # notice that when it exists multiple objects with the same id (adaptation,
+    # overriding) only the first encountered definition is considered, so those
+    # objects can't try to have different default values for instance.
+    #
+    # you can then access to a property value using self.propval, where self is
+    # an instance of class
+
+    @classmethod
+    def _cwpropkey(cls, propid):
+        """return cw property key for the property of the given id for this
+        class
+        """
+        return '%s.%s.%s' % (cls.__registry__, cls.id, propid)
+
+    def cw_propval(self, propid):
+        """return cw property value associated to key
+
+        <cls.__registry__>.<cls.id>.<propid>
+        """
+        return self.req.property_value(self._cwpropkey(propid))
+
     # deprecated ###############################################################
 
     @classproperty
@@ -397,4 +404,8 @@
     def parse_datetime(self, value, etype='Datetime'):
         return self.req.parse_datetime(value, etype)
 
+    @deprecated('[3.5] use self.cw_propval')
+    def propval(self, propid):
+        return self.req.property_value(self._cwpropkey(propid))
+
 set_log_methods(AppObject, getLogger('cubicweb.appobject'))
--- a/devtools/devctl.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/devtools/devctl.py	Thu Aug 13 10:20:57 2009 +0200
@@ -205,7 +205,7 @@
                 objid = '%s_%s' % (reg, obj.id)
                 if objid in done:
                     break
-                if obj.property_defs:
+                if obj.cw_property_defs:
                     yield objid
                     done.add(objid)
                     break
--- a/view.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/view.py	Thu Aug 13 10:20:57 2009 +0200
@@ -479,7 +479,6 @@
     """base class for components"""
     __registry__ = 'components'
     __select__ = yes()
-    property_defs = {}
 
     def div_class(self):
         return '%s %s' % (self.propval('htmlclass'), self.id)
--- a/web/action.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/web/action.py	Thu Aug 13 10:20:57 2009 +0200
@@ -22,7 +22,7 @@
     __registry__ = 'actions'
     __select__ = match_search_state('normal')
 
-    property_defs = {
+    cw_property_defs = {
         'visible':  dict(type='Boolean', default=True,
                          help=_('display the action or not')),
         'order':    dict(type='Int', default=99,
--- a/web/box.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/web/box.py	Thu Aug 13 10:20:57 2009 +0200
@@ -42,7 +42,7 @@
     registered = classmethod(require_group_compat(View.registered))
 
     categories_in_order = ()
-    property_defs = {
+    cw_property_defs = {
         _('visible'): dict(type='Boolean', default=True,
                            help=_('display the box or not')),
         _('order'):   dict(type='Int', default=99,
--- a/web/component.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/web/component.py	Thu Aug 13 10:20:57 2009 +0200
@@ -35,7 +35,7 @@
     __select__ = one_line_rset() & primary_view() & match_context_prop()
     registered = accepts_compat(has_relation_compat(condition_compat(View.registered)))
 
-    property_defs = {
+    cw_property_defs = {
         _('visible'):  dict(type='Boolean', default=True,
                             help=_('display the component or not')),
         _('order'):    dict(type='Int', default=99,
@@ -63,7 +63,7 @@
     id = 'navigation'
     __select__ = paginated_rset()
 
-    property_defs = {
+    cw_property_defs = {
         _('visible'):  dict(type='Boolean', default=True,
                             help=_('display the component or not')),
         }
--- a/web/facet.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/web/facet.py	Thu Aug 13 10:20:57 2009 +0200
@@ -244,7 +244,7 @@
 class AbstractFacet(AppObject):
     __abstract__ = True
     __registry__ = 'facets'
-    property_defs = {
+    cw_property_defs = {
         _('visible'): dict(type='Boolean', default=True,
                            help=_('display the box or not')),
         _('order'):   dict(type='Int', default=99,
--- a/web/views/ajaxedit.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/web/views/ajaxedit.py	Thu Aug 13 10:20:57 2009 +0200
@@ -21,7 +21,7 @@
     __registry__ = 'views'
     __select__ = (match_form_params('rtype', 'target')
                   | match_kwargs('rtype', 'target'))
-    property_defs = {} # don't want to inherit this from Box
+    cw_property_defs = {} # don't want to inherit this from Box
     id = 'xaddrelation'
     expected_kwargs = form_params = ('rtype', 'target')
 
--- a/web/views/basecomponents.py	Thu Aug 13 09:59:35 2009 +0200
+++ b/web/views/basecomponents.py	Thu Aug 13 10:20:57 2009 +0200
@@ -29,7 +29,7 @@
 class RQLInputForm(component.Component):
     """build the rql input form, usually displayed in the header"""
     id = 'rqlinput'
-    property_defs = VISIBLE_PROP_DEF
+    cw_property_defs = VISIBLE_PROP_DEF
     visible = False
 
     def call(self, view=None):
@@ -59,7 +59,7 @@
 class ApplLogo(component.Component):
     """build the instance logo, usually displayed in the header"""
     id = 'logo'
-    property_defs = VISIBLE_PROP_DEF
+    cw_property_defs = VISIBLE_PROP_DEF
     # don't want user to hide this component using an cwproperty
     site_wide = True
 
@@ -71,7 +71,7 @@
 class ApplHelp(component.Component):
     """build the help button, usually displayed in the header"""
     id = 'help'
-    property_defs = VISIBLE_PROP_DEF
+    cw_property_defs = VISIBLE_PROP_DEF
     def call(self):
         self.w(u'<a href="%s" class="help" title="%s">&nbsp;</a>'
                % (self.build_url(_restpath='doc/main'),
@@ -82,7 +82,7 @@
     """if the user is the anonymous user, build a link to login
     else a link to the connected user object with a loggout link
     """
-    property_defs = VISIBLE_PROP_DEF
+    cw_property_defs = VISIBLE_PROP_DEF
     # don't want user to hide this component using an cwproperty
     site_wide = True
     id = 'loggeduserlink'
@@ -124,7 +124,7 @@
     __select__ = yes()
     id = 'applmessages'
     # don't want user to hide this component using an cwproperty
-    property_defs = {}
+    cw_property_defs = {}
 
     def call(self):
         msgs = [msg for msg in (self.req.get_shared_data('sources_error', pop=True),
@@ -140,7 +140,7 @@
 class ApplicationName(component.Component):
     """display the instance name"""
     id = 'appliname'
-    property_defs = VISIBLE_PROP_DEF
+    cw_property_defs = VISIBLE_PROP_DEF
     # don't want user to hide this component using an cwproperty
     site_wide = True
 
@@ -170,7 +170,7 @@
     id = 'etypenavigation'
     __select__ = two_etypes_rset() | match_form_params('__restrtype', '__restrtypes',
                                                        '__restrrql')
-    property_defs = VISIBLE_PROP_DEF
+    cw_property_defs = VISIBLE_PROP_DEF
     # don't want user to hide this component using an cwproperty
     site_wide = True
     visible = False # disabled by default