# HG changeset patch # User Sylvain Thénault # Date 1249289457 -7200 # Node ID 18aec79ec3a32c5c80c5a28b78e12136a7e30b7f # Parent 5d4a943695d1ff5d287a1345cc9c30d19b02739a R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw diff -r 5d4a943695d1 -r 18aec79ec3a3 appobject.py --- a/appobject.py Mon Aug 03 09:37:13 2009 +0200 +++ b/appobject.py Mon Aug 03 10:50:57 2009 +0200 @@ -55,11 +55,11 @@ __select__ = yes() @classmethod - def registered(cls, vreg): - super(AppRsetObject, cls).registered(vreg) - cls.vreg = vreg - cls.schema = vreg.schema - cls.config = vreg.config + def registered(cls, reg): + super(AppRsetObject, cls).registered(reg) + cls.vreg = reg.vreg + cls.schema = reg.schema + cls.config = reg.config cls.register_properties() return cls @@ -151,8 +151,8 @@ # try to get page boundaries from the navigation component # XXX we should probably not have a ref to this component here (eg in # cubicweb.common) - nav = self.vreg.select_object('components', 'navigation', self.req, - rset=self.rset) + nav = self.vreg['components'].select_object('navigation', self.req, + rset=self.rset) if nav: start, stop = nav.page_boundaries() rql = self._limit_offset_rql(stop - start, start) @@ -188,10 +188,11 @@ rqlst.parent = None return rql - def view(self, __vid, rset=None, __fallback_vid=None, **kwargs): + 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.render(__vid, self.req, __fallback_vid, rset=rset, - **kwargs) + return self.vreg[__registry].render(__vid, self.req, __fallback_oid, + rset=rset, **kwargs) def initialize_varmaker(self): varmaker = self.req.get_page_data('rql_varmaker') diff -r 5d4a943695d1 -r 18aec79ec3a3 cwvreg.py --- a/cwvreg.py Mon Aug 03 09:37:13 2009 +0200 +++ b/cwvreg.py Mon Aug 03 10:50:57 2009 +0200 @@ -8,13 +8,14 @@ __docformat__ = "restructuredtext en" _ = unicode -from logilab.common.decorators import cached, clear_cache +from logilab.common.decorators import cached, clear_cache, monkeypatch from logilab.common.deprecation import deprecated from rql import RQLHelper -from cubicweb import ETYPE_NAME_MAP, Binary, UnknownProperty, UnknownEid -from cubicweb.vregistry import VRegistry, ObjectNotFound, NoSelectableObject +from cubicweb import (ETYPE_NAME_MAP, Binary, UnknownProperty, UnknownEid, + ObjectNotFound, NoSelectableObject, RegistryNotFound) +from cubicweb.vregistry import VRegistry, Registry from cubicweb.rtags import RTAGS @@ -39,7 +40,149 @@ return () -class CubicWebRegistry(VRegistry): +class CWRegistry(Registry): + def __init__(self, vreg): + super(CWRegistry, self).__init__(vreg.config) + self.vreg = vreg + self.schema = vreg.schema + + def initialization_completed(self): + # call vreg_initialization_completed on appobjects and print + # registry content + for appobjects in self.itervalues(): + for appobject in appobjects: + appobject.vreg_initialization_completed() + + def render(self, __oid, req, __fallback_oid=None, rset=None, **kwargs): + """select object, or fallback object if specified and the first one + isn't selectable, then render it + """ + try: + obj = self.select(__oid, req, rset=rset, **kwargs) + except NoSelectableObject: + if __fallback_oid is None: + raise + obj = self.select(__fallback_oid, req, **kwargs) + return obj.render(**kwargs) + + def select_vobject(self, oid, *args, **kwargs): + selected = self.select_object(oid, *args, **kwargs) + if selected and selected.propval('visible'): + return selected + return None + + def possible_vobjects(self, *args, **kwargs): + """return an ordered list of possible app objects in a given registry, + supposing they support the 'visible' and 'order' properties (as most + visualizable objects) + """ + return sorted([x for x in self.possible_objects(*args, **kwargs) + if x.propval('visible')], + key=lambda x: x.propval('order')) + + +VRegistry.REGISTRY_FACTORY[None] = CWRegistry + + +class ETypeRegistry(CWRegistry): + + def initialization_completed(self): + super(ETypeRegistry, self).initialization_completed() + # clear etype cache if you don't want to run into deep weirdness + clear_cache(self, 'etype_class') + + def register(self, obj, **kwargs): + oid = kwargs.get('oid') or obj.id + if oid != 'Any' and not oid in self.schema: + self.error('don\'t register %s, %s type not defined in the ' + 'schema', obj, obj.id) + return + kwargs['clear'] = True + super(ETypeRegistry, self).register(obj, **kwargs) + + @cached + def etype_class(self, etype): + """return an entity class for the given entity type. + Try to find out a specific class for this kind of entity or + default to a dump of the class registered for 'Any' + """ + etype = str(etype) + if etype == 'Any': + return self.select('Any', 'Any') + eschema = self.schema.eschema(etype) + baseschemas = [eschema] + eschema.ancestors() + # browse ancestors from most specific to most generic and + # try to find an associated custom entity class + for baseschema in baseschemas: + try: + btype = ETYPE_NAME_MAP[baseschema] + except KeyError: + btype = str(baseschema) + try: + cls = self.select(btype, etype) + break + except ObjectNotFound: + pass + else: + # no entity class for any of the ancestors, fallback to the default + # one + cls = self.select('Any', etype) + return cls + +VRegistry.REGISTRY_FACTORY['etypes'] = ETypeRegistry + + +class ViewsRegistry(CWRegistry): + + def main_template(self, req, oid='main-template', **kwargs): + """display query by calling the given template (default to main), + and returning the output as a string instead of requiring the [w]rite + method as argument + """ + res = self.render(oid, req, **kwargs) + if isinstance(res, unicode): + return res.encode(req.encoding) + assert isinstance(res, str) + return res + + def possible_views(self, req, rset=None, **kwargs): + """return an iterator on possible views for this result set + + views returned are classes, not instances + """ + for vid, views in self.items(): + if vid[0] == '_': + continue + try: + view = self.select_best(views, req, rset=rset, **kwargs) + if view.linkable(): + yield view + except NoSelectableObject: + continue + except Exception: + self.exception('error while trying to select %s view for %s', + vid, rset) + +VRegistry.REGISTRY_FACTORY['views'] = ViewsRegistry + + +class ActionsRegistry(CWRegistry): + + def possible_actions(self, req, rset=None, **kwargs): + if rset is None: + actions = self.possible_vobjects(req, rset=rset, **kwargs) + else: + actions = rset.possible_actions(**kwargs) # cached implementation + result = {} + for action in actions: + result.setdefault(action.category, []).append(action) + return result + +VRegistry.REGISTRY_FACTORY['actions'] = ActionsRegistry + + + +class CubicWebVRegistry(VRegistry): """Central registry for the cubicweb instance, extending the generic VRegistry with some cubicweb specific stuff. @@ -65,28 +208,33 @@ if initlog: # first init log service config.init_log(debug=debug) - super(CubicWebRegistry, self).__init__(config) + super(CubicWebVRegistry, self).__init__(config) self.schema = None self.reset() self.initialized = False + def setdefault(self, regid): + try: + return self[regid] + except RegistryNotFound: + self[regid] = self.registry_class(regid)(self) + return self[regid] + def items(self): - return [item for item in self._registries.items() + return [item for item in super(CubicWebVRegistry, self).items() if not item[0] in ('propertydefs', 'propertyvalues')] def values(self): - return [value for key, value in self._registries.items() - if not key in ('propertydefs', 'propertyvalues')] + return [value for key, value in self.items()] def reset(self): - self._registries = {} - self._lastmodifs = {} + super(CubicWebVRegistry, self).reset() self._needs_iface = {} # two special registries, propertydefs which care all the property # definitions, and propertyvals which contains values for those # properties - self._registries['propertydefs'] = {} - self._registries['propertyvalues'] = self.eprop_values = {} + self['propertydefs'] = {} + self['propertyvalues'] = self.eprop_values = {} for key, propdef in self.config.eproperty_definitions(): self.register_property(key, **propdef) @@ -107,9 +255,7 @@ tests """ self.schema = schema - for registry, regcontent in self._registries.items(): - if registry in ('propertydefs', 'propertyvalues'): - continue + for registry, regcontent in self.items(): for objects in regcontent.values(): for obj in objects: obj.schema = schema @@ -125,13 +271,7 @@ self._needs_iface[obj] = ifaces def register(self, obj, **kwargs): - if kwargs.get('registryname', obj.__registry__) == 'etypes': - if obj.id != 'Any' and not obj.id in self.schema: - self.error('don\'t register %s, %s type not defined in the ' - 'schema', obj, obj.id) - return - kwargs['clear'] = True - super(CubicWebRegistry, self).register(obj, **kwargs) + super(CubicWebVRegistry, self).register(obj, **kwargs) # XXX bw compat ifaces = use_interfaces(obj) if ifaces: @@ -143,25 +283,18 @@ for cubesdir in self.config.cubes_search_path(): if cubesdir != self.config.CUBES_DIR: extrapath[cubesdir] = 'cubes' - if super(CubicWebRegistry, self).register_objects(path, force_reload, + if super(CubicWebVRegistry, self).register_objects(path, force_reload, extrapath): self.initialization_completed() - # call vreg_initialization_completed on appobjects and print - # registry content - for registry, objects in self.items(): - self.debug('available in registry %s: %s', registry, - sorted(objects)) - for appobjects in objects.itervalues(): - for appobject in appobjects: - appobject.vreg_initialization_completed() # don't check rtags if we don't want to cleanup_interface_sobjects for rtag in RTAGS: rtag.init(self.schema, check=self.config.cleanup_interface_sobjects) def initialization_completed(self): - # clear etype cache if you don't want to run into deep weirdness - clear_cache(self, 'etype_class') + for regname, reg in self.items(): + self.debug('available in registry %s: %s', regname, sorted(reg)) + reg.initialization_completed() # we may want to keep interface dependent objects (e.g.for i18n # catalog generation) if self.config.cleanup_interface_sobjects: @@ -169,14 +302,14 @@ implemented_interfaces = set() if 'Any' in self.get('etypes', ()): for etype in self.schema.entities(): - cls = self.etype_class(etype) + cls = self['etypes'].etype_class(etype) for iface in cls.__implements__: implemented_interfaces.update(iface.__mro__) implemented_interfaces.update(cls.__mro__) for obj, ifaces in self._needs_iface.items(): ifaces = frozenset(isinstance(iface, basestring) and iface in self.schema - and self.etype_class(iface) + and self['etypes'].etype_class(iface) or iface for iface in ifaces) if not ('Any' in ifaces or ifaces & implemented_interfaces): @@ -187,122 +320,55 @@ # objects on automatic reloading self._needs_iface.clear() + def parse(self, session, rql, args=None): + rqlst = self.rqlhelper.parse(rql) + def type_from_eid(eid, session=session): + return session.describe(eid)[0] + try: + self.rqlhelper.compute_solutions(rqlst, {'eid': type_from_eid}, args) + except UnknownEid: + for select in rqlst.children: + select.solutions = [] + return rqlst + + @property @cached + def rqlhelper(self): + return RQLHelper(self.schema, + special_relations={'eid': 'uid', 'has_text': 'fti'}) + + + @deprecated('use vreg["etypes"].etype_class(etype)') def etype_class(self, etype): - """return an entity class for the given entity type. - Try to find out a specific class for this kind of entity or - default to a dump of the class registered for 'Any' - """ - etype = str(etype) - if etype == 'Any': - return self.select('etypes', 'Any', 'Any') - eschema = self.schema.eschema(etype) - baseschemas = [eschema] + eschema.ancestors() - # browse ancestors from most specific to most generic and - # try to find an associated custom entity class - for baseschema in baseschemas: - try: - btype = ETYPE_NAME_MAP[baseschema] - except KeyError: - btype = str(baseschema) - try: - cls = self.select('etypes', btype, etype) - break - except ObjectNotFound: - pass - else: - # no entity class for any of the ancestors, fallback to the default - # one - cls = self.select('etypes', 'Any', etype) - return cls + return self["etypes"].etype_class(etype) - def render(self, __oid, req, __fallback_oid=None, __registry='views', - rset=None, **kwargs): - """select object, or fallback object if specified and the first one - isn't selectable, then render it - """ - try: - obj = self.select(__registry, __oid, req, rset=rset, **kwargs) - except NoSelectableObject: - if __fallback_oid is None: - raise - obj = self.select(__registry, __fallback_oid, req, rset=rset, - **kwargs) - return obj.render(**kwargs) - + @deprecated('use vreg["views"].main_template(*args, **kwargs)') def main_template(self, req, oid='main-template', **context): - """display query by calling the given template (default to main), - and returning the output as a string instead of requiring the [w]rite - method as argument - """ - res = self.render(oid, req, **context) - if isinstance(res, unicode): - return res.encode(req.encoding) - assert isinstance(res, str) - return res + return self["views"].main_template(req, oid, **context) - def select_vobject(self, registry, oid, *args, **kwargs): - selected = self.select_object(registry, oid, *args, **kwargs) - if selected and selected.propval('visible'): - return selected - return None - + @deprecated('use vreg[registry].possible_vobjects(*args, **kwargs)') def possible_vobjects(self, registry, *args, **kwargs): - """return an ordered list of possible app objects in a given registry, - supposing they support the 'visible' and 'order' properties (as most - visualizable objects) - """ - return [x for x in sorted(self.possible_objects(registry, *args, **kwargs), - key=lambda x: x.propval('order')) - if x.propval('visible')] + return self[registry].possible_vobjects(*args, **kwargs) + @deprecated('use vreg["actions"].possible_actions(*args, **kwargs)') def possible_actions(self, req, rset=None, **kwargs): - if rset is None: - actions = self.possible_vobjects('actions', req, rset=rset, **kwargs) - else: - actions = rset.possible_actions(**kwargs) # cached implementation - result = {} - for action in actions: - result.setdefault(action.category, []).append(action) - return result - - def possible_views(self, req, rset=None, **kwargs): - """return an iterator on possible views for this result set - - views returned are classes, not instances - """ - for vid, views in self.registry('views').items(): - if vid[0] == '_': - continue - try: - view = self.select_best(views, req, rset=rset, **kwargs) - if view.linkable(): - yield view - except NoSelectableObject: - continue - except Exception: - self.exception('error while trying to select %s view for %s', - vid, rset) + return self["actions"].possible_actions(req, rest=rset, **kwargs) @deprecated("use .select_object('boxes', ...)") def select_box(self, oid, *args, **kwargs): - """return the most specific view according to the result set""" - return self.select_object('boxes', oid, *args, **kwargs) + return self['boxes'].select_object(oid, *args, **kwargs) @deprecated("use .select_object('components', ...)") def select_component(self, cid, *args, **kwargs): - """return the most specific component according to the result set""" - return self.select_object('components', cid, *args, **kwargs) + return self['components'].select_object(cid, *args, **kwargs) @deprecated("use .select_object('actions', ...)") def select_action(self, oid, *args, **kwargs): - """return the most specific view according to the result set""" - return self.select_object('actions', oid, *args, **kwargs) + return self['actions'].select_object(oid, *args, **kwargs) @deprecated("use .select('views', ...)") def select_view(self, __vid, req, rset=None, **kwargs): - """return the most specific view according to the result set""" - return self.select('views', __vid, req, rset=rset, **kwargs) + return self['views'].select(__vid, req, rset=rset, **kwargs) # properties handling ##################################################### @@ -316,7 +382,7 @@ def register_property(self, key, type, help, default=None, vocabulary=None, sitewide=False): """register a given property""" - properties = self._registries['propertydefs'] + properties = self['propertydefs'] assert type in YAMS_TO_PY properties[key] = {'type': type, 'vocabulary': vocabulary, 'default': default, 'help': help, @@ -328,7 +394,7 @@ boolean) """ try: - return self._registries['propertydefs'][key] + return self['propertydefs'][key] except KeyError: if key.startswith('system.version.'): soft = key.split('.')[-1] @@ -339,9 +405,9 @@ def property_value(self, key): try: - return self._registries['propertyvalues'][key] + return self['propertyvalues'][key] except KeyError: - return self._registries['propertydefs'][key]['default'] + return self['propertydefs'][key]['default'] def typed_value(self, key, value): """value is an unicode string, return it correctly typed. Let potential @@ -364,7 +430,7 @@ """init the property values registry using the given set of couple (key, value) """ self.initialized = True - values = self._registries['propertyvalues'] + values = self['propertyvalues'] for key, val in propvalues: try: values[key] = self.typed_value(key, val) @@ -375,61 +441,6 @@ self.warning('%s (you should probably delete that property ' 'from the database)', ex) - def parse(self, session, rql, args=None): - rqlst = self.rqlhelper.parse(rql) - def type_from_eid(eid, session=session): - return session.describe(eid)[0] - try: - self.rqlhelper.compute_solutions(rqlst, {'eid': type_from_eid}, args) - except UnknownEid: - for select in rqlst.children: - select.solutions = [] - return rqlst - - @property - @cached - def rqlhelper(self): - return RQLHelper(self.schema, - special_relations={'eid': 'uid', 'has_text': 'fti'}) - - -class MulCnxCubicWebRegistry(CubicWebRegistry): - """special registry to be used when an application has to deal with - connections to differents repository. This class add some additional wrapper - trying to hide buggy class attributes since classes are not designed to be - shared among multiple registries. - """ - def etype_class(self, etype): - """return an entity class for the given entity type. - Try to find out a specific class for this kind of entity or - default to a dump of the class registered for 'Any' - """ - usercls = super(MulCnxCubicWebRegistry, self).etype_class(etype) - if etype == 'Any': - return usercls - usercls.e_schema = self.schema.eschema(etype) - return usercls - - def select_best(self, vobjects, *args, **kwargs): - """return an instance of the most specific object according - to parameters - - raise NoSelectableObject if no object apply - """ - for vobjectcls in vobjects: - self._fix_cls_attrs(vobjectcls) - selected = super(MulCnxCubicWebRegistry, self).select_best( - vobjects, *args, **kwargs) - # redo the same thing on the instance so it won't use equivalent class - # attributes (which may change) - self._fix_cls_attrs(selected) - return selected - - def _fix_cls_attrs(self, vobject): - vobject.vreg = self - vobject.schema = self.schema - vobject.config = self.config - from datetime import datetime, date, time, timedelta diff -r 5d4a943695d1 -r 18aec79ec3a3 dbapi.py --- a/dbapi.py Mon Aug 03 09:37:13 2009 +0200 +++ b/dbapi.py Mon Aug 03 10:50:57 2009 +0200 @@ -16,9 +16,10 @@ from itertools import count from logilab.common.logging_ext import set_log_methods +from logilab.common.decorators import monkeypatch + from cubicweb import ETYPE_NAME_MAP, ConnectionError, RequestSessionMixIn -from cubicweb.cwvreg import CubicWebRegistry, MulCnxCubicWebRegistry -from cubicweb.cwconfig import CubicWebNoAppConfiguration +from cubicweb import cwvreg, cwconfig _MARKER = object() @@ -28,6 +29,54 @@ except KeyError: return '' +def _fix_cls_attrs(reg, vobject): + vobject.vreg = reg.vreg + vobject.schema = reg.schema + vobject.config = reg.config + +def multiple_connections_fix(): + """some monkey patching necessary when an application has to deal with + several connections to different repositories. It tries to hide buggy class + attributes since classes are not designed to be shared among multiple + registries. + """ + defaultcls = cwvreg.VRegistry.REGISTRY_FACTORY[None] + orig_select_best = defaultcls.orig_select_best = defaultcls.select_best + @monkeypatch(defaultcls) + def select_best(self, vobjects, *args, **kwargs): + """return an instance of the most specific object according + to parameters + + raise NoSelectableObject if no object apply + """ + for vobjectcls in vobjects: + _fix_cls_attrs(self, vobjectcls) + selected = orig_select_best(self, vobjects, *args, **kwargs) + # redo the same thing on the instance so it won't use equivalent class + # attributes (which may change) + _fix_cls_attrs(self, selected) + return selected + + etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] + orig_etype_class = etypescls.orig_etype_class = etypescls.etype_class + @monkeypatch(defaultcls) + def etype_class(self, etype): + """return an entity class for the given entity type. + Try to find out a specific class for this kind of entity or + default to a dump of the class registered for 'Any' + """ + usercls = orig_etype_class(self, etype) + if etype == 'Any': + return usercls + usercls.e_schema = self.schema.eschema(etype) + return usercls + +def multiple_connections_unfix(): + defaultcls = cwvreg.VRegistry.REGISTRY_FACTORY[None] + defaultcls.select_best = defaultcls.orig_select_best + etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] + etypescls.etype_class = etypescls.orig_etype_class + class ConnectionProperties(object): def __init__(self, cnxtype=None, lang=None, close=True, log=False): self.cnxtype = cnxtype or 'pyro' @@ -88,12 +137,11 @@ """Constructor for creating a connection to the CubicWeb repository. Returns a Connection object. - When method is 'pyro' and setvreg is True, use a special registry class - (MulCnxCubicWebRegistry) made to deal with connections to differents instances - in the same process unless specified otherwise by setting the mulcnx to - False. + When method is 'pyro', setvreg is True, try to deal with connections to + differents instances in the same process unless specified otherwise by + setting the mulcnx to False. """ - config = CubicWebNoAppConfiguration() + config = cwconfig.CubicWebNoAppConfiguration() if host: config.global_set_option('pyro-ns-host', host) if port: @@ -107,9 +155,8 @@ vreg = repo.vreg elif setvreg: if mulcnx: - vreg = MulCnxCubicWebRegistry(config, initlog=initlog) - else: - vreg = CubicWebRegistry(config, initlog=initlog) + multiple_connections_fix() + vreg = cwvreg.CubicWebVRegistry(config, initlog=initlog) schema = repo.get_schema() for oldetype, newetype in ETYPE_NAME_MAP.items(): if oldetype in schema: @@ -126,7 +173,7 @@ """usefull method for testing and scripting to get a dbapi.Connection object connected to an in-memory repository instance """ - if isinstance(config, CubicWebRegistry): + if isinstance(config, cwvreg.CubicWebVRegistry): vreg = config config = None else: @@ -476,8 +523,9 @@ if req is None: req = self.request() rset = req.eid_rset(eid, 'CWUser') - user = self.vreg.etype_class('CWUser')(req, rset, row=0, groups=groups, - properties=properties) + user = self.vreg['etypes'].etype_class('CWUser')(req, rset, row=0, + groups=groups, + properties=properties) user['login'] = login # cache login return user diff -r 5d4a943695d1 -r 18aec79ec3a3 devtools/_apptest.py --- a/devtools/_apptest.py Mon Aug 03 09:37:13 2009 +0200 +++ b/devtools/_apptest.py Mon Aug 03 10:50:57 2009 +0200 @@ -14,7 +14,7 @@ import yams.schema from cubicweb.dbapi import repo_connect, ConnectionProperties, ProgrammingError -from cubicweb.cwvreg import CubicWebRegistry +from cubicweb.cwvreg import CubicWebVRegistry from cubicweb.web.application import CubicWebPublisher from cubicweb.web import Redirect @@ -79,7 +79,7 @@ source = config.sources()['system'] if verbose: print "init test database ..." - self.vreg = vreg = CubicWebRegistry(config) + self.vreg = vreg = CubicWebVRegistry(config) self.admlogin = source['db-user'] # restore database <=> init database self.restore_database() @@ -191,7 +191,7 @@ optional_args = {} optional_args['vid'] = vid req = self.create_request(rql=rql, **optional_args) - return self.vreg.main_template(req, template) + return self.vreg['views'].main_template(req, template) def call_edit(self, req): """shortcut for self.app.edit()""" @@ -207,7 +207,7 @@ def iter_possible_views(self, req, rset): """returns a list of possible vids for """ - for view in self.vreg.possible_views(req, rset): + for view in self.vreg['views'].possible_views(req, rset): if view.category == 'startupview': continue yield view.id @@ -216,7 +216,7 @@ def iter_startup_views(self, req): """returns the list of startup views""" - for view in self.vreg.possible_views(req, None): + for view in self.vreg['views'].possible_views(req, None): if view.category != 'startupview': continue yield view.id @@ -233,7 +233,7 @@ if verbose: print "init test database ..." source = config.sources()['system'] - self.vreg = CubicWebRegistry(config) + self.vreg = CubicWebVRegistry(config) self.cnx = init_test_database(driver=source['db-driver'], vreg=self.vreg)[1] if verbose: diff -r 5d4a943695d1 -r 18aec79ec3a3 devtools/apptest.py --- a/devtools/apptest.py Mon Aug 03 09:37:13 2009 +0200 +++ b/devtools/apptest.py Mon Aug 03 10:50:57 2009 +0200 @@ -175,7 +175,7 @@ def etype_instance(self, etype, req=None): req = req or self.request() - e = self.env.vreg.etype_class(etype)(req, None, None) + e = self.env.vreg['etypes'].etype_class(etype)(req) e.eid = None return e @@ -224,21 +224,21 @@ self.vreg.config.global_set_option(optname, value) def pviews(self, req, rset): - return sorted((a.id, a.__class__) for a in self.vreg.possible_views(req, rset)) + return sorted((a.id, a.__class__) for a in self.vreg['views'].possible_views(req, rset=rset)) def pactions(self, req, rset, skipcategories=('addrelated', 'siteactions', 'useractions')): - return [(a.id, a.__class__) for a in self.vreg.possible_vobjects('actions', req, rset=rset) + return [(a.id, a.__class__) for a in self.vreg['actions'].possible_vobjects(req, rset=rset) if a.category not in skipcategories] def pactions_by_cats(self, req, rset, categories=('addrelated',)): - return [(a.id, a.__class__) for a in self.vreg.possible_vobjects('actions', req, rset=rset) + return [(a.id, a.__class__) for a in self.vreg['actions'].possible_vobjects(req, rset=rset) if a.category in categories] paddrelactions = deprecated()(pactions_by_cats) def pactionsdict(self, req, rset, skipcategories=('addrelated', 'siteactions', 'useractions')): res = {} - for a in self.vreg.possible_vobjects('actions', req, rset=rset): + for a in self.vreg['actions'].possible_vobjects(req, rset=rset): if a.category not in skipcategories: res.setdefault(a.category, []).append(a.__class__) return res diff -r 5d4a943695d1 -r 18aec79ec3a3 devtools/devctl.py --- a/devtools/devctl.py Mon Aug 03 09:37:13 2009 +0200 +++ b/devtools/devctl.py Mon Aug 03 10:50:57 2009 +0200 @@ -90,7 +90,7 @@ notice that relation definitions description and static vocabulary should be marked using '_' and extracted using xgettext """ - from cubicweb.cwvreg import CubicWebRegistry + from cubicweb.cwvreg import CubicWebVRegistry cube = cubedir and split(cubedir)[-1] libconfig = DevDepConfiguration(cube) libconfig.cleanup_interface_sobjects = False @@ -102,7 +102,7 @@ config = libconfig libconfig = None schema = config.load_schema(remove_unused_rtypes=False) - vreg = CubicWebRegistry(config) + vreg = CubicWebVRegistry(config) # set_schema triggers objects registrations vreg.set_schema(schema) w(DEFAULT_POT_HEAD) @@ -187,8 +187,8 @@ #cube = (cube and 'cubes.%s.' % cube or 'cubicweb.') done = set() if libconfig is not None: - from cubicweb.cwvreg import CubicWebRegistry - libvreg = CubicWebRegistry(libconfig) + from cubicweb.cwvreg import CubicWebVRegistry + libvreg = CubicWebVRegistry(libconfig) libvreg.set_schema(libschema) # trigger objects registration # prefill done set list(_iter_vreg_objids(libvreg, done)) diff -r 5d4a943695d1 -r 18aec79ec3a3 devtools/fake.py --- a/devtools/fake.py Mon Aug 03 09:37:13 2009 +0200 +++ b/devtools/fake.py Mon Aug 03 10:50:57 2009 +0200 @@ -35,26 +35,21 @@ def sources(self): return {} -class FakeVReg(object): +class FakeVReg(dict): def __init__(self, schema=None, config=None): self.schema = schema self.config = config or FakeConfig() self.properties = {'ui.encoding': 'UTF8', 'ui.language': 'en', } + self.update({ + 'controllers' : {'login': []}, + 'views' : {}, + }) def property_value(self, key): return self.properties[key] - _registries = { - 'controllers' : [Mock(id='view'), Mock(id='login'), - Mock(id='logout'), Mock(id='edit')], - 'views' : [Mock(id='primary'), Mock(id='oneline'), Mock(id='list')], - } - - def registry_objects(self, name, oid=None): - return self._registries[name] - def etype_class(self, etype): class Entity(dict): e_schema = self.schema[etype] diff -r 5d4a943695d1 -r 18aec79ec3a3 devtools/testlib.py --- a/devtools/testlib.py Mon Aug 03 09:37:13 2009 +0200 +++ b/devtools/testlib.py Mon Aug 03 10:50:57 2009 +0200 @@ -185,7 +185,8 @@ req = req or rset and rset.req or self.request() req.form['vid'] = vid kwargs['rset'] = rset - view = self.vreg.select('views', vid, req, **kwargs) + viewsreg = self.vreg['views'] + view = viewsreg.select(vid, req, **kwargs) # set explicit test description if rset is not None: self.set_description("testing %s, mod=%s (%s)" % ( @@ -197,9 +198,9 @@ viewfunc = view.render else: kwargs['view'] = view - templateview = self.vreg.select('views', template, req, **kwargs) - viewfunc = lambda **k: self.vreg.main_template(req, template, - **kwargs) + templateview = viewsreg.select(template, req, **kwargs) + viewfunc = lambda **k: viewsreg.main_template(req, template, + **kwargs) kwargs.pop('rset') return self._test_view(viewfunc, view, template, kwargs) @@ -272,7 +273,8 @@ req = rset.req only_once_vids = ('primary', 'secondary', 'text') req.data['ex'] = ValueError("whatever") - for vid, views in self.vreg.registry('views').items(): + viewsvreg = self.vreg['views'] + for vid, views in viewsvreg.items(): if vid[0] == '_': continue if rset.rowcount > 1 and vid in only_once_vids: @@ -282,7 +284,7 @@ and not issubclass(view, NotificationView)] if views: try: - view = self.vreg.select_best(views, req, rset=rset) + view = viewsvreg.select_best(views, req, rset=rset) if view.linkable(): yield view else: @@ -295,19 +297,19 @@ def list_actions_for(self, rset): """returns the list of actions that can be applied on `rset`""" req = rset.req - for action in self.vreg.possible_objects('actions', req, rset=rset): + for action in self.vreg['actions'].possible_objects(req, rset=rset): yield action def list_boxes_for(self, rset): """returns the list of boxes that can be applied on `rset`""" req = rset.req - for box in self.vreg.possible_objects('boxes', req, rset=rset): + for box in self.vreg['boxes'].possible_objects(req, rset=rset): yield box def list_startup_views(self): """returns the list of startup views""" req = self.request() - for view in self.vreg.possible_views(req, None): + for view in self.vreg['views'].possible_views(req, None): if view.category == 'startupview': yield view.id else: @@ -385,26 +387,25 @@ from cubicweb.devtools.apptest import TestEnvironment env = testclass._env = TestEnvironment('data', configcls=testclass.configcls, requestcls=testclass.requestcls) - vreg = env.vreg - vreg._selected = {} - orig_select_best = vreg.__class__.select_best - def instr_select_best(self, *args, **kwargs): - selected = orig_select_best(self, *args, **kwargs) - try: - self._selected[selected.__class__] += 1 - except KeyError: - self._selected[selected.__class__] = 1 - except AttributeError: - pass # occurs on vreg used to restore database - return selected - vreg.__class__.select_best = instr_select_best + for reg in env.vreg.values(): + reg._selected = {} + orig_select_best = reg.__class__.select_best + def instr_select_best(self, *args, **kwargs): + selected = orig_select_best(self, *args, **kwargs) + try: + self._selected[selected.__class__] += 1 + except KeyError: + self._selected[selected.__class__] = 1 + except AttributeError: + pass # occurs on reg used to restore database + return selected + reg.__class__.select_best = instr_select_best def print_untested_objects(testclass, skipregs=('hooks', 'etypes')): - vreg = testclass._env.vreg - for registry, vobjectsdict in vreg.items(): - if registry in skipregs: + for regname, reg in testclass._env.vreg.iteritems(): + if regname in skipregs: continue - for vobjects in vobjectsdict.values(): + for vobjects in reg.itervalues(): for vobject in vobjects: - if not vreg._selected.get(vobject): - print 'not tested', registry, vobject + if not reg._selected.get(vobject): + print 'not tested', regname, vobject diff -r 5d4a943695d1 -r 18aec79ec3a3 entities/test/unittest_base.py --- a/entities/test/unittest_base.py Mon Aug 03 09:37:13 2009 +0200 +++ b/entities/test/unittest_base.py Mon Aug 03 10:50:57 2009 +0200 @@ -276,8 +276,8 @@ def select_eclass(self, etype): # clear selector cache - clear_cache(self.vreg, 'etype_class') - return self.vreg.etype_class(etype) + clear_cache(self.vreg['etypes'], 'etype_class') + return self.vreg['etypes'].etype_class(etype) def test_etype_class_selection_and_specialization(self): # no specific class for Subdivisions, the default one should be selected diff -r 5d4a943695d1 -r 18aec79ec3a3 entity.py --- a/entity.py Mon Aug 03 09:37:13 2009 +0200 +++ b/entity.py Mon Aug 03 10:50:57 2009 +0200 @@ -265,7 +265,7 @@ continue if card == '?': restrictions[-1] += '?' # left outer join if not mandatory - destcls = cls.vreg.etype_class(desttype) + destcls = cls.vreg['etypes'].etype_class(desttype) destcls._fetch_restrictions(var, varmaker, destcls.fetch_attrs, selection, orderby, restrictions, user, ordermethod, visited=visited) @@ -277,8 +277,9 @@ @classmethod @cached def parent_classes(cls): - parents = [cls.vreg.etype_class(e.type) for e in cls.e_schema.ancestors()] - parents.append(cls.vreg.etype_class('Any')) + parents = [cls.vreg['etypes'].etype_class(e.type) + for e in cls.e_schema.ancestors()] + parents.append(cls.vreg['etypes'].etype_class('Any')) return parents @classmethod @@ -364,10 +365,10 @@ def has_perm(self, action): return self.e_schema.has_perm(self.req, action, self.eid) - def view(self, vid, **kwargs): + def view(self, vid, __registry='views', **kwargs): """shortcut to apply a view on this entity""" - return self.vreg.render(vid, self.req, rset=self.rset, - row=self.row, col=self.col, **kwargs) + return self.vreg[__registry].render(vid, self.req, rset=self.rset, + row=self.row, col=self.col, **kwargs) def absolute_url(self, *args, **kwargs): """return an absolute url to view this entity""" @@ -702,13 +703,13 @@ if len(targettypes) > 1: fetchattrs_list = [] for ttype in targettypes: - etypecls = self.vreg.etype_class(ttype) + etypecls = self.vreg['etypes'].etype_class(ttype) fetchattrs_list.append(set(etypecls.fetch_attrs)) fetchattrs = reduce(set.intersection, fetchattrs_list) rql = etypecls.fetch_rql(self.req.user, [restriction], fetchattrs, settype=False) else: - etypecls = self.vreg.etype_class(targettypes[0]) + etypecls = self.vreg['etypes'].etype_class(targettypes[0]) rql = etypecls.fetch_rql(self.req.user, [restriction], settype=False) # optimisation: remove ORDERBY if cardinality is 1 or ? (though # greater_card return 1 for those both cases) @@ -764,7 +765,7 @@ else: restriction += [cstr.restriction for cstr in constraints if isinstance(cstr, RQLConstraint)] - etypecls = self.vreg.etype_class(targettype) + etypecls = self.vreg['etypes'].etype_class(targettype) rql = etypecls.fetch_rql(self.req.user, restriction, mainvar=searchedvar, ordermethod=ordermethod) # ensure we have an order defined diff -r 5d4a943695d1 -r 18aec79ec3a3 goa/db.py --- a/goa/db.py Mon Aug 03 09:37:13 2009 +0200 +++ b/goa/db.py Mon Aug 03 10:50:57 2009 +0200 @@ -274,8 +274,8 @@ def view(self, vid, __registry='views', **kwargs): """shortcut to apply a view on this entity""" - return self.vreg.render(__registry, vid, self.req, rset=self.rset, - row=self.row, col=self.col, **kwargs) + return self.vreg[__registry]render(vid, self.req, rset=self.rset, + row=self.row, col=self.col, **kwargs) @classmethod def _rest_attr_info(cls): diff -r 5d4a943695d1 -r 18aec79ec3a3 goa/goavreg.py --- a/goa/goavreg.py Mon Aug 03 09:37:13 2009 +0200 +++ b/goa/goavreg.py Mon Aug 03 10:50:57 2009 +0200 @@ -11,7 +11,7 @@ from os.path import join, isdir from cubicweb import CW_SOFTWARE_ROOT -from cubicweb.cwvreg import CubicWebRegistry +from cubicweb.cwvreg import CubicWebVRegistry def _pkg_name(cube, module): @@ -19,7 +19,7 @@ return module return 'cubes.%s.%s' % (cube, module) -class GAERegistry(CubicWebRegistry): +class GAEVRegistry(CubicWebVRegistry): def set_schema(self, schema): """disable reload hooks of cubicweb registry set_schema method""" diff -r 5d4a943695d1 -r 18aec79ec3a3 goa/skel/main.py --- a/goa/skel/main.py Mon Aug 03 09:37:13 2009 +0200 +++ b/goa/skel/main.py Mon Aug 03 10:50:57 2009 +0200 @@ -22,8 +22,8 @@ config = GAEConfiguration('toto', APPLROOT) # dynamic objects registry -from cubicweb.goa.goavreg import GAERegistry -vreg = GAERegistry(config, debug=goa.MODE == 'dev') +from cubicweb.goa.goavreg import GAEVregistry +vreg = GAEVregistry(config, debug=goa.MODE == 'dev') # trigger automatic classes registration (metaclass magic), should be done # before schema loading diff -r 5d4a943695d1 -r 18aec79ec3a3 goa/test/unittest_views.py --- a/goa/test/unittest_views.py Mon Aug 03 09:37:13 2009 +0200 +++ b/goa/test/unittest_views.py Mon Aug 03 10:50:57 2009 +0200 @@ -46,10 +46,10 @@ self.blog.put(self.req) def test_hcal(self): - self.vreg.render('views', 'hcal', self.req, rset=self.blog.rset) + self.vreg['views'].render('hcal', self.req, rset=self.blog.rset) def test_django_index(self): - self.vreg.render('views', 'index', self.req, rset=None) + self.vreg'views'].render('index', self.req, rset=None) for vid in ('primary', 'oneline', 'incontext', 'outofcontext', 'text'): setattr(SomeViewsTC, 'test_%s'%vid, lambda self, vid=vid: self.blog.view(vid)) diff -r 5d4a943695d1 -r 18aec79ec3a3 goa/testlib.py --- a/goa/testlib.py Mon Aug 03 09:37:13 2009 +0200 +++ b/goa/testlib.py Mon Aug 03 10:50:57 2009 +0200 @@ -42,7 +42,7 @@ from cubicweb.devtools.fake import FakeRequest -from cubicweb.goa.goavreg import GAERegistry +from cubicweb.goa.goavreg import GAEVregistry from cubicweb.goa.goaconfig import GAEConfiguration from cubicweb.goa.dbinit import (create_user, create_groups, fix_entities, init_persistent_schema, insert_versions) @@ -115,7 +115,7 @@ self.config.init_log(logging.CRITICAL) self.schema = self.config.load_schema(self.MODEL_CLASSES, self.load_schema_hook) - self.vreg = GAERegistry(self.config) + self.vreg = GAEVregistry(self.config) self.vreg.schema = self.schema self.vreg.load_module(db) from cubicweb.goa.appobjects import sessions diff -r 5d4a943695d1 -r 18aec79ec3a3 goa/tools/laxctl.py --- a/goa/tools/laxctl.py Mon Aug 03 09:37:13 2009 +0200 +++ b/goa/tools/laxctl.py Mon Aug 03 10:50:57 2009 +0200 @@ -28,11 +28,11 @@ # apply monkey patches first from cubicweb.goa import do_monkey_patch do_monkey_patch() - from cubicweb.goa.goavreg import GAERegistry + from cubicweb.goa.goavreg import GAEVregistry from cubicweb.goa.goaconfig import GAEConfiguration #WebConfiguration.ext_resources['JAVASCRIPTS'].append('DATADIR/goa.js') config = GAEConfiguration('toto', applroot) - vreg = GAERegistry(config) + vreg = GAEVregistry(config) vreg.set_schema(config.load_schema()) return vreg diff -r 5d4a943695d1 -r 18aec79ec3a3 rset.py --- a/rset.py Mon Aug 03 09:37:13 2009 +0200 +++ b/rset.py Mon Aug 03 10:50:57 2009 +0200 @@ -83,8 +83,8 @@ try: return self._rsetactions[key] except KeyError: - actions = self.vreg.possible_vobjects('actions', self.req, - rset=self, **kwargs) + actions = self.vreg['actions'].possible_vobjects( + self.req, rset=self, **kwargs) self._rsetactions[key] = actions return actions @@ -383,7 +383,8 @@ pass # build entity instance etype = self.description[row][col] - entity = self.vreg.etype_class(etype)(req, self, row, col) + entity = self.vreg['etypes'].etype_class(etype)(req, rset=self, + row=row, col=col) entity.set_eid(eid) # cache entity req.set_entity_cache(entity) diff -r 5d4a943695d1 -r 18aec79ec3a3 schemaviewer.py --- a/schemaviewer.py Mon Aug 03 09:37:13 2009 +0200 +++ b/schemaviewer.py Mon Aug 03 10:50:57 2009 +0200 @@ -19,7 +19,7 @@ self.req = req if req is not None: self.req.add_css('cubicweb.schema.css') - self._possible_views = req.vreg.possible_views + self._possible_views = req.vreg['views'].possible_views if not encoding: encoding = req.encoding else: diff -r 5d4a943695d1 -r 18aec79ec3a3 selectors.py --- a/selectors.py Mon Aug 03 09:37:13 2009 +0200 +++ b/selectors.py Mon Aug 03 10:50:57 2009 +0200 @@ -165,7 +165,7 @@ if isinstance(iface, basestring): # entity type try: - iface = vreg.etype_class(iface) + iface = vreg['etypes'].etype_class(iface) except KeyError: continue # entity type not in the schema score += score_interface(cls_or_inst, cls, iface) @@ -212,7 +212,7 @@ def score(self, cls, req, etype): if etype in BASE_TYPES: return 0 - return self.score_class(cls.vreg.etype_class(etype), req) + return self.score_class(cls.vreg['etypes'].etype_class(etype), req) def score_class(self, eclass, req): raise NotImplementedError() @@ -570,9 +570,9 @@ self.registry = registry self.oid = oid - def __call__(self, cls, req, rset=None, *args, **kwargs): + def __call__(self, cls, req, **kwargs): try: - cls.vreg.select(self.registry, self.oid, req, rset=rset, **kwargs) + cls.vreg[self.registry].select(self.oid, req, **kwargs) return 1 except NoSelectableObject: return 0 @@ -630,7 +630,7 @@ req.form['etype'] = etype except KeyError: return 0 - return self.score_class(cls.vreg.etype_class(etype), req) + return self.score_class(cls.vreg['etypes'].etype_class(etype), req) class entity_implements(ImplementsMixIn, EntitySelector): diff -r 5d4a943695d1 -r 18aec79ec3a3 server/repository.py --- a/server/repository.py Mon Aug 03 09:37:13 2009 +0200 +++ b/server/repository.py Mon Aug 03 10:50:57 2009 +0200 @@ -33,7 +33,7 @@ BadConnectionId, Unauthorized, ValidationError, ExecutionError, typed_eid, CW_MIGRATION_MAP) -from cubicweb.cwvreg import CubicWebRegistry +from cubicweb.cwvreg import CubicWebVRegistry from cubicweb.schema import VIRTUAL_RTYPES, CubicWebSchema from cubicweb import server from cubicweb.server.utils import RepoThread, LoopTask @@ -137,7 +137,7 @@ def __init__(self, config, vreg=None, debug=False): self.config = config if vreg is None: - vreg = CubicWebRegistry(config, debug) + vreg = CubicWebVRegistry(config, debug) self.vreg = vreg self.pyro_registered = False self.info('starting repository from %s', self.config.apphome) @@ -428,7 +428,7 @@ def _build_user(self, session, eid): """return a CWUser entity for user with the given eid""" - cls = self.vreg.etype_class('CWUser') + cls = self.vreg['etypes'].etype_class('CWUser') rql = cls.fetch_rql(session.user, ['X eid %(x)s']) rset = session.execute(rql, {'x': eid}, 'x') assert len(rset) == 1, rset @@ -532,7 +532,7 @@ {'login': login})): raise ValidationError(None, {'login': errmsg % login}) # we have to create the user - user = self.vreg.etype_class('CWUser')(session, None) + user = self.vreg['etypes'].etype_class('CWUser')(session, None) if isinstance(password, unicode): # password should *always* be utf8 encoded password = password.encode('UTF8') diff -r 5d4a943695d1 -r 18aec79ec3a3 server/serverconfig.py --- a/server/serverconfig.py Mon Aug 03 09:37:13 2009 +0200 +++ b/server/serverconfig.py Mon Aug 03 10:50:57 2009 +0200 @@ -265,7 +265,7 @@ def load_hooks(self, vreg): hooks = {} try: - apphookdefs = vreg.registry_objects('hooks') + apphookdefs = vreg['hooks'].all_objects() except RegistryNotFound: return hooks for hookdef in apphookdefs: diff -r 5d4a943695d1 -r 18aec79ec3a3 server/session.py --- a/server/session.py Mon Aug 03 09:37:13 2009 +0200 +++ b/server/session.py Mon Aug 03 10:50:57 2009 +0200 @@ -142,10 +142,6 @@ """return the original parent session if any, else self""" return self - def etype_class(self, etype): - """return an entity class for the given entity type""" - return self.vreg.etype_class(etype) - def system_sql(self, sql, args=None, rollback_on_failure=True): """return a sql cursor on the system database""" if not sql.split(None, 1)[0].upper() == 'SELECT': @@ -555,6 +551,11 @@ description.append(tuple(row_descr)) return description + @deprecated("use vreg['etypes'].etype_class(etype)") + def etype_class(self, etype): + """return an entity class for the given entity type""" + return self.vreg['etypes'].etype_class(etype) + @deprecated('use direct access to session.transaction_data') def query_data(self, key, default=None, setdefault=False, pop=False): if setdefault: diff -r 5d4a943695d1 -r 18aec79ec3a3 server/sources/__init__.py --- a/server/sources/__init__.py Mon Aug 03 09:37:13 2009 +0200 +++ b/server/sources/__init__.py Mon Aug 03 10:50:57 2009 +0200 @@ -325,7 +325,7 @@ This method must return the an Entity instance representation of this entity. """ - entity = self.repo.vreg.etype_class(etype)(session, None) + entity = self.repo.vreg['etypes'].etype_class(etype)(session) entity.set_eid(eid) return entity diff -r 5d4a943695d1 -r 18aec79ec3a3 server/ssplanner.py --- a/server/ssplanner.py Mon Aug 03 09:37:13 2009 +0200 +++ b/server/ssplanner.py Mon Aug 03 10:50:57 2009 +0200 @@ -114,9 +114,10 @@ # each variable in main variables is a new entity to insert to_build = {} session = plan.session + etype_class = session.vreg['etypes'].etype_class for etype, var in rqlst.main_variables: # need to do this since entity class is shared w. web client code ! - to_build[var.name] = session.etype_class(etype)(session, None, None) + to_build[var.name] = etype_class(etype)(session) plan.add_entity_def(to_build[var.name]) # add constant values to entity def, mark variables to be selected to_select = plan.relation_definitions(rqlst, to_build) diff -r 5d4a943695d1 -r 18aec79ec3a3 server/test/unittest_repository.py --- a/server/test/unittest_repository.py Mon Aug 03 09:37:13 2009 +0200 +++ b/server/test/unittest_repository.py Mon Aug 03 10:50:57 2009 +0200 @@ -20,7 +20,7 @@ from cubicweb import BadConnectionId, RepositoryError, ValidationError, UnknownEid, AuthenticationError from cubicweb.schema import CubicWebSchema, RQLConstraint -from cubicweb.dbapi import connect, repo_connect +from cubicweb.dbapi import connect, repo_connect, multiple_connections_unfix from cubicweb.devtools.apptest import RepositoryBasedTC from cubicweb.devtools.repotest import tuplify from cubicweb.server import repository @@ -276,13 +276,17 @@ def _pyro_client(self, done): cnx = connect(self.repo.config.appid, u'admin', 'gingkow') - # check we can get the schema - schema = cnx.get_schema() - self.assertEquals(schema.__hashmode__, None) - cu = cnx.cursor() - rset = cu.execute('Any U,G WHERE U in_group G') - cnx.close() - done.append(True) + try: + # check we can get the schema + schema = cnx.get_schema() + self.assertEquals(schema.__hashmode__, None) + cu = cnx.cursor() + rset = cu.execute('Any U,G WHERE U in_group G') + cnx.close() + done.append(True) + finally: + # connect monkey path some method by default, remove them + multiple_connections_unfix() def test_internal_api(self): repo = self.repo @@ -367,7 +371,7 @@ self.assertRaises(UnknownEid, self.repo.type_from_eid, -2, self.session) def test_add_delete_info(self): - entity = self.repo.vreg.etype_class('Personne')(self.session, None, None) + entity = self.repo.vreg['etypes'].etype_class('Personne')(self.session) entity.eid = -1 entity.complete = lambda x: None self.repo.add_info(self.session, entity, self.repo.sources_by_uri['system']) diff -r 5d4a943695d1 -r 18aec79ec3a3 sobjects/notification.py --- a/sobjects/notification.py Mon Aug 03 09:37:13 2009 +0200 +++ b/sobjects/notification.py Mon Aug 03 10:50:57 2009 +0200 @@ -76,8 +76,8 @@ return rset = entity.related('wf_info_for') try: - view = session.vreg.select('views', 'notif_status_change', - session, rset=rset, row=0) + view = session.vreg['views'].select('notif_status_change', session, + rset=rset, row=0) except RegistryException: return comment = entity.printable_value('comment', format='text/plain') @@ -100,7 +100,7 @@ rset = session.eid_rset(fromeid) vid = 'notif_%s_%s' % (self.event, rtype) try: - view = session.vreg.select('views', vid, session, rset=rset, row=0) + view = session.vreg['views'].select(vid, session, rset=rset, row=0) except RegistryException: return RenderAndSendNotificationView(session, view=view) @@ -117,7 +117,7 @@ rset = entity.as_rset() vid = 'notif_%s' % self.event try: - view = session.vreg.select('views', vid, session, rset=rset, row=0) + view = session.vreg['views'].select(vid, session, rset=rset, row=0) except RegistryException: return RenderAndSendNotificationView(session, view=view) @@ -138,7 +138,7 @@ msgid_timestamp = True def recipients(self): - finder = self.vreg.select('components', 'recipients_finder', self.req, + finder = self.vreg['components'].select('recipients_finder', self.req, rset=self.rset) return finder.recipients() diff -r 5d4a943695d1 -r 18aec79ec3a3 sobjects/supervising.py --- a/sobjects/supervising.py Mon Aug 03 09:37:13 2009 +0200 +++ b/sobjects/supervising.py Mon Aug 03 10:50:57 2009 +0200 @@ -222,8 +222,8 @@ of changes """ def _get_view(self): - return self.session.vreg.select('components', 'supervision_notif', - self.session) + return self.session.vreg['components'].select('supervision_notif', + self.session) def _prepare_email(self): session = self.session diff -r 5d4a943695d1 -r 18aec79ec3a3 sobjects/test/unittest_notification.py --- a/sobjects/test/unittest_notification.py Mon Aug 03 09:37:13 2009 +0200 +++ b/sobjects/test/unittest_notification.py Mon Aug 03 10:50:57 2009 +0200 @@ -56,8 +56,8 @@ self.execute('INSERT CWProperty X: X pkey "ui.language", X value "fr", X for_user U ' 'WHERE U eid %(x)s', {'x': urset[0][0]}) self.commit() # commit so that admin get its properties updated - finder = self.vreg.select('components', 'recipients_finder', self.request(), - rset=urset) + finder = self.vreg['components'].select('recipients_finder', + self.request(), rset=urset) self.set_option('default-recipients-mode', 'none') self.assertEquals(finder.recipients(), []) self.set_option('default-recipients-mode', 'users') @@ -73,8 +73,9 @@ req = self.session() u = self.create_user('toto', req=req) assert u.req + assert u.rset self.execute('SET X in_state S WHERE X eid %s, S name "deactivated"' % u.eid) - v = self.vreg.select('views', 'notif_status_change', req, rset=u.rset, row=0) + v = self.vreg['views'].select('notif_status_change', req, rset=u.rset, row=0) content = v.render(row=0, comment='yeah', previous_state='activated', current_state='deactivated') diff -r 5d4a943695d1 -r 18aec79ec3a3 test/unittest_entity.py --- a/test/unittest_entity.py Mon Aug 03 09:37:13 2009 +0200 +++ b/test/unittest_entity.py Mon Aug 03 10:50:57 2009 +0200 @@ -121,9 +121,9 @@ def test_fetch_rql(self): user = self.user() - Personne = self.vreg.etype_class('Personne') - Societe = self.vreg.etype_class('Societe') - Note = self.vreg.etype_class('Note') + Personne = self.vreg['etypes'].etype_class('Personne') + Societe = self.vreg['etypes'].etype_class('Societe') + Note = self.vreg['etypes'].etype_class('Note') peschema = Personne.e_schema seschema = Societe.e_schema peschema.subject_relation('travaille').set_rproperty(peschema, seschema, 'cardinality', '1*') @@ -175,8 +175,8 @@ def test_related_rql(self): from cubicweb.entities import fetch_config - Personne = self.vreg.etype_class('Personne') - Note = self.vreg.etype_class('Note') + Personne = self.vreg['etypes'].etype_class('Personne') + Note = self.vreg['etypes'].etype_class('Note') Personne.fetch_attrs, Personne.fetch_order = fetch_config(('nom', 'type')) Note.fetch_attrs, Note.fetch_order = fetch_config(('type',)) aff = self.add_entity('Personne', nom=u'pouet') diff -r 5d4a943695d1 -r 18aec79ec3a3 test/unittest_vregistry.py --- a/test/unittest_vregistry.py Mon Aug 03 09:37:13 2009 +0200 +++ b/test/unittest_vregistry.py Mon Aug 03 10:50:57 2009 +0200 @@ -11,7 +11,7 @@ from cubicweb import CW_SOFTWARE_ROOT as BASE from cubicweb.vregistry import VObject -from cubicweb.cwvreg import CubicWebRegistry, UnknownProperty +from cubicweb.cwvreg import CubicWebVRegistry, UnknownProperty from cubicweb.devtools import TestServerConfiguration from cubicweb.interfaces import IMileStone @@ -27,7 +27,7 @@ def setUp(self): config = TestServerConfiguration('data') - self.vreg = CubicWebRegistry(config) + self.vreg = CubicWebVRegistry(config) config.bootstrap_cubes() self.vreg.schema = config.load_schema() diff -r 5d4a943695d1 -r 18aec79ec3a3 vregistry.py --- a/vregistry.py Mon Aug 03 09:37:13 2009 +0200 +++ b/vregistry.py Mon Aug 03 10:50:57 2009 +0200 @@ -28,6 +28,8 @@ from logging import getLogger from warnings import warn +from logilab.common.deprecation import deprecated + from cubicweb import CW_SOFTWARE_ROOT, set_log_methods from cubicweb import RegistryNotFound, ObjectNotFound, NoSelectableObject @@ -125,97 +127,111 @@ cls.__select__ = select -class VRegistry(object): - """class responsible to register, propose and select the various - elements used to build the web interface. Currently, we have templates, - views, actions and components. - """ - - def __init__(self, config):#, cache_size=1000): - self.config = config - # dictionnary of registry (themself dictionnary) by name - self._registries = {} - self._lastmodifs = {} - - def reset(self): - self._registries = {} - self._lastmodifs = {} +class Registry(dict): - def __getitem__(self, key): - return self._registries[key] - - def get(self, key, default=None): - return self._registries.get(key, default) + def __init__(self, config): + super(Registry, self).__init__() + self.config = config - def items(self): - return self._registries.items() - - def values(self): - return self._registries.values() - - def __contains__(self, key): - return key in self._registries - - def registry(self, name): + def __getitem__(self, name): """return the registry (dictionary of class objects) associated to this name """ try: - return self._registries[name] + return super(Registry, self).__getitem__(name) except KeyError: - raise RegistryNotFound(name), None, sys.exc_info()[-1] + raise ObjectNotFound(name), None, sys.exc_info()[-1] + + def register(self, obj, oid=None, clear=False): + """base method to add an object in the registry""" + assert not '__abstract__' in obj.__dict__ + oid = oid or obj.id + assert oid + if clear: + vobjects = self[oid] = [] + else: + vobjects = self.setdefault(oid, []) + # registered() is technically a classmethod but is not declared + # as such because we need to compose registered in some cases + vobject = obj.registered.im_func(obj, self) + assert not vobject in vobjects, \ + 'object %s is already registered' % vobject + assert callable(vobject.__select__), vobject + vobjects.append(vobject) - def registry_objects(self, name, oid=None): - """returns objects registered with the given oid in the given registry. - If no oid is given, return all objects in this registry + def register_and_replace(self, obj, replaced): + # XXXFIXME this is a duplication of unregister() + # remove register_and_replace in favor of unregister + register + # or simplify by calling unregister then register here + if hasattr(replaced, 'classid'): + replaced = replaced.classid() + registered_objs = self.get(obj.id, ()) + for index, registered in enumerate(registered_objs): + if registered.classid() == replaced: + del registered_objs[index] + break + else: + self.warning('trying to replace an unregistered view %s by %s', + replaced, obj) + self.register(obj) + + def unregister(self, obj): + oid = obj.classid() + for registered in self.get(obj.id, ()): + # use classid() to compare classes because vreg will probably + # have its own version of the class, loaded through execfile + if registered.classid() == oid: + # XXX automatic reloading management + self[obj.id].remove(registered) + break + else: + self.warning('can\'t remove %s, no id %s in the registry', + oid, obj.id) + + def all_objects(self): + """return a list containing all objects in this registry. """ - registry = self.registry(name) - if oid is not None: - try: - return registry[oid] - except KeyError: - raise ObjectNotFound(oid), None, sys.exc_info()[-1] result = [] - for objs in registry.values(): + for objs in self.values(): result += objs return result # dynamic selection methods ################################################ - def object_by_id(self, registry, oid, *args, **kwargs): - """return object in . + def object_by_id(self, oid, *args, **kwargs): + """return object with the given oid. Only one object is expected to be + found. raise `ObjectNotFound` if not object with id in raise `AssertionError` if there is more than one object there """ - objects = self.registry_objects(registry, oid) + objects = self[oid] assert len(objects) == 1, objects return objects[0].selected(*args, **kwargs) - def select(self, registry, oid, *args, **kwargs): - """return the most specific object in . according to - the given context + def select(self, oid, *args, **kwargs): + """return the most specific object among those with the given oid + according to the given context. raise `ObjectNotFound` if not object with id in raise `NoSelectableObject` if not object apply """ - return self.select_best(self.registry_objects(registry, oid), - *args, **kwargs) + return self.select_best(self[oid], *args, **kwargs) - def select_object(self, registry, oid, *args, **kwargs): - """return the most specific object in . according to - the given context, or None if no object apply + def select_object(self, oid, *args, **kwargs): + """return the most specific object among those with the given oid + according to the given context, or None if no object applies. """ try: - return self.select(registry, oid, *args, **kwargs) + return self.select(oid, *args, **kwargs) except (NoSelectableObject, ObjectNotFound): return None - def possible_objects(self, registry, *args, **kwargs): - """return an iterator on possible objects in for the given + def possible_objects(self, *args, **kwargs): + """return an iterator on possible objects in this registry for the given context """ - for vobjects in self.registry(registry).itervalues(): + for vobjects in self.itervalues(): try: yield self.select_best(vobjects, *args, **kwargs) except NoSelectableObject: @@ -252,8 +268,83 @@ # return the result of the .selected method of the vobject return winners[0].selected(*args, **kwargs) + +class VRegistry(dict): + """class responsible to register, propose and select the various + elements used to build the web interface. Currently, we have templates, + views, actions and components. + """ + + def __init__(self, config): + super(VRegistry, self).__init__() + self.config = config + + def reset(self): + self.clear() + self._lastmodifs = {} + + def __getitem__(self, name): + """return the registry (dictionary of class objects) associated to + this name + """ + try: + return super(VRegistry, self).__getitem__(name) + except KeyError: + raise RegistryNotFound(name), None, sys.exc_info()[-1] + + # dynamic selection methods ################################################ + + @deprecated('use vreg[registry].object_by_id(oid, *args, **kwargs)') + def object_by_id(self, registry, oid, *args, **kwargs): + """return object in . + + raise `ObjectNotFound` if not object with id in + raise `AssertionError` if there is more than one object there + """ + return self[registry].object_by_id(oid) + + @deprecated('use vreg[registry].select(oid, *args, **kwargs)') + def select(self, registry, oid, *args, **kwargs): + """return the most specific object in . according to + the given context + + raise `ObjectNotFound` if not object with id in + raise `NoSelectableObject` if not object apply + """ + return self[registry].select(oid, *args, **kwargs) + + @deprecated('use vreg[registry].select_object(oid, *args, **kwargs)') + def select_object(self, registry, oid, *args, **kwargs): + """return the most specific object in . according to + the given context, or None if no object apply + """ + return self[registry].select_object(oid, *args, **kwargs) + + @deprecated('use vreg[registry].possible_objects(*args, **kwargs)') + def possible_objects(self, registry, *args, **kwargs): + """return an iterator on possible objects in for the given + context + """ + return self[registry].possible_objects(*args, **kwargs) + # methods for explicit (un)registration ################################### + # default class, when no specific class set + REGISTRY_FACTORY = {None: Registry} + + def registry_class(self, regid): + try: + return self.REGISTRY_FACTORY[regid] + except KeyError: + return self.REGISTRY_FACTORY[None] + + def setdefault(self, regid): + try: + return self[regid] + except KeyError: + self[regid] = self.registry_class(regid)(self.config) + return self[regid] + # def clear(self, key): # regname, oid = key.split('.') # self[regname].pop(oid, None) @@ -273,63 +364,24 @@ """base method to add an object in the registry""" assert not '__abstract__' in obj.__dict__ registryname = registryname or obj.__registry__ - oid = oid or obj.id - assert oid - registry = self._registries.setdefault(registryname, {}) - if clear: - vobjects = registry[oid] = [] - else: - vobjects = registry.setdefault(oid, []) - # registered() is technically a classmethod but is not declared - # as such because we need to compose registered in some cases - vobject = obj.registered.im_func(obj, self) - assert not vobject in vobjects, \ - 'object %s is already registered' % vobject - assert callable(vobject.__select__), vobject - vobjects.append(vobject) + registry = self.setdefault(registryname) + registry.register(obj, oid=oid, clear=clear) try: - vname = vobject.__name__ + vname = obj.__name__ except AttributeError: - vname = vobject.__class__.__name__ + vname = obj.__class__.__name__ self.debug('registered vobject %s in registry %s with id %s', vname, registryname, oid) # automatic reloading management self._loadedmods[obj.__module__]['%s.%s' % (obj.__module__, oid)] = obj def unregister(self, obj, registryname=None): - registryname = registryname or obj.__registry__ - registry = self.registry(registryname) - removed_id = obj.classid() - for registered in registry.get(obj.id, ()): - # use classid() to compare classes because vreg will probably - # have its own version of the class, loaded through execfile - if registered.classid() == removed_id: - # XXX automatic reloading management - registry[obj.id].remove(registered) - break - else: - self.warning('can\'t remove %s, no id %s in the %s registry', - removed_id, obj.id, registryname) + self[registryname or obj.__registry__].unregister(obj) def register_and_replace(self, obj, replaced, registryname=None): - # XXXFIXME this is a duplication of unregister() - # remove register_and_replace in favor of unregister + register - # or simplify by calling unregister then register here - if hasattr(replaced, 'classid'): - replaced = replaced.classid() - registryname = registryname or obj.__registry__ - registry = self.registry(registryname) - registered_objs = registry.get(obj.id, ()) - for index, registered in enumerate(registered_objs): - if registered.classid() == replaced: - del registry[obj.id][index] - break - else: - self.warning('trying to replace an unregistered view %s by %s', - replaced, obj) - self.register(obj, registryname=registryname) + self[registryname or obj.__registry__].register_and_replace(obj, replaced) - # intialization methods ################################################### + # initialization methods ################################################### def init_registration(self, path, extrapath=None): # compute list of all modules that have to be loaded @@ -521,8 +573,9 @@ obj.__bases__ = newbases # init logging -set_log_methods(VObject, getLogger('cubicweb')) -set_log_methods(VRegistry, getLogger('cubicweb.registry')) +set_log_methods(VObject, getLogger('cubicweb.appobject')) +set_log_methods(VRegistry, getLogger('cubicweb.vreg')) +set_log_methods(Registry, getLogger('cubicweb.registry')) # selector base classes and operations ######################################## diff -r 5d4a943695d1 -r 18aec79ec3a3 web/application.py --- a/web/application.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/application.py Mon Aug 03 10:50:57 2009 +0200 @@ -41,7 +41,7 @@ if self.session_time: assert self.cleanup_session_time < self.session_time assert self.cleanup_anon_session_time < self.session_time - self.authmanager = self.vreg.select('components', 'authmanager') + self.authmanager = self.vreg['components'].select('authmanager') def clean_sessions(self): """cleanup sessions which has not been unused since a given amount of @@ -112,7 +112,7 @@ SESSION_VAR = '__session' def __init__(self, appli): - self.session_manager = appli.vreg.select('components', 'sessionmanager') + self.session_manager = appli.vreg['components'].select('sessionmanager') global SESSION_MANAGER SESSION_MANAGER = self.session_manager if not 'last_login_time' in appli.vreg.schema: @@ -239,7 +239,7 @@ self.publish = self.main_publish # instantiate session and url resolving helpers self.session_handler = session_handler_fact(self) - self.url_resolver = vreg.select('components', 'urlpublisher') + self.url_resolver = vreg['components'].select('urlpublisher') def connect(self, req): """return a connection for a logged user object according to existing @@ -275,7 +275,7 @@ @deprecated("use vreg.select('controllers', ...)") def select_controller(self, oid, req): try: - return self.vreg.select('controllers', oid, req=req, appli=self) + return self.vreg['controllers'].select(oid, req=req, appli=self) except NoSelectableObject: raise Unauthorized(req._('not authorized')) @@ -304,8 +304,8 @@ try: ctrlid, rset = self.url_resolver.process(req, path) try: - controller = self.vreg.select('controllers', ctrlid, req, - appli=self) + controller = self.vreg['controllers'].select(ctrlid, req, + appli=self) except NoSelectableObject: raise Unauthorized(req._('not authorized')) req.update_search_state() @@ -375,28 +375,28 @@ if tb: req.data['excinfo'] = excinfo req.form['vid'] = 'error' - errview = self.vreg.select('views', 'error', req) + errview = self.vreg['views'].select('error', req) template = self.main_template_id(req) - content = self.vreg.main_template(req, template, view=errview) + content = self.vreg['views'].main_template(req, template, view=errview) except: - content = self.vreg.main_template(req, 'error-template') + content = self.vreg['views'].main_template(req, 'error-template') raise StatusResponse(500, content) def need_login_content(self, req): - return self.vreg.main_template(req, 'login') + return self.vreg['views'].main_template(req, 'login') def loggedout_content(self, req): - return self.vreg.main_template(req, 'loggedout') + return self.vreg['views'].main_template(req, 'loggedout') def notfound_content(self, req): req.form['vid'] = '404' - view = self.vreg.select('views', '404', req) + view = self.vreg['views'].select('404', req) template = self.main_template_id(req) - return self.vreg.main_template(req, template, view=view) + return self.vreg['views'].main_template(req, template, view=view) def main_template_id(self, req): template = req.form.get('__template', req.property_value('ui.main-template')) - if template not in self.vreg.registry('views'): + if template not in self.vreg['views']: template = 'main-template' return template diff -r 5d4a943695d1 -r 18aec79ec3a3 web/controller.py --- a/web/controller.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/controller.py Mon Aug 03 10:50:57 2009 +0200 @@ -92,7 +92,7 @@ self.ensure_ro_rql(rql) if not isinstance(rql, unicode): rql = unicode(rql, self.req.encoding) - pp = self.vreg.select_object('components', 'magicsearch', self.req) + pp = self.vreg['components'].select_object('magicsearch', self.req) if pp is not None: self.rset = pp.process_query(rql, self.req) return self.rset diff -r 5d4a943695d1 -r 18aec79ec3a3 web/facet.py --- a/web/facet.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/facet.py Mon Aug 03 10:50:57 2009 +0200 @@ -64,8 +64,8 @@ def get_facet(req, facetid, rqlst, mainvar): - return req.vreg.object_by_id('facets', facetid, req, rqlst=rqlst, - filtered_variable=mainvar) + return req.vreg['facets'].object_by_id(facetid, req, rqlst=rqlst, + filtered_variable=mainvar) def filter_hiddens(w, **kwargs): diff -r 5d4a943695d1 -r 18aec79ec3a3 web/request.py --- a/web/request.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/request.py Mon Aug 03 10:50:57 2009 +0200 @@ -539,8 +539,7 @@ def from_controller(self): """return the id (string) of the controller issuing the request""" controller = self.relative_path(False).split('/', 1)[0] - registered_controllers = (ctrl.id for ctrl in - self.vreg.registry_objects('controllers')) + registered_controllers = self.vreg['controllers'].keys() if controller in registered_controllers: return controller return 'view' diff -r 5d4a943695d1 -r 18aec79ec3a3 web/test/unittest_views_actions.py --- a/web/test/unittest_views_actions.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/test/unittest_views_actions.py Mon Aug 03 10:50:57 2009 +0200 @@ -13,19 +13,19 @@ def test_view_action(self): req = self.request(__message='bla bla bla', vid='rss', rql='CWUser X') rset = self.execute('CWUser X') - vaction = [action for action in self.vreg.possible_vobjects('actions', req, rset=rset) + vaction = [action for action in self.vreg['actions'].possible_vobjects(req, rset=rset) if action.id == 'view'][0] self.assertEquals(vaction.url(), 'http://testing.fr/cubicweb/view?rql=CWUser%20X') def test_sendmail_action(self): req = self.request() rset = self.execute('Any X WHERE X login "admin"', req=req) - self.failUnless([action for action in self.vreg.possible_vobjects('actions', req, rset=rset) + self.failUnless([action for action in self.vreg['actions'].possible_vobjects(req, rset=rset) if action.id == 'sendemail']) self.login('anon') req = self.request() rset = self.execute('Any X WHERE X login "anon"', req=req) - self.failIf([action for action in self.vreg.possible_vobjects('actions', req, rset=rset) + self.failIf([action for action in self.vreg['actions'].possible_vobjects(req, rset=rset) if action.id == 'sendemail']) if __name__ == '__main__': diff -r 5d4a943695d1 -r 18aec79ec3a3 web/test/unittest_views_basetemplates.py --- a/web/test/unittest_views_basetemplates.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/test/unittest_views_basetemplates.py Mon Aug 03 10:50:57 2009 +0200 @@ -13,7 +13,7 @@ def _login_labels(self): valid = self.content_type_validators.get('text/html', DTDValidator)() - page = valid.parse_string(self.vreg.main_template(self.request(), 'login')) + page = valid.parse_string(self.vreg['views'].main_template(self.request(), 'login')) return page.find_tag('label') def test_label(self): diff -r 5d4a943695d1 -r 18aec79ec3a3 web/test/unittest_views_baseviews.py --- a/web/test/unittest_views_baseviews.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/test/unittest_views_baseviews.py Mon Aug 03 10:50:57 2009 +0200 @@ -91,7 +91,7 @@ rset = self.execute('Any X, D, CD, NOW - CD WHERE X is State, X description D, X creation_date CD, X eid %(x)s', {'x': e.eid}, 'x') req = self.request() - view = self.vreg.select('views', 'table', req, rset=rset) + view = self.vreg['views'].select('table', req, rset=rset) return e, rset, view def test_headers(self): diff -r 5d4a943695d1 -r 18aec79ec3a3 web/test/unittest_views_pyviews.py --- a/web/test/unittest_views_pyviews.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/test/unittest_views_pyviews.py Mon Aug 03 10:50:57 2009 +0200 @@ -4,9 +4,9 @@ class PyViewsTC(EnvBasedTC): def test_pyvaltable(self): - content = self.vreg.render('pyvaltable', self.request(), - pyvalue=[[1, 'a'], [2, 'b']], - headers=['num', 'char']) + content = self.vreg['views'].render('pyvaltable', self.request(), + pyvalue=[[1, 'a'], [2, 'b']], + headers=['num', 'char']) self.assertEquals(content.strip(), ''' @@ -14,8 +14,8 @@
numchar
1a
''') def test_pyvallist(self): - content = self.vreg.render('pyvallist', self.request(), - pyvalue=[1, 'a']) + content = self.vreg['views'].render('pyvallist', self.request(), + pyvalue=[1, 'a']) self.assertEquals(content.strip(), '''
  • 1
  • a
  • diff -r 5d4a943695d1 -r 18aec79ec3a3 web/test/unittest_viewselector.py --- a/web/test/unittest_viewselector.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/test/unittest_viewselector.py Mon Aug 03 10:50:57 2009 +0200 @@ -35,7 +35,7 @@ self.add_entity('Tag', name=u'x') def pactions(self, req, rset): - resdict = self.vreg.possible_actions(req, rset) + resdict = self.vreg['actions'].possible_actions(req, rset) for cat, actions in resdict.items(): resdict[cat] = [(a.id, a.__class__) for a in actions] return resdict @@ -132,26 +132,26 @@ assert self.vreg['views']['propertiesform'] rset1, req1 = self.env.get_rset_and_req('CWUser X WHERE X login "admin"') rset2, req2 = self.env.get_rset_and_req('CWUser X WHERE X login "anon"') - self.failUnless(self.vreg.select('views', 'propertiesform', req1, rset=None)) - self.failUnless(self.vreg.select('views', 'propertiesform', req1, rset=rset1)) - self.failUnless(self.vreg.select('views', 'propertiesform', req2, rset=rset2)) + self.failUnless(self.vreg['views'].select('propertiesform', req1, rset=None)) + self.failUnless(self.vreg['views'].select('propertiesform', req1, rset=rset1)) + self.failUnless(self.vreg['views'].select('propertiesform', req2, rset=rset2)) def test_propertiesform_anon(self): self.login('anon') rset1, req1 = self.env.get_rset_and_req('CWUser X WHERE X login "admin"') rset2, req2 = self.env.get_rset_and_req('CWUser X WHERE X login "anon"') - self.assertRaises(NoSelectableObject, self.vreg.select, 'views', 'propertiesform', req1, rset=None) - self.assertRaises(NoSelectableObject, self.vreg.select, 'views', 'propertiesform', req1, rset=rset1) - self.assertRaises(NoSelectableObject, self.vreg.select, 'views', 'propertiesform', req1, rset=rset2) + self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'propertiesform', req1, rset=None) + self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'propertiesform', req1, rset=rset1) + self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'propertiesform', req1, rset=rset2) def test_propertiesform_jdoe(self): self.create_user('jdoe') self.login('jdoe') rset1, req1 = self.env.get_rset_and_req('CWUser X WHERE X login "admin"') rset2, req2 = self.env.get_rset_and_req('CWUser X WHERE X login "jdoe"') - self.failUnless(self.vreg.select('views', 'propertiesform', req1, rset=None)) - self.assertRaises(NoSelectableObject, self.vreg.select, 'views', 'propertiesform', req1, rset=rset1) - self.failUnless(self.vreg.select('views', 'propertiesform', req2, rset=rset2)) + self.failUnless(self.vreg['views'].select('propertiesform', req1, rset=None)) + self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'propertiesform', req1, rset=rset1) + self.failUnless(self.vreg['views'].select('propertiesform', req2, rset=rset2)) def test_possible_views_multiple_different_types(self): rset, req = self.env.get_rset_and_req('Any X') @@ -267,7 +267,7 @@ req = self.request() # creation form req.form['etype'] = 'CWGroup' - self.assertIsInstance(self.vreg.select('views', 'creation', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('creation', req, rset=rset), editforms.CreationFormView) del req.form['etype'] # custom creation form @@ -276,94 +276,94 @@ self.vreg._loadedmods[__name__] = {} self.vreg.register_vobject_class(CWUserCreationForm) req.form['etype'] = 'CWUser' - self.assertIsInstance(self.vreg.select('views', 'creation', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('creation', req, rset=rset), CWUserCreationForm) def test_select_view(self): # no entity rset = None req = self.request() - self.assertIsInstance(self.vreg.select('views', 'index', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('index', req, rset=rset), startup.IndexView) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'primary', req, rset=rset) + self.vreg['views'].select, 'primary', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'table', req, rset=rset) + self.vreg['views'].select, 'table', req, rset=rset) # no entity rset, req = self.env.get_rset_and_req('Any X WHERE X eid 999999') self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'index', req, rset=rset) + self.vreg['views'].select, 'index', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'creation', req, rset=rset) + self.vreg['views'].select, 'creation', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'primary', req, rset=rset) + self.vreg['views'].select, 'primary', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'table', req, rset=rset) + self.vreg['views'].select, 'table', req, rset=rset) # one entity rset, req = self.env.get_rset_and_req('CWGroup X WHERE X name "managers"') - self.assertIsInstance(self.vreg.select('views', 'primary', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('primary', req, rset=rset), primary.PrimaryView) - self.assertIsInstance(self.vreg.select('views', 'list', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('list', req, rset=rset), baseviews.ListView) - self.assertIsInstance(self.vreg.select('views', 'edition', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('edition', req, rset=rset), editforms.EditionFormView) - self.assertIsInstance(self.vreg.select('views', 'table', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('table', req, rset=rset), tableview.TableView) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'creation', req, rset=rset) + self.vreg['views'].select, 'creation', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'index', req, rset=rset) + self.vreg['views'].select, 'index', req, rset=rset) # list of entities of the same type rset, req = self.env.get_rset_and_req('CWGroup X') - self.assertIsInstance(self.vreg.select('views', 'primary', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('primary', req, rset=rset), primary.PrimaryView) - self.assertIsInstance(self.vreg.select('views', 'list', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('list', req, rset=rset), baseviews.ListView) - self.assertIsInstance(self.vreg.select('views', 'table', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('table', req, rset=rset), tableview.TableView) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'creation', req, rset=rset) + self.vreg['views'].select, 'creation', req, rset=rset) # list of entities of different types rset, req = self.env.get_rset_and_req('Any X') - self.assertIsInstance(self.vreg.select('views', 'primary', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('primary', req, rset=rset), primary.PrimaryView) - self.assertIsInstance(self.vreg.select('views', 'list', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('list', req, rset=rset), baseviews.ListView) - self.assertIsInstance(self.vreg.select('views', 'table', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('table', req, rset=rset), tableview.TableView) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'creation', req, rset=rset) + self.vreg['views'].select, 'creation', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'index', req, rset=rset) + self.vreg['views'].select, 'index', req, rset=rset) # whatever rset, req = self.env.get_rset_and_req('Any N, X WHERE X in_group Y, Y name N') - self.assertIsInstance(self.vreg.select('views', 'table', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('table', req, rset=rset), tableview.TableView) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'index', req, rset=rset) + self.vreg['views'].select, 'index', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'creation', req, rset=rset) + self.vreg['views'].select, 'creation', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'primary', req, rset=rset) + self.vreg['views'].select, 'primary', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'list', req, rset=rset) + self.vreg['views'].select, 'list', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'edition', req, rset=rset) + self.vreg['views'].select, 'edition', req, rset=rset) # mixed query rset, req = self.env.get_rset_and_req('Any U,G WHERE U is CWUser, G is CWGroup') self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'edition', req, rset=rset) + self.vreg['views'].select, 'edition', req, rset=rset) self.failUnlessRaises(NoSelectableObject, - self.vreg.select, 'views', 'creation', req, rset=rset) - self.assertIsInstance(self.vreg.select('views', 'table', req, rset=rset), + self.vreg['views'].select, 'creation', req, rset=rset) + self.assertIsInstance(self.vreg['views'].select('table', req, rset=rset), tableview.TableView) def test_interface_selector(self): image = self.add_entity('Image', name=u'bim.png', data=Binary('bim')) # image primary view priority rset, req = self.env.get_rset_and_req('Image X WHERE X name "bim.png"') - self.assertIsInstance(self.vreg.select('views', 'primary', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('primary', req, rset=rset), idownloadable.IDownloadablePrimaryView) @@ -371,12 +371,12 @@ image = self.add_entity('Image', name=u'bim.png', data=Binary('bim')) # image primary view priority rset, req = self.env.get_rset_and_req('Image X WHERE X name "bim.png"') - self.assertIsInstance(self.vreg.select('views', 'image', req, rset=rset), + self.assertIsInstance(self.vreg['views'].select('image', req, rset=rset), idownloadable.ImageView) fileobj = self.add_entity('File', name=u'bim.txt', data=Binary('bim')) # image primary view priority rset, req = self.env.get_rset_and_req('File X WHERE X name "bim.txt"') - self.assertRaises(NoSelectableObject, self.vreg.select, 'views', 'image', req, rset=rset) + self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'image', req, rset=rset) @@ -387,7 +387,7 @@ else: rset, req = self.env.get_rset_and_req(rql) try: - self.vreg.render(vid, req, rset=rset, **args) + self.vreg['views'].render(vid, req, rset=rset, **args) except: print vid, rset, args raise @@ -435,7 +435,7 @@ def tearDown(self): super(RQLActionTC, self).tearDown() - del self.vreg._registries['actions']['testaction'] + del self.vreg['actions']['testaction'] def test(self): rset, req = self.env.get_rset_and_req('CWEType X WHERE X name "CWEType"') diff -r 5d4a943695d1 -r 18aec79ec3a3 web/views/basecomponents.py --- a/web/views/basecomponents.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/views/basecomponents.py Mon Aug 03 10:50:57 2009 +0200 @@ -90,7 +90,7 @@ def call(self): if not self.req.cnx.anonymous_connection: # display useractions and siteactions - actions = self.vreg.possible_actions(self.req, self.rset) + actions = self.vreg['actions'].possible_actions(self.req, rset=self.rset) box = MenuWidget('', 'userActionsBox', _class='', islist=False) menu = PopupBoxMenu(self.req.user.login, isitem=False) box.append(menu) diff -r 5d4a943695d1 -r 18aec79ec3a3 web/views/basecontrollers.py --- a/web/views/basecontrollers.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/views/basecontrollers.py Mon Aug 03 10:50:57 2009 +0200 @@ -100,7 +100,8 @@ self.add_to_breadcrumbs(view) self.validate_cache(view) template = self.appli.main_template_id(self.req) - return self.vreg.main_template(self.req, template, rset=rset, view=view) + return self.vreg['views'].main_template(self.req, template, + rset=rset, view=view) def _select_view_and_rset(self, rset): req = self.req @@ -119,12 +120,12 @@ req.set_message(req._("error while handling __method: %s") % req._(ex)) vid = req.form.get('vid') or vid_from_rset(req, rset, self.schema) try: - view = self.vreg.select('views', vid, req, rset=rset) + view = self.vreg['views'].select(vid, req, rset=rset) except ObjectNotFound: self.warning("the view %s could not be found", vid) req.set_message(req._("The view %s could not be found") % vid) vid = vid_from_rset(req, rset, self.schema) - view = self.vreg.select('views', vid, req, rset=rset) + view = self.vreg['views'].select(vid, req, rset=rset) except NoSelectableObject: if rset: req.set_message(req._("The view %s can not be applied to this query") % vid) @@ -132,7 +133,7 @@ req.set_message(req._("You have no access to this view or it's not applyable to current data")) self.warning("the view %s can not be applied to this query", vid) vid = vid_from_rset(req, rset, self.schema) - view = self.vreg.select('views', vid, req, rset=rset) + view = self.vreg['views'].select(vid, req, rset=rset) return view, rset def add_to_breadcrumbs(self, view): @@ -183,7 +184,7 @@ def _validate_form(req, vreg): # XXX should use the `RemoteCallFailed` mechanism try: - ctrl = vreg.select('controllers', 'edit', req=req) + ctrl = vreg['controllers'].select('edit', req=req) except NoSelectableObject: return (False, {None: req._('not authorized')}) try: @@ -309,10 +310,10 @@ rset = None vid = req.form.get('vid') or vid_from_rset(req, rset, self.schema) try: - view = self.vreg.select('views', vid, req, rset=rset) + view = self.vreg['views'].select(vid, req, rset=rset) except NoSelectableObject: vid = req.form.get('fallbackvid', 'noresult') - view = self.vreg.select('views', vid, req, rset=rset) + view = self.vreg['views'].select(vid, req, rset=rset) divid = req.form.get('divid', 'pageContent') # we need to call pagination before with the stream set stream = view.set_stream() @@ -339,10 +340,10 @@ @xhtmlize def js_prop_widget(self, propkey, varname, tabindex=None): """specific method for CWProperty handling""" - entity = self.vreg.etype_class('CWProperty')(self.req, None, None) + entity = self.vreg['etypes'].etype_class('CWProperty')(self.req) entity.eid = varname entity['pkey'] = propkey - form = self.vreg.select('forms', 'edition', self.req, entity=entity) + form = self.vreg['forms'].select('edition', self.req, entity=entity) form.form_build_context() vfield = form.field_by_name('value') renderer = FormRenderer(self.req) @@ -355,7 +356,7 @@ rset = self._exec(rql) else: rset = None - comp = self.vreg.select(registry, compid, self.req, rset=rset) + comp = self.vreg[registry].select(compid, self.req, rset=rset) if extraargs is None: extraargs = {} else: # we receive unicode keys which is not supported by the **syntax @@ -367,8 +368,9 @@ @check_pageid @xhtmlize def js_inline_creation_form(self, peid, ttype, rtype, role): - view = self.vreg.select('views', 'inline-creation', self.req, - etype=ttype, peid=peid, rtype=rtype, role=role) + view = self.vreg['views'].select('inline-creation', self.req, + etype=ttype, peid=peid, rtype=rtype, + role=role) return view.render(etype=ttype, peid=peid, rtype=rtype, role=role) @jsonize diff -r 5d4a943695d1 -r 18aec79ec3a3 web/views/basetemplates.py --- a/web/views/basetemplates.py Mon Aug 03 09:37:13 2009 +0200 +++ b/web/views/basetemplates.py Mon Aug 03 10:50:57 2009 +0200 @@ -113,8 +113,8 @@ if vtitle: w(u'

    %s

    \n' % xml_escape(vtitle)) # display entity type restriction component - etypefilter = self.vreg.select_vobject('components', 'etypenavigation', - self.req, rset=self.rset) + etypefilter = self.vreg['components'].select_vobject( + 'etypenavigation', self.req, rset=self.rset) if etypefilter: etypefilter.render(w=w) self.nav_html = UStringIO() @@ -154,12 +154,12 @@ w(u'
    \n') self.nav_column(view, 'left') w(u'
    \n') - rqlcomp = self.vreg.select_object('components', 'rqlinput', self.req, - rset=self.rset) + rqlcomp = self.vreg['components'].select_object('rqlinput', self.req, + rset=self.rset) if rqlcomp: rqlcomp.render(w=self.w, view=view) - msgcomp = self.vreg.select_object('components', 'applmessages', - self.req, rset=self.rset) + msgcomp = self.vreg['components'].select_object('applmessages', + self.req, rset=self.rset) if msgcomp: msgcomp.render(w=self.w) self.content_header(view) @@ -173,8 +173,8 @@ self.w(u'') def nav_column(self, view, context): - boxes = list(self.vreg.possible_vobjects('boxes', self.req, rset=self.rset, - view=view, context=context)) + boxes = list(self.vreg['boxes'].possible_vobjects( + self.req, rset=self.rset, view=view, context=context)) if boxes: self.w(u'