|
1 """undoable transaction objects. |
|
2 |
|
3 |
|
4 This module is in the cubicweb package and not in cubicweb.server because those |
|
5 objects should be accessible to client through pyro, where the cubicweb.server |
|
6 package may not be installed. |
|
7 |
|
8 :organization: Logilab |
|
9 :copyright: 2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
|
10 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
11 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
|
12 """ |
|
13 __docformat__ = "restructuredtext en" |
|
14 _ = unicode |
|
15 |
|
16 from cubicweb import RepositoryError |
|
17 |
|
18 |
|
19 ACTION_LABELS = { |
|
20 'C': _('entity creation'), |
|
21 'U': _('entity update'), |
|
22 'D': _('entity deletion'), |
|
23 'A': _('relation add'), |
|
24 'R': _('relation removal'), |
|
25 } |
|
26 |
|
27 |
|
28 class NoSuchTransaction(RepositoryError): |
|
29 pass |
|
30 |
|
31 |
|
32 class Transaction(object): |
|
33 """an undoable transaction""" |
|
34 |
|
35 def __init__(self, uuid, time, ueid): |
|
36 self.uuid = uuid |
|
37 self.datetime = time |
|
38 self.user_eid = ueid |
|
39 # should be set by the dbapi connection |
|
40 self.req = None |
|
41 |
|
42 def __repr__(self): |
|
43 return '<Transaction %s by %s on %s>' % ( |
|
44 self.uuid, self.user_eid, self.datetime) |
|
45 |
|
46 def user(self): |
|
47 """return the user entity which has done the transaction, |
|
48 none if not found. |
|
49 """ |
|
50 return self.req.execute('Any X WHERE X eid %(x)s', |
|
51 {'x': self.user_eid}, 'x').get_entity(0, 0) |
|
52 |
|
53 def actions_list(self, public=True): |
|
54 """return an ordered list of action effectued during that transaction |
|
55 |
|
56 if public is true, return only 'public' action, eg not ones triggered |
|
57 under the cover by hooks. |
|
58 """ |
|
59 return self.req.cnx.transaction_actions(self.uuid, public) |
|
60 |
|
61 |
|
62 class AbstractAction(object): |
|
63 def __init__(self, action, public, order): |
|
64 self.action = action |
|
65 self.public = public |
|
66 self.order = order |
|
67 |
|
68 @property |
|
69 def label(self): |
|
70 return ACTION_LABELS[self.action] |
|
71 |
|
72 |
|
73 class EntityAction(AbstractAction): |
|
74 def __init__(self, action, public, order, etype, eid, changes): |
|
75 AbstractAction.__init__(self, action, public, order) |
|
76 self.etype = etype |
|
77 self.eid = eid |
|
78 self.changes = changes |
|
79 |
|
80 def __repr__(self): |
|
81 return '<%s: %s %s (%s)>' % ( |
|
82 self.label, self.eid, self.changes, |
|
83 self.public and 'dbapi' or 'hook') |
|
84 |
|
85 |
|
86 class RelationAction(AbstractAction): |
|
87 def __init__(self, action, public, order, rtype, eidfrom, eidto): |
|
88 AbstractAction.__init__(self, action, public, order) |
|
89 self.rtype = rtype |
|
90 self.eid_from = eidfrom |
|
91 self.eid_to = eidto |
|
92 |
|
93 def __repr__(self): |
|
94 return '<%s: %s %s %s (%s)>' % ( |
|
95 self.label, self.eid_from, self.rtype, self.eid_to, |
|
96 self.public and 'dbapi' or 'hook') |