20 from cubicweb.utils import parse_repo_uri |
20 from cubicweb.utils import parse_repo_uri |
21 from cubicweb import ConnectionError, ProgrammingError, AuthenticationError |
21 from cubicweb import ConnectionError, ProgrammingError, AuthenticationError |
22 from uuid import uuid4 |
22 from uuid import uuid4 |
23 from contextlib import contextmanager |
23 from contextlib import contextmanager |
24 from cubicweb.req import RequestSessionBase |
24 from cubicweb.req import RequestSessionBase |
|
25 from functools import wraps |
25 |
26 |
26 ### private function for specific method ############################ |
27 ### private function for specific method ############################ |
27 |
28 |
28 def _get_inmemory_repo(config, vreg=None): |
29 def _get_inmemory_repo(config, vreg=None): |
29 from cubicweb.server.repository import Repository |
30 from cubicweb.server.repository import Repository |
110 def proxy(clt_cnx, *args, **kwargs): |
111 def proxy(clt_cnx, *args, **kwargs): |
111 # the ``with`` dance is transitional. We do not have Standalone |
112 # the ``with`` dance is transitional. We do not have Standalone |
112 # Connection yet so we use this trick to unsure the session have the |
113 # Connection yet so we use this trick to unsure the session have the |
113 # proper cnx loaded. This can be simplified one we have Standalone |
114 # proper cnx loaded. This can be simplified one we have Standalone |
114 # Connection object |
115 # Connection object |
|
116 if not clt_cnx._open: |
|
117 raise ProgrammingError('Closed client connection') |
115 with clt_cnx._srv_cnx as cnx: |
118 with clt_cnx._srv_cnx as cnx: |
116 return getattr(cnx, name)(*args, **kwargs) |
119 return getattr(cnx, name)(*args, **kwargs) |
117 return proxy |
120 return proxy |
|
121 |
|
122 def _open_only(func): |
|
123 """decorator for ClientConnection method that check it is open""" |
|
124 @wraps(func) |
|
125 def check_open(clt_cnx, *args, **kwargs): |
|
126 if not clt_cnx._open: |
|
127 raise ProgrammingError('Closed client connection') |
|
128 return func(clt_cnx, *args, **kwargs) |
|
129 return check_open |
|
130 |
118 |
131 |
119 class ClientConnection(RequestSessionBase): |
132 class ClientConnection(RequestSessionBase): |
120 """A Connection object to be used Client side. |
133 """A Connection object to be used Client side. |
121 |
134 |
122 This object is aimed to be used client side (so potential communication |
135 This object is aimed to be used client side (so potential communication |
199 |
212 |
200 # Main Connection purpose in life ######################################### |
213 # Main Connection purpose in life ######################################### |
201 |
214 |
202 call_service = _srv_cnx_func('call_service') |
215 call_service = _srv_cnx_func('call_service') |
203 |
216 |
|
217 @_open_only |
204 def execute(self, *args, **kwargs): |
218 def execute(self, *args, **kwargs): |
205 # the ``with`` dance is transitional. We do not have Standalone |
219 # the ``with`` dance is transitional. We do not have Standalone |
206 # Connection yet so we use this trick to unsure the session have the |
220 # Connection yet so we use this trick to unsure the session have the |
207 # proper cnx loaded. This can be simplified one we have Standalone |
221 # proper cnx loaded. This can be simplified one we have Standalone |
208 # Connection object |
222 # Connection object |
223 get_shared_data = _srv_cnx_func('get_shared_data') |
237 get_shared_data = _srv_cnx_func('get_shared_data') |
224 set_shared_data = _srv_cnx_func('set_shared_data') |
238 set_shared_data = _srv_cnx_func('set_shared_data') |
225 |
239 |
226 # meta-data accessors ###################################################### |
240 # meta-data accessors ###################################################### |
227 |
241 |
|
242 @_open_only |
228 def source_defs(self): |
243 def source_defs(self): |
229 """Return the definition of sources used by the repository.""" |
244 """Return the definition of sources used by the repository.""" |
230 return self._session.repo.source_defs() |
245 return self._session.repo.source_defs() |
231 |
246 |
|
247 @_open_only |
232 def get_schema(self): |
248 def get_schema(self): |
233 """Return the schema currently used by the repository.""" |
249 """Return the schema currently used by the repository.""" |
234 return self._session.repo.source_defs() |
250 return self._session.repo.source_defs() |
235 |
251 |
|
252 @_open_only |
236 def get_option_value(self, option, foreid=None): |
253 def get_option_value(self, option, foreid=None): |
237 """Return the value for `option` in the configuration. If `foreid` is |
254 """Return the value for `option` in the configuration. If `foreid` is |
238 specified, the actual repository to which this entity belongs is |
255 specified, the actual repository to which this entity belongs is |
239 dereferenced and the option value retrieved from it. |
256 dereferenced and the option value retrieved from it. |
240 """ |
257 """ |
242 |
259 |
243 describe = _srv_cnx_func('describe') |
260 describe = _srv_cnx_func('describe') |
244 |
261 |
245 # undo support ############################################################ |
262 # undo support ############################################################ |
246 |
263 |
|
264 @_open_only |
247 def undoable_transactions(self, ueid=None, req=None, **actionfilters): |
265 def undoable_transactions(self, ueid=None, req=None, **actionfilters): |
248 """Return a list of undoable transaction objects by the connection's |
266 """Return a list of undoable transaction objects by the connection's |
249 user, ordered by descendant transaction time. |
267 user, ordered by descendant transaction time. |
250 |
268 |
251 Managers may filter according to user (eid) who has done the transaction |
269 Managers may filter according to user (eid) who has done the transaction |
276 txinfos = source.undoable_transactions(cnx, ueid, **actionfilters) |
294 txinfos = source.undoable_transactions(cnx, ueid, **actionfilters) |
277 for txinfo in txinfos: |
295 for txinfo in txinfos: |
278 txinfo.req = req or self # XXX mostly wrong |
296 txinfo.req = req or self # XXX mostly wrong |
279 return txinfos |
297 return txinfos |
280 |
298 |
|
299 @_open_only |
281 def transaction_info(self, txuuid, req=None): |
300 def transaction_info(self, txuuid, req=None): |
282 """Return transaction object for the given uid. |
301 """Return transaction object for the given uid. |
283 |
302 |
284 raise `NoSuchTransaction` if not found or if session's user is not |
303 raise `NoSuchTransaction` if not found or if session's user is not |
285 allowed (eg not in managers group and the transaction doesn't belong to |
304 allowed (eg not in managers group and the transaction doesn't belong to |
295 txinfo.req = req |
314 txinfo.req = req |
296 else: |
315 else: |
297 txinfo.cnx = self |
316 txinfo.cnx = self |
298 return txinfo |
317 return txinfo |
299 |
318 |
|
319 @_open_only |
300 def transaction_actions(self, txuuid, public=True): |
320 def transaction_actions(self, txuuid, public=True): |
301 """Return an ordered list of action effectued during that transaction. |
321 """Return an ordered list of action effectued during that transaction. |
302 |
322 |
303 If public is true, return only 'public' actions, eg not ones triggered |
323 If public is true, return only 'public' actions, eg not ones triggered |
304 under the cover by hooks, else return all actions. |
324 under the cover by hooks, else return all actions. |
312 # proper cnx loaded. This can be simplified one we have Standalone |
332 # proper cnx loaded. This can be simplified one we have Standalone |
313 # Connection object |
333 # Connection object |
314 with self._srv_cnx as cnx: |
334 with self._srv_cnx as cnx: |
315 return cnx.repo.system_source.tx_actions(cnx, txuuid, public) |
335 return cnx.repo.system_source.tx_actions(cnx, txuuid, public) |
316 |
336 |
|
337 @_open_only |
317 def undo_transaction(self, txuuid): |
338 def undo_transaction(self, txuuid): |
318 """Undo the given transaction. Return potential restoration errors. |
339 """Undo the given transaction. Return potential restoration errors. |
319 |
340 |
320 raise `NoSuchTransaction` if not found or if session's user is not |
341 raise `NoSuchTransaction` if not found or if session's user is not |
321 allowed (eg not in managers group and the transaction doesn't belong to |
342 allowed (eg not in managers group and the transaction doesn't belong to |