14 from logging import getLogger |
14 from logging import getLogger |
15 from time import time, clock |
15 from time import time, clock |
16 from itertools import count |
16 from itertools import count |
17 |
17 |
18 from logilab.common.logging_ext import set_log_methods |
18 from logilab.common.logging_ext import set_log_methods |
|
19 from logilab.common.decorators import monkeypatch |
|
20 |
19 from cubicweb import ETYPE_NAME_MAP, ConnectionError, RequestSessionMixIn |
21 from cubicweb import ETYPE_NAME_MAP, ConnectionError, RequestSessionMixIn |
20 from cubicweb.cwvreg import CubicWebRegistry, MulCnxCubicWebRegistry |
22 from cubicweb import cwvreg, cwconfig |
21 from cubicweb.cwconfig import CubicWebNoAppConfiguration |
|
22 |
23 |
23 _MARKER = object() |
24 _MARKER = object() |
24 |
25 |
25 def _fake_property_value(self, name): |
26 def _fake_property_value(self, name): |
26 try: |
27 try: |
27 return super(dbapi.DBAPIRequest, self).property_value(name) |
28 return super(dbapi.DBAPIRequest, self).property_value(name) |
28 except KeyError: |
29 except KeyError: |
29 return '' |
30 return '' |
|
31 |
|
32 def _fix_cls_attrs(reg, vobject): |
|
33 vobject.vreg = reg.vreg |
|
34 vobject.schema = reg.schema |
|
35 vobject.config = reg.config |
|
36 |
|
37 def multiple_connections_fix(): |
|
38 """some monkey patching necessary when an application has to deal with |
|
39 several connections to different repositories. It tries to hide buggy class |
|
40 attributes since classes are not designed to be shared among multiple |
|
41 registries. |
|
42 """ |
|
43 defaultcls = cwvreg.VRegistry.REGISTRY_FACTORY[None] |
|
44 orig_select_best = defaultcls.orig_select_best = defaultcls.select_best |
|
45 @monkeypatch(defaultcls) |
|
46 def select_best(self, vobjects, *args, **kwargs): |
|
47 """return an instance of the most specific object according |
|
48 to parameters |
|
49 |
|
50 raise NoSelectableObject if no object apply |
|
51 """ |
|
52 for vobjectcls in vobjects: |
|
53 _fix_cls_attrs(self, vobjectcls) |
|
54 selected = orig_select_best(self, vobjects, *args, **kwargs) |
|
55 # redo the same thing on the instance so it won't use equivalent class |
|
56 # attributes (which may change) |
|
57 _fix_cls_attrs(self, selected) |
|
58 return selected |
|
59 |
|
60 etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] |
|
61 orig_etype_class = etypescls.orig_etype_class = etypescls.etype_class |
|
62 @monkeypatch(defaultcls) |
|
63 def etype_class(self, etype): |
|
64 """return an entity class for the given entity type. |
|
65 Try to find out a specific class for this kind of entity or |
|
66 default to a dump of the class registered for 'Any' |
|
67 """ |
|
68 usercls = orig_etype_class(self, etype) |
|
69 if etype == 'Any': |
|
70 return usercls |
|
71 usercls.e_schema = self.schema.eschema(etype) |
|
72 return usercls |
|
73 |
|
74 def multiple_connections_unfix(): |
|
75 defaultcls = cwvreg.VRegistry.REGISTRY_FACTORY[None] |
|
76 defaultcls.select_best = defaultcls.orig_select_best |
|
77 etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] |
|
78 etypescls.etype_class = etypescls.orig_etype_class |
30 |
79 |
31 class ConnectionProperties(object): |
80 class ConnectionProperties(object): |
32 def __init__(self, cnxtype=None, lang=None, close=True, log=False): |
81 def __init__(self, cnxtype=None, lang=None, close=True, log=False): |
33 self.cnxtype = cnxtype or 'pyro' |
82 self.cnxtype = cnxtype or 'pyro' |
34 self.lang = lang |
83 self.lang = lang |
86 group=None, cnxprops=None, port=None, setvreg=True, mulcnx=True, |
135 group=None, cnxprops=None, port=None, setvreg=True, mulcnx=True, |
87 initlog=True): |
136 initlog=True): |
88 """Constructor for creating a connection to the CubicWeb repository. |
137 """Constructor for creating a connection to the CubicWeb repository. |
89 Returns a Connection object. |
138 Returns a Connection object. |
90 |
139 |
91 When method is 'pyro' and setvreg is True, use a special registry class |
140 When method is 'pyro', setvreg is True, try to deal with connections to |
92 (MulCnxCubicWebRegistry) made to deal with connections to differents instances |
141 differents instances in the same process unless specified otherwise by |
93 in the same process unless specified otherwise by setting the mulcnx to |
142 setting the mulcnx to False. |
94 False. |
|
95 """ |
143 """ |
96 config = CubicWebNoAppConfiguration() |
144 config = cwconfig.CubicWebNoAppConfiguration() |
97 if host: |
145 if host: |
98 config.global_set_option('pyro-ns-host', host) |
146 config.global_set_option('pyro-ns-host', host) |
99 if port: |
147 if port: |
100 config.global_set_option('pyro-ns-port', port) |
148 config.global_set_option('pyro-ns-port', port) |
101 if group: |
149 if group: |
105 repo = get_repository(method, database, config=config) |
153 repo = get_repository(method, database, config=config) |
106 if method == 'inmemory': |
154 if method == 'inmemory': |
107 vreg = repo.vreg |
155 vreg = repo.vreg |
108 elif setvreg: |
156 elif setvreg: |
109 if mulcnx: |
157 if mulcnx: |
110 vreg = MulCnxCubicWebRegistry(config, initlog=initlog) |
158 multiple_connections_fix() |
111 else: |
159 vreg = cwvreg.CubicWebVRegistry(config, initlog=initlog) |
112 vreg = CubicWebRegistry(config, initlog=initlog) |
|
113 schema = repo.get_schema() |
160 schema = repo.get_schema() |
114 for oldetype, newetype in ETYPE_NAME_MAP.items(): |
161 for oldetype, newetype in ETYPE_NAME_MAP.items(): |
115 if oldetype in schema: |
162 if oldetype in schema: |
116 print 'aliasing', newetype, 'to', oldetype |
163 print 'aliasing', newetype, 'to', oldetype |
117 schema._entities[newetype] = schema._entities[oldetype] |
164 schema._entities[newetype] = schema._entities[oldetype] |
474 eid, login, groups, properties = self._repo.user_info(self.sessionid, |
521 eid, login, groups, properties = self._repo.user_info(self.sessionid, |
475 props) |
522 props) |
476 if req is None: |
523 if req is None: |
477 req = self.request() |
524 req = self.request() |
478 rset = req.eid_rset(eid, 'CWUser') |
525 rset = req.eid_rset(eid, 'CWUser') |
479 user = self.vreg.etype_class('CWUser')(req, rset, row=0, groups=groups, |
526 user = self.vreg['etypes'].etype_class('CWUser')(req, rset, row=0, |
480 properties=properties) |
527 groups=groups, |
|
528 properties=properties) |
481 user['login'] = login # cache login |
529 user['login'] = login # cache login |
482 return user |
530 return user |
483 |
531 |
484 def __del__(self): |
532 def __del__(self): |
485 """close the remote connection if necessary""" |
533 """close the remote connection if necessary""" |