merge
authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
Tue, 04 Aug 2009 15:08:18 +0200
changeset 2675 f84ba1a66abb
parent 2674 ff6114c2c416 (current diff)
parent 2670 4747145ff69c (diff)
child 2676 1282a15eb20f
merge
web/views/editforms.py
web/views/tabs.py
--- a/appobject.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/appobject.py	Tue Aug 04 15:08:18 2009 +0200
@@ -1,4 +1,6 @@
-"""Base class for dynamically loaded objects manipulated in the web interface
+"""Base class for dynamically loaded objects accessible through the vregistry.
+
+You'll also find some convenience classes to build selectors.
 
 :organization: Logilab
 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
@@ -7,20 +9,23 @@
 """
 __docformat__ = "restructuredtext en"
 
+import types
+from logging import getLogger
 from datetime import datetime, timedelta, time
 
 from logilab.common.decorators import classproperty
 from logilab.common.deprecation import deprecated
+from logilab.common.logging_ext import set_log_methods
 
 from rql.nodes import VariableRef, SubQuery
 from rql.stmts import Union, Select
 
 from cubicweb import Unauthorized, NoSelectableObject
-from cubicweb.vregistry import VObject, AndSelector
-from cubicweb.selectors import yes
 from cubicweb.utils import UStringIO, ustrftime, strptime, todate, todatetime
 
 ONESECOND = timedelta(0, 1, 0)
+CACHE_REGISTRY = {}
+
 
 class Cache(dict):
     def __init__(self):
@@ -29,14 +34,200 @@
         self.cache_creation_date = _now
         self.latest_cache_lookup = _now
 
-CACHE_REGISTRY = {}
+
+# selector base classes and operations ########################################
+
+def objectify_selector(selector_func):
+    """convenience decorator for simple selectors where a class definition
+    would be overkill::
+
+        @objectify_selector
+        def yes(cls, *args, **kwargs):
+            return 1
+
+    """
+    return type(selector_func.__name__, (Selector,),
+                {'__call__': lambda self, *args, **kwargs: selector_func(*args, **kwargs)})
+
+
+def _instantiate_selector(selector):
+    """ensures `selector` is a `Selector` instance
+
+    NOTE: This should only be used locally in build___select__()
+    XXX: then, why not do it ??
+    """
+    if isinstance(selector, types.FunctionType):
+        return objectify_selector(selector)()
+    if isinstance(selector, type) and issubclass(selector, Selector):
+        return selector()
+    return selector
+
+
+class Selector(object):
+    """base class for selector classes providing implementation
+    for operators ``&`` and ``|``
+
+    This class is only here to give access to binary operators, the
+    selector logic itself should be implemented in the __call__ method
+
+
+    a selector is called to help choosing the correct object for a
+    particular context by returning a score (`int`) telling how well
+    the class given as first argument apply to the given context.
+
+    0 score means that the class doesn't apply.
+    """
+
+    @property
+    def func_name(self):
+        # backward compatibility
+        return self.__class__.__name__
+
+    def search_selector(self, selector):
+        """search for the given selector or selector instance in the selectors
+        tree. Return it of None if not found
+        """
+        if self is selector:
+            return self
+        if isinstance(selector, type) and isinstance(self, selector):
+            return self
+        return None
+
+    def __str__(self):
+        return self.__class__.__name__
+
+    def __and__(self, other):
+        return AndSelector(self, other)
+    def __rand__(self, other):
+        return AndSelector(other, self)
+
+    def __or__(self, other):
+        return OrSelector(self, other)
+    def __ror__(self, other):
+        return OrSelector(other, self)
+
+    def __invert__(self):
+        return NotSelector(self)
+
+    # XXX (function | function) or (function & function) not managed yet
+
+    def __call__(self, cls, *args, **kwargs):
+        return NotImplementedError("selector %s must implement its logic "
+                                   "in its __call__ method" % self.__class__)
+
+
+class MultiSelector(Selector):
+    """base class for compound selector classes"""
+
+    def __init__(self, *selectors):
+        self.selectors = self.merge_selectors(selectors)
+
+    def __str__(self):
+        return '%s(%s)' % (self.__class__.__name__,
+                           ','.join(str(s) for s in self.selectors))
+
+    @classmethod
+    def merge_selectors(cls, selectors):
+        """deal with selector instanciation when necessary and merge
+        multi-selectors if possible:
 
-class AppRsetObject(VObject):
-    """This is the base class for CubicWeb application objects
-    which are selected according to a request and result set.
+        AndSelector(AndSelector(sel1, sel2), AndSelector(sel3, sel4))
+        ==> AndSelector(sel1, sel2, sel3, sel4)
+        """
+        merged_selectors = []
+        for selector in selectors:
+            try:
+                selector = _instantiate_selector(selector)
+            except:
+                pass
+            #assert isinstance(selector, Selector), selector
+            if isinstance(selector, cls):
+                merged_selectors += selector.selectors
+            else:
+                merged_selectors.append(selector)
+        return merged_selectors
+
+    def search_selector(self, selector):
+        """search for the given selector or selector instance in the selectors
+        tree. Return it of None if not found
+        """
+        for childselector in self.selectors:
+            if childselector is selector:
+                return childselector
+            found = childselector.search_selector(selector)
+            if found is not None:
+                return found
+        return None
+
+
+class AndSelector(MultiSelector):
+    """and-chained selectors (formerly known as chainall)"""
+    def __call__(self, cls, *args, **kwargs):
+        score = 0
+        for selector in self.selectors:
+            partscore = selector(cls, *args, **kwargs)
+            if not partscore:
+                return 0
+            score += partscore
+        return score
+
 
-    Classes are kept in the vregistry and instantiation is done at selection
-    time.
+class OrSelector(MultiSelector):
+    """or-chained selectors (formerly known as chainfirst)"""
+    def __call__(self, cls, *args, **kwargs):
+        for selector in self.selectors:
+            partscore = selector(cls, *args, **kwargs)
+            if partscore:
+                return partscore
+        return 0
+
+class NotSelector(Selector):
+    """negation selector"""
+    def __init__(self, selector):
+        self.selector = selector
+
+    def __call__(self, cls, *args, **kwargs):
+        score = self.selector(cls, *args, **kwargs)
+        return int(not score)
+
+    def __str__(self):
+        return 'NOT(%s)' % super(NotSelector, self).__str__()
+
+
+class yes(Selector):
+    """return arbitrary score
+
+    default score of 0.5 so any other selector take precedence
+    """
+    def __init__(self, score=0.5):
+        self.score = score
+
+    def __call__(self, *args, **kwargs):
+        return self.score
+
+
+# the base class for all appobjects ############################################
+
+class AppObject(object):
+    """This is the base class for CubicWeb application objects which are
+    selected according to a context (usually at least a request and a result
+    set).
+
+    Concrete application objects classes are designed to be loaded by the
+    vregistry and should be accessed through it, not by direct instantiation.
+
+    The following attributes should be set on concret appobject classes:
+    :__registry__:
+      name of the registry for this object (string like 'views',
+      'templates'...)
+    :id:
+      object's identifier in the registry (string like 'main',
+      'primary', 'folder_box')
+    :__select__:
+      class'selector
+
+    Moreover, the `__abstract__` attribute may be set to True to indicate
+    that a appobject is abstract and should not be registered.
 
     At registration time, the following attributes are set on the class:
     :vreg:
@@ -46,20 +237,64 @@
     :config:
       the instance's configuration
 
-    At instantiation time, the following attributes are set on the instance:
+    At selection time, the following attributes are set on the instance:
     :req:
       current request
     :rset:
-      result set on which the object is applied
+      context result set or None
+    :row:
+      if a result set is set and the context is about a particular cell in the
+      result set, and not the result set as a whole, specify the row number we
+      are interested in, else None
+    :col:
+      if a result set is set and the context is about a particular cell in the
+      result set, and not the result set as a whole, specify the col number we
+      are interested in, else None
     """
+    __registry__ = None
+    id = None
     __select__ = yes()
 
     @classmethod
-    def registered(cls, vreg):
-        super(AppRsetObject, cls).registered(vreg)
-        cls.vreg = vreg
-        cls.schema = vreg.schema
-        cls.config = vreg.config
+    def classid(cls):
+        """returns a unique identifier for the appobject"""
+        return '%s.%s' % (cls.__module__, cls.__name__)
+
+    # XXX bw compat code
+    @classmethod
+    def build___select__(cls):
+        for klass in cls.mro():
+            if klass.__name__ == 'AppObject':
+                continue # the bw compat __selector__ is there
+            klassdict = klass.__dict__
+            if ('__select__' in klassdict and '__selectors__' in klassdict
+                and '__selgenerated__' not in klassdict):
+                raise TypeError("__select__ and __selectors__ can't be used together on class %s" % cls)
+            if '__selectors__' in klassdict and '__selgenerated__' not in klassdict:
+                cls.__selgenerated__ = True
+                # case where __selectors__ is defined locally (but __select__
+                # is in a parent class)
+                selectors = klassdict['__selectors__']
+                if len(selectors) == 1:
+                    # micro optimization: don't bother with AndSelector if there's
+                    # only one selector
+                    select = _instantiate_selector(selectors[0])
+                else:
+                    select = AndSelector(*selectors)
+                cls.__select__ = select
+
+    @classmethod
+    def registered(cls, registry):
+        """called by the registry when the appobject has been registered.
+
+        It must return the object that will be actually registered (this may be
+        the right hook to create an instance for example). By default the
+        appobject is returned without any transformation.
+        """
+        cls.build___select__()
+        cls.vreg = registry.vreg
+        cls.schema = registry.schema
+        cls.config = registry.config
         cls.register_properties()
         return cls
 
@@ -67,15 +302,6 @@
     def vreg_initialization_completed(cls):
         pass
 
-    @classmethod
-    def selected(cls, *args, **kwargs):
-        """by default web app objects are usually instantiated on
-        selection according to a request, a result set, and optional
-        row and col
-        """
-        assert len(args) <= 2
-        return cls(*args, **kwargs)
-
     # Eproperties definition:
     # key: id of the property (the actual CWProperty key is build using
     #      <registry name>.<obj id>.<property id>
@@ -111,7 +337,7 @@
         return selector
 
     def __init__(self, req=None, rset=None, row=None, col=None, **extra):
-        super(AppRsetObject, self).__init__()
+        super(AppObject, self).__init__()
         self.req = req
         self.rset = rset
         self.row = row
@@ -151,8 +377,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 +414,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')
@@ -341,22 +568,4 @@
         if first in ('insert', 'set', 'delete'):
             raise Unauthorized(self.req._('only select queries are authorized'))
 
-
-class AppObject(AppRsetObject):
-    """base class for application objects which are not selected
-    according to a result set, only by their identifier.
-
-    Those objects may not have req, rset and cursor set.
-    """
-
-    @classmethod
-    def selected(cls, *args, **kwargs):
-        """by default web app objects are usually instantiated on
-        selection
-        """
-        return cls(*args, **kwargs)
-
-    def __init__(self, req=None, rset=None, **kwargs):
-        self.req = req
-        self.rset = rset
-        self.__dict__.update(kwargs)
+set_log_methods(AppObject, getLogger('cubicweb.appobject'))
--- a/common/test/unittest_migration.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/common/test/unittest_migration.py	Tue Aug 04 15:08:18 2009 +0200
@@ -37,8 +37,8 @@
         self.config = MigrTestConfig('data')
         from yams.schema import Schema
         self.config.load_schema = lambda expand_cubes=False: Schema('test')
-        self.config.__class__.cubicweb_vobject_path = frozenset()
-        self.config.__class__.cube_vobject_path = frozenset()
+        self.config.__class__.cubicweb_appobject_path = frozenset()
+        self.config.__class__.cube_appobject_path = frozenset()
 
     def test_filter_scripts_base(self):
         self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,3,0), (2,4,0)),
--- a/cwconfig.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/cwconfig.py	Tue Aug 04 15:08:18 2009 +0200
@@ -142,7 +142,7 @@
     name = None
     # log messages format (see logging module documentation for available keys)
     log_format = '%(asctime)s - (%(name)s) %(levelname)s: %(message)s'
-    # nor remove vobjects based on unused interface
+    # nor remove appobjects based on unused interface
     cleanup_interface_sobjects = True
 
     if os.environ.get('APYCOT_ROOT'):
@@ -169,14 +169,7 @@
          {'type' : 'string',
           'default': '',
           'help': 'Pyro name server\'s host. If not set, will be detected by a \
-broadcast query',
-          'group': 'pyro-name-server', 'inputlevel': 1,
-          }),
-        ('pyro-ns-port',
-         {'type' : 'int',
-          'default': None,
-          'help': 'Pyro name server\'s listening port. If not set, default \
-port will be used.',
+broadcast query. It may contains port information using <host>:<port> notation.',
           'group': 'pyro-name-server', 'inputlevel': 1,
           }),
         ('pyro-ns-group',
@@ -419,8 +412,8 @@
             except Exception, ex:
                 cls.warning("can't init cube %s: %s", cube, ex)
 
-    cubicweb_vobject_path = set(['entities'])
-    cube_vobject_path = set(['entities'])
+    cubicweb_appobject_path = set(['entities'])
+    cube_appobject_path = set(['entities'])
 
     @classmethod
     def build_vregistry_path(cls, templpath, evobjpath=None, tvobjpath=None):
@@ -430,13 +423,13 @@
         :param evobjpath:
           optional list of sub-directories (or files without the .py ext) of
           the cubicweb library that should be tested and added to the output list
-          if they exists. If not give, default to `cubicweb_vobject_path` class
+          if they exists. If not give, default to `cubicweb_appobject_path` class
           attribute.
         :param tvobjpath:
           optional list of sub-directories (or files without the .py ext) of
           directories given in `templpath` that should be tested and added to
           the output list if they exists. If not give, default to
-          `cube_vobject_path` class attribute.
+          `cube_appobject_path` class attribute.
         """
         vregpath = cls.build_vregistry_cubicweb_path(evobjpath)
         vregpath += cls.build_vregistry_cube_path(templpath, tvobjpath)
@@ -446,7 +439,7 @@
     def build_vregistry_cubicweb_path(cls, evobjpath=None):
         vregpath = []
         if evobjpath is None:
-            evobjpath = cls.cubicweb_vobject_path
+            evobjpath = cls.cubicweb_appobject_path
         for subdir in evobjpath:
             path = join(CW_SOFTWARE_ROOT, subdir)
             if exists(path):
@@ -457,7 +450,7 @@
     def build_vregistry_cube_path(cls, templpath, tvobjpath=None):
         vregpath = []
         if tvobjpath is None:
-            tvobjpath = cls.cube_vobject_path
+            tvobjpath = cls.cube_appobject_path
         for directory in templpath:
             for subdir in tvobjpath:
                 path = join(directory, subdir)
--- a/cwvreg.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/cwvreg.py	Tue Aug 04 15:08:18 2009 +0200
@@ -8,14 +8,16 @@
 __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,
+                      ObjectNotFound, NoSelectableObject, RegistryNotFound,
                       RegistryOutOfDate)
-from cubicweb.vregistry import VRegistry, ObjectNotFound, NoSelectableObject
+from cubicweb.utils import dump_class
+from cubicweb.vregistry import VRegistry, Registry
 from cubicweb.rtags import RTAGS
 
 
@@ -33,14 +35,171 @@
             if impl:
                 return sorted(impl.expected_ifaces)
         except AttributeError:
-            pass # old-style vobject classes with no accepts_interfaces
+            pass # old-style appobject classes with no accepts_interfaces
         except:
             print 'bad selector %s on %s' % (obj.__select__, obj)
             raise
         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):
+        """on registration completed, clear etype_class internal cache
+        """
+        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 nearest parent class (in yams inheritance) registered.
+
+        Fall back to 'Any' if not yams parent class found.
+        """
+        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:
+                objects = self[btype]
+                assert len(objects) == 1, objects
+                cls = objects[0]
+                break
+            except ObjectNotFound:
+                pass
+        else:
+            # no entity class for any of the ancestors, fallback to the default
+            # one
+            objects = self['Any']
+            assert len(objects) == 1, objects
+            cls = objects[0]
+        if cls.id == etype:
+            cls.__initialize__()
+            return cls
+        cls = dump_class(cls, etype)
+        cls.id = etype
+        cls.__initialize__()
+        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.
 
@@ -66,28 +225,38 @@
         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 iteritems(self):
+        return (item for item in super(CubicWebVRegistry, self).iteritems()
+                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 itervalues(self):
+        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)
 
@@ -108,9 +277,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
@@ -126,13 +293,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:
@@ -153,166 +314,92 @@
         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:
-            # remove vobjects that don't support any available interface
+            # remove appobjects that don't support any available interface
             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):
-                    self.debug('kicking vobject %s (no implemented '
+                    self.debug('kicking appobject %s (no implemented '
                                'interface among %s)', obj, ifaces)
                     self.unregister(obj)
         # clear needs_iface so we don't try to remove some not-anymore-in
         # 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
-
-    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)
-
-    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["etypes"].etype_class(etype)
 
-    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["views"].main_template(*args, **kwargs)')
+    def main_template(self, req, oid='main-template', **context):
+        return self["views"].main_template(req, oid, **context)
 
+    @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
+        return self["actions"].possible_actions(req, rest=rset, **kwargs)
 
-        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)
-
-    @deprecated("use .select_object('boxes', ...)")
+    @deprecated("use vreg['boxes'].select_object(...)")
     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', ...)")
+    @deprecated("use vreg['components'].select_object(...)")
     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', ...)")
+    @deprecated("use vreg['actions'].select_object(...)")
     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', ...)")
+    @deprecated("use vreg['views'].select(...)")
     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 #####################################################
 
@@ -326,7 +413,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,
@@ -338,7 +425,7 @@
         boolean)
         """
         try:
-            return self._registries['propertydefs'][key]
+            return self['propertydefs'][key]
         except KeyError:
             if key.startswith('system.version.'):
                 soft = key.split('.')[-1]
@@ -349,9 +436,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
@@ -374,7 +461,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)
@@ -385,61 +472,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
 
--- a/dbapi.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/dbapi.py	Tue Aug 04 15:08:18 2009 +0200
@@ -16,9 +16,11 @@
 from itertools import count
 
 from logilab.common.logging_ext import set_log_methods
+from logilab.common.decorators import monkeypatch
+from logilab.common.deprecation import deprecated
+
 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 +30,54 @@
     except KeyError:
         return ''
 
+def _fix_cls_attrs(reg, appobject):
+    appobject.vreg = reg.vreg
+    appobject.schema = reg.schema
+    appobject.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, appobjects, *args, **kwargs):
+        """return an instance of the most specific object according
+        to parameters
+
+        raise NoSelectableObject if no object apply
+        """
+        for appobjectcls in appobjects:
+            _fix_cls_attrs(self, appobjectcls)
+        selected = orig_select_best(self, appobjects, *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'
@@ -51,24 +101,14 @@
         from cubicweb.server.repository import Repository
         return Repository(config, vreg=vreg)
     else: # method == 'pyro'
-        from Pyro import core, naming
-        from Pyro.errors import NamingError, ProtocolError
-        core.initClient(banner=0)
-        nsid = ':%s.%s' % (config['pyro-ns-group'], database)
-        locator = naming.NameServerLocator()
         # resolve the Pyro object
+        from logilab.common.pyro_ext import ns_get_proxy
         try:
-            nshost, nsport = config['pyro-ns-host'], config['pyro-ns-port']
-            uri = locator.getNS(nshost, nsport).resolve(nsid)
-        except ProtocolError:
-            raise ConnectionError('Could not connect to the Pyro name server '
-                                  '(host: %s:%i)' % (nshost, nsport))
-        except NamingError:
-            raise ConnectionError('Could not get repository for %s '
-                                  '(not registered in Pyro), '
-                                  'you may have to restart your server-side '
-                                  'instance' % nsid)
-        return core.getProxyForURI(uri)
+            return ns_get_proxy(database,
+                                defaultnsgroup=config['pyro-ns-group'],
+                                nshost=config['pyro-ns-host'])
+        except Exception, ex:
+            raise ConnectionError(str(ex))
 
 def repo_connect(repo, login, password, cnxprops=None):
     """Constructor to create a new connection to the CubicWeb repository.
@@ -82,22 +122,18 @@
         cnx.vreg = repo.vreg
     return cnx
 
-def connect(database=None, login=None, password=None, host=None,
-            group=None, cnxprops=None, port=None, setvreg=True, mulcnx=True,
-            initlog=True):
+def connect(database=None, login=None, password=None, host=None, group=None,
+            cnxprops=None, setvreg=True, mulcnx=True, initlog=True):
     """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:
-        config.global_set_option('pyro-ns-port', port)
     if group:
         config.global_set_option('pyro-ns-group', group)
     cnxprops = cnxprops or ConnectionProperties()
@@ -107,9 +143,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 +161,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:
@@ -401,7 +436,7 @@
             raise ProgrammingError('Closed connection')
         return self._repo.get_schema()
 
-    def load_vobjects(self, cubes=_MARKER, subpath=None, expand=True,
+    def load_appobjects(self, cubes=_MARKER, subpath=None, expand=True,
                       force_reload=None):
         config = self.vreg.config
         if cubes is _MARKER:
@@ -434,11 +469,13 @@
             if self._repo.config.instance_hooks:
                 hm.register_hooks(config.load_hooks(self.vreg))
 
+    load_vobjects = deprecated()(load_appobjects)
+
     def use_web_compatible_requests(self, baseurl, sitetitle=None):
         """monkey patch DBAPIRequest to fake a cw.web.request, so you should
         able to call html views using rset from a simple dbapi connection.
 
-        You should call `load_vobjects` at some point to register those views.
+        You should call `load_appobjects` at some point to register those views.
         """
         from cubicweb.web.request import CubicWebRequestBase as cwrb
         DBAPIRequest.build_ajax_replace_url = cwrb.build_ajax_replace_url.im_func
@@ -476,8 +513,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
 
--- a/devtools/__init__.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/devtools/__init__.py	Tue Aug 04 15:08:18 2009 +0200
@@ -142,8 +142,8 @@
 class BaseApptestConfiguration(TestServerConfiguration, TwistedConfiguration):
     repo_method = 'inmemory'
     options = merge_options(TestServerConfiguration.options + TwistedConfiguration.options)
-    cubicweb_vobject_path = TestServerConfiguration.cubicweb_vobject_path | TwistedConfiguration.cubicweb_vobject_path
-    cube_vobject_path = TestServerConfiguration.cube_vobject_path | TwistedConfiguration.cube_vobject_path
+    cubicweb_appobject_path = TestServerConfiguration.cubicweb_appobject_path | TwistedConfiguration.cubicweb_appobject_path
+    cube_appobject_path = TestServerConfiguration.cube_appobject_path | TwistedConfiguration.cube_appobject_path
 
     def available_languages(self, *args):
         return ('en', 'fr', 'de')
--- a/devtools/_apptest.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/devtools/_apptest.py	Tue Aug 04 15:08:18 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 <rql>"""
-        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:
--- a/devtools/apptest.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/devtools/apptest.py	Tue Aug 04 15:08:18 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
@@ -249,7 +249,7 @@
         dump = simplejson.dumps
         args = [dump(arg) for arg in args]
         req = self.request(fname=fname, pageid='123', arg=args)
-        ctrl = self.vreg.select('controllers', 'json', req)
+        ctrl = self.vreg['controllers'].select('json', req)
         return ctrl.publish(), req
 
     # default test setup and teardown #########################################
@@ -294,7 +294,7 @@
         def setUp(self):
             super(ControllerTC, self).setUp()
             self.req = self.request()
-            self.ctrl = self.vreg.select('controllers', 'edit', self.req)
+            self.ctrl = self.vreg['controllers'].select('edit', self.req)
 
         def publish(self, req):
             assert req is self.ctrl.req
@@ -308,7 +308,7 @@
 
         def expect_redirect_publish(self, req=None):
             if req is not None:
-                self.ctrl = self.vreg.select('controllers', 'edit', req)
+                self.ctrl = self.vreg['controllers'].select('edit', req)
             else:
                 req = self.req
             try:
--- a/devtools/devctl.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/devtools/devctl.py	Tue Aug 04 15:08:18 2009 +0200
@@ -29,8 +29,8 @@
 class DevCubeConfiguration(ServerConfiguration, WebConfiguration):
     """dummy config to get full library schema and entities"""
     creating = True
-    cubicweb_vobject_path = ServerConfiguration.cubicweb_vobject_path | WebConfiguration.cubicweb_vobject_path
-    cube_vobject_path = ServerConfiguration.cube_vobject_path | WebConfiguration.cube_vobject_path
+    cubicweb_appobject_path = ServerConfiguration.cubicweb_appobject_path | WebConfiguration.cubicweb_appobject_path
+    cube_appobject_path = ServerConfiguration.cube_appobject_path | WebConfiguration.cube_appobject_path
 
     def __init__(self, cube):
         super(DevCubeConfiguration, self).__init__(cube)
@@ -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))
--- a/devtools/fake.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/devtools/fake.py	Tue Aug 04 15:08:18 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]
--- a/devtools/testlib.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/devtools/testlib.py	Tue Aug 04 15:08:18 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:
@@ -375,9 +377,9 @@
                 rset2 = rset.limit(limit=1, offset=row)
                 yield rset2
 
-def not_selected(vreg, vobject):
+def not_selected(vreg, appobject):
     try:
-        vreg._selected[vobject.__class__] -= 1
+        vreg._selected[appobject.__class__] -= 1
     except (KeyError, AttributeError):
         pass
 
@@ -385,26 +387,29 @@
     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)
+    for reg in env.vreg.values():
+        reg._selected = {}
         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
+            orig_select_best = reg.__class__.__orig_select_best
+        except:
+            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
+        reg.__class__.__orig_select_best = orig_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 vobject in vobjects:
-                if not vreg._selected.get(vobject):
-                    print 'not tested', registry, vobject
+        for appobjects in reg.itervalues():
+            for appobject in appobjects:
+                if not reg._selected.get(appobject):
+                    print 'not tested', regname, appobject
--- a/entities/__init__.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/entities/__init__.py	Tue Aug 04 15:08:18 2009 +0200
@@ -14,7 +14,6 @@
 
 from cubicweb import Unauthorized, typed_eid
 from cubicweb.entity import Entity
-from cubicweb.utils import dump_class
 
 from cubicweb.interfaces import IBreadCrumbs, IFeed
 
@@ -26,19 +25,6 @@
     id = 'Any'
     __implements__ = (IBreadCrumbs, IFeed)
 
-    @classmethod
-    def selected(cls, etype):
-        """the special Any entity is used as the default factory, so
-        the actual class has to be constructed at selection time once we
-        have an actual entity'type
-        """
-        if cls.id == etype:
-            return cls
-        usercls = dump_class(cls, etype)
-        usercls.id = etype
-        usercls.__initialize__()
-        return usercls
-
     fetch_attrs = ('modification_date',)
     @classmethod
     def fetch_order(cls, attr, var):
--- a/entities/test/unittest_base.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/entities/test/unittest_base.py	Tue Aug 04 15:08:18 2009 +0200
@@ -263,21 +263,24 @@
 class InterfaceTC(EnvBasedTC):
 
     def test_nonregr_subclasses_and_mixins_interfaces(self):
+        self.failUnless(implements(CWUser, IWorkflowable))
         class MyUser(CWUser):
             __implements__ = (IMileStone,)
         self.vreg._loadedmods[__name__] = {}
-        self.vreg.register_vobject_class(MyUser)
-        self.failUnless(implements(CWUser, IWorkflowable))
-        self.failUnless(implements(MyUser, IMileStone))
-        self.failUnless(implements(MyUser, IWorkflowable))
+        self.vreg.register_appobject_class(MyUser)
+        self.vreg['etypes'].initialization_completed()
+        MyUser_ = self.vreg['etypes'].etype_class('CWUser')
+        self.failUnless(MyUser is MyUser_)
+        self.failUnless(implements(MyUser_, IMileStone))
+        self.failUnless(implements(MyUser_, IWorkflowable))
 
 
 class SpecializedEntityClassesTC(EnvBasedTC):
 
     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
@@ -290,7 +293,7 @@
         for etype in ('Company', 'Division', 'SubDivision'):
             class Foo(AnyEntity):
                 id = etype
-            self.vreg.register_vobject_class(Foo)
+            self.vreg.register_appobject_class(Foo)
             eclass = self.select_eclass('SubDivision')
             if etype == 'SubDivision':
                 self.failUnless(eclass is Foo)
--- a/entity.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/entity.py	Tue Aug 04 15:08:18 2009 +0200
@@ -20,7 +20,7 @@
 from cubicweb import Unauthorized
 from cubicweb.rset import ResultSet
 from cubicweb.selectors import yes
-from cubicweb.appobject import AppRsetObject
+from cubicweb.appobject import AppObject
 from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint, bw_normalize_etype
 
 from cubicweb.common.uilib import printable_value, soup2xhtml
@@ -132,7 +132,7 @@
         return super(_metaentity, mcs).__new__(mcs, name, bases, classdict)
 
 
-class Entity(AppRsetObject, dict):
+class Entity(AppObject, dict):
     """an entity instance has e_schema automagically set on
     the class and instances has access to their issuing cursor.
 
@@ -167,15 +167,6 @@
     # class attributes set automatically at registration time
     e_schema = None
 
-    @classmethod
-    def registered(cls, registry):
-        """build class using descriptor at registration time"""
-        assert cls.id is not None
-        super(Entity, cls).registered(registry)
-        if cls.id != 'Any':
-            cls.__initialize__()
-        return cls
-
     MODE_TAGS = set(('link', 'create'))
     CATEGORY_TAGS = set(('primary', 'secondary', 'generic', 'generated')) # , 'metadata'))
     @classmethod
@@ -265,7 +256,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 +268,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
@@ -299,7 +291,7 @@
         return mainattr, needcheck
 
     def __init__(self, req, rset=None, row=None, col=0):
-        AppRsetObject.__init__(self, req, rset, row, col)
+        AppObject.__init__(self, req, rset, row, col)
         dict.__init__(self)
         self._related_cache = {}
         if rset is not None:
@@ -364,10 +356,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 +694,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 +756,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
--- a/etwist/server.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/etwist/server.py	Tue Aug 04 15:08:18 2009 +0200
@@ -109,7 +109,7 @@
                 self.pyro_listen_timeout = 0.02
                 start_task(1, self.pyro_loop_event)
             self.appli.repo.start_looping_tasks()
-        self.url_rewriter = self.appli.vreg.select_object('components', 'urlrewriter')
+        self.url_rewriter = self.appli.vreg['components'].select_object('urlrewriter')
         interval = min(config['cleanup-session-time'] or 120,
                        config['cleanup-anonymous-session-time'] or 720) / 2.
         start_task(interval, self.appli.session_handler.clean_sessions)
@@ -330,7 +330,7 @@
 def _gc_debug():
     import gc
     from pprint import pprint
-    from cubicweb.vregistry import VObject
+    from cubicweb.appobject import AppObject
     gc.collect()
     count = 0
     acount = 0
@@ -338,7 +338,7 @@
     for obj in gc.get_objects():
         if isinstance(obj, CubicWebTwistedRequestAdapter):
             count += 1
-        elif isinstance(obj, VObject):
+        elif isinstance(obj, AppObject):
             acount += 1
         else:
             try:
--- a/etwist/twconfig.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/etwist/twconfig.py	Tue Aug 04 15:08:18 2009 +0200
@@ -87,8 +87,8 @@
         options = merge_options(TwistedConfiguration.options
                                 + ServerConfiguration.options)
 
-        cubicweb_vobject_path = TwistedConfiguration.cubicweb_vobject_path | ServerConfiguration.cubicweb_vobject_path
-        cube_vobject_path = TwistedConfiguration.cube_vobject_path | ServerConfiguration.cube_vobject_path
+        cubicweb_appobject_path = TwistedConfiguration.cubicweb_appobject_path | ServerConfiguration.cubicweb_appobject_path
+        cube_appobject_path = TwistedConfiguration.cube_appobject_path | ServerConfiguration.cube_appobject_path
         def pyro_enabled(self):
             """tell if pyro is activated for the in memory repository"""
             return self['pyro-server']
--- a/goa/db.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/goa/db.py	Tue Aug 04 15:08:18 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):
--- a/goa/goaconfig.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/goa/goaconfig.py	Tue Aug 04 15:08:18 2009 +0200
@@ -17,8 +17,8 @@
 from cubicweb.goa.dbmyams import load_schema
 
 UNSUPPORTED_OPTIONS = set(('connections-pool-size',
-                           'pyro-port', 'pyro-id', 'pyro-instance-id',
-                           'pyro-ns-host', 'pyro-ns-port', 'pyro-ns-group',
+                           'pyro-host', 'pyro-id', 'pyro-instance-id',
+                           'pyro-ns-host', 'pyro-ns-group',
                            'https-url', 'host', 'pid-file', 'uid', 'base-url', 'log-file',
                            'smtp-host', 'smtp-port',
                            'embed-allowed',
@@ -81,9 +81,9 @@
     options = [(optname, optdict) for optname, optdict in options
                if not optname in UNSUPPORTED_OPTIONS]
 
-    cubicweb_vobject_path = WebConfiguration.cubicweb_vobject_path | ServerConfiguration.cubicweb_vobject_path
-    cubicweb_vobject_path = list(cubicweb_vobject_path) + ['goa/appobjects']
-    cube_vobject_path = WebConfiguration.cube_vobject_path | ServerConfiguration.cube_vobject_path
+    cubicweb_appobject_path = WebConfiguration.cubicweb_appobject_path | ServerConfiguration.cubicweb_appobject_path
+    cubicweb_appobject_path = list(cubicweb_appobject_path) + ['goa/appobjects']
+    cube_appobject_path = WebConfiguration.cube_appobject_path | ServerConfiguration.cube_appobject_path
 
     # use file system schema
     bootstrap_schema = read_instance_schema = False
--- a/goa/goavreg.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/goa/goavreg.py	Tue Aug 04 15:08:18 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"""
@@ -59,7 +59,7 @@
         self.load_module(obj)
 
     def _auto_load(self, path, loadschema, cube=None):
-        vobjpath = self.config.cube_vobject_path
+        vobjpath = self.config.cube_appobject_path
         for filename in listdir(path):
             if filename[-3:] == '.py' and filename[:-3] in vobjpath:
                 self._import(_pkg_name(cube, filename[:-3]))
--- a/goa/skel/main.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/goa/skel/main.py	Tue Aug 04 15:08:18 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
--- a/goa/test/unittest_views.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/goa/test/unittest_views.py	Tue Aug 04 15:08:18 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))
--- a/goa/testlib.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/goa/testlib.py	Tue Aug 04 15:08:18 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
--- a/goa/tools/laxctl.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/goa/tools/laxctl.py	Tue Aug 04 15:08:18 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
 
--- a/rset.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/rset.py	Tue Aug 04 15:08:18 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
 
@@ -370,12 +370,21 @@
         # XXX should we consider updating a cached entity with possible
         #     new attributes found in this resultset ?
         try:
-            return req.entity_cache(eid)
+            entity = req.entity_cache(eid)
+            if entity.rset is None:
+                # entity has no rset set, this means entity has been cached by
+                # the repository (req is a repository session) which had no rset
+                # info. Add id.
+                entity.rset = self
+                entity.row = row
+                entity.col = col
+            return entity
         except KeyError:
             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)
--- a/schemas/base.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/schemas/base.py	Tue Aug 04 15:08:18 2009 +0200
@@ -242,7 +242,7 @@
     The target application is responsible for updating timestamp
     when necessary to invalidate the cache (typically in hooks).
 
-    Also, checkout the AppRsetObject.get_cache() method.
+    Also, checkout the AppObject.get_cache() method.
     """
     permissions = {
         'read':   ('managers', 'users', 'guests'),
--- a/schemaviewer.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/schemaviewer.py	Tue Aug 04 15:08:18 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:
--- a/selectors.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/selectors.py	Tue Aug 04 15:08:18 2009 +0200
@@ -53,8 +53,8 @@
 
 from cubicweb import (Unauthorized, NoSelectableObject, NotAnEntity,
                       role, typed_eid)
-from cubicweb.vregistry import (NoSelectableObject, Selector,
-                                chainall, objectify_selector)
+# even if not used, let yes here so it's importable through this module
+from cubicweb.appobject import Selector, objectify_selector, yes
 from cubicweb.cwconfig import CubicWebConfiguration
 from cubicweb.schema import split_expression
 
@@ -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()
@@ -274,17 +274,6 @@
 
 # very basic selectors ########################################################
 
-class yes(Selector):
-    """return arbitrary score
-
-    default score of 0.5 so any other selector take precedence
-    """
-    def __init__(self, score=0.5):
-        self.score = score
-
-    def __call__(self, *args, **kwargs):
-        return self.score
-
 @objectify_selector
 @lltrace
 def none_rset(cls, req, rset=None, **kwargs):
@@ -570,9 +559,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 +619,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):
@@ -975,6 +964,7 @@
 
 
 # XXX DEPRECATED ##############################################################
+from cubicweb.vregistry import chainall
 
 yes_selector = deprecated()(yes)
 norset_selector = deprecated()(none_rset)
@@ -1040,7 +1030,7 @@
 accept_selector = deprecated()(accept)
 
 accept_one = deprecated()(chainall(one_line_rset, accept,
-                                          name='accept_one'))
+                                   name='accept_one'))
 accept_one_selector = deprecated()(accept_one)
 
 
--- a/server/repository.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/server/repository.py	Tue Aug 04 15:08:18 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')
@@ -1038,13 +1038,15 @@
                                     entity.eid, attr, value)
         return entity.eid
 
-    def glob_update_entity(self, session, entity):
+    def glob_update_entity(self, session, entity, edited_attributes):
         """replace an entity in the repository
         the type and the eid of an entity must not be changed
         """
         etype = str(entity.e_schema)
         if server.DEBUG & server.DBG_REPO:
-            print 'UPDATE entity', etype, entity.eid, dict(entity)
+            print 'UPDATE entity', etype, entity.eid, \
+                  dict(entity), edited_attributes
+        entity.edited_attributes = edited_attributes
         entity.check()
         eschema = entity.e_schema
         session.set_entity_cache(entity)
@@ -1164,36 +1166,16 @@
 
     def pyro_register(self, host=''):
         """register the repository as a pyro object"""
-        from Pyro import core
-        port = self.config['pyro-port']
-        nshost, nsgroup = self.config['pyro-ns-host'], self.config['pyro-ns-group']
-        nsgroup = ':' + nsgroup
-        core.initServer(banner=0)
-        daemon = core.Daemon(host=host, port=port)
-        daemon.useNameServer(self.pyro_nameserver(nshost, nsgroup))
-        # use Delegation approach
-        impl = core.ObjBase()
-        impl.delegateTo(self)
-        nsid = self.config['pyro-id'] or self.config.appid
-        daemon.connect(impl, '%s.%s' % (nsgroup, nsid))
+        from logilab.common.pyro_ext import register_object
+        appid = self.config['pyro-id'] or self.config.appid
+        daemon = register_object(self, appid, self.config['pyro-ns-group'],
+                                 self.config['pyro-host'],
+                                 self.config['pyro-ns-host'])
         msg = 'repository registered as a pyro object using group %s and id %s'
-        self.info(msg, nsgroup, nsid)
+        self.info(msg, self.config['pyro-ns-group'], appid)
         self.pyro_registered = True
         return daemon
 
-    def pyro_nameserver(self, host=None, group=None):
-        """locate and bind the the name server to the daemon"""
-        from Pyro import naming, errors
-        # locate the name server
-        nameserver = naming.NameServerLocator().getNS(host)
-        if group is not None:
-            # make sure our namespace group exists
-            try:
-                nameserver.createGroup(group)
-            except errors.NamingError:
-                pass
-        return nameserver
-
     # multi-sources planner helpers ###########################################
 
     @cached
@@ -1217,21 +1199,9 @@
 
 def pyro_unregister(config):
     """unregister the repository from the pyro name server"""
-    nshost, nsgroup = config['pyro-ns-host'], config['pyro-ns-group']
+    from logilab.common.pyro_ext import ns_unregister
     appid = config['pyro-id'] or config.appid
-    from Pyro import core, naming, errors
-    core.initClient(banner=False)
-    try:
-        nameserver = naming.NameServerLocator().getNS(nshost)
-    except errors.PyroError, ex:
-        # name server not responding
-        config.error('can\'t locate pyro name server: %s', ex)
-        return
-    try:
-        nameserver.unregister(':%s.%s' % (nsgroup, appid))
-        config.info('%s unregistered from pyro name server', appid)
-    except errors.NamingError:
-        config.warning('%s already unregistered from pyro name server', appid)
+    ns_unregister(appid, config['pyro-ns-group'], config['pyro-ns-host'])
 
 
 from logging import getLogger
--- a/server/serverconfig.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/server/serverconfig.py	Tue Aug 04 15:08:18 2009 +0200
@@ -85,8 +85,8 @@
         SCHEMAS_LIB_DIR = '/usr/share/cubicweb/schemas/'
         BACKUP_DIR = '/var/lib/cubicweb/backup/'
 
-    cubicweb_vobject_path = CubicWebConfiguration.cubicweb_vobject_path | set(['sobjects'])
-    cube_vobject_path = CubicWebConfiguration.cube_vobject_path | set(['sobjects', 'hooks'])
+    cubicweb_appobject_path = CubicWebConfiguration.cubicweb_appobject_path | set(['sobjects'])
+    cube_appobject_path = CubicWebConfiguration.cube_appobject_path | set(['sobjects', 'hooks'])
 
     options = merge_options((
         # ctl configuration
@@ -165,10 +165,12 @@
           'group': 'email', 'inputlevel': 2,
           }),
         # pyro server.serverconfig
-        ('pyro-port',
+        ('pyro-host',
          {'type' : 'int',
           'default': None,
-          'help': 'Pyro server port. If not set, it will be choosen randomly',
+          'help': 'Pyro server host, if not detectable correctly through \
+gethostname(). It may contains port information using <host>:<port> notation, \
+and if not set, it will be choosen randomly',
           'group': 'pyro-server', 'inputlevel': 2,
           }),
         ('pyro-id', # XXX reuse pyro-instance-id
@@ -265,7 +267,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:
--- a/server/session.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/server/session.py	Tue Aug 04 15:08:18 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:
--- a/server/sources/__init__.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/server/sources/__init__.py	Tue Aug 04 15:08:18 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
 
--- a/server/sources/pyrorql.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/server/sources/pyrorql.py	Tue Aug 04 15:08:18 2009 +0200
@@ -79,14 +79,7 @@
          {'type' : 'string',
           'default': None,
           'help': 'Pyro name server\'s host. If not set, default to the value \
-from all_in_one.conf.',
-          'group': 'pyro-source', 'inputlevel': 1,
-          }),
-        ('pyro-ns-port',
-         {'type' : 'int',
-          'default': None,
-          'help': 'Pyro name server\'s listening port. If not set, default to \
-the value from all_in_one.conf.',
+from all_in_one.conf. It may contains port information using <host>:<port> notation.',
           'group': 'pyro-source', 'inputlevel': 1,
           }),
         ('pyro-ns-group',
@@ -214,13 +207,12 @@
     def _get_connection(self):
         """open and return a connection to the source"""
         nshost = self.config.get('pyro-ns-host') or self.repo.config['pyro-ns-host']
-        nsport = self.config.get('pyro-ns-port') or self.repo.config['pyro-ns-port']
         nsgroup = self.config.get('pyro-ns-group') or self.repo.config['pyro-ns-group']
         #cnxprops = ConnectionProperties(cnxtype=self.config['cnx-type'])
         return dbapi.connect(database=self.config['pyro-ns-id'],
                              login=self.config['cubicweb-user'],
                              password=self.config['cubicweb-password'],
-                             host=nshost, port=nsport, group=nsgroup,
+                             host=nshost, group=nsgroup,
                              setvreg=False) #cnxprops=cnxprops)
 
     def get_connection(self):
--- a/server/ssplanner.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/server/ssplanner.py	Tue Aug 04 15:08:18 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)
@@ -481,6 +482,7 @@
         repo = session.repo
         edefs = {}
         # insert relations
+        attributes = [relation.r_type for relation in self.attribute_relations]
         for row in self.execute_child():
             for relation in self.attribute_relations:
                 lhs, rhs = relation.get_variable_parts()
@@ -488,7 +490,7 @@
                 try:
                     edef = edefs[eid]
                 except KeyError:
-                    edefs[eid] = edef = session.eid_rset(eid).get_entity(0, 0)
+                    edefs[eid] = edef = session.entity_from_eid(eid)
                 if isinstance(rhs, Constant):
                     # add constant values to entity def
                     value = rhs.eval(plan.args)
@@ -502,6 +504,6 @@
         # update entities
         result = []
         for eid, edef in edefs.iteritems():
-            repo.glob_update_entity(session, edef)
+            repo.glob_update_entity(session, edef, attributes)
             result.append( (eid,) )
         return result
--- a/server/test/unittest_repository.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/server/test/unittest_repository.py	Tue Aug 04 15:08:18 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'])
--- a/sobjects/notification.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/sobjects/notification.py	Tue Aug 04 15:08:18 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()
 
--- a/sobjects/supervising.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/sobjects/supervising.py	Tue Aug 04 15:08:18 2009 +0200
@@ -31,12 +31,16 @@
             SupervisionMailOp(session)
 
     def _call(self, *args):
-        if self._event() == 'update_entity' and args[0].e_schema == 'CWUser':
-            updated = set(args[0].iterkeys())
-            if not (updated - frozenset(('eid', 'modification_date', 'last_login_time'))):
-                # don't record last_login_time update which are done
-                # automatically at login time
+        if self._event() == 'update_entity':
+            if args[0].eid in self.session.transaction_data.get('neweids', ()):
                 return False
+            if args[0].e_schema == 'CWUser':
+                updated = set(args[0].iterkeys())
+                if not (updated - frozenset(('eid', 'modification_date',
+                                             'last_login_time'))):
+                    # don't record last_login_time update which are done
+                    # automatically at login time
+                    return False
         self.session.transaction_data.setdefault('pendingchanges', []).append(
             (self._event(), args))
         return True
@@ -218,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
--- a/sobjects/test/data/schema.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/sobjects/test/data/schema.py	Tue Aug 04 15:08:18 2009 +0200
@@ -5,6 +5,8 @@
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
+from yams.buildobjs import RelationDefinition
+
 class comments(RelationDefinition):
     subject = 'Comment'
     object = 'Card'
--- a/sobjects/test/unittest_notification.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/sobjects/test/unittest_notification.py	Tue Aug 04 15:08:18 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')
--- a/test/unittest_entity.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/test/unittest_entity.py	Tue Aug 04 15:08:18 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')
--- a/test/unittest_rtags.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/test/unittest_rtags.py	Tue Aug 04 15:08:18 2009 +0200
@@ -39,7 +39,7 @@
 #             __rtags__ = {
 #                 ('evaluee', 'Note', 'subject') : set(('inlineview',)),
 #                 }
-#         self.vreg.register_vobject_class(Personne2)
+#         self.vreg.register_appobject_class(Personne2)
 #         rtags = Personne2.rtags
 #         self.assertEquals(rtags.rtag('evaluee', 'Note', 'subject'), set(('inlineview', 'link')))
 #         self.assertEquals(rtags.is_inlined('evaluee', 'Note', 'subject'), True)
--- a/test/unittest_selectors.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/test/unittest_selectors.py	Tue Aug 04 15:08:18 2009 +0200
@@ -9,7 +9,7 @@
 from logilab.common.testlib import TestCase, unittest_main
 
 from cubicweb.devtools.testlib import EnvBasedTC
-from cubicweb.vregistry import Selector, AndSelector, OrSelector
+from cubicweb.appobject import Selector, AndSelector, OrSelector
 from cubicweb.selectors import implements, match_user_groups
 from cubicweb.interfaces import IDownloadable
 from cubicweb.web import action
@@ -91,7 +91,7 @@
 class ImplementsSelectorTC(EnvBasedTC):
     def test_etype_priority(self):
         req = self.request()
-        cls = self.vreg.etype_class('File')
+        cls = self.vreg['etypes'].etype_class('File')
         anyscore = implements('Any').score_class(cls, req)
         idownscore = implements(IDownloadable).score_class(cls, req)
         self.failUnless(idownscore > anyscore, (idownscore, anyscore))
@@ -99,7 +99,7 @@
         self.failUnless(filescore > idownscore, (filescore, idownscore))
 
     def test_etype_inheritance_no_yams_inheritance(self):
-        cls = self.vreg.etype_class('Personne')
+        cls = self.vreg['etypes'].etype_class('Personne')
         self.failIf(implements('Societe').score_class(cls, self.request()))
 
 
@@ -111,7 +111,7 @@
             category = 'foo'
             __select__ = match_user_groups('owners')
         self.vreg._loadedmods[__name__] = {}
-        self.vreg.register_vobject_class(SomeAction)
+        self.vreg.register_appobject_class(SomeAction)
         self.failUnless(SomeAction in self.vreg['actions']['yo'], self.vreg['actions'])
         try:
             # login as a simple user
--- a/test/unittest_vregistry.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/test/unittest_vregistry.py	Tue Aug 04 15:08:18 2009 +0200
@@ -10,8 +10,8 @@
 from os.path import join
 
 from cubicweb import CW_SOFTWARE_ROOT as BASE
-from cubicweb.vregistry import VObject
-from cubicweb.cwvreg import CubicWebRegistry, UnknownProperty
+from cubicweb.appobject import AppObject
+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()
 
@@ -43,7 +43,7 @@
     def test___selectors__compat(self):
         myselector1 = lambda *args: 1
         myselector2 = lambda *args: 1
-        class AnAppObject(VObject):
+        class AnAppObject(AppObject):
             __selectors__ = (myselector1, myselector2)
         AnAppObject.build___select__()
         self.assertEquals(AnAppObject.__select__(AnAppObject), 2)
@@ -53,7 +53,7 @@
         self.failUnless(self.vreg.property_info('system.version.cubicweb'))
         self.assertRaises(UnknownProperty, self.vreg.property_info, 'a.non.existent.key')
 
-    def test_load_subinterface_based_vobjects(self):
+    def test_load_subinterface_based_appobjects(self):
         self.vreg.reset()
         self.vreg.register_objects([join(BASE, 'web', 'views', 'iprogress.py')])
         # check progressbar was kicked
@@ -62,7 +62,7 @@
             __implements__ = (IMileStone,)
         self.vreg.reset()
         self.vreg._loadedmods[__name__] = {}
-        self.vreg.register_vobject_class(MyCard)
+        self.vreg.register_appobject_class(MyCard)
         self.vreg.register_objects([join(BASE, 'entities', '__init__.py'),
                                     join(BASE, 'web', 'views', 'iprogress.py')])
         # check progressbar isn't kicked
--- a/utils.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/utils.py	Tue Aug 04 15:08:18 2009 +0200
@@ -321,7 +321,7 @@
 
 
 class AcceptMixIn(object):
-    """Mixin class for vobjects defining the 'accepts' attribute describing
+    """Mixin class for appobjects defining the 'accepts' attribute describing
     a set of supported entity type (Any by default).
     """
     # XXX deprecated, no more necessary
--- a/view.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/view.py	Tue Aug 04 15:08:18 2009 +0200
@@ -18,7 +18,7 @@
 from cubicweb import NotAnEntity
 from cubicweb.selectors import yes, non_final_entity, nonempty_rset, none_rset
 from cubicweb.selectors import require_group_compat, accepts_compat
-from cubicweb.appobject import AppRsetObject
+from cubicweb.appobject import AppObject
 from cubicweb.utils import UStringIO, HTMLStream
 from cubicweb.schema import display_name
 
@@ -73,7 +73,7 @@
 
 # base view object ############################################################
 
-class View(AppRsetObject):
+class View(AppObject):
     """abstract view class, used as base for every renderable object such
     as views, templates, some components...web
 
@@ -93,7 +93,7 @@
     time to a write function to use.
     """
     __registry__ = 'views'
-    registered = require_group_compat(AppRsetObject.registered)
+    registered = require_group_compat(AppObject.registered)
 
     templatable = True
     need_navigation = True
--- a/vregistry.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/vregistry.py	Tue Aug 04 15:08:18 2009 +0200
@@ -5,13 +5,13 @@
   according to a context
 
 * to interact with the vregistry, objects should inherit from the
-  VObject abstract class
+  AppObject abstract class
 
 * the selection procedure has been generalized by delegating to a
-  selector, which is responsible to score the vobject according to the
+  selector, which is responsible to score the appobject according to the
   current state (req, rset, row, col). At the end of the selection, if
-  a vobject class has been found, an instance of this class is
-  returned. The selector is instantiated at vobject registration
+  a appobject class has been found, an instance of this class is
+  returned. The selector is instantiated at appobject registration
 
 
 :organization: Logilab
@@ -22,15 +22,18 @@
 __docformat__ = "restructuredtext en"
 
 import sys
-import types
 from os import listdir, stat
 from os.path import dirname, join, realpath, split, isdir, exists
 from logging import getLogger
 from warnings import warn
 
-from cubicweb import CW_SOFTWARE_ROOT, set_log_methods
+from logilab.common.deprecation import deprecated, class_moved
+from logilab.common.logging_ext import set_log_methods
+
+from cubicweb import CW_SOFTWARE_ROOT
 from cubicweb import (RegistryNotFound, ObjectNotFound, NoSelectableObject,
                       RegistryOutOfDate)
+from cubicweb.appobject import AppObject
 
 # XXX depending on cubicweb.web is ugly, we should deal with uicfg
 #     reset with a good old event / callback system
@@ -58,179 +61,117 @@
     return _toload
 
 
-class VObject(object):
-    """visual object, use to be handled somehow by the visual components
-    registry.
-
-    The following attributes should be set on concret vobject subclasses:
-
-    :__registry__:
-      name of the registry for this object (string like 'views',
-      'templates'...)
-    :id:
-      object's identifier in the registry (string like 'main',
-      'primary', 'folder_box')
-    :__select__:
-      class'selector
-
-    Moreover, the `__abstract__` attribute may be set to True to indicate
-    that a vobject is abstract and should not be registered
-    """
-    # necessary attributes to interact with the registry
-    id = None
-    __registry__ = None
-    __select__ = None
-
-    @classmethod
-    def registered(cls, registry):
-        """called by the registry when the vobject has been registered.
-
-        It must return the  object that will be actually registered (this
-        may be the right hook to create an instance for example). By
-        default the vobject is returned without any transformation.
-        """
-        cls.build___select__()
-        return cls
-
-    @classmethod
-    def selected(cls, *args, **kwargs):
-        """called by the registry when the vobject has been selected.
-
-        It must return the  object that will be actually returned by the
-        .select method (this may be the right hook to create an
-        instance for example). By default the selected object is
-        returned without any transformation.
-        """
-        return cls
-
-    @classmethod
-    def classid(cls):
-        """returns a unique identifier for the vobject"""
-        return '%s.%s' % (cls.__module__, cls.__name__)
+class Registry(dict):
 
-    # XXX bw compat code
-    @classmethod
-    def build___select__(cls):
-        for klass in cls.mro():
-            if klass.__name__ == 'AppRsetObject':
-                continue # the bw compat __selector__ is there
-            klassdict = klass.__dict__
-            if ('__select__' in klassdict and '__selectors__' in klassdict
-                and '__selgenerated__' not in klassdict):
-                raise TypeError("__select__ and __selectors__ can't be used together on class %s" % cls)
-            if '__selectors__' in klassdict and '__selgenerated__' not in klassdict:
-                cls.__selgenerated__ = True
-                # case where __selectors__ is defined locally (but __select__
-                # is in a parent class)
-                selectors = klassdict['__selectors__']
-                if len(selectors) == 1:
-                    # micro optimization: don't bother with AndSelector if there's
-                    # only one selector
-                    select = _instantiate_selector(selectors[0])
-                else:
-                    select = AndSelector(*selectors)
-                cls.__select__ = select
-
+    def __init__(self, config):
+        super(Registry, self).__init__()
+        self.config = config
 
-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 = {}
-        if uicfg is not None:
-            reload(uicfg)
-
-    def __getitem__(self, key):
-        return self._registries[key]
-
-    def get(self, key, default=None):
-        return self._registries.get(key, default)
-
-    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:
+            appobjects = self[oid] =  []
+        else:
+            appobjects = self.setdefault(oid, [])
+        # registered() is technically a classmethod but is not declared
+        # as such because we need to compose registered in some cases
+        appobject = obj.registered.im_func(obj, self)
+        assert not appobject in appobjects, \
+               'object %s is already registered' % appobject
+        assert callable(appobject.__select__), appobject
+        appobjects.append(appobject)
 
-    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 <registry>.<oid>
+    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 <oid> in <registry>
         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)
+        return objects[0](*args, **kwargs)
 
-    def select(self, registry, oid, *args, **kwargs):
-        """return the most specific object in <registry>.<oid> 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 <oid> in <registry>
         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 <registry>.<oid> 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 <registry> 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 appobjects in self.itervalues():
             try:
-                yield self.select_best(vobjects, *args, **kwargs)
+                yield self.select_best(appobjects, *args, **kwargs)
             except NoSelectableObject:
                 continue
 
-    def select_best(self, vobjects, *args, **kwargs):
+    def select_best(self, appobjects, *args, **kwargs):
         """return an instance of the most specific object according
         to parameters
 
@@ -240,16 +181,16 @@
             warn('only the request param can not be named when calling select',
                  DeprecationWarning, stacklevel=3)
         score, winners = 0, []
-        for vobject in vobjects:
-            vobjectscore = vobject.__select__(vobject, *args, **kwargs)
-            if vobjectscore > score:
-                score, winners = vobjectscore, [vobject]
-            elif vobjectscore > 0 and vobjectscore == score:
-                winners.append(vobject)
+        for appobject in appobjects:
+            appobjectscore = appobject.__select__(appobject, *args, **kwargs)
+            if appobjectscore > score:
+                score, winners = appobjectscore, [appobject]
+            elif appobjectscore > 0 and appobjectscore == score:
+                winners.append(appobject)
         if not winners:
             raise NoSelectableObject('args: %s\nkwargs: %s %s'
                                      % (args, kwargs.keys(),
-                                        [repr(v) for v in vobjects]))
+                                        [repr(v) for v in appobjects]))
         if len(winners) > 1:
             if self.config.mode == 'installed':
                 self.error('select ambiguity, args: %s\nkwargs: %s %s',
@@ -258,11 +199,92 @@
                 raise Exception('select ambiguity, args: %s\nkwargs: %s %s'
                                 % (args, kwargs.keys(),
                                    [repr(v) for v in winners]))
-        # return the result of the .selected method of the vobject
-        return winners[0].selected(*args, **kwargs)
+        # return the result of calling the appobject
+        return winners[0](*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, force_reload=None):
+        self.clear()
+        self._lastmodifs = {}
+        # don't reload uicfg when appobjects modules won't be reloaded as well
+        if uicfg is not None:
+            if force_reload is None:
+                force_reload = self.config.mode == 'dev'
+            if force_reload:
+                reload(uicfg)
+
+    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 <registry>.<oid>
+
+        raise `ObjectNotFound` if not object with id <oid> in <registry>
+        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 <registry>.<oid> according to
+        the given context
+
+        raise `ObjectNotFound` if not object with id <oid> in <registry>
+        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 <registry>.<oid> 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 <registry> 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)
@@ -282,62 +304,23 @@
         """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__
-        self.debug('registered vobject %s in registry %s with id %s',
+            vname = obj.__class__.__name__
+        self.debug('registered appobject %s in registry %s with id %s',
                    vname, registryname, oid)
         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
@@ -421,7 +404,7 @@
             return
         # skip non registerable object
         try:
-            if not issubclass(obj, VObject):
+            if not issubclass(obj, AppObject):
                 return
         except TypeError:
             return
@@ -435,20 +418,20 @@
 
     def load_object(self, obj):
         try:
-            self.register_vobject_class(obj)
+            self.register_appobject_class(obj)
         except Exception, ex:
             if self.config.mode in ('test', 'dev'):
                 raise
-            self.exception('vobject %s registration failed: %s', obj, ex)
+            self.exception('appobject %s registration failed: %s', obj, ex)
 
     # old automatic registration XXX deprecated ###############################
 
-    def register_vobject_class(self, cls):
-        """handle vobject class registration
+    def register_appobject_class(self, cls):
+        """handle appobject class registration
 
-        vobject class with __abstract__ == True in their local dictionnary or
+        appobject class with __abstract__ == True in their local dictionnary or
         with a name starting starting by an underscore are not registered.
-        Also a vobject class needs to have __registry__ and id attributes set
+        Also a appobject class needs to have __registry__ and id attributes set
         to a non empty string to be registered.
         """
         if (cls.__dict__.get('__abstract__') or cls.__name__[0] == '_'
@@ -460,169 +443,19 @@
         self.register(cls)
 
 # init logging
-set_log_methods(VObject, getLogger('cubicweb'))
-set_log_methods(VRegistry, getLogger('cubicweb.registry'))
-
-
-# selector base classes and operations ########################################
-
-class Selector(object):
-    """base class for selector classes providing implementation
-    for operators ``&`` and ``|``
-
-    This class is only here to give access to binary operators, the
-    selector logic itself should be implemented in the __call__ method
-
-
-    a selector is called to help choosing the correct object for a
-    particular context by returning a score (`int`) telling how well
-    the class given as first argument apply to the given context.
-
-    0 score means that the class doesn't apply.
-    """
-
-    @property
-    def func_name(self):
-        # backward compatibility
-        return self.__class__.__name__
-
-    def search_selector(self, selector):
-        """search for the given selector or selector instance in the selectors
-        tree. Return it of None if not found
-        """
-        if self is selector:
-            return self
-        if isinstance(selector, type) and isinstance(self, selector):
-            return self
-        return None
-
-    def __str__(self):
-        return self.__class__.__name__
-
-    def __and__(self, other):
-        return AndSelector(self, other)
-    def __rand__(self, other):
-        return AndSelector(other, self)
-
-    def __or__(self, other):
-        return OrSelector(self, other)
-    def __ror__(self, other):
-        return OrSelector(other, self)
-
-    def __invert__(self):
-        return NotSelector(self)
-
-    # XXX (function | function) or (function & function) not managed yet
-
-    def __call__(self, cls, *args, **kwargs):
-        return NotImplementedError("selector %s must implement its logic "
-                                   "in its __call__ method" % self.__class__)
-
-class MultiSelector(Selector):
-    """base class for compound selector classes"""
-
-    def __init__(self, *selectors):
-        self.selectors = self.merge_selectors(selectors)
-
-    def __str__(self):
-        return '%s(%s)' % (self.__class__.__name__,
-                           ','.join(str(s) for s in self.selectors))
-
-    @classmethod
-    def merge_selectors(cls, selectors):
-        """deal with selector instanciation when necessary and merge
-        multi-selectors if possible:
-
-        AndSelector(AndSelector(sel1, sel2), AndSelector(sel3, sel4))
-        ==> AndSelector(sel1, sel2, sel3, sel4)
-        """
-        merged_selectors = []
-        for selector in selectors:
-            try:
-                selector = _instantiate_selector(selector)
-            except:
-                pass
-            #assert isinstance(selector, Selector), selector
-            if isinstance(selector, cls):
-                merged_selectors += selector.selectors
-            else:
-                merged_selectors.append(selector)
-        return merged_selectors
-
-    def search_selector(self, selector):
-        """search for the given selector or selector instance in the selectors
-        tree. Return it of None if not found
-        """
-        for childselector in self.selectors:
-            if childselector is selector:
-                return childselector
-            found = childselector.search_selector(selector)
-            if found is not None:
-                return found
-        return None
-
-
-def objectify_selector(selector_func):
-    """convenience decorator for simple selectors where a class definition
-    would be overkill::
-
-        @objectify_selector
-        def yes(cls, *args, **kwargs):
-            return 1
-
-    """
-    return type(selector_func.__name__, (Selector,),
-                {'__call__': lambda self, *args, **kwargs: selector_func(*args, **kwargs)})
-
-def _instantiate_selector(selector):
-    """ensures `selector` is a `Selector` instance
-
-    NOTE: This should only be used locally in build___select__()
-    XXX: then, why not do it ??
-    """
-    if isinstance(selector, types.FunctionType):
-        return objectify_selector(selector)()
-    if isinstance(selector, type) and issubclass(selector, Selector):
-        return selector()
-    return selector
-
-
-class AndSelector(MultiSelector):
-    """and-chained selectors (formerly known as chainall)"""
-    def __call__(self, cls, *args, **kwargs):
-        score = 0
-        for selector in self.selectors:
-            partscore = selector(cls, *args, **kwargs)
-            if not partscore:
-                return 0
-            score += partscore
-        return score
-
-
-class OrSelector(MultiSelector):
-    """or-chained selectors (formerly known as chainfirst)"""
-    def __call__(self, cls, *args, **kwargs):
-        for selector in self.selectors:
-            partscore = selector(cls, *args, **kwargs)
-            if partscore:
-                return partscore
-        return 0
-
-class NotSelector(Selector):
-    """negation selector"""
-    def __init__(self, selector):
-        self.selector = selector
-
-    def __call__(self, cls, *args, **kwargs):
-        score = self.selector(cls, *args, **kwargs)
-        return int(not score)
-
-    def __str__(self):
-        return 'NOT(%s)' % super(NotSelector, self).__str__()
+set_log_methods(VRegistry, getLogger('cubicweb.vreg'))
+set_log_methods(Registry, getLogger('cubicweb.registry'))
 
 
 # XXX bw compat functions #####################################################
 
+from cubicweb.appobject import objectify_selector, AndSelector, OrSelector, Selector
+
+objectify_selector = deprecated('objectify_selector has been moved to appobject module')(objectify_selector)
+
+Selector = class_moved(Selector)
+
+@deprecated('use & operator (binary and)')
 def chainall(*selectors, **kwargs):
     """return a selector chaining given selectors. If one of
     the selectors fail, selection will fail, else the returned score
@@ -635,6 +468,7 @@
         selector.__name__ = kwargs['name']
     return selector
 
+@deprecated('use | operator (binary or)')
 def chainfirst(*selectors, **kwargs):
     """return a selector chaining given selectors. If all
     the selectors fail, selection will fail, else the returned score
--- a/web/action.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/action.py	Tue Aug 04 15:08:18 2009 +0200
@@ -11,12 +11,12 @@
 from cubicweb.selectors import (partial_relation_possible, match_search_state,
                                 one_line_rset, partial_may_add_relation, yes,
                                 accepts_compat, condition_compat, deprecate)
-from cubicweb.appobject import AppRsetObject
+from cubicweb.appobject import AppObject
 
 _ = unicode
 
 
-class Action(AppRsetObject):
+class Action(AppObject):
     """abstract action. Handle the .search_states attribute to match
     request search state.
     """
--- a/web/application.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/application.py	Tue Aug 04 15:08:18 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:
@@ -220,7 +220,7 @@
         super(CubicWebPublisher, self).__init__()
         # connect to the repository and get instance's schema
         if vreg is None:
-            vreg = cwvreg.CubicWebRegistry(config, debug=debug)
+            vreg = cwvreg.CubicWebVRegistry(config, debug=debug)
         self.vreg = vreg
         self.info('starting web instance from %s', config.apphome)
         self.repo = config.repository(vreg)
@@ -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
 
--- a/web/controller.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/controller.py	Tue Aug 04 15:08:18 2009 +0200
@@ -71,6 +71,7 @@
     registered = require_group_compat(AppObject.registered)
 
     def __init__(self, *args, **kwargs):
+        self.appli = kwargs.pop('appli', None)
         super(Controller, self).__init__(*args, **kwargs)
         # attributes use to control after edition redirection
         self._after_deletion_path = None
@@ -92,7 +93,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
--- a/web/facet.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/facet.py	Tue Aug 04 15:08:18 2009 +0200
@@ -24,7 +24,7 @@
 from cubicweb.schema import display_name
 from cubicweb.utils import datetime2ticks, make_uid, ustrftime
 from cubicweb.selectors import match_context_prop, partial_relation_possible
-from cubicweb.appobject import AppRsetObject
+from cubicweb.appobject import AppObject
 from cubicweb.web.htmlwidgets import HTMLWidget
 
 ## rqlst manipulation functions used by facets ################################
@@ -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):
@@ -241,7 +241,7 @@
 
 
 ## base facet classes #########################################################
-class AbstractFacet(AppRsetObject):
+class AbstractFacet(AppObject):
     __abstract__ = True
     __registry__ = 'facets'
     property_defs = {
@@ -259,22 +259,18 @@
     needs_update = False
     start_unfolded = True
 
-    @classmethod
-    def selected(cls, req, rset=None, rqlst=None, context=None,
-                 filtered_variable=None):
+    def __init__(self, req, rset=None, rqlst=None, filtered_variable=None,
+                 **kwargs):
+        super(AbstractFacet, self).__init__(req, rset, **kwargs)
         assert rset is not None or rqlst is not None
         assert filtered_variable
-        instance = super(AbstractFacet, cls).selected(req, rset)
-        #instance = AppRsetObject.selected(req, rset)
-        #instance.__class__ = cls
         # facet retreived using `object_by_id` from an ajax call
         if rset is None:
-            instance.init_from_form(rqlst=rqlst)
+            self.init_from_form(rqlst=rqlst)
         # facet retreived from `select` using the result set to filter
         else:
-            instance.init_from_rset()
-        instance.filtered_variable = filtered_variable
-        return instance
+            self.init_from_rset()
+        self.filtered_variable = filtered_variable
 
     def init_from_rset(self):
         self.rqlst = self.rset.syntax_tree().children[0]
--- a/web/form.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/form.py	Tue Aug 04 15:08:18 2009 +0200
@@ -7,7 +7,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from cubicweb.appobject import AppRsetObject
+from cubicweb.appobject import AppObject
 from cubicweb.view import NOINDEX, NOFOLLOW
 from cubicweb.common import tags
 from cubicweb.web import stdmsgs, httpcache, formfields
@@ -202,6 +202,6 @@
     found
     """
 
-class Form(FormMixIn, AppRsetObject):
+class Form(FormMixIn, AppObject):
     __metaclass__ = metafieldsform
     __registry__ = 'forms'
--- a/web/request.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/request.py	Tue Aug 04 15:08:18 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'
--- a/web/test/test_views.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/test_views.py	Tue Aug 04 15:08:18 2009 +0200
@@ -52,7 +52,7 @@
 
     def test_js_added_only_once(self):
         self.vreg._loadedmods[__name__] = {}
-        self.vreg.register_vobject_class(SomeView)
+        self.vreg.register_appobject_class(SomeView)
         rset = self.execute('CWUser X')
         source = self.view('someview', rset).source
         self.assertEquals(source.count('spam.js'), 1)
--- a/web/test/unittest_application.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_application.py	Tue Aug 04 15:08:18 2009 +0200
@@ -7,16 +7,17 @@
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
-from logilab.common.testlib import TestCase, unittest_main
 import base64, Cookie
-
 import sys
 from urllib import unquote
+
+from logilab.common.testlib import TestCase, unittest_main
 from logilab.common.decorators import clear_cache
 
+from cubicweb.devtools.apptest import EnvBasedTC
+from cubicweb.devtools.fake import FakeRequest
 from cubicweb.web import Redirect, AuthenticationError, ExplicitLogin, INTERNAL_FIELD_VALUE
 from cubicweb.web.views.basecontrollers import ViewController
-from cubicweb.devtools._apptest import FakeRequest
 
 class FakeMapping:
     """emulates a mapping module"""
@@ -133,9 +134,6 @@
                            for i in (12, 13, 14)])
 
 
-from cubicweb.devtools.apptest import EnvBasedTC
-
-
 class ApplicationTC(EnvBasedTC):
 
     def publish(self, req, path='view'):
--- a/web/test/unittest_form.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_form.py	Tue Aug 04 15:08:18 2009 +0200
@@ -91,7 +91,7 @@
         e.req = self.req
         geid = self.execute('CWGroup X WHERE X name "users"')[0][0]
         self.req.form['__linkto'] = 'in_group:%s:subject' % geid
-        form = self.vreg.select('forms', 'edition', self.req, entity=e)
+        form = self.vreg['forms'].select('edition', self.req, entity=e)
         form.content_type = 'text/html'
         pageinfo = self._check_html(form.form_render(), form, template=None)
         inputs = pageinfo.find_tag('select', False)
@@ -101,8 +101,8 @@
 
     def test_reledit_composite_field(self):
         rset = self.execute('INSERT BlogEntry X: X title "cubicweb.org", X content "hop"')
-        form = self.vreg.select_object('views', 'reledit', self.request(),
-                                       rset=rset, row=0, rtype='content')
+        form = self.vreg['views'].select('reledit', self.request(),
+                                         rset=rset, row=0, rtype='content')
         data = form.render(row=0, rtype='content')
         self.failUnless('edits-content' in data)
         self.failUnless('edits-content_format' in data)
--- a/web/test/unittest_magicsearch.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_magicsearch.py	Tue Aug 04 15:08:18 2009 +0200
@@ -44,7 +44,7 @@
         super(QueryTranslatorTC, self).setUp()
         self.req = self.env.create_request()
         self.vreg.config.translations = {'en': _translate}
-        proc = self.vreg.select('components', 'magicsearch', self.req)
+        proc = self.vreg['components'].select('magicsearch', self.req)
         self.proc = [p for p in proc.processors if isinstance(p, QueryTranslator)][0]
 
     def test_basic_translations(self):
@@ -69,7 +69,7 @@
         super(QSPreProcessorTC, self).setUp()
         self.vreg.config.translations = {'en': _translate}
         self.req = self.request()
-        proc = self.vreg.select('components', 'magicsearch', self.req)
+        proc = self.vreg['components'].select('magicsearch', self.req)
         self.proc = [p for p in proc.processors if isinstance(p, QSPreProcessor)][0]
         self.proc.req = self.req
 
@@ -187,7 +187,7 @@
         super(ProcessorChainTC, self).setUp()
         self.vreg.config.translations = {'en': _translate}
         self.req = self.request()
-        self.proc = self.vreg.select('components', 'magicsearch', self.req)
+        self.proc = self.vreg['components'].select('magicsearch', self.req)
 
     def test_main_preprocessor_chain(self):
         """tests QUERY_PROCESSOR"""
--- a/web/test/unittest_views_actions.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_views_actions.py	Tue Aug 04 15:08:18 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__':
--- a/web/test/unittest_views_basecontrollers.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_views_basecontrollers.py	Tue Aug 04 15:08:18 2009 +0200
@@ -496,7 +496,7 @@
         # updated (which is what happened before this test)
         req = self.request()
         req.form['url'] = 'http://intranet.logilab.fr/'
-        controller = self.vreg.select('controllers', 'embed', req)
+        controller = self.vreg['controllers'].select('embed', req)
         result = controller.publish(rset=None)
 
 
@@ -504,7 +504,7 @@
 
     def test_usable_by_guets(self):
         req = self.request()
-        self.vreg.select('controllers', 'reportbug', req)
+        self.vreg['controllers'].select('reportbug', req)
 
 
 class SendMailControllerTC(EnvBasedTC):
@@ -512,7 +512,7 @@
     def test_not_usable_by_guets(self):
         self.login('anon')
         req = self.request()
-        self.assertRaises(NoSelectableObject, self.env.vreg.select, 'controllers', 'sendmail', req)
+        self.assertRaises(NoSelectableObject, self.env.vreg['controllers'].select, 'sendmail', req)
 
 
 
@@ -520,7 +520,7 @@
 
     def ctrl(self, req=None):
         req = req or self.request(url='http://whatever.fr/')
-        return self.vreg.select('controllers', 'json', req)
+        return self.vreg['controllers'].select('json', req)
 
     def setup_database(self):
         self.pytag = self.add_entity('Tag', name=u'python')
--- a/web/test/unittest_views_basetemplates.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_views_basetemplates.py	Tue Aug 04 15:08:18 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):
--- a/web/test/unittest_views_baseviews.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_views_baseviews.py	Tue Aug 04 15:08:18 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):
--- a/web/test/unittest_views_editforms.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_views_editforms.py	Tue Aug 04 15:08:18 2009 +0200
@@ -18,8 +18,8 @@
     def test_custom_widget(self):
         AEF.rfields_kwargs.tag_subject_of(('CWUser', 'login', '*'),
                                           {'widget': AutoCompletionWidget(autocomplete_initfunc='get_logins')})
-        form = self.vreg.select('forms', 'edition', self.request(),
-                                entity=self.user())
+        form = self.vreg['forms'].select('edition', self.request(),
+                                         entity=self.user())
         field = form.field_by_name('login')
         self.assertIsInstance(field.widget, AutoCompletionWidget)
         AEF.rfields_kwargs.del_rtag('CWUser', 'login', '*', 'subject')
@@ -116,10 +116,10 @@
 
     def test_edition_form(self):
         rset = self.execute('CWUser X LIMIT 1')
-        form = self.vreg.select('forms', 'edition', rset.req, rset=rset,
+        form = self.vreg['forms'].select('edition', rset.req, rset=rset,
                                 row=0, col=0)
         # should be also selectable by specifying entity
-        self.vreg.select('forms', 'edition', rset.req,
+        self.vreg['forms'].select('edition', rset.req,
                          entity=rset.get_entity(0, 0))
         self.failIf(any(f for f in form.fields if f is None))
 
--- a/web/test/unittest_views_navigation.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_views_navigation.py	Tue Aug 04 15:08:18 2009 +0200
@@ -19,31 +19,31 @@
     def test_navigation_selection(self):
         rset = self.execute('Any X,N WHERE X name N')
         req = self.request()
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         self.assertIsInstance(navcomp, PageNavigation)
         req.set_search_state('W:X:Y:Z')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         self.assertIsInstance(navcomp, PageNavigation)
         req.set_search_state('normal')
         rset = self.execute('Any X,N ORDERBY N WHERE X name N')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         self.assertIsInstance(navcomp, SortedNavigation)
         req.set_search_state('W:X:Y:Z')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         self.assertIsInstance(navcomp, SortedNavigation)
         req.set_search_state('normal')
         rset = self.execute('Any X,N LIMIT 10 WHERE X name N')
-        navcomp = self.vreg.select_object('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select_object('navigation', req, rset=rset)
         self.assertEquals(navcomp, None)
         req.set_search_state('W:X:Y:Z')
-        navcomp = self.vreg.select_object('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select_object('navigation', req, rset=rset)
         self.assertEquals(navcomp, None)
         req.set_search_state('normal')
         rset = self.execute('Any N, COUNT(RDEF) GROUPBY N ORDERBY N WHERE RDEF relation_type RT, RT name N')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         self.assertIsInstance(navcomp, SortedNavigation)
         req.set_search_state('W:X:Y:Z')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         self.assertIsInstance(navcomp, SortedNavigation)
 
 
@@ -51,22 +51,22 @@
         rset = self.execute('Any X,N ORDERBY N WHERE X name N')
         req = self.request()
         req.set_search_state('W:X:Y:Z')
-        navcomp = self.vreg.select('components', 'navigation', rset.req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', rset.req, rset=rset)
         html = navcomp.render()
         rset = self.execute('Any RDEF ORDERBY RT WHERE RDEF relation_type RT')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         html = navcomp.render()
         rset = self.execute('Any RDEF ORDERBY RDEF WHERE RDEF relation_type RT')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         html = navcomp.render()
         rset = self.execute('CWAttribute RDEF ORDERBY RDEF')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         html = navcomp.render()
         rset = self.execute('Any RDEF ORDERBY N WHERE RDEF relation_type RT, RT name N')
-        navcomp = self.vreg.select('components', 'navigation', req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', req, rset=rset)
         html = navcomp.render()
         rset = self.execute('Any N, COUNT(RDEF) GROUPBY N ORDERBY N WHERE RDEF relation_type RT, RT name N')
-        navcomp = self.vreg.select('components', 'navigation', rset.req, rset=rset)
+        navcomp = self.vreg['components'].select('navigation', rset.req, rset=rset)
         html = navcomp.render()
 
 
@@ -77,12 +77,12 @@
         view = mock_object(is_primary=lambda x: True)
         rset = self.execute('CWUser X LIMIT 1')
         req = self.request()
-        objs = self.vreg.possible_vobjects('contentnavigation', req, rset=rset,
+        objs = self.vreg['contentnavigation'].possible_vobjects(req, rset=rset,
                                            view=view, context='navtop')
         # breadcrumbs should be in headers by default
         clsids = set(obj.id for obj in objs)
         self.failUnless('breadcrumbs' in clsids)
-        objs = self.vreg.possible_vobjects('contentnavigation', req, rset=rset,
+        objs = self.vreg['contentnavigation'].possible_vobjects(req, rset=rset,
                                           view=view, context='navbottom')
         # breadcrumbs should _NOT_ be in footers by default
         clsids = set(obj.id for obj in objs)
@@ -91,12 +91,12 @@
                      'P value "navbottom"')
         # breadcrumbs should now be in footers
         req.cnx.commit()
-        objs = self.vreg.possible_vobjects('contentnavigation', req, rset=rset,
+        objs = self.vreg['contentnavigation'].possible_vobjects(req, rset=rset,
                                           view=view, context='navbottom')
 
         clsids = [obj.id for obj in objs]
         self.failUnless('breadcrumbs' in clsids)
-        objs = self.vreg.possible_vobjects('contentnavigation', req, rset=rset,
+        objs = self.vreg['contentnavigation'].possible_vobjects(req, rset=rset,
                                           view=view, context='navtop')
 
         clsids = [obj.id for obj in objs]
--- a/web/test/unittest_views_pyviews.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_views_pyviews.py	Tue Aug 04 15:08:18 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(), '''<table class="listing">
 <tr><th>num</th><th>char</th></tr>
 <tr><td>1</td><td>a</td></tr>
@@ -14,8 +14,8 @@
 </table>''')
 
     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(), '''<ul>
 <li>1</li>
 <li>a</li>
--- a/web/test/unittest_viewselector.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/test/unittest_viewselector.py	Tue Aug 04 15:08:18 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,103 +267,103 @@
         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
         class CWUserCreationForm(editforms.CreationFormView):
             __select__ = specified_etype_implements('CWUser')
         self.vreg._loadedmods[__name__] = {}
-        self.vreg.register_vobject_class(CWUserCreationForm)
+        self.vreg.register_appobject_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
@@ -431,11 +431,11 @@
     def setUp(self):
         super(RQLActionTC, self).setUp()
         self.vreg._loadedmods[__name__] = {}
-        self.vreg.register_vobject_class(CWETypeRQLAction)
+        self.vreg.register_appobject_class(CWETypeRQLAction)
 
     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"')
--- a/web/views/actions.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/actions.py	Tue Aug 04 15:08:18 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from cubicweb.vregistry import objectify_selector
+from cubicweb.appobject import objectify_selector
 from cubicweb.selectors import (EntitySelector,
     one_line_rset, two_lines_rset, one_etype_rset, relation_possible,
     nonempty_rset, non_final_entity,
--- a/web/views/basecomponents.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/basecomponents.py	Tue Aug 04 15:08:18 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)
--- a/web/views/basecontrollers.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/basecontrollers.py	Tue Aug 04 15:08:18 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
--- a/web/views/basetemplates.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/basetemplates.py	Tue Aug 04 15:08:18 2009 +0200
@@ -10,7 +10,7 @@
 
 from logilab.mtconverter import xml_escape
 
-from cubicweb.vregistry import objectify_selector
+from cubicweb.appobject import objectify_selector
 from cubicweb.selectors import match_kwargs
 from cubicweb.view import View, MainTemplate, NOINDEX, NOFOLLOW
 from cubicweb.utils import make_uid, UStringIO
@@ -113,8 +113,8 @@
         if vtitle:
             w(u'<h1 class="vtitle">%s</h1>\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'<div id="page"><table width="100%" border="0" id="mainLayout"><tr>\n')
         self.nav_column(view, 'left')
         w(u'<td id="contentcol">\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'</body>')
 
     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'<td class="navcol"><div class="navboxes">\n')
             for box in boxes:
@@ -200,7 +200,7 @@
         """display an unexpected error"""
         self.set_request_content_type()
         self.req.reset_headers()
-        view = self.vreg.select('views', 'error', self.req, rset=self.rset)
+        view = self.vreg['views'].select('error', self.req, rset=self.rset)
         self.template_header(self.content_type, view, self.req._('an error occured'),
                              [NOINDEX, NOFOLLOW])
         view.render(w=self.w)
@@ -242,8 +242,8 @@
         w(u'<table width="100%" height="100%" border="0"><tr>\n')
         w(u'<td class="navcol">\n')
         self.topleft_header()
-        boxes = list(self.vreg.possible_vobjects('boxes', self.req, rset=self.rset,
-                                                 view=view, context='left'))
+        boxes = list(self.vreg['boxes'].possible_vobjects(
+            self.req, rset=self.rset, view=view, context='left'))
         if boxes:
             w(u'<div class="navboxes">\n')
             for box in boxes:
@@ -257,8 +257,8 @@
             w(u'<h1 class="vtitle">%s</h1>' % xml_escape(vtitle))
 
     def topleft_header(self):
-        logo = self.vreg.select_vobject('components', 'logo', self.req,
-                                        rset=self.rset)
+        logo = self.vreg['components'].select_vobject('logo', self.req,
+                                                      rset=self.rset)
         if logo:
             self.w(u'<table id="header"><tr>\n')
             self.w(u'<td>')
@@ -299,7 +299,7 @@
             self.req.add_js(jscript, localfile=False)
 
     def alternates(self):
-        urlgetter = self.vreg.select_object('components', 'rss_feed_url',
+        urlgetter = self.vreg['components'].select_object('rss_feed_url',
                                             self.req, rset=self.rset)
         if urlgetter is not None:
             self.whead(u'<link rel="alternate" type="application/rss+xml" title="RSS feed" href="%s"/>\n'
@@ -329,28 +329,28 @@
         """build the top menu with authentification info and the rql box"""
         self.w(u'<table id="header"><tr>\n')
         self.w(u'<td id="firstcolumn">')
-        logo = self.vreg.select_vobject('components', 'logo',
-                                        self.req, rset=self.rset)
+        logo = self.vreg['components'].select_vobject(
+            'logo', self.req, rset=self.rset)
         if logo:
             logo.render(w=self.w)
         self.w(u'</td>\n')
         # appliname and breadcrumbs
         self.w(u'<td id="headtext">')
         for cid in ('appliname', 'breadcrumbs'):
-            comp = self.vreg.select_vobject('components', cid,
-                                            self.req, rset=self.rset)
+            comp = self.vreg['components'].select_vobject(
+                cid, self.req, rset=self.rset)
             if comp:
                 comp.render(w=self.w)
         self.w(u'</td>')
         # logged user and help
         self.w(u'<td>\n')
-        comp = self.vreg.select_vobject('components', 'loggeduserlink',
-                                        self.req, rset=self.rset)
+        comp = self.vreg['components'].select_vobject(
+            'loggeduserlink', self.req, rset=self.rset)
         if comp:
             comp.render(w=self.w)
         self.w(u'</td><td>')
-        helpcomp = self.vreg.select_vobject('components', 'help',
-                                            self.req, rset=self.rset)
+        helpcomp = self.vreg['components'].select_vobject(
+            'help', self.req, rset=self.rset)
         if helpcomp:
             helpcomp.render(w=self.w)
         self.w(u'</td>')
@@ -405,9 +405,8 @@
 
     def call(self, view, **kwargs):
         """by default, display informal messages in content header"""
-        components = self.vreg.possible_vobjects('contentnavigation',
-                                                 self.req, rset=self.rset,
-                                                 view=view, context='navtop')
+        components = self.vreg['contentnavigation'].possible_vobjects(
+            self.req, rset=self.rset, view=view, context='navtop')
         if components:
             self.w(u'<div id="contentheader">')
             for comp in components:
@@ -422,9 +421,8 @@
     id = 'contentfooter'
 
     def call(self, view, **kwargs):
-        components = self.vreg.possible_vobjects('contentnavigation',
-                                                 self.req, rset=self.rset,
-                                                 view=view, context='navbottom')
+        components = self.vreg['contentnavigation'].possible_vobjects(
+            self.req, rset=self.rset, view=view, context='navbottom')
         if components:
             self.w(u'<div id="contentfooter">')
             for comp in components:
--- a/web/views/boxes.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/boxes.py	Tue Aug 04 15:08:18 2009 +0200
@@ -51,7 +51,8 @@
                 title = u'%s - %s' % (title, etypelabel.lower())
         box = BoxWidget(title, self.id, _class="greyBoxFrame")
         # build list of actions
-        actions = self.vreg.possible_actions(self.req, self.rset, view=view)
+        actions = self.vreg['actions'].possible_actions(self.req, self.rset,
+                                                        view=view)
         add_menu = BoxMenu(_('add')) # 'addrelated' category
         other_menu = BoxMenu(_('more actions')) # 'moreactions' category
         searchstate = self.req.search_state[0]
@@ -207,7 +208,8 @@
 
     def call(self, **kwargs):
         box = BoxWidget(self.req._(self.title), self.id)
-        views = [v for v in self.vreg.possible_views(self.req, self.rset)
+        views = [v for v in self.vreg['views'].possible_views(self.req,
+                                                              rset=self.rset)
                  if v.category != 'startupview']
         for category, views in self.sort_actions(views):
             menu = BoxMenu(category)
@@ -227,7 +229,7 @@
 
     def call(self, **kwargs):
         box = BoxWidget(self.req._(self.title), self.id)
-        for view in self.vreg.possible_views(self.req, None):
+        for view in self.vreg['views'].possible_views(self.req, None):
             if view.category == 'startupview':
                 box.append(self.box_action(view))
 
--- a/web/views/cwproperties.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/cwproperties.py	Tue Aug 04 15:08:18 2009 +0200
@@ -180,7 +180,7 @@
         if key in values:
             entity = self.cwprops_rset.get_entity(values[key], 0)
         else:
-            entity = self.vreg.etype_class('CWProperty')(self.req, None, None)
+            entity = self.vreg['etypes'].etype_class('CWProperty')(self.req)
             entity.eid = self.req.varmaker.next()
             entity['pkey'] = key
             entity['value'] = self.vreg.property_value(key)
@@ -188,11 +188,11 @@
 
     def form(self, formid, keys, splitlabel=False):
         buttons = [SubmitButton()]
-        form = self.vreg.select('forms', 'composite', self.req,
-                                domid=formid, action=self.build_url(),
-                                form_buttons=buttons,
-                                onsubmit="return validatePrefsForm('%s')" % formid,
-                                submitmsg=self.req._('changes applied'))
+        form = self.vreg['forms'].select(
+            'composite', self.req, domid=formid, action=self.build_url(),
+            form_buttons=buttons,
+            onsubmit="return validatePrefsForm('%s')" % formid,
+            submitmsg=self.req._('changes applied'))
         path = self.req.relative_path()
         if '?' in path:
             path, params = path.split('?', 1)
@@ -200,8 +200,8 @@
         form.form_add_hidden('__redirectpath', path)
         for key in keys:
             self.form_row(form, key, splitlabel)
-        renderer = self.vreg.select('formrenderers', 'cwproperties', self.req,
-                                    display_progress_div=False)
+        renderer = self.vreg['formrenderers'].select('cwproperties', self.req,
+                                                     display_progress_div=False)
         return form.form_render(renderer=renderer)
 
     def form_row(self, form, key, splitlabel):
@@ -210,8 +210,8 @@
             label = key.split('.')[-1]
         else:
             label = key
-        subform = self.vreg.select('forms', 'base', self.req, entity=entity,
-                                   mainform=False)
+        subform = self.vreg['forms'].select('base', self.req, entity=entity,
+                                            mainform=False)
         subform.append_field(PropertyValueField(name='value', label=label,
                                                 eidparam=True))
         subform.vreg = self.vreg
--- a/web/views/editcontroller.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/editcontroller.py	Tue Aug 04 15:08:18 2009 +0200
@@ -81,7 +81,7 @@
     def edit_entity(self, formparams, multiple=False):
         """edit / create / copy an entity and return its eid"""
         etype = formparams['__type']
-        entity = self.vreg.etype_class(etype)(self.req, None, None)
+        entity = self.vreg['etypes'].etype_class(etype)(self.req)
         entity.eid = eid = self._get_eid(formparams['eid'])
         edited = self.req.form.get('__maineid') == formparams['eid']
         # let a chance to do some entity specific stuff.
--- a/web/views/editforms.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/editforms.py	Tue Aug 04 15:08:18 2009 +0200
@@ -62,8 +62,8 @@
             if entity.eid in done:
                 continue
             done.add(entity.eid)
-            subform = self.vreg.select('forms', 'base', self.req, entity=entity,
-                                       mainform=False)
+            subform = self.vreg['forms'].select('base', self.req, entity=entity,
+                                                mainform=False)
             self.form_add_subform(subform)
 
 
@@ -83,8 +83,8 @@
           % _('this action is not reversible!'))
         # XXX above message should have style of a warning
         w(u'<h4>%s</h4>\n' % _('Do you want to delete the following element(s) ?'))
-        form = self.vreg.select('forms', self.id, req, rset=self.rset,
-                                onsubmit=onsubmit)
+        form = self.vreg['forms'].select(self.id, req, rset=self.rset,
+                                         onsubmit=onsubmit)
         w(u'<ul>\n')
         for entity in self.rset.entities():
             # don't use outofcontext view or any other that may contain inline edition form
@@ -127,12 +127,10 @@
         return lzone or self._defaultlandingzone % {'msg' : xml_escape(self.req._(self._landingzonemsg))}
 
     def _build_renderer(self, entity, rtype, role):
-        return self.vreg.select_object('formrenderers', 'base', self.req,
-                                       entity=entity,
-                                       display_label=False, display_help=False,
-                                       display_fields=[(rtype, role)],
-                                       table_class='', button_bar_class='buttonbar',
-                                       display_progress_div=False)
+        return self.vreg['formrenderers'].select(
+            'base', self.req, entity=entity, display_label=False,
+            display_help=False, display_fields=[(rtype, role)], table_class='',
+            button_bar_class='buttonbar', display_progress_div=False)
 
     def cell_call(self, row, col, rtype=None, role='subject',
                   reload=False,      # controls reloading the whole page after change
@@ -207,12 +205,12 @@
                     % event_data)
         cancelclick = "hideInlineEdit(%s,\'%s\',\'%s\')" % (
             entity.eid, rtype, divid)
-        form = self.vreg.select('forms', 'base', self.req, entity=entity,
-                                domid='%s-form' % divid, cssstyle='display: none',
-                                onsubmit=onsubmit, action='#',
-                                form_buttons=[SubmitButton(),
-                                              Button(stdmsgs.BUTTON_CANCEL,
-                                                     onclick=cancelclick)])
+        form = self.vreg['forms'].select('base', self.req, entity=entity,
+                                         domid='%s-form' % divid, cssstyle='display: none',
+                                         onsubmit=onsubmit, action='#',
+                                         form_buttons=[SubmitButton(),
+                                                       Button(stdmsgs.BUTTON_CANCEL,
+                                                              onclick=cancelclick)])
         field = guess_field(entity.e_schema, entity.schema.rschema(rtype), role)
         form.append_field(field)
         w = self.w
@@ -243,12 +241,12 @@
                    Button(stdmsgs.BUTTON_CANCEL,
                           onclick="hideInlineEdit(%s,\'%s\',\'%s\')" % (
                               eid, rtype, divid))]
-        form = self.vreg.select('forms', 'edition', self.req, rset=self.rset,
-                                row=row, col=col, form_buttons=buttons,
-                                attrcategories=self.attrcategories,
-                                domid='%s-form' % divid, action='#',
-                                cssstyle='display: none',
-                                onsubmit=onsubmit % event_data)
+        form = self.vreg['forms'].select('edition', self.req, rset=self.rset,
+                                         row=row, col=col, form_buttons=buttons,
+                                         attrcategories=self.attrcategories,
+                                         domid='%s-form' % divid, action='#',
+                                         cssstyle='display: none',
+                                         onsubmit=onsubmit % event_data)
         try:
             field = form.field_by_name(rtype, role)
         except FieldNotFound:
@@ -283,9 +281,9 @@
     def render_form(self, entity):
         """fetch and render the form"""
         self.form_title(entity)
-        form = self.vreg.select('forms', 'edition', self.req, rset=entity.rset,
-                                row=entity.row, col=entity.col, entity=entity,
-                                submitmsg=self.submited_message())
+        form = self.vreg['forms'].select('edition', self.req, rset=entity.rset,
+                                         row=entity.row, col=entity.col, entity=entity,
+                                         submitmsg=self.submited_message())
         self.init_form(form, entity)
         self.w(form.form_render(formvid=u'edition'))
 
@@ -315,7 +313,7 @@
         """creation view for an entity"""
         etype = kwargs.pop('etype', self.req.form.get('etype'))
         try:
-            entity = self.vreg.etype_class(etype)(self.req)
+            entity = self.vreg['etypes'].etype_class(etype)(self.req)
         except:
             self.w(self.req._('no such entity type %s') % etype)
         else:
@@ -402,9 +400,10 @@
         kwargs.setdefault('__redirectrql', rset.printable_rql())
         super(TableEditForm, self).__init__(req, rset, **kwargs)
         for row in xrange(len(self.rset)):
-            form = self.vreg.select('forms', 'edition', self.req, rset=self.rset,
-                                    row=row, attrcategories=('primary',),
-                                    mainform=False)
+            form = self.vreg['forms'].select('edition', self.req,
+                                             rset=self.rset, row=row,
+                                             attrcategories=('primary',),
+                                             mainform=False)
             # XXX rely on the EntityCompositeFormRenderer to put the eid input
             form.remove_field(form.field_by_name('eid'))
             self.form_add_subform(form)
@@ -420,7 +419,7 @@
         should be the eid
         """
         #self.form_title(entity)
-        form = self.vreg.select('forms', self.id, self.req, rset=self.rset)
+        form = self.vreg['forms'].select(self.id, self.req, rset=self.rset)
         self.w(form.form_render())
 
 
@@ -451,9 +450,9 @@
 
     def render_form(self, entity, peid, rtype, role, **kwargs):
         """fetch and render the form"""
-        form = self.vreg.select('forms', 'edition', self.req, entity=entity,
-                                form_renderer_id='inline', mainform=False,
-                                copy_nav_params=False)
+        form = self.vreg['forms'].select('edition', self.req, entity=entity,
+                                         form_renderer_id='inline',
+                                         mainform=False, copy_nav_params=False)
         self.add_hiddens(form, entity, peid, rtype, role)
         divid = '%s-%s-%s' % (peid, rtype, entity.eid)
         title = self.schema.rschema(rtype).display_name(self.req, role)
@@ -503,7 +502,7 @@
         :param role: the role played by the `peid` in the relation
         """
         try:
-            entity = self.vreg.etype_class(etype)(self.req, None, None)
+            entity = self.vreg['etypes'].etype_class(etype)(self.req, None, None)
         except:
             self.w(self.req._('no such entity type %s') % etype)
             return
--- a/web/views/editviews.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/editviews.py	Tue Aug 04 15:08:18 2009 +0200
@@ -120,7 +120,7 @@
         eid = entity.eid
         pending_inserts = self.req.get_pending_inserts(eid)
         rtype = rschema.type
-        form = self.vreg.select('forms', 'edition', self.req, entity=entity)
+        form = self.vreg['forms'].select('edition', self.req, entity=entity)
         field = form.field_by_name(rschema, target, entity.e_schema)
         limit = self.req.property_value('navigation.combobox-limit')
         for eview, reid in form.form_field_vocabulary(field, limit):
--- a/web/views/embedding.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/embedding.py	Tue Aug 04 15:08:18 2009 +0200
@@ -73,7 +73,8 @@
                 body = '<h2>%s</h2><h3>%s</h3>' % (
                     _('error while embedding page'), err)
         self.process_rql(req.form.get('rql'))
-        return self.vreg.main_template(req, self.template, rset=self.rset, body=body)
+        return self.vreg['views'].main_template(req, self.template,
+                                                rset=self.rset, body=body)
 
 
 def entity_has_embedable_url(entity):
--- a/web/views/facets.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/facets.py	Tue Aug 04 15:08:18 2009 +0200
@@ -11,7 +11,7 @@
 
 from logilab.mtconverter import xml_escape
 
-from cubicweb.vregistry import objectify_selector
+from cubicweb.appobject import objectify_selector
 from cubicweb.selectors import (non_final_entity, two_lines_rset,
                                 match_context_prop, yes, relation_possible)
 from cubicweb.web.box import BoxTemplate
@@ -118,9 +118,9 @@
             self.w(self.bk_linkbox_template % bk_link)
 
     def get_facets(self, rset, mainvar):
-        return self.vreg.possible_vobjects('facets', self.req, rset=rset,
-                                           context='facetbox',
-                                           filtered_variable=mainvar)
+        return self.vreg['facets'].possible_vobjects(self.req, rset=rset,
+                                                     context='facetbox',
+                                                     filtered_variable=mainvar)
 
 # facets ######################################################################
 
--- a/web/views/formrenderers.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/formrenderers.py	Tue Aug 04 15:08:18 2009 +0200
@@ -13,7 +13,7 @@
 from simplejson import dumps
 
 from cubicweb.common import tags
-from cubicweb.appobject import AppRsetObject
+from cubicweb.appobject import AppObject
 from cubicweb.selectors import entity_implements, yes
 from cubicweb.web import eid_param
 from cubicweb.web import formwidgets as fwdgs
@@ -21,7 +21,7 @@
 from cubicweb.web.formfields import HiddenInitialValueField
 
 
-class FormRenderer(AppRsetObject):
+class FormRenderer(AppObject):
     """basic renderer displaying fields in a two columns table label | value
 
     +--------------+--------------+
--- a/web/views/forms.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/forms.py	Tue Aug 04 15:08:18 2009 +0200
@@ -179,9 +179,9 @@
         return renderer.render(self, values)
 
     def form_default_renderer(self):
-        return self.vreg.select('formrenderers', self.form_renderer_id,
-                                self.req, rset=self.rset,
-                                row=self.row, col=self.col)
+        return self.vreg['formrenderers'].select(self.form_renderer_id,
+                                                self.req, rset=self.rset,
+                                                row=self.row, col=self.col)
 
     def form_build_context(self, rendervalues=None):
         """build form context values (the .context attribute which is a
@@ -288,7 +288,8 @@
 
 class EntityFieldsForm(FieldsForm):
     id = 'base'
-    __select__ = (match_kwargs('entity') | (one_line_rset & non_final_entity()))
+    __select__ = (match_kwargs('entity')
+                  | (one_line_rset() & non_final_entity()))
 
     internal_fields = FieldsForm.internal_fields + ('__type', 'eid', '__maineid')
     domid = 'entityForm'
@@ -366,9 +367,9 @@
         return value
 
     def form_default_renderer(self):
-        return self.vreg.select('formrenderers', self.form_renderer_id,
-                                self.req, rset=self.rset, row=self.row,
-                                col=self.col, entity=self.edited_entity)
+        return self.vreg['formrenderers'].select(
+            self.form_renderer_id, self.req, rset=self.rset, row=self.row,
+            col=self.col, entity=self.edited_entity)
 
     def form_build_context(self, values=None):
         """overriden to add edit[s|o] hidden fields and to ensure schema fields
--- a/web/views/iprogress.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/iprogress.py	Tue Aug 04 15:08:18 2009 +0200
@@ -48,7 +48,7 @@
         self.req.add_css('cubicweb.iprogress.css')
         _ = self.req._
         self.columns = columns or self.columns
-        ecls = self.vreg.etype_class(self.rset.description[0][0])
+        ecls = self.vreg['etypes'].etype_class(self.rset.description[0][0])
         self.w(u'<table class="progress">')
         self.table_header(ecls)
         self.w(u'<tbody>')
@@ -168,8 +168,8 @@
     id = 'ic_progress_table_view'
 
     def call(self):
-        view = self.vreg.select('views', 'progress_table_view', self.req,
-                                rset=self.rset)
+        view = self.vreg['views'].select('progress_table_view', self.req,
+                                         rset=self.rset)
         columns = list(view.columns)
         try:
             columns.remove('project')
--- a/web/views/magicsearch.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/magicsearch.py	Tue Aug 04 15:08:18 2009 +0200
@@ -348,8 +348,7 @@
         super(MagicSearchComponent, self).__init__(req, rset)
         processors = []
         self.by_name = {}
-        for processorcls in self.vreg.registry_objects('components',
-                                                       'magicsearch_processor'):
+        for processorcls in self.vreg['components']['magicsearch_processor']:
             # instantiation needed
             processor = processorcls()
             processors.append(processor)
--- a/web/views/management.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/management.py	Tue Aug 04 15:08:18 2009 +0200
@@ -107,12 +107,12 @@
     def owned_by_edit_form(self, entity):
         self.w('<h3>%s</h3>' % self.req._('ownership'))
         msg = self.req._('ownerships have been changed')
-        form = self.vreg.select('forms', 'base', self.req, entity=entity,
-                                form_renderer_id='base', submitmsg=msg,
-                                form_buttons=[wdgs.SubmitButton()],
-                                domid='ownership%s' % entity.eid,
-                                __redirectvid='security',
-                                __redirectpath=entity.rest_path())
+        form = self.vreg['forms'].select('base', self.req, entity=entity,
+                                         form_renderer_id='base', submitmsg=msg,
+                                         form_buttons=[wdgs.SubmitButton()],
+                                         domid='ownership%s' % entity.eid,
+                                         __redirectvid='security',
+                                         __redirectpath=entity.rest_path())
         field = guess_field(entity.e_schema, self.schema.rschema('owned_by'))
         form.append_field(field)
         self.w(form.form_render(display_progress_div=False))
@@ -160,14 +160,14 @@
             self.w(self.req._('no associated permissions'))
 
     def require_permission_edit_form(self, entity):
-        newperm = self.vreg.etype_class('CWPermission')(self.req, None)
+        newperm = self.vreg['etypes'].etype_class('CWPermission')(self.req)
         newperm.eid = self.req.varmaker.next()
         self.w(u'<p>%s</p>' % self.req._('add a new permission'))
-        form = self.vreg.select('forms', 'base', self.req, entity=newperm,
-                                form_buttons=[wdgs.SubmitButton()],
-                                domid='reqperm%s' % entity.eid,
-                                __redirectvid='security',
-                                __redirectpath=entity.rest_path())
+        form = self.vreg['forms'].select('base', self.req, entity=newperm,
+                                         form_buttons=[wdgs.SubmitButton()],
+                                         domid='reqperm%s' % entity.eid,
+                                         __redirectvid='security',
+                                         __redirectpath=entity.rest_path())
         form.form_add_hidden('require_permission', entity.eid, role='object',
                              eidparam=True)
         permnames = getattr(entity, '__permissions__', None)
@@ -183,8 +183,8 @@
         form.append_field(field)
         field = guess_field(cwpermschema, self.schema.rschema('require_group'))
         form.append_field(field)
-        renderer = self.vreg.select('formrenderers', 'htable', self.req,
-                                    rset=None, display_progress_div=False)
+        renderer = self.vreg['formrenderers'].select(
+            'htable', self.req, rset=None, display_progress_div=False)
         self.w(form.form_render(renderer=renderer))
 
 
@@ -241,8 +241,8 @@
         submiturl = self.config['submit-url']
         submitmail = self.config['submit-mail']
         if submiturl or submitmail:
-            form = self.vreg.select('forms', 'base', self.req, rset=None,
-                                    mainform=False)
+            form = self.vreg['forms'].select('base', self.req, rset=None,
+                                             mainform=False)
             binfo = text_error_description(ex, excinfo, req, eversion, cversions)
             form.form_add_hidden('description', binfo,
                                  # we must use a text area to keep line breaks
--- a/web/views/massmailing.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/massmailing.py	Tue Aug 04 15:08:18 2009 +0200
@@ -68,7 +68,7 @@
     def get_allowed_substitutions(self):
         attrs = []
         for coltype in self.rset.column_types(0):
-            eclass = self.vreg.etype_class(coltype)
+            eclass = self.vreg['etypes'].etype_class(coltype)
             attrs.append(eclass.allowed_massmail_keys())
         return sorted(reduce(operator.and_, attrs))
 
@@ -126,6 +126,6 @@
         req.add_js('cubicweb.widgets.js', 'cubicweb.massmailing.js')
         req.add_css('cubicweb.mailform.css')
         from_addr = '%s <%s>' % (req.user.dc_title(), req.user.get_email())
-        form = self.vreg.select('forms', 'massmailing', self.req, rset=self.rset,
+        form = self.vreg['forms'].select('massmailing', self.req, rset=self.rset,
                                 action='sendmail', domid='sendmail')
         self.w(form.form_render(sender=from_addr))
--- a/web/views/navigation.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/navigation.py	Tue Aug 04 15:08:18 2009 +0200
@@ -149,7 +149,7 @@
 def limit_rset_using_paged_nav(self, req, rset, w, forcedisplay=False,
                                show_all_option=True, page_size=None):
     if not (forcedisplay or req.form.get('__force_display') is not None):
-        nav = self.vreg.select_object('components', 'navigation', req,
+        nav = self.vreg['components'].select_object('navigation', req,
                                       rset=rset, page_size=page_size)
         if nav:
             # get boundaries before component rendering
--- a/web/views/plots.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/plots.py	Tue Aug 04 15:08:18 2009 +0200
@@ -16,7 +16,7 @@
 from logilab.mtconverter import xml_escape
 
 from cubicweb.utils import make_uid, UStringIO, datetime2ticks
-from cubicweb.vregistry import objectify_selector
+from cubicweb.appobject import objectify_selector
 from cubicweb.web.views import baseviews
 
 @objectify_selector
--- a/web/views/primary.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/primary.py	Tue Aug 04 15:08:18 2009 +0200
@@ -71,9 +71,8 @@
 
     def content_navigation_components(self, context):
         self.w(u'<div class="%s">' % context)
-        for comp in self.vreg.possible_vobjects('contentnavigation', self.req,
-                                                rset=self.rset, row=self.row,
-                                                view=self, context=context):
+        for comp in self.vreg['contentnavigation'].possible_vobjects(
+            self.req, rset=self.rset, row=self.row, view=self, context=context):
             try:
                 comp.render(w=self.w, row=self.row, view=self)
             except NotImplementedError:
@@ -148,9 +147,9 @@
             label = display_name(self.req, rschema.type, role)
             vid = dispctrl.get('vid', 'sidebox')
             sideboxes.append( (label, rset, vid) )
-        sideboxes += self.vreg.possible_vobjects('boxes', self.req, rset=self.rset,
-                                                 row=self.row, view=self,
-                                                 context='incontext')
+        sideboxes += self.vreg['boxes'].possible_vobjects(
+            self.req, rset=self.rset, row=self.row, view=self,
+            context='incontext')
         return sideboxes
 
     def _section_def(self, entity, where):
--- a/web/views/startup.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/startup.py	Tue Aug 04 15:08:18 2009 +0200
@@ -83,7 +83,7 @@
         self.startupviews_table()
 
     def startupviews_table(self):
-        for v in self.vreg.possible_views(self.req, None):
+        for v in self.vreg['views'].possible_views(self.req, None):
             if v.category != 'startupview' or v.id in ('index', 'tree', 'manage'):
                 continue
             self.w('<p><a href="%s">%s</a></p>' % (
--- a/web/views/tableview.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/tableview.py	Tue Aug 04 15:08:18 2009 +0200
@@ -34,8 +34,8 @@
             return ()
         rqlst.save_state()
         mainvar, baserql = prepare_facets_rqlst(rqlst, self.rset.args)
-        wdgs = [facet.get_widget() for facet in self.vreg.possible_vobjects(
-            'facets', self.req, rset=self.rset, context='tablefilter',
+        wdgs = [facet.get_widget() for facet in self.vreg['facets'].possible_vobjects(
+            self.req, rset=self.rset, context='tablefilter',
             filtered_variable=mainvar)]
         wdgs = [wdg for wdg in wdgs if wdg is not None]
         rqlst.recover()
--- a/web/views/tabs.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/tabs.py	Tue Aug 04 15:08:18 2009 +0200
@@ -86,7 +86,7 @@
         selected_tabs = []
         for tab in tabs:
             try:
-                self.vreg.select('views', tab, self.req, rset=self.rset)
+                self.vreg['views'].select(tab, self.req, rset=self.rset)
                 selected_tabs.append(tab)
             except NoSelectableObject:
                 continue
--- a/web/views/urlpublishing.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/urlpublishing.py	Tue Aug 04 15:08:18 2009 +0200
@@ -56,8 +56,7 @@
         super(URLPublisherComponent, self).__init__()
         self.default_method = default_method
         evaluators = []
-        for evaluatorcls in self.vreg.registry_objects('components',
-                                                       'urlpathevaluator'):
+        for evaluatorcls in self.vreg['components']['urlpathevaluator']:
             # instantiation needed
             evaluator = evaluatorcls(self)
             evaluators.append(evaluator)
@@ -83,7 +82,7 @@
         parts = [part for part in path.split('/')
                  if part != ''] or (self.default_method,)
         if req.form.get('rql'):
-            if parts[0] in self.vreg.registry('controllers'):
+            if parts[0] in self.vreg['controllers']:
                 return parts[0], None
             return 'view', None
         for evaluator in self.evaluators:
@@ -114,7 +113,7 @@
     """
     priority = 0
     def evaluate_path(self, req, parts):
-        if len(parts) == 1 and parts[0] in self.vreg.registry('controllers'):
+        if len(parts) == 1 and parts[0] in self.vreg['controllers']:
             return parts[0], None
         raise PathDontMatch()
 
@@ -152,7 +151,7 @@
             etype = self.vreg.case_insensitive_etypes[parts.pop(0).lower()]
         except KeyError:
             raise PathDontMatch()
-        cls = self.vreg.etype_class(etype)
+        cls = self.vreg['etypes'].etype_class(etype)
         if parts:
             if len(parts) == 2:
                 attrname = parts.pop(0).lower()
@@ -195,10 +194,9 @@
     def evaluate_path(self, req, parts):
         # uri <=> req._twreq.path or req._twreq.uri
         uri = req.url_unquote('/' + '/'.join(parts))
-        vobjects = sorted(self.vreg.registry_objects('urlrewriting'),
-                          key=lambda x: x.priority,
-                          reverse=True)
-        for rewritercls in vobjects:
+        evaluators = sorted(self.vreg['urlrewriting'].all_objects(),
+                            key=lambda x: x.priority, reverse=True)
+        for rewritercls in evaluators:
             rewriter = rewritercls()
             try:
                 # XXX we might want to chain url rewrites
@@ -220,8 +218,9 @@
         # remove last part and see if this is something like an actions
         # if so, call
         try:
+            actionsreg = self.vreg['actions']
             requested = parts.pop(-1)
-            actions = self.vreg.registry_objects('actions', requested)
+            actions = actionsreg[requested]
         except RegistryException:
             raise PathDontMatch()
         for evaluator in self.urlpublisher.evaluators:
@@ -233,9 +232,9 @@
                 continue
             else:
                 try:
-                    action = self.vreg.select_best(actions, req, rset=rset)
+                    action = actionsreg.select_best(actions, req, rset=rset)
                 except RegistryException:
-                    raise PathDontMatch()
+                    continue
                 else:
                     # XXX avoid redirect
                     raise Redirect(action.url())
--- a/web/views/urlrewrite.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/urlrewrite.py	Tue Aug 04 15:08:18 2009 +0200
@@ -54,8 +54,6 @@
     __metaclass__ = metarewriter
     __registry__ = 'urlrewriting'
     __abstract__ = True
-
-    id = 'urlrewriting'
     priority = 1
 
     def rewrite(self, req, uri):
--- a/web/views/xmlrss.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/views/xmlrss.py	Tue Aug 04 15:08:18 2009 +0200
@@ -135,8 +135,8 @@
         except KeyError:
             self.error('missing RSS_LOGO external resource')
             return
-        urlgetter = self.vreg.select('components', 'rss_feed_url',
-                                     self.req, rset=self.rset)
+        urlgetter = self.vreg['components'].select('rss_feed_url', self.req,
+                                                   rset=self.rset)
         url = urlgetter.feed_url()
         self.w(u'<a href="%s"><img src="%s" alt="rss"/></a>\n' % (xml_escape(url), rss))
 
--- a/web/webconfig.py	Tue Aug 04 15:06:09 2009 +0200
+++ b/web/webconfig.py	Tue Aug 04 15:08:18 2009 +0200
@@ -63,8 +63,8 @@
     """the WebConfiguration is a singleton object handling instance's
     configuration and preferences
     """
-    cubicweb_vobject_path = CubicWebConfiguration.cubicweb_vobject_path | set(['web/views'])
-    cube_vobject_path = CubicWebConfiguration.cube_vobject_path | set(['views'])
+    cubicweb_appobject_path = CubicWebConfiguration.cubicweb_appobject_path | set(['web/views'])
+    cube_appobject_path = CubicWebConfiguration.cube_appobject_path | set(['views'])
 
     options = merge_options(CubicWebConfiguration.options + (
         ('anonymous-user',