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