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 |
19 from logilab.common.decorators import monkeypatch |
20 from logilab.common.deprecation import deprecated |
20 from logilab.common.deprecation import deprecated |
21 |
21 |
22 from cubicweb import ETYPE_NAME_MAP, ConnectionError, RequestSessionMixIn |
22 from cubicweb import ETYPE_NAME_MAP, ConnectionError, cwvreg, cwconfig |
23 from cubicweb import cwvreg, cwconfig |
23 from cubicweb.req import RequestSessionBase |
|
24 |
24 |
25 |
25 _MARKER = object() |
26 _MARKER = object() |
26 |
27 |
27 def _fake_property_value(self, name): |
28 def _fake_property_value(self, name): |
28 try: |
29 try: |
29 return super(dbapi.DBAPIRequest, self).property_value(name) |
30 return super(DBAPIRequest, self).property_value(name) |
30 except KeyError: |
31 except KeyError: |
31 return '' |
32 return '' |
32 |
|
33 def _fix_cls_attrs(reg, appobject): |
|
34 appobject.vreg = reg.vreg |
|
35 appobject.schema = reg.schema |
|
36 appobject.config = reg.config |
|
37 |
33 |
38 def multiple_connections_fix(): |
34 def multiple_connections_fix(): |
39 """some monkey patching necessary when an application has to deal with |
35 """some monkey patching necessary when an application has to deal with |
40 several connections to different repositories. It tries to hide buggy class |
36 several connections to different repositories. It tries to hide buggy class |
41 attributes since classes are not designed to be shared among multiple |
37 attributes since classes are not designed to be shared among multiple |
42 registries. |
38 registries. |
43 """ |
39 """ |
44 defaultcls = cwvreg.VRegistry.REGISTRY_FACTORY[None] |
40 defaultcls = cwvreg.VRegistry.REGISTRY_FACTORY[None] |
45 orig_select_best = defaultcls.orig_select_best = defaultcls.select_best |
|
46 @monkeypatch(defaultcls) |
|
47 def select_best(self, appobjects, *args, **kwargs): |
|
48 """return an instance of the most specific object according |
|
49 to parameters |
|
50 |
|
51 raise NoSelectableObject if no object apply |
|
52 """ |
|
53 for appobjectcls in appobjects: |
|
54 _fix_cls_attrs(self, appobjectcls) |
|
55 selected = orig_select_best(self, appobjects, *args, **kwargs) |
|
56 # redo the same thing on the instance so it won't use equivalent class |
|
57 # attributes (which may change) |
|
58 _fix_cls_attrs(self, selected) |
|
59 return selected |
|
60 |
41 |
61 etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] |
42 etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] |
62 orig_etype_class = etypescls.orig_etype_class = etypescls.etype_class |
43 orig_etype_class = etypescls.orig_etype_class = etypescls.etype_class |
63 @monkeypatch(defaultcls) |
44 @monkeypatch(defaultcls) |
64 def etype_class(self, etype): |
45 def etype_class(self, etype): |
71 return usercls |
52 return usercls |
72 usercls.e_schema = self.schema.eschema(etype) |
53 usercls.e_schema = self.schema.eschema(etype) |
73 return usercls |
54 return usercls |
74 |
55 |
75 def multiple_connections_unfix(): |
56 def multiple_connections_unfix(): |
76 defaultcls = cwvreg.VRegistry.REGISTRY_FACTORY[None] |
|
77 defaultcls.select_best = defaultcls.orig_select_best |
|
78 etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] |
57 etypescls = cwvreg.VRegistry.REGISTRY_FACTORY['etypes'] |
79 etypescls.etype_class = etypescls.orig_etype_class |
58 etypescls.etype_class = etypescls.orig_etype_class |
80 |
59 |
81 class ConnectionProperties(object): |
60 class ConnectionProperties(object): |
82 def __init__(self, cnxtype=None, lang=None, close=True, log=False): |
61 def __init__(self, cnxtype=None, lang=None, close=True, log=False): |
108 defaultnsgroup=config['pyro-ns-group'], |
87 defaultnsgroup=config['pyro-ns-group'], |
109 nshost=config['pyro-ns-host']) |
88 nshost=config['pyro-ns-host']) |
110 except Exception, ex: |
89 except Exception, ex: |
111 raise ConnectionError(str(ex)) |
90 raise ConnectionError(str(ex)) |
112 |
91 |
113 def repo_connect(repo, login, password, cnxprops=None): |
92 def repo_connect(repo, login, **kwargs): |
114 """Constructor to create a new connection to the CubicWeb repository. |
93 """Constructor to create a new connection to the CubicWeb repository. |
115 |
94 |
116 Returns a Connection instance. |
95 Returns a Connection instance. |
117 """ |
96 """ |
118 cnxprops = cnxprops or ConnectionProperties('inmemory') |
97 if not 'cnxprops' in kwargs: |
119 cnxid = repo.connect(unicode(login), password, cnxprops=cnxprops) |
98 kwargs['cnxprops'] = ConnectionProperties('inmemory') |
120 cnx = Connection(repo, cnxid, cnxprops) |
99 cnxid = repo.connect(unicode(login), **kwargs) |
121 if cnxprops.cnxtype == 'inmemory': |
100 cnx = Connection(repo, cnxid, kwargs['cnxprops']) |
|
101 if kwargs['cnxprops'].cnxtype == 'inmemory': |
122 cnx.vreg = repo.vreg |
102 cnx.vreg = repo.vreg |
123 return cnx |
103 return cnx |
124 |
104 |
125 def connect(database=None, login=None, password=None, host=None, group=None, |
105 def connect(database=None, login=None, host=None, group=None, |
126 cnxprops=None, setvreg=True, mulcnx=True, initlog=True): |
106 cnxprops=None, setvreg=True, mulcnx=True, initlog=True, **kwargs): |
127 """Constructor for creating a connection to the CubicWeb repository. |
107 """Constructor for creating a connection to the CubicWeb repository. |
128 Returns a Connection object. |
108 Returns a Connection object. |
129 |
109 |
130 When method is 'pyro', setvreg is True, try to deal with connections to |
110 When method is 'pyro', setvreg is True, try to deal with connections to |
131 differents instances in the same process unless specified otherwise by |
111 differents instances in the same process unless specified otherwise by |
151 print 'aliasing', newetype, 'to', oldetype |
131 print 'aliasing', newetype, 'to', oldetype |
152 schema._entities[newetype] = schema._entities[oldetype] |
132 schema._entities[newetype] = schema._entities[oldetype] |
153 vreg.set_schema(schema) |
133 vreg.set_schema(schema) |
154 else: |
134 else: |
155 vreg = None |
135 vreg = None |
156 cnx = repo_connect(repo, login, password, cnxprops) |
136 cnx = repo_connect(repo, login, cnxprops=cnxprops, **kwargs) |
157 cnx.vreg = vreg |
137 cnx.vreg = vreg |
158 return cnx |
138 return cnx |
159 |
139 |
160 def in_memory_cnx(config, login, password): |
140 def in_memory_cnx(config, login, **kwargs): |
161 """usefull method for testing and scripting to get a dbapi.Connection |
141 """usefull method for testing and scripting to get a dbapi.Connection |
162 object connected to an in-memory repository instance |
142 object connected to an in-memory repository instance |
163 """ |
143 """ |
164 if isinstance(config, cwvreg.CubicWebVRegistry): |
144 if isinstance(config, cwvreg.CubicWebVRegistry): |
165 vreg = config |
145 vreg = config |
168 vreg = None |
148 vreg = None |
169 # get local access to the repository |
149 # get local access to the repository |
170 repo = get_repository('inmemory', config=config, vreg=vreg) |
150 repo = get_repository('inmemory', config=config, vreg=vreg) |
171 # connection to the CubicWeb repository |
151 # connection to the CubicWeb repository |
172 cnxprops = ConnectionProperties('inmemory') |
152 cnxprops = ConnectionProperties('inmemory') |
173 cnx = repo_connect(repo, login, password, cnxprops=cnxprops) |
153 cnx = repo_connect(repo, login, cnxprops=cnxprops, **kwargs) |
174 return repo, cnx |
154 return repo, cnx |
175 |
155 |
176 |
156 |
177 class DBAPIRequest(RequestSessionMixIn): |
157 class DBAPIRequest(RequestSessionBase): |
178 |
158 |
179 def __init__(self, vreg, cnx=None): |
159 def __init__(self, vreg, cnx=None): |
180 super(DBAPIRequest, self).__init__(vreg) |
160 super(DBAPIRequest, self).__init__(vreg) |
181 try: |
161 try: |
182 # no vreg or config which doesn't handle translations |
162 # no vreg or config which doesn't handle translations |
218 self._ = self.__ = gettext |
198 self._ = self.__ = gettext |
219 self.pgettext = pgettext |
199 self.pgettext = pgettext |
220 except KeyError: |
200 except KeyError: |
221 # this occurs usually during test execution |
201 # this occurs usually during test execution |
222 self._ = self.__ = unicode |
202 self._ = self.__ = unicode |
223 self.pgettext = lambda x,y: y |
203 self.pgettext = lambda x, y: y |
224 self.debug('request default language: %s', self.lang) |
204 self.debug('request default language: %s', self.lang) |
225 |
205 |
226 def decorate_rset(self, rset): |
206 def decorate_rset(self, rset): |
227 rset.vreg = self.vreg |
207 rset.vreg = self.vreg |
228 rset.req = self |
208 rset.req = self |
259 """return a dictionnary containing session data""" |
239 """return a dictionnary containing session data""" |
260 return self.cnx.session_data() |
240 return self.cnx.session_data() |
261 |
241 |
262 def get_session_data(self, key, default=None, pop=False): |
242 def get_session_data(self, key, default=None, pop=False): |
263 """return value associated to `key` in session data""" |
243 """return value associated to `key` in session data""" |
|
244 if self.cnx is None: |
|
245 return None # before the connection has been established |
264 return self.cnx.get_session_data(key, default, pop) |
246 return self.cnx.get_session_data(key, default, pop) |
265 |
247 |
266 def set_session_data(self, key, value): |
248 def set_session_data(self, key, value): |
267 """set value associated to `key` in session data""" |
249 """set value associated to `key` in session data""" |
268 return self.cnx.set_session_data(key, value) |
250 return self.cnx.set_session_data(key, value) |