1 # copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
3 # |
|
4 # This file is part of CubicWeb. |
|
5 # |
|
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
|
7 # terms of the GNU Lesser General Public License as published by the Free |
|
8 # Software Foundation, either version 2.1 of the License, or (at your option) |
|
9 # any later version. |
|
10 # |
|
11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
|
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
|
14 # details. |
|
15 # |
|
16 # You should have received a copy of the GNU Lesser General Public License along |
|
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
|
18 """ undoable transaction objects. """ |
|
19 __docformat__ = "restructuredtext en" |
|
20 from cubicweb import _ |
|
21 |
|
22 from cubicweb import RepositoryError |
|
23 |
|
24 |
|
25 ACTION_LABELS = { |
|
26 'C': _('entity creation'), |
|
27 'U': _('entity update'), |
|
28 'D': _('entity deletion'), |
|
29 'A': _('relation add'), |
|
30 'R': _('relation removal'), |
|
31 } |
|
32 |
|
33 |
|
34 class NoSuchTransaction(RepositoryError): |
|
35 # Used by CubicWebException |
|
36 msg = _("there is no transaction #%s") |
|
37 |
|
38 def __init__(self, txuuid): |
|
39 super(NoSuchTransaction, self).__init__(txuuid) |
|
40 self.txuuid = txuuid |
|
41 |
|
42 class Transaction(object): |
|
43 """an undoable transaction""" |
|
44 |
|
45 def __init__(self, cnx, uuid, time, ueid): |
|
46 self.cnx = cnx |
|
47 self.uuid = uuid |
|
48 self.datetime = time |
|
49 self.user_eid = ueid |
|
50 |
|
51 def _execute(self, *args, **kwargs): |
|
52 """execute a query using either the req or the cnx""" |
|
53 return self.cnx.execute(*args, **kwargs) |
|
54 |
|
55 |
|
56 def __repr__(self): |
|
57 return '<Transaction %s by %s on %s>' % ( |
|
58 self.uuid, self.user_eid, self.datetime) |
|
59 |
|
60 def user(self): |
|
61 """return the user entity which has done the transaction, |
|
62 none if not found. |
|
63 """ |
|
64 return self.cnx.find('CWUser', eid=self.user_eid).one() |
|
65 |
|
66 def actions_list(self, public=True): |
|
67 """return an ordered list of action effectued during that transaction |
|
68 |
|
69 if public is true, return only 'public' action, eg not ones triggered |
|
70 under the cover by hooks. |
|
71 """ |
|
72 return self.cnx.transaction_actions(self.uuid, public) |
|
73 |
|
74 |
|
75 class AbstractAction(object): |
|
76 |
|
77 def __init__(self, action, public, order): |
|
78 self.action = action |
|
79 self.public = public |
|
80 self.order = order |
|
81 |
|
82 @property |
|
83 def label(self): |
|
84 return ACTION_LABELS[self.action] |
|
85 |
|
86 @property |
|
87 def ertype(self): |
|
88 """ Return the entity or relation type this action is related to""" |
|
89 raise NotImplementedError(self) |
|
90 |
|
91 |
|
92 class EntityAction(AbstractAction): |
|
93 |
|
94 def __init__(self, action, public, order, etype, eid, changes): |
|
95 super(EntityAction, self).__init__(action, public, order) |
|
96 self.etype = etype |
|
97 self.eid = eid |
|
98 self.changes = changes |
|
99 |
|
100 def __repr__(self): |
|
101 return '<%s: %s %s (%s)>' % ( |
|
102 self.label, self.eid, self.changes, |
|
103 self.public and 'dbapi' or 'hook') |
|
104 |
|
105 @property |
|
106 def ertype(self): |
|
107 """ Return the entity or relation type this action is related to""" |
|
108 return self.etype |
|
109 |
|
110 |
|
111 class RelationAction(AbstractAction): |
|
112 |
|
113 def __init__(self, action, public, order, rtype, eidfrom, eidto): |
|
114 super(RelationAction, self).__init__(action, public, order) |
|
115 self.rtype = rtype |
|
116 self.eid_from = eidfrom |
|
117 self.eid_to = eidto |
|
118 |
|
119 def __repr__(self): |
|
120 return '<%s: %s %s %s (%s)>' % ( |
|
121 self.label, self.eid_from, self.rtype, self.eid_to, |
|
122 self.public and 'dbapi' or 'hook') |
|
123 |
|
124 @property |
|
125 def ertype(self): |
|
126 """ Return the entity or relation type this action is related to""" |
|
127 return self.rtype |
|