Merge lp:~flacoste/storm/bug-360846 into lp:storm

Proposed by Francis J. Lacoste
Status: Rejected
Rejected by: James Henstridge
Proposed branch: lp:~flacoste/storm/bug-360846
Merge into: lp:storm
Diff against target: 3708 lines (has conflicts)
Text conflict in Makefile
Text conflict in NEWS
Text conflict in storm/__init__.py
Text conflict in storm/cextensions.c
Text conflict in storm/databases/postgres.py
Text conflict in storm/sqlobject.py
Text conflict in storm/store.py
Text conflict in storm/tracer.py
Text conflict in storm/variables.py
Text conflict in storm/zope/__init__.py
Text conflict in tests/expr.py
Text conflict in tests/store/base.py
Text conflict in tests/tracer.py
Text conflict in tests/zope/zstorm.py
To merge this branch: bzr merge lp:~flacoste/storm/bug-360846
Reviewer Review Type Date Requested Status
James Henstridge Needs Resubmitting
Review via email: mp+6271@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

Hi storm developers,

In Launchpad, we are encountering an error which isn't recognized as a disconnection error (and thus should trigger the reconnection code).

Since I didn't see tests for the existing ones, I didn't bother adding one.

Revision history for this message
James Henstridge (jamesh) wrote :

> Hi storm developers,
>
> In Launchpad, we are encountering an error which isn't recognized as a
> disconnection error (and thus should trigger the reconnection code).
>
> Since I didn't see tests for the existing ones, I didn't bother adding one.

This branch doesn't apply to Storm's trunk. It looks like you're missing about 8 months of development in the version of Storm Launchpad is using. There have been important bug fixes in that time (e.g. bug 276690), so you should seriously consider upgrading.

Looking at the diff against Launchpad's version of Storm, the change looks worth merging although it lacks a test.

IIRC, this message only occurs if you try to use the connection a second time after libpq reports that the connection was lost. Storm should be catching the first message just fine, so this probably indicates that there was some use of the underlying connection object outside of Storm that reported the initial error. You'd probably need to do the same sort of thing to test it.

review: Needs Resubmitting
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

On Thursday 07 May 2009, James Henstridge wrote:
> Review: Resubmit
>
> > Hi storm developers,
> >
> > In Launchpad, we are encountering an error which isn't recognized as a
> > disconnection error (and thus should trigger the reconnection code).
> >
> > Since I didn't see tests for the existing ones, I didn't bother adding
> > one.
>
> This branch doesn't apply to Storm's trunk. It looks like you're missing
> about 8 months of development in the version of Storm Launchpad is using.
> There have been important bug fixes in that time (e.g. bug 276690), so you
> should seriously consider upgrading.
>
> Looking at the diff against Launchpad's version of Storm, the change looks
> worth merging although it lacks a test.
>
> IIRC, this message only occurs if you try to use the connection a second
> time after libpq reports that the connection was lost. Storm should be
> catching the first message just fine, so this probably indicates that there
> was some use of the underlying connection object outside of Storm that
> reported the initial error. You'd probably need to do the same sort of
> thing to test it.

I didn't found tests for the existing functionality. Are there any? I don't
mean the general reconnecting facility, but about which errors are caught. To
me this is simply another kind of these errors.

--
Francis J. Lacoste
<email address hidden>

Unmerged revisions

122. By Francis J. Lacoste

InterfaceError: connection already closed should trigger a reconnection.

121. By Launchpad PQM Bot

[rs=salgado] Backport ISQLObjectResultSet to IResultSet adapter from
 trunk.

120. By Launchpad PQM Bot

[r=flacoste][!log] Pull changes from storm's trunk.

119. By Launchpad PQM Bot

[r=flacoste][release-critical=joey] Implementation of Store.reset
 (from radix), which we're going to use after every request

118. By Launchpad PQM Bot

[r=thumper] Implement SQLObjectResultSet.__contains__()

117. By Launchpad PQM Bot

[rs=jamesh] merge Storm trunk and ~jamesh/storm/slots

116. By Launchpad PQM Bot

[rs=jamesh] merge Gustavo's need-for-speed-revenge branch. Renable
 ZStormTest.test_wb_reset test. Disable event emission in Store.flush()

115. By Launchpad PQM Bot

[rs=jamesh] merge Storm trunk to rocketfuel

114. By Launchpad PQM Bot

[r=jamesh][!log] Disable an intermittently failing test in the storm
 suite. See bug 240801.

113. By Launchpad PQM Bot

[r=jamesh] adjust PostgresConnection.is_disconnection_error() to
 accept some forms that weren't being caught

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile'
--- Makefile 2008-11-19 18:22:29 +0000
+++ Makefile 2009-05-06 21:20:15 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1PYTHON ?= python2PYTHON ?= python
23
3TEST_COMMAND = $(PYTHON) test4TEST_COMMAND = $(PYTHON) test
@@ -28,3 +29,29 @@
28 find . -name "*~" -type f -exec rm -f {} \;29 find . -name "*~" -type f -exec rm -f {} \;
2930
30.PHONY: all build test31.PHONY: all build test
32=======
33PYTHON = python
34
35TEST_COMMAND = $(PYTHON) test
36
37STORM_POSTGRES_URI = postgres:storm_test
38STORM_POSTGRES_HOST_URI = postgres://localhost/storm_test
39STORM_MYSQL_URI = mysql:storm_test
40STORM_MYSQL_HOST_URI = mysql://localhost/storm_test
41
42export STORM_POSTGRES_URI
43export STORM_POSTGRES_HOST_URI
44export STORM_MYSQL_URI
45export STORM_MYSQL_HOST_URI
46
47all: build
48
49build:
50 $(PYTHON) setup.py build_ext -i
51
52check: build
53 # Run the tests once with cextensions and once without them.
54 $(TEST_COMMAND) && STORM_CEXTENSIONS=1 $(TEST_COMMAND)
55
56.PHONY: all build test
57>>>>>>> MERGE-SOURCE
3158
=== modified file 'NEWS'
--- NEWS 2009-03-18 07:11:14 +0000
+++ NEWS 2009-05-06 21:20:15 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
10.15 (2009-XX-XX)20.15 (2009-XX-XX)
2=================3=================
34
@@ -67,6 +68,17 @@
67 the "GROUP BY" and "HAVING" statements.68 the "GROUP BY" and "HAVING" statements.
68 - Change tests/store to keep the connection during the tests to make it69 - Change tests/store to keep the connection during the tests to make it
69 faster.70 faster.
71=======
720.13 (2008-XX-XX)
73=================
74
75Improvements
76------------
77 - Add group_by/having methods on ResultSet objects, to allow access to
78 the "GROUP BY" and "HAVING" statements.
79 - Change tests/store to keep the connection during the tests to make it
80 faster.
81>>>>>>> MERGE-SOURCE
70 - Implemented support for plugging generic "tracers". Statement82 - Implemented support for plugging generic "tracers". Statement
71 debugging is now implemented using a tracer, and easily enabled83 debugging is now implemented using a tracer, and easily enabled
72 with storm.tracer.debug(True) (storm.database.DEBUG = True is gone).84 with storm.tracer.debug(True) (storm.database.DEBUG = True is gone).
@@ -76,6 +88,7 @@
76 the property. The value assigned to the property is the result88 the property. The value assigned to the property is the result
77 of the validator, so the original value should be returned if89 of the validator, so the original value should be returned if
78 changing it isn't intended.90 changing it isn't intended.
91<<<<<<< TREE
79 - Expressions can be passed to Store.find() as well as classes. This92 - Expressions can be passed to Store.find() as well as classes. This
80 makes it possible to request individual columns from a table,93 makes it possible to request individual columns from a table,
81 computed expressions or aggregates.94 computed expressions or aggregates.
@@ -97,6 +110,26 @@
97 zope.interface and transaction packages installed. This makes it110 zope.interface and transaction packages installed. This makes it
98 easier to reuse the per-thread store management and global111 easier to reuse the per-thread store management and global
99 transaction handling from other web frameworks.112 transaction handling from other web frameworks.
113=======
114 - Expressions can be passed to Store.find() as well as classes. This
115 makes it possible to request individual columns from a table,
116 computed expressions or aggregates.
117 - Objects will be flushed in the order they become dirty by default.
118 This means that generally the order in which Python operations are
119 performed will be used to define the order in which flushes are done,
120 which is generally the most expected.
121 - The cextensions module was fixed, optimized, and improved. It's now
122 built by default, but to actually enable it the environment variable
123 STORM_CEXTENSIONS=1 must be defined at runtime. The module will
124 likely be enabled by default on a future release.
125 - ClassAlias will now cache all explicitly named aliases, to prevent
126 the cost of rebuilding it.
127 - Result sets and reference sets now have a __contains__() method.
128 While code like "item in set" was previously possible, it involved
129 iterating over the result set, which is expensive for large
130 databases.
131
132>>>>>>> MERGE-SOURCE
100133
101Bug fixes134Bug fixes
102---------135---------
@@ -115,10 +148,15 @@
115 previously raise OrderLoopError.148 previously raise OrderLoopError.
116 - If the remote object in a back reference is removed, the reference149 - If the remote object in a back reference is removed, the reference
117 will now be broken.150 will now be broken.
151<<<<<<< TREE
118 - Fixed a race condition when two threads try to initialize the152 - Fixed a race condition when two threads try to initialize the
119 ClassInfo for a given class at the same time.153 ClassInfo for a given class at the same time.
120 - Improve handling of AUTO INCREMENT columns in the MySQL backend to154 - Improve handling of AUTO INCREMENT columns in the MySQL backend to
121 remove an unnecessary query when adding objects to a store.155 remove an unnecessary query when adding objects to a store.
156=======
157 - Fixed a race condition when two threads try to initialize the
158 ClassInfo for a given class at the same time.
159>>>>>>> MERGE-SOURCE
122160
123161
1240.12 (2008-01-28)1620.12 (2008-01-28)
125163
=== modified file 'storm/__init__.py'
--- storm/__init__.py 2009-01-09 17:40:25 +0000
+++ storm/__init__.py 2009-05-06 21:20:16 +0000
@@ -19,10 +19,17 @@
19# along with this program. If not, see <http://www.gnu.org/licenses/>.19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#20#
2121
22<<<<<<< TREE
22import os23import os
2324
2425
25version = "0.14"26version = "0.14"
27=======
28import os
29
30
31version = "0.12"
32>>>>>>> MERGE-SOURCE
26version_info = tuple([int(x) for x in version.split(".")])33version_info = tuple([int(x) for x in version.split(".")])
2734
2835
2936
=== modified file 'storm/cextensions.c'
--- storm/cextensions.c 2009-02-09 16:59:07 +0000
+++ storm/cextensions.c 2009-05-06 21:20:16 +0000
@@ -165,86 +165,165 @@
165165
166 initialized = 1;166 initialized = 1;
167167
168 /* Import objects from storm module */168<<<<<<< TREE
169 module = PyImport_ImportModule("storm");169 /* Import objects from storm module */
170 if (!module)170 module = PyImport_ImportModule("storm");
171 return 0;171 if (!module)
172172 return 0;
173 Undef = PyObject_GetAttrString(module, "Undef");173
174 if (!Undef)174 Undef = PyObject_GetAttrString(module, "Undef");
175 return 0;175 if (!Undef)
176176 return 0;
177 Py_DECREF(module);177
178178 Py_DECREF(module);
179 /* Import objects from storm.variables module */179
180 module = PyImport_ImportModule("storm.variables");180 /* Import objects from storm.variables module */
181 if (!module)181 module = PyImport_ImportModule("storm.variables");
182 return 0;182 if (!module)
183183 return 0;
184 raise_none_error = PyObject_GetAttrString(module, "raise_none_error");184
185 if (!raise_none_error)185 raise_none_error = PyObject_GetAttrString(module, "raise_none_error");
186 return 0;186 if (!raise_none_error)
187187 return 0;
188 LazyValue = PyObject_GetAttrString(module, "LazyValue");188
189 if (!LazyValue)189 LazyValue = PyObject_GetAttrString(module, "LazyValue");
190 return 0;190 if (!LazyValue)
191191 return 0;
192 Py_DECREF(module);192
193193 Py_DECREF(module);
194 /* Import objects from storm.info module */194
195 module = PyImport_ImportModule("storm.info");195 /* Import objects from storm.info module */
196 if (!module)196 module = PyImport_ImportModule("storm.info");
197 return 0;197 if (!module)
198198 return 0;
199 get_cls_info = PyObject_GetAttrString(module, "get_cls_info");199
200 if (!get_cls_info)200 get_cls_info = PyObject_GetAttrString(module, "get_cls_info");
201 return 0;201 if (!get_cls_info)
202202 return 0;
203 Py_DECREF(module);203
204204 Py_DECREF(module);
205 /* Import objects from storm.event module */205
206 module = PyImport_ImportModule("storm.event");206 /* Import objects from storm.event module */
207 if (!module)207 module = PyImport_ImportModule("storm.event");
208 return 0;208 if (!module)
209209 return 0;
210 EventSystem = PyObject_GetAttrString(module, "EventSystem");210
211 if (!EventSystem)211 EventSystem = PyObject_GetAttrString(module, "EventSystem");
212 return 0;212 if (!EventSystem)
213213 return 0;
214 Py_DECREF(module);214
215215 Py_DECREF(module);
216 /* Import objects from storm.expr module */216
217 module = PyImport_ImportModule("storm.expr");217 /* Import objects from storm.expr module */
218 if (!module)218 module = PyImport_ImportModule("storm.expr");
219 return 0;219 if (!module)
220220 return 0;
221 SQLRaw = PyObject_GetAttrString(module, "SQLRaw");221
222 if (!SQLRaw)222 SQLRaw = PyObject_GetAttrString(module, "SQLRaw");
223 return 0;223 if (!SQLRaw)
224224 return 0;
225 SQLToken = PyObject_GetAttrString(module, "SQLToken");225
226 if (!SQLToken)226 SQLToken = PyObject_GetAttrString(module, "SQLToken");
227 return 0;227 if (!SQLToken)
228228 return 0;
229 State = PyObject_GetAttrString(module, "State");229
230 if (!State)230 State = PyObject_GetAttrString(module, "State");
231 return 0;231 if (!State)
232232 return 0;
233 CompileError = PyObject_GetAttrString(module, "CompileError");233
234 if (!CompileError)234 CompileError = PyObject_GetAttrString(module, "CompileError");
235 return 0;235 if (!CompileError)
236236 return 0;
237 Py_DECREF(module);237
238238 Py_DECREF(module);
239 /* A few frequently used objects which are part of the fast path. */239
240240 /* A few frequently used objects which are part of the fast path. */
241 parenthesis_format = PyUnicode_DecodeASCII("(%s)", 4, "strict");241
242 default_compile_join = PyUnicode_DecodeASCII(", ", 2, "strict");242 parenthesis_format = PyUnicode_DecodeASCII("(%s)", 4, "strict");
243 default_compile_join = PyUnicode_DecodeASCII(", ", 2, "strict");
244=======
245 /* Import objects from storm module */
246 module = PyImport_ImportModule("storm");
247 if (!module)
248 return 0;
249
250 Undef = PyObject_GetAttrString(module, "Undef");
251 if (!Undef)
252 return 0;
253
254 Py_DECREF(module);
255
256 /* Import objects from storm.variables module */
257 module = PyImport_ImportModule("storm.variables");
258 if (!module)
259 return 0;
260
261 raise_none_error = PyObject_GetAttrString(module, "raise_none_error");
262 if (!raise_none_error)
263 return 0;
264
265 LazyValue = PyObject_GetAttrString(module, "LazyValue");
266 if (!LazyValue)
267 return 0;
268
269 Py_DECREF(module);
270
271 /* Import objects from storm.info module */
272 module = PyImport_ImportModule("storm.info");
273 if (!module)
274 return 0;
275
276 get_cls_info = PyObject_GetAttrString(module, "get_cls_info");
277 if (!get_cls_info)
278 return 0;
279
280 Py_DECREF(module);
281
282 /* Import objects from storm.event module */
283 module = PyImport_ImportModule("storm.event");
284 if (!module)
285 return 0;
286
287 EventSystem = PyObject_GetAttrString(module, "EventSystem");
288 if (!EventSystem)
289 return 0;
290
291 Py_DECREF(module);
292
293 /* Import objects from storm.expr module */
294 module = PyImport_ImportModule("storm.expr");
295 if (!module)
296 return 0;
297
298 SQLRaw = PyObject_GetAttrString(module, "SQLRaw");
299 if (!SQLRaw)
300 return 0;
301
302 SQLToken = PyObject_GetAttrString(module, "SQLToken");
303 if (!SQLToken)
304 return 0;
305
306 State = PyObject_GetAttrString(module, "State");
307 if (!State)
308 return 0;
309
310 CompileError = PyObject_GetAttrString(module, "CompileError");
311 if (!CompileError)
312 return 0;
313
314 Py_DECREF(module);
315
316 /* A few frequently used objects which are part of the fast path. */
317
318 parenthesis_format = PyUnicode_DecodeASCII("(%s)", 4, "strict");
319 default_compile_join = PyUnicode_DecodeASCII(", ", 2, "strict");
320>>>>>>> MERGE-SOURCE
243321
244 return 1;322 return 1;
245}323}
246324
247325
326<<<<<<< TREE
248static int327static int
249EventSystem_init(EventSystemObject *self, PyObject *args, PyObject *kwargs)328EventSystem_init(EventSystemObject *self, PyObject *args, PyObject *kwargs)
250{329{
@@ -554,6 +633,317 @@
554};633};
555634
556635
636=======
637static int
638EventSystem_init(EventSystemObject *self, PyObject *args, PyObject *kwargs)
639{
640 static char *kwlist[] = {"owner", NULL};
641 PyObject *owner;
642 int result = -1;
643
644 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &owner))
645 return -1;
646
647 /* self._owner_ref = weakref.ref(owner) */
648 self->_owner_ref = PyWeakref_NewRef(owner, NULL);
649 if (self->_owner_ref) {
650 /* self._hooks = {} */
651 self->_hooks = PyDict_New();
652 if (self->_hooks) {
653 result = 0;
654 }
655 }
656
657 return result;
658}
659
660static int
661EventSystem_traverse(EventSystemObject *self, visitproc visit, void *arg)
662{
663 Py_VISIT(self->_owner_ref);
664 Py_VISIT(self->_hooks);
665 return 0;
666}
667
668static int
669EventSystem_clear(EventSystemObject *self)
670{
671 Py_CLEAR(self->_owner_ref);
672 Py_CLEAR(self->_hooks);
673 return 0;
674}
675
676static void
677EventSystem_dealloc(EventSystemObject *self)
678{
679 EventSystem_clear(self);
680 self->ob_type->tp_free((PyObject *)self);
681}
682
683static PyObject *
684EventSystem_hook(EventSystemObject *self, PyObject *args)
685{
686 PyObject *result = NULL;
687 PyObject *name, *callback, *data;
688
689 if (PyTuple_GET_SIZE(args) < 2) {
690 PyErr_SetString(PyExc_TypeError, "Invalid number of arguments");
691 return NULL;
692 }
693
694 name = PyTuple_GET_ITEM(args, 0);
695 callback = PyTuple_GET_ITEM(args, 1);
696 data = PyTuple_GetSlice(args, 2, PyTuple_GET_SIZE(args));
697 if (data) {
698 /*
699 callbacks = self._hooks.get(name)
700 if callbacks is None:
701 self._hooks.setdefault(name, set()).add((callback, data))
702 else:
703 callbacks.add((callback, data))
704 */
705 PyObject *callbacks = PyDict_GetItem(self->_hooks, name);
706 if (!PyErr_Occurred()) {
707 if (callbacks == NULL) {
708 callbacks = PySet_New(NULL);
709 if (callbacks &&
710 PyDict_SetItem(self->_hooks, name, callbacks) == -1) {
711 Py_DECREF(callbacks);
712 callbacks = NULL;
713 }
714 } else {
715 Py_INCREF(callbacks);
716 }
717 if (callbacks) {
718 PyObject *tuple = PyTuple_New(2);
719 if (tuple) {
720 Py_INCREF(callback);
721 PyTuple_SET_ITEM(tuple, 0, callback);
722 Py_INCREF(data);
723 PyTuple_SET_ITEM(tuple, 1, data);
724 if (PySet_Add(callbacks, tuple) != -1) {
725 Py_INCREF(Py_None);
726 result = Py_None;
727 }
728 Py_DECREF(tuple);
729 }
730 Py_DECREF(callbacks);
731 }
732 }
733 Py_DECREF(data);
734 }
735
736 return result;
737}
738
739static PyObject *
740EventSystem_unhook(EventSystemObject *self, PyObject *args)
741{
742 PyObject *result = NULL;
743 PyObject *name, *callback, *data;
744
745 if (PyTuple_GET_SIZE(args) < 2) {
746 PyErr_SetString(PyExc_TypeError, "Invalid number of arguments");
747 return NULL;
748 }
749
750 name = PyTuple_GET_ITEM(args, 0);
751 callback = PyTuple_GET_ITEM(args, 1);
752 data = PyTuple_GetSlice(args, 2, PyTuple_GET_SIZE(args));
753 if (data) {
754 /*
755 callbacks = self._hooks.get(name)
756 if callbacks is not None:
757 callbacks.discard((callback, data))
758 */
759 PyObject *callbacks = PyDict_GetItem(self->_hooks, name);
760 if (callbacks) {
761 PyObject *tuple = PyTuple_New(2);
762 if (tuple) {
763 Py_INCREF(callback);
764 PyTuple_SET_ITEM(tuple, 0, callback);
765 Py_INCREF(data);
766 PyTuple_SET_ITEM(tuple, 1, data);
767 if (PySet_Discard(callbacks, tuple) != -1) {
768 Py_INCREF(Py_None);
769 result = Py_None;
770 }
771 Py_DECREF(tuple);
772 }
773 } else if (!PyErr_Occurred()) {
774 Py_INCREF(Py_None);
775 result = Py_None;
776 }
777 Py_DECREF(data);
778 }
779
780 return result;
781}
782
783static PyObject *
784EventSystem__do_emit_call(PyObject *callback, PyObject *owner,
785 PyObject *args, PyObject *data)
786{
787 /* return callback(owner, *(args+data)) */
788 PyObject *result = NULL;
789 PyObject *tuple = PyTuple_New(PyTuple_GET_SIZE(args) +
790 PyTuple_GET_SIZE(data) + 1);
791 if (tuple) {
792 Py_ssize_t i, tuple_i;
793
794 Py_INCREF(owner);
795 PyTuple_SET_ITEM(tuple, 0, owner);
796 tuple_i = 1;
797 for (i = 0; i != PyTuple_GET_SIZE(args); i++) {
798 PyObject *item = PyTuple_GET_ITEM(args, i);
799 Py_INCREF(item);
800 PyTuple_SET_ITEM(tuple, tuple_i++, item);
801 }
802 for (i = 0; i != PyTuple_GET_SIZE(data); i++) {
803 PyObject *item = PyTuple_GET_ITEM(data, i);
804 Py_INCREF(item);
805 PyTuple_SET_ITEM(tuple, tuple_i++, item);
806 }
807 result = PyObject_Call(callback, tuple, NULL);
808 Py_DECREF(tuple);
809 }
810 return result;
811}
812
813static PyObject *
814EventSystem_emit(EventSystemObject *self, PyObject *all_args)
815{
816 PyObject *result = NULL;
817 PyObject *name, *args;
818
819 if (PyTuple_GET_SIZE(all_args) == 0) {
820 PyErr_SetString(PyExc_TypeError, "Invalid number of arguments");
821 return NULL;
822 }
823
824 /* XXX In the following code we trust on the format inserted by
825 * the hook() method. If it's hacked somehow, it may blow up. */
826
827 name = PyTuple_GET_ITEM(all_args, 0);
828 args = PyTuple_GetSlice(all_args, 1, PyTuple_GET_SIZE(all_args));
829 if (args) {
830 /* owner = self._owner_ref() */
831 PyObject *owner = PyWeakref_GET_OBJECT(self->_owner_ref);
832 /* if owner is not None: */
833 if (owner != Py_None) {
834 /* callbacks = self._hooks.get(name) */
835 PyObject *callbacks = PyDict_GetItem(self->_hooks, name);
836 Py_INCREF(owner);
837 /* if callbacks: */
838 if (callbacks && PySet_GET_SIZE(callbacks) != 0) {
839 /* for callback, data in tuple(callbacks): */
840 PyObject *sequence = \
841 PySequence_Fast(callbacks, "callbacks object isn't a set");
842 if (sequence) {
843 int failed = 0;
844 Py_ssize_t i;
845 for (i = 0; i != PySequence_Fast_GET_SIZE(sequence); i++) {
846 PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
847 PyObject *callback = PyTuple_GET_ITEM(item, 0);
848 PyObject *data = PyTuple_GET_ITEM(item, 1);
849 PyObject *res;
850 /*
851 if callback(owner, *(args+data)) is False:
852 callbacks.discard((callback, data))
853 */
854 res = EventSystem__do_emit_call(callback, owner,
855 args, data);
856 Py_XDECREF(res);
857 if (res == NULL ||
858 (res == Py_False &&
859 PySet_Discard(callbacks, item) == -1)) {
860 failed = 1;
861 break;
862 }
863 }
864 if (!failed) {
865 Py_INCREF(Py_None);
866 result = Py_None;
867 }
868 Py_DECREF(sequence);
869 }
870 } else if (!PyErr_Occurred()) {
871 Py_INCREF(Py_None);
872 result = Py_None;
873 }
874 Py_DECREF(owner);
875 } else {
876 Py_INCREF(Py_None);
877 result = Py_None;
878 }
879 Py_DECREF(args);
880 }
881
882 return result;
883}
884
885
886static PyMethodDef EventSystem_methods[] = {
887 {"hook", (PyCFunction)EventSystem_hook, METH_VARARGS, NULL},
888 {"unhook", (PyCFunction)EventSystem_unhook, METH_VARARGS, NULL},
889 {"emit", (PyCFunction)EventSystem_emit, METH_VARARGS, NULL},
890 {NULL, NULL}
891};
892
893#define OFFSETOF(x) offsetof(EventSystemObject, x)
894static PyMemberDef EventSystem_members[] = {
895 {"_object_ref", T_OBJECT, OFFSETOF(_owner_ref), READONLY, 0},
896 {"_hooks", T_OBJECT, OFFSETOF(_hooks), READONLY, 0},
897 {NULL}
898};
899#undef OFFSETOF
900
901statichere PyTypeObject EventSystem_Type = {
902 PyObject_HEAD_INIT(NULL)
903 0, /*ob_size*/
904 "storm.variables.EventSystem", /*tp_name*/
905 sizeof(EventSystemObject), /*tp_basicsize*/
906 0, /*tp_itemsize*/
907 (destructor)EventSystem_dealloc, /*tp_dealloc*/
908 0, /*tp_print*/
909 0, /*tp_getattr*/
910 0, /*tp_setattr*/
911 0, /*tp_compare*/
912 0, /*tp_repr*/
913 0, /*tp_as_number*/
914 0, /*tp_as_sequence*/
915 0, /*tp_as_mapping*/
916 0, /*tp_hash*/
917 0, /*tp_call*/
918 0, /*tp_str*/
919 PyObject_GenericGetAttr,/*tp_getattro*/
920 PyObject_GenericSetAttr,/*tp_setattro*/
921 0, /*tp_as_buffer*/
922 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
923 0, /*tp_doc*/
924 (traverseproc)EventSystem_traverse, /*tp_traverse*/
925 (inquiry)EventSystem_clear, /*tp_clear*/
926 0, /*tp_richcompare*/
927 0, /*tp_weaklistoffset*/
928 0, /*tp_iter*/
929 0, /*tp_iternext*/
930 EventSystem_methods, /*tp_methods*/
931 EventSystem_members, /*tp_members*/
932 0, /*tp_getset*/
933 0, /*tp_base*/
934 0, /*tp_dict*/
935 0, /*tp_descr_get*/
936 0, /*tp_descr_set*/
937 0, /*tp_dictoffset*/
938 (initproc)EventSystem_init, /*tp_init*/
939 PyType_GenericAlloc, /*tp_alloc*/
940 PyType_GenericNew, /*tp_new*/
941 PyObject_GC_Del, /*tp_free*/
942 0, /*tp_is_gc*/
943};
944
945
946>>>>>>> MERGE-SOURCE
557static PyObject *947static PyObject *
558Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)948Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
559{949{
@@ -1150,670 +1540,1337 @@
11501540
11511541
1152static PyObject *1542static PyObject *
1153Compile__update_cache(CompileObject *self, PyObject *args);1543<<<<<<< TREE
11541544Compile__update_cache(CompileObject *self, PyObject *args);
1155static int1545
1156Compile_init(CompileObject *self, PyObject *args, PyObject *kwargs)1546static int
1157{1547Compile_init(CompileObject *self, PyObject *args, PyObject *kwargs)
1158 static char *kwlist[] = {"parent", NULL};1548{
11591549 static char *kwlist[] = {"parent", NULL};
1160 PyObject *parent = Py_None;1550
11611551 PyObject *parent = Py_None;
1162 PyObject *module = NULL;1552
1163 PyObject *WeakKeyDictionary = NULL;1553 PyObject *module = NULL;
11641554 PyObject *WeakKeyDictionary = NULL;
1165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &parent))1555
1166 return -1;1556 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &parent))
11671557 return -1;
1168 /*1558
1169 self._local_dispatch_table = {}1559 /*
1170 self._local_precedence = {}1560 self._local_dispatch_table = {}
1171 self._local_reserved_words = {}1561 self._local_precedence = {}
1172 self._dispatch_table = {}1562 self._local_reserved_words = {}
1173 self._precedence = {}1563 self._dispatch_table = {}
1174 self._reserved_words = {}1564 self._precedence = {}
1175 */1565 self._reserved_words = {}
1176 CATCH(NULL, self->_local_dispatch_table = PyDict_New());1566 */
1177 CATCH(NULL, self->_local_precedence = PyDict_New());1567 CATCH(NULL, self->_local_dispatch_table = PyDict_New());
1178 CATCH(NULL, self->_local_reserved_words = PyDict_New());1568 CATCH(NULL, self->_local_precedence = PyDict_New());
1179 CATCH(NULL, self->_dispatch_table = PyDict_New());1569 CATCH(NULL, self->_local_reserved_words = PyDict_New());
1180 CATCH(NULL, self->_precedence = PyDict_New());1570 CATCH(NULL, self->_dispatch_table = PyDict_New());
1181 CATCH(NULL, self->_reserved_words = PyDict_New());1571 CATCH(NULL, self->_precedence = PyDict_New());
11821572 CATCH(NULL, self->_reserved_words = PyDict_New());
1183 /* self._children = WeakKeyDictionary() */1573
1184 CATCH(NULL, module = PyImport_ImportModule("weakref"));1574 /* self._children = WeakKeyDictionary() */
1185 CATCH(NULL, WeakKeyDictionary = \1575 CATCH(NULL, module = PyImport_ImportModule("weakref"));
1186 PyObject_GetAttrString(module, "WeakKeyDictionary"));1576 CATCH(NULL, WeakKeyDictionary = \
1187 Py_CLEAR(module);1577 PyObject_GetAttrString(module, "WeakKeyDictionary"));
1188 CATCH(NULL, self->_children = \1578 Py_CLEAR(module);
1189 PyObject_CallFunctionObjArgs(WeakKeyDictionary, NULL));1579 CATCH(NULL, self->_children = \
1190 Py_CLEAR(WeakKeyDictionary);1580 PyObject_CallFunctionObjArgs(WeakKeyDictionary, NULL));
11911581 Py_CLEAR(WeakKeyDictionary);
1192 /* self._parents = [] */1582
1193 CATCH(NULL, self->_parents = PyList_New(0));1583 /* self._parents = [] */
11941584 CATCH(NULL, self->_parents = PyList_New(0));
1195 /* if parent: */1585
1196 if (parent != Py_None) {1586 /* if parent: */
1197 PyObject *tmp;1587 if (parent != Py_None) {
11981588 PyObject *tmp;
1199 /* self._parents.extend(parent._parents) */1589
1200 CompileObject *parent_object = (CompileObject *)parent;1590 /* self._parents.extend(parent._parents) */
1201 CATCH(-1, PyList_SetSlice(self->_parents, 0, 0,1591 CompileObject *parent_object = (CompileObject *)parent;
1202 parent_object->_parents));1592 CATCH(-1, PyList_SetSlice(self->_parents, 0, 0,
12031593 parent_object->_parents));
1204 /* self._parents.append(parent) */1594
1205 CATCH(-1, PyList_Append(self->_parents, parent));1595 /* self._parents.append(parent) */
12061596 CATCH(-1, PyList_Append(self->_parents, parent));
1207 /* parent._children[self] = True */1597
1208 CATCH(-1, PyObject_SetItem(parent_object->_children,1598 /* parent._children[self] = True */
1209 (PyObject *)self, Py_True));1599 CATCH(-1, PyObject_SetItem(parent_object->_children,
12101600 (PyObject *)self, Py_True));
1211 /* self._update_cache() */1601
1212 CATCH(NULL, tmp = Compile__update_cache(self, NULL));1602 /* self._update_cache() */
1213 Py_DECREF(tmp);1603 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
1214 }1604 Py_DECREF(tmp);
12151605 }
1216 return 0;1606
12171607 return 0;
1218error:1608
1219 Py_XDECREF(module);1609error:
1220 Py_XDECREF(WeakKeyDictionary);1610 Py_XDECREF(module);
1221 return -1;1611 Py_XDECREF(WeakKeyDictionary);
1222}1612 return -1;
12231613}
1224static int1614
1225Compile_traverse(CompileObject *self, visitproc visit, void *arg)1615static int
1226{1616Compile_traverse(CompileObject *self, visitproc visit, void *arg)
1227 Py_VISIT(self->_local_dispatch_table);1617{
1228 Py_VISIT(self->_local_precedence);1618 Py_VISIT(self->_local_dispatch_table);
1229 Py_VISIT(self->_local_reserved_words);1619 Py_VISIT(self->_local_precedence);
1230 Py_VISIT(self->_dispatch_table);1620 Py_VISIT(self->_local_reserved_words);
1231 Py_VISIT(self->_precedence);1621 Py_VISIT(self->_dispatch_table);
1232 Py_VISIT(self->_reserved_words);1622 Py_VISIT(self->_precedence);
1233 Py_VISIT(self->_children);1623 Py_VISIT(self->_reserved_words);
1234 Py_VISIT(self->_parents);1624 Py_VISIT(self->_children);
1235 return 0;1625 Py_VISIT(self->_parents);
1236}1626 return 0;
12371627}
1238static int1628
1239Compile_clear(CompileObject *self)1629static int
1240{1630Compile_clear(CompileObject *self)
1241 if (self->__weakreflist)1631{
1242 PyObject_ClearWeakRefs((PyObject *)self);1632 if (self->__weakreflist)
1243 Py_CLEAR(self->_local_dispatch_table);1633 PyObject_ClearWeakRefs((PyObject *)self);
1244 Py_CLEAR(self->_local_precedence);1634 Py_CLEAR(self->_local_dispatch_table);
1245 Py_CLEAR(self->_local_reserved_words);1635 Py_CLEAR(self->_local_precedence);
1246 Py_CLEAR(self->_dispatch_table);1636 Py_CLEAR(self->_local_reserved_words);
1247 Py_CLEAR(self->_precedence);1637 Py_CLEAR(self->_dispatch_table);
1248 Py_CLEAR(self->_reserved_words);1638 Py_CLEAR(self->_precedence);
1249 Py_CLEAR(self->_children);1639 Py_CLEAR(self->_reserved_words);
1250 Py_CLEAR(self->_parents);1640 Py_CLEAR(self->_children);
1251 return 0;1641 Py_CLEAR(self->_parents);
1252}1642 return 0;
12531643}
1254static void1644
1255Compile_dealloc(CompileObject *self)1645static void
1256{1646Compile_dealloc(CompileObject *self)
1257 Compile_clear(self);1647{
1258 self->ob_type->tp_free((PyObject *)self);1648 Compile_clear(self);
1259}1649 self->ob_type->tp_free((PyObject *)self);
12601650}
1261static PyObject *1651
1262Compile__update_cache(CompileObject *self, PyObject *args)1652static PyObject *
1263{1653Compile__update_cache(CompileObject *self, PyObject *args)
1264 PyObject *iter = NULL;1654{
1265 PyObject *child = NULL;1655 PyObject *iter = NULL;
1266 Py_ssize_t size;1656 PyObject *child = NULL;
1267 int i;1657 Py_ssize_t size;
12681658 int i;
1269 /* for parent in self._parents: */1659
1270 size = PyList_GET_SIZE(self->_parents);1660 /* for parent in self._parents: */
1271 for (i = 0; i != size; i++) {1661 size = PyList_GET_SIZE(self->_parents);
1272 CompileObject *parent = \1662 for (i = 0; i != size; i++) {
1273 (CompileObject *)PyList_GET_ITEM(self->_parents, i);1663 CompileObject *parent = \
1274 /* self._dispatch_table.update(parent._local_dispatch_table) */1664 (CompileObject *)PyList_GET_ITEM(self->_parents, i);
1275 CATCH(-1, PyDict_Update(self->_dispatch_table,1665 /* self._dispatch_table.update(parent._local_dispatch_table) */
1276 parent->_local_dispatch_table));1666 CATCH(-1, PyDict_Update(self->_dispatch_table,
1277 /* self._precedence.update(parent._local_precedence) */1667 parent->_local_dispatch_table));
1278 CATCH(-1, PyDict_Update(self->_precedence,1668 /* self._precedence.update(parent._local_precedence) */
1279 parent->_local_precedence));1669 CATCH(-1, PyDict_Update(self->_precedence,
1280 /* self._reserved_words.update(parent._local_reserved_words) */1670 parent->_local_precedence));
1281 CATCH(-1, PyDict_Update(self->_reserved_words,1671 /* self._reserved_words.update(parent._local_reserved_words) */
1282 parent->_local_reserved_words));1672 CATCH(-1, PyDict_Update(self->_reserved_words,
1283 }1673 parent->_local_reserved_words));
1284 /* self._dispatch_table.update(self._local_dispatch_table) */1674 }
1285 CATCH(-1, PyDict_Update(self->_dispatch_table,1675 /* self._dispatch_table.update(self._local_dispatch_table) */
1286 self->_local_dispatch_table));1676 CATCH(-1, PyDict_Update(self->_dispatch_table,
1287 /* self._precedence.update(self._local_precedence) */1677 self->_local_dispatch_table));
1288 CATCH(-1, PyDict_Update(self->_precedence, self->_local_precedence));1678 /* self._precedence.update(self._local_precedence) */
1289 /* self._reserved_words.update(self._local_reserved_words) */1679 CATCH(-1, PyDict_Update(self->_precedence, self->_local_precedence));
1290 CATCH(-1, PyDict_Update(self->_reserved_words,1680 /* self._reserved_words.update(self._local_reserved_words) */
1291 self->_local_reserved_words));1681 CATCH(-1, PyDict_Update(self->_reserved_words,
12921682 self->_local_reserved_words));
1293 /* for child in self._children: */1683
1294 CATCH(NULL, iter = PyObject_GetIter(self->_children));1684 /* for child in self._children: */
1295 while((child = PyIter_Next(iter))) {1685 CATCH(NULL, iter = PyObject_GetIter(self->_children));
1296 PyObject *tmp;1686 while((child = PyIter_Next(iter))) {
12971687 PyObject *tmp;
1298 /* child._update_cache() */1688
1299 CATCH(NULL, tmp = Compile__update_cache((CompileObject *)child, NULL));1689 /* child._update_cache() */
1300 Py_DECREF(tmp);1690 CATCH(NULL, tmp = Compile__update_cache((CompileObject *)child, NULL));
1301 Py_DECREF(child);1691 Py_DECREF(tmp);
1302 }1692 Py_DECREF(child);
1303 if (PyErr_Occurred())1693 }
1304 goto error;1694 if (PyErr_Occurred())
1305 Py_CLEAR(iter);1695 goto error;
13061696 Py_CLEAR(iter);
1307 Py_RETURN_NONE;1697
13081698 Py_RETURN_NONE;
1309error:1699
1310 Py_XDECREF(child);1700error:
1311 Py_XDECREF(iter);1701 Py_XDECREF(child);
1312 return NULL;1702 Py_XDECREF(iter);
1313}1703 return NULL;
13141704}
1315static PyObject *1705
1316Compile_when(CompileObject *self, PyObject *types)1706static PyObject *
1317{1707Compile_when(CompileObject *self, PyObject *types)
1318 PyObject *result = NULL;1708{
1319 PyObject *module = PyImport_ImportModule("storm.expr");1709 PyObject *result = NULL;
1320 if (module) {1710 PyObject *module = PyImport_ImportModule("storm.expr");
1321 PyObject *_when = PyObject_GetAttrString(module, "_when");1711 if (module) {
1322 if (_when) {1712 PyObject *_when = PyObject_GetAttrString(module, "_when");
1323 result = PyObject_CallFunctionObjArgs(_when, self, types, NULL);1713 if (_when) {
1324 Py_DECREF(_when);1714 result = PyObject_CallFunctionObjArgs(_when, self, types, NULL);
1325 }1715 Py_DECREF(_when);
1326 Py_DECREF(module);1716 }
1327 }1717 Py_DECREF(module);
1328 return result;1718 }
1329}1719 return result;
13301720}
1331static PyObject *1721
1332Compile_add_reserved_words(CompileObject *self, PyObject *words)1722static PyObject *
1333{1723Compile_add_reserved_words(CompileObject *self, PyObject *words)
1334 PyObject *lower_word = NULL;1724{
1335 PyObject *iter = NULL;1725 PyObject *lower_word = NULL;
1336 PyObject *word = NULL;1726 PyObject *iter = NULL;
1337 PyObject *tmp;1727 PyObject *word = NULL;
13381728 PyObject *tmp;
1339 /* self._local_reserved_words.update((word.lower(), True)1729
1340 for word in words) */1730 /* self._local_reserved_words.update((word.lower(), True)
1341 CATCH(NULL, iter = PyObject_GetIter(words));1731 for word in words) */
1342 while ((word = PyIter_Next(iter))) {1732 CATCH(NULL, iter = PyObject_GetIter(words));
1343 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));1733 while ((word = PyIter_Next(iter))) {
1344 CATCH(-1, PyDict_SetItem(self->_local_reserved_words,1734 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
1345 lower_word, Py_True));1735 CATCH(-1, PyDict_SetItem(self->_local_reserved_words,
1346 Py_CLEAR(lower_word);1736 lower_word, Py_True));
1347 Py_DECREF(word);1737 Py_CLEAR(lower_word);
1348 }1738 Py_DECREF(word);
1349 if (PyErr_Occurred())1739 }
1350 goto error;1740 if (PyErr_Occurred())
1351 Py_CLEAR(iter);1741 goto error;
13521742 Py_CLEAR(iter);
1353 /* self._update_cache() */1743
1354 CATCH(NULL, tmp = Compile__update_cache(self, NULL));1744 /* self._update_cache() */
1355 Py_DECREF(tmp);1745 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
13561746 Py_DECREF(tmp);
1357 Py_RETURN_NONE;1747
13581748 Py_RETURN_NONE;
1359error:1749
1360 Py_XDECREF(lower_word);1750error:
1361 Py_XDECREF(word);1751 Py_XDECREF(lower_word);
1362 Py_XDECREF(iter);1752 Py_XDECREF(word);
1363 return NULL;1753 Py_XDECREF(iter);
1364}1754 return NULL;
13651755}
1366static PyObject *1756
1367Compile_remove_reserved_words(CompileObject *self, PyObject *words)1757static PyObject *
1368{1758Compile_remove_reserved_words(CompileObject *self, PyObject *words)
1369 PyObject *lower_word = NULL;1759{
1370 PyObject *word = NULL;1760 PyObject *lower_word = NULL;
1371 PyObject *iter = NULL;1761 PyObject *word = NULL;
1372 PyObject *tmp;1762 PyObject *iter = NULL;
13731763 PyObject *tmp;
1374 /* self._local_reserved_words.update((word.lower(), None)1764
1375 for word in words) */1765 /* self._local_reserved_words.update((word.lower(), None)
1376 CATCH(NULL, iter = PyObject_GetIter(words));1766 for word in words) */
1377 while ((word = PyIter_Next(iter))) {1767 CATCH(NULL, iter = PyObject_GetIter(words));
1378 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));1768 while ((word = PyIter_Next(iter))) {
1379 CATCH(-1, PyDict_SetItem(self->_local_reserved_words,1769 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
1380 lower_word, Py_None));1770 CATCH(-1, PyDict_SetItem(self->_local_reserved_words,
1381 Py_CLEAR(lower_word);1771 lower_word, Py_None));
1382 Py_DECREF(word);1772 Py_CLEAR(lower_word);
1383 }1773 Py_DECREF(word);
1384 if (PyErr_Occurred())1774 }
1385 goto error;1775 if (PyErr_Occurred())
1386 Py_CLEAR(iter);1776 goto error;
13871777 Py_CLEAR(iter);
1388 /* self._update_cache() */1778
1389 CATCH(NULL, tmp = Compile__update_cache(self, NULL));1779 /* self._update_cache() */
1390 Py_DECREF(tmp);1780 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
13911781 Py_DECREF(tmp);
1392 Py_RETURN_NONE;1782
13931783 Py_RETURN_NONE;
1394error:1784
1395 Py_XDECREF(lower_word);1785error:
1396 Py_XDECREF(word);1786 Py_XDECREF(lower_word);
1397 Py_XDECREF(iter);1787 Py_XDECREF(word);
1398 return NULL;1788 Py_XDECREF(iter);
1399}1789 return NULL;
14001790}
1401static PyObject *1791
1402Compile_is_reserved_word(CompileObject *self, PyObject *word)1792static PyObject *
1403{1793Compile_is_reserved_word(CompileObject *self, PyObject *word)
1404 PyObject *lower_word = NULL;1794{
1405 PyObject *result = Py_False;1795 PyObject *lower_word = NULL;
1406 PyObject *item;1796 PyObject *result = Py_False;
14071797 PyObject *item;
1408 /* return self._reserved_words.get(word.lower()) is not None */1798
1409 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));1799 /* return self._reserved_words.get(word.lower()) is not None */
1410 item = PyDict_GetItem(self->_reserved_words, lower_word);1800 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
1411 if (item == NULL && PyErr_Occurred()) {1801 item = PyDict_GetItem(self->_reserved_words, lower_word);
1412 goto error;1802 if (item == NULL && PyErr_Occurred()) {
1413 } else if (item != NULL && item != Py_None) {1803 goto error;
1414 result = Py_True;1804 } else if (item != NULL && item != Py_None) {
1415 }1805 result = Py_True;
1416 Py_DECREF(lower_word);1806 }
1417 Py_INCREF(result);1807 Py_DECREF(lower_word);
1418 return result;1808 Py_INCREF(result);
14191809 return result;
1420error:1810
1421 Py_XDECREF(lower_word);1811error:
1422 return NULL;1812 Py_XDECREF(lower_word);
1423}1813 return NULL;
14241814}
1425staticforward PyTypeObject Compile_Type;1815
14261816staticforward PyTypeObject Compile_Type;
1427static PyObject *1817
1428Compile_create_child(CompileObject *self, PyObject *args)1818static PyObject *
1429{1819Compile_create_child(CompileObject *self, PyObject *args)
1430 /* return self.__class__(self) */1820{
1431 return PyObject_CallFunctionObjArgs((PyObject *)self->ob_type, self, NULL);1821 /* return self.__class__(self) */
1432}1822 return PyObject_CallFunctionObjArgs((PyObject *)self->ob_type, self, NULL);
14331823}
1434static PyObject *1824
1435Compile_get_precedence(CompileObject *self, PyObject *type)1825static PyObject *
1436{1826Compile_get_precedence(CompileObject *self, PyObject *type)
1437 /* return self._precedence.get(type, MAX_PRECEDENCE) */1827{
1438 PyObject *result = PyDict_GetItem(self->_precedence, type);1828 /* return self._precedence.get(type, MAX_PRECEDENCE) */
1439 if (result == NULL && !PyErr_Occurred()) {1829 PyObject *result = PyDict_GetItem(self->_precedence, type);
1440 /* That should be MAX_PRECEDENCE, defined in expr.py */1830 if (result == NULL && !PyErr_Occurred()) {
1441 return PyInt_FromLong(1000);1831 /* That should be MAX_PRECEDENCE, defined in expr.py */
1442 }1832 return PyInt_FromLong(1000);
1443 Py_INCREF(result);1833 }
1444 return result;1834 Py_INCREF(result);
1445}1835 return result;
14461836}
1447static PyObject *1837
1448Compile_set_precedence(CompileObject *self, PyObject *args)1838static PyObject *
1449{1839Compile_set_precedence(CompileObject *self, PyObject *args)
1450 Py_ssize_t size = PyTuple_GET_SIZE(args);1840{
1451 PyObject *precedence = NULL;1841 Py_ssize_t size = PyTuple_GET_SIZE(args);
1452 PyObject *tmp;1842 PyObject *precedence = NULL;
1453 int i;1843 PyObject *tmp;
14541844 int i;
1455 if (size < 2) {1845
1456 PyErr_SetString(PyExc_TypeError,1846 if (size < 2) {
1457 "set_precedence() takes at least 2 arguments.");1847 PyErr_SetString(PyExc_TypeError,
1458 return NULL;1848 "set_precedence() takes at least 2 arguments.");
1459 }1849 return NULL;
14601850 }
1461 /* for type in types: */1851
1462 precedence = PyTuple_GET_ITEM(args, 0);1852 /* for type in types: */
1463 for (i = 1; i != size; i++) {1853 precedence = PyTuple_GET_ITEM(args, 0);
1464 PyObject *type = PyTuple_GET_ITEM(args, i);1854 for (i = 1; i != size; i++) {
1465 /* self._local_precedence[type] = precedence */1855 PyObject *type = PyTuple_GET_ITEM(args, i);
1466 CATCH(-1, PyDict_SetItem(self->_local_precedence, type, precedence));1856 /* self._local_precedence[type] = precedence */
1467 }1857 CATCH(-1, PyDict_SetItem(self->_local_precedence, type, precedence));
14681858 }
1469 /* self._update_cache() */1859
1470 CATCH(NULL, tmp = Compile__update_cache(self, NULL));1860 /* self._update_cache() */
1471 Py_DECREF(tmp);1861 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
14721862 Py_DECREF(tmp);
1473 Py_RETURN_NONE;1863
1474error:1864 Py_RETURN_NONE;
1475 return NULL;1865error:
1476}1866 return NULL;
14771867}
1478PyObject *1868
1479Compile_single(CompileObject *self,1869PyObject *
1480 PyObject *expr, PyObject *state, PyObject *outer_precedence)1870Compile_single(CompileObject *self,
1481{1871 PyObject *expr, PyObject *state, PyObject *outer_precedence)
1482 PyObject *inner_precedence = NULL;1872{
1483 PyObject *statement = NULL;1873 PyObject *inner_precedence = NULL;
14841874 PyObject *statement = NULL;
1485 /* cls = expr.__class__ */1875
1486 PyObject *cls = (PyObject *)expr->ob_type;1876 /* cls = expr.__class__ */
14871877 PyObject *cls = (PyObject *)expr->ob_type;
1488 /*1878
1489 dispatch_table = self._dispatch_table1879 /*
1490 if cls in dispatch_table:1880 dispatch_table = self._dispatch_table
1491 handler = dispatch_table[cls]1881 if cls in dispatch_table:
1492 else:1882 handler = dispatch_table[cls]
1493 */1883 else:
1494 PyObject *handler = PyDict_GetItem(self->_dispatch_table, cls);1884 */
1495 if (!handler) {1885 PyObject *handler = PyDict_GetItem(self->_dispatch_table, cls);
1496 PyObject *mro;1886 if (!handler) {
1497 Py_ssize_t size, i;1887 PyObject *mro;
14981888 Py_ssize_t size, i;
1499 if (PyErr_Occurred())1889
1500 goto error;1890 if (PyErr_Occurred())
15011891 goto error;
1502 /* for mro_cls in cls.__mro__: */1892
1503 mro = expr->ob_type->tp_mro;1893 /* for mro_cls in cls.__mro__: */
1504 size = PyTuple_GET_SIZE(mro);1894 mro = expr->ob_type->tp_mro;
1505 for (i = 0; i != size; i++) {1895 size = PyTuple_GET_SIZE(mro);
1506 PyObject *mro_cls = PyTuple_GET_ITEM(mro, i);1896 for (i = 0; i != size; i++) {
1507 /*1897 PyObject *mro_cls = PyTuple_GET_ITEM(mro, i);
1508 if mro_cls in dispatch_table:1898 /*
1509 handler = dispatch_table[mro_cls]1899 if mro_cls in dispatch_table:
1510 break1900 handler = dispatch_table[mro_cls]
1511 */1901 break
1512 handler = PyDict_GetItem(self->_dispatch_table, mro_cls);1902 */
1513 if (handler)1903 handler = PyDict_GetItem(self->_dispatch_table, mro_cls);
1514 break;1904 if (handler)
15151905 break;
1516 if (PyErr_Occurred())1906
1517 goto error;1907 if (PyErr_Occurred())
1518 }1908 goto error;
1519 /* else: */1909 }
1520 if (i == size) {1910 /* else: */
1521 /*1911 if (i == size) {
1522 raise CompileError("Don't know how to compile type %r of %r"1912 /*
1523 % (expr.__class__, expr))1913 raise CompileError("Don't know how to compile type %r of %r"
1524 */1914 % (expr.__class__, expr))
1525 PyObject *repr = PyObject_Repr(expr);1915 */
1526 if (repr) {1916 PyObject *repr = PyObject_Repr(expr);
1527 PyErr_Format(CompileError,1917 if (repr) {
1528 "Don't know how to compile type %s of %s",1918 PyErr_Format(CompileError,
1529 expr->ob_type->tp_name, PyString_AS_STRING(repr));1919 "Don't know how to compile type %s of %s",
1530 Py_DECREF(repr);1920 expr->ob_type->tp_name, PyString_AS_STRING(repr));
1531 }1921 Py_DECREF(repr);
1532 goto error;1922 }
1533 }1923 goto error;
1534 }1924 }
15351925 }
1536 /*1926
1537 inner_precedence = state.precedence = \1927 /*
1538 self._precedence.get(cls, MAX_PRECEDENCE)1928 inner_precedence = state.precedence = \
1539 */1929 self._precedence.get(cls, MAX_PRECEDENCE)
1540 CATCH(NULL, inner_precedence = Compile_get_precedence(self, cls));1930 */
1541 CATCH(-1, PyObject_SetAttrString(state, "precedence", inner_precedence));1931 CATCH(NULL, inner_precedence = Compile_get_precedence(self, cls));
15421932 CATCH(-1, PyObject_SetAttrString(state, "precedence", inner_precedence));
1543 /* statement = handler(self, expr, state) */1933
1544 CATCH(NULL, statement = PyObject_CallFunctionObjArgs(handler, self, expr,1934 /* statement = handler(self, expr, state) */
1545 state, NULL));1935 CATCH(NULL, statement = PyObject_CallFunctionObjArgs(handler, self, expr,
15461936 state, NULL));
1547 /* if inner_precedence < outer_precedence: */1937
1548 if (PyObject_Compare(inner_precedence, outer_precedence) == -1) {1938 /* if inner_precedence < outer_precedence: */
1549 PyObject *args, *tmp;1939 if (PyObject_Compare(inner_precedence, outer_precedence) == -1) {
15501940 PyObject *args, *tmp;
1551 if (PyErr_Occurred())1941
1552 goto error;1942 if (PyErr_Occurred())
15531943 goto error;
1554 /* return "(%s)" % statement */1944
1555 CATCH(NULL, args = PyTuple_Pack(1, statement));1945 /* return "(%s)" % statement */
1556 tmp = PyUnicode_Format(parenthesis_format, args);1946 CATCH(NULL, args = PyTuple_Pack(1, statement));
1557 Py_DECREF(args);1947 tmp = PyUnicode_Format(parenthesis_format, args);
1558 CATCH(NULL, tmp);1948 Py_DECREF(args);
1559 Py_DECREF(statement);1949 CATCH(NULL, tmp);
1560 statement = tmp;1950 Py_DECREF(statement);
1561 }1951 statement = tmp;
15621952 }
1563 Py_DECREF(inner_precedence);1953
15641954 Py_DECREF(inner_precedence);
1565 return statement;1955
15661956 return statement;
1567error:1957
1568 Py_XDECREF(inner_precedence);1958error:
1569 Py_XDECREF(statement);1959 Py_XDECREF(inner_precedence);
15701960 Py_XDECREF(statement);
1571 return NULL;1961
1572}1962 return NULL;
15731963}
1574PyObject *1964
1575Compile_one_or_many(CompileObject *self, PyObject *expr, PyObject *state,1965PyObject *
1576 PyObject *join, int raw, int token)1966Compile_one_or_many(CompileObject *self, PyObject *expr, PyObject *state,
1577{1967 PyObject *join, int raw, int token)
1578 PyObject *outer_precedence = NULL;1968{
1579 PyObject *compiled = NULL;1969 PyObject *outer_precedence = NULL;
1580 PyObject *sequence = NULL;1970 PyObject *compiled = NULL;
1581 PyObject *statement = NULL;1971 PyObject *sequence = NULL;
1582 Py_ssize_t size, i;1972 PyObject *statement = NULL;
15831973 Py_ssize_t size, i;
1584 Py_INCREF(expr);1974
15851975 Py_INCREF(expr);
1586 /*1976
1587 expr_type = type(expr)1977 /*
1588 if (expr_type is SQLRaw or1978 expr_type = type(expr)
1589 raw and (expr_type is str or expr_type is unicode)):1979 if (expr_type is SQLRaw or
1590 return expr1980 raw and (expr_type is str or expr_type is unicode)):
1591 */1981 return expr
1592 if ((PyObject *)expr->ob_type == SQLRaw ||1982 */
1593 (raw && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr)))) {1983 if ((PyObject *)expr->ob_type == SQLRaw ||
1594 /* Pass our reference on. */1984 (raw && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr)))) {
1595 return expr;1985 /* Pass our reference on. */
1596 }1986 return expr;
15971987 }
1598 /*1988
1599 if token and (expr_type is str or expr_type is unicode):1989 /*
1600 expr = SQLToken(expr)1990 if token and (expr_type is str or expr_type is unicode):
1601 */1991 expr = SQLToken(expr)
1602 if (token && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr))) {1992 */
1603 PyObject *tmp;1993 if (token && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr))) {
1604 CATCH(NULL, tmp = PyObject_CallFunctionObjArgs(SQLToken, expr, NULL));1994 PyObject *tmp;
1605 Py_DECREF(expr);1995 CATCH(NULL, tmp = PyObject_CallFunctionObjArgs(SQLToken, expr, NULL));
1606 expr = tmp;1996 Py_DECREF(expr);
1607 }1997 expr = tmp;
16081998 }
1609 /*1999
1610 if state is None:2000 /*
1611 state = State()2001 if state is None:
1612 */2002 state = State()
1613 /* That's done in Compile__call__ just once. */2003 */
16142004 /* That's done in Compile__call__ just once. */
1615 /* outer_precedence = state.precedence */2005
1616 CATCH(NULL, outer_precedence = PyObject_GetAttrString(state, "precedence"));2006 /* outer_precedence = state.precedence */
1617 /* if expr_type is tuple or expr_type is list: */2007 CATCH(NULL, outer_precedence = PyObject_GetAttrString(state, "precedence"));
1618 if (PyTuple_CheckExact(expr) || PyList_CheckExact(expr)) {2008 /* if expr_type is tuple or expr_type is list: */
1619 /* compiled = [] */2009 if (PyTuple_CheckExact(expr) || PyList_CheckExact(expr)) {
1620 CATCH(NULL, compiled = PyList_New(0));2010 /* compiled = [] */
16212011 CATCH(NULL, compiled = PyList_New(0));
1622 /* for subexpr in expr: */2012
1623 sequence = PySequence_Fast(expr, "This can't actually fail! ;-)");2013 /* for subexpr in expr: */
1624 size = PySequence_Fast_GET_SIZE(sequence);2014 sequence = PySequence_Fast(expr, "This can't actually fail! ;-)");
1625 for (i = 0; i != size; i++) {2015 size = PySequence_Fast_GET_SIZE(sequence);
1626 PyObject *subexpr = PySequence_Fast_GET_ITEM(sequence, i);2016 for (i = 0; i != size; i++) {
1627 /*2017 PyObject *subexpr = PySequence_Fast_GET_ITEM(sequence, i);
1628 subexpr_type = type(subexpr)2018 /*
1629 if subexpr_type is SQLRaw or raw and (subexpr_type is str or2019 subexpr_type = type(subexpr)
1630 subexpr_type is unicode):2020 if subexpr_type is SQLRaw or raw and (subexpr_type is str or
1631 */2021 subexpr_type is unicode):
1632 if ((PyObject *)subexpr->ob_type == (PyObject *)SQLRaw ||2022 */
1633 (raw && (PyString_CheckExact(subexpr) ||2023 if ((PyObject *)subexpr->ob_type == (PyObject *)SQLRaw ||
1634 PyUnicode_CheckExact(subexpr)))) {2024 (raw && (PyString_CheckExact(subexpr) ||
1635 /* statement = subexpr */2025 PyUnicode_CheckExact(subexpr)))) {
1636 Py_INCREF(subexpr);2026 /* statement = subexpr */
1637 statement = subexpr;2027 Py_INCREF(subexpr);
1638 /* elif subexpr_type is tuple or subexpr_type is list: */2028 statement = subexpr;
1639 } else if (PyTuple_CheckExact(subexpr) ||2029 /* elif subexpr_type is tuple or subexpr_type is list: */
1640 PyList_CheckExact(subexpr)) {2030 } else if (PyTuple_CheckExact(subexpr) ||
1641 /* state.precedence = outer_precedence */2031 PyList_CheckExact(subexpr)) {
1642 CATCH(-1, PyObject_SetAttrString(state, "precedence",2032 /* state.precedence = outer_precedence */
1643 outer_precedence));2033 CATCH(-1, PyObject_SetAttrString(state, "precedence",
1644 /* statement = self(subexpr, state, join, raw, token) */2034 outer_precedence));
1645 CATCH(NULL,2035 /* statement = self(subexpr, state, join, raw, token) */
1646 statement = Compile_one_or_many(self, subexpr, state,2036 CATCH(NULL,
1647 join, raw, token));2037 statement = Compile_one_or_many(self, subexpr, state,
1648 /* else: */2038 join, raw, token));
1649 } else {2039 /* else: */
1650 /*2040 } else {
1651 if token and (subexpr_type is unicode or2041 /*
1652 subexpr_type is str):2042 if token and (subexpr_type is unicode or
1653 */2043 subexpr_type is str):
1654 if (token && (PyUnicode_CheckExact(subexpr) ||2044 */
1655 PyString_CheckExact(subexpr))) {2045 if (token && (PyUnicode_CheckExact(subexpr) ||
1656 /* subexpr = SQLToken(subexpr) */2046 PyString_CheckExact(subexpr))) {
1657 CATCH(NULL,2047 /* subexpr = SQLToken(subexpr) */
1658 subexpr = PyObject_CallFunctionObjArgs(SQLToken,2048 CATCH(NULL,
1659 subexpr,2049 subexpr = PyObject_CallFunctionObjArgs(SQLToken,
1660 NULL));2050 subexpr,
1661 } else {2051 NULL));
1662 Py_INCREF(subexpr);2052 } else {
1663 }2053 Py_INCREF(subexpr);
16642054 }
1665 /*2055
1666 statement = self._compile_single(subexpr, state,2056 /*
1667 outer_precedence)2057 statement = self._compile_single(subexpr, state,
1668 */2058 outer_precedence)
1669 statement = Compile_single(self, subexpr, state,2059 */
1670 outer_precedence);2060 statement = Compile_single(self, subexpr, state,
1671 Py_DECREF(subexpr);2061 outer_precedence);
1672 CATCH(NULL, statement);2062 Py_DECREF(subexpr);
1673 }2063 CATCH(NULL, statement);
16742064 }
1675 /* compiled.append(statement) */2065
1676 CATCH(-1, PyList_Append(compiled, statement));2066 /* compiled.append(statement) */
1677 Py_CLEAR(statement);2067 CATCH(-1, PyList_Append(compiled, statement));
1678 }2068 Py_CLEAR(statement);
1679 Py_CLEAR(sequence);2069 }
16802070 Py_CLEAR(sequence);
1681 /* statement = join.join(compiled) */2071
1682 CATCH(NULL, statement = PyUnicode_Join(join, compiled));2072 /* statement = join.join(compiled) */
1683 Py_CLEAR(compiled);2073 CATCH(NULL, statement = PyUnicode_Join(join, compiled));
1684 } else {2074 Py_CLEAR(compiled);
1685 /* statement = self._compile_single(expr, state, outer_precedence) */2075 } else {
1686 CATCH(NULL, statement = Compile_single(self, expr, state,2076 /* statement = self._compile_single(expr, state, outer_precedence) */
1687 outer_precedence));2077 CATCH(NULL, statement = Compile_single(self, expr, state,
1688 }2078 outer_precedence));
16892079 }
1690 /* state.precedence = outer_precedence */2080
1691 CATCH(-1, PyObject_SetAttrString(state, "precedence", outer_precedence));2081 /* state.precedence = outer_precedence */
1692 Py_CLEAR(outer_precedence);2082 CATCH(-1, PyObject_SetAttrString(state, "precedence", outer_precedence));
16932083 Py_CLEAR(outer_precedence);
1694 Py_DECREF(expr);2084
16952085 Py_DECREF(expr);
1696 return statement;2086
16972087 return statement;
1698error:2088
1699 Py_XDECREF(expr);2089error:
1700 Py_XDECREF(outer_precedence);2090 Py_XDECREF(expr);
1701 Py_XDECREF(compiled);2091 Py_XDECREF(outer_precedence);
1702 Py_XDECREF(sequence);2092 Py_XDECREF(compiled);
1703 Py_XDECREF(statement);2093 Py_XDECREF(sequence);
17042094 Py_XDECREF(statement);
1705 return NULL;2095
1706}2096 return NULL;
17072097}
1708static PyObject *2098
1709Compile__call__(CompileObject *self, PyObject *args, PyObject *kwargs)2099static PyObject *
1710{2100Compile__call__(CompileObject *self, PyObject *args, PyObject *kwargs)
1711 static char *kwlist[] = {"expr", "state", "join", "raw", "token", NULL};2101{
1712 PyObject *expr = NULL;2102 static char *kwlist[] = {"expr", "state", "join", "raw", "token", NULL};
1713 PyObject *state = Py_None;2103 PyObject *expr = NULL;
1714 PyObject *join;2104 PyObject *state = Py_None;
1715 char raw = 0;2105 PyObject *join;
1716 char token = 0;2106 char raw = 0;
17172107 char token = 0;
1718 PyObject *result = NULL;2108
17192109 PyObject *result = NULL;
1720 if (!initialize_globals())2110
1721 return NULL;2111 if (!initialize_globals())
17222112 return NULL;
1723 join = default_compile_join;2113
17242114 join = default_compile_join;
1725 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OSbb", kwlist,2115
1726 &expr, &state, &join, &raw, &token)) {2116 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OSbb", kwlist,
1727 return NULL;2117 &expr, &state, &join, &raw, &token)) {
1728 }2118 return NULL;
17292119 }
1730 if (state == Py_None) {2120
1731 state = PyObject_CallFunctionObjArgs(State, NULL);2121 if (state == Py_None) {
1732 } else {2122 state = PyObject_CallFunctionObjArgs(State, NULL);
1733 Py_INCREF(state);2123 } else {
1734 }2124 Py_INCREF(state);
1735 if (state) {2125 }
1736 result = Compile_one_or_many(self, expr, state, join, raw, token);2126 if (state) {
1737 Py_DECREF(state);2127 result = Compile_one_or_many(self, expr, state, join, raw, token);
1738 }2128 Py_DECREF(state);
1739 return result;2129 }
1740}2130 return result;
17412131}
17422132
1743static PyMethodDef Compile_methods[] = {2133
1744 {"_update_cache", (PyCFunction)Compile__update_cache, METH_NOARGS, NULL},2134static PyMethodDef Compile_methods[] = {
1745 {"when", (PyCFunction)Compile_when, METH_VARARGS, NULL},2135 {"_update_cache", (PyCFunction)Compile__update_cache, METH_NOARGS, NULL},
1746 {"add_reserved_words", (PyCFunction)Compile_add_reserved_words,2136 {"when", (PyCFunction)Compile_when, METH_VARARGS, NULL},
1747 METH_O, NULL},2137 {"add_reserved_words", (PyCFunction)Compile_add_reserved_words,
1748 {"remove_reserved_words", (PyCFunction)Compile_remove_reserved_words,2138 METH_O, NULL},
1749 METH_O, NULL},2139 {"remove_reserved_words", (PyCFunction)Compile_remove_reserved_words,
1750 {"is_reserved_word", (PyCFunction)Compile_is_reserved_word, METH_O, NULL},2140 METH_O, NULL},
1751 {"create_child", (PyCFunction)Compile_create_child, METH_NOARGS, NULL},2141 {"is_reserved_word", (PyCFunction)Compile_is_reserved_word, METH_O, NULL},
1752 {"get_precedence", (PyCFunction)Compile_get_precedence, METH_O, NULL},2142 {"create_child", (PyCFunction)Compile_create_child, METH_NOARGS, NULL},
1753 {"set_precedence", (PyCFunction)Compile_set_precedence, METH_VARARGS, NULL},2143 {"get_precedence", (PyCFunction)Compile_get_precedence, METH_O, NULL},
1754 {NULL, NULL}2144 {"set_precedence", (PyCFunction)Compile_set_precedence, METH_VARARGS, NULL},
1755};2145 {NULL, NULL}
17562146};
1757#define OFFSETOF(x) offsetof(CompileObject, x)2147
1758static PyMemberDef Compile_members[] = {2148#define OFFSETOF(x) offsetof(CompileObject, x)
1759 {"_local_dispatch_table", T_OBJECT, OFFSETOF(_local_dispatch_table), 0, 0},2149static PyMemberDef Compile_members[] = {
1760 {"_local_precedence", T_OBJECT, OFFSETOF(_local_precedence), 0, 0},2150 {"_local_dispatch_table", T_OBJECT, OFFSETOF(_local_dispatch_table), 0, 0},
1761 {"_local_reserved_words", T_OBJECT, OFFSETOF(_local_reserved_words), 0, 0},2151 {"_local_precedence", T_OBJECT, OFFSETOF(_local_precedence), 0, 0},
1762 {"_dispatch_table", T_OBJECT, OFFSETOF(_dispatch_table), 0, 0},2152 {"_local_reserved_words", T_OBJECT, OFFSETOF(_local_reserved_words), 0, 0},
1763 {"_precedence", T_OBJECT, OFFSETOF(_precedence), 0, 0},2153 {"_dispatch_table", T_OBJECT, OFFSETOF(_dispatch_table), 0, 0},
1764 {"_reserved_words", T_OBJECT, OFFSETOF(_reserved_words), 0, 0},2154 {"_precedence", T_OBJECT, OFFSETOF(_precedence), 0, 0},
1765 {"_children", T_OBJECT, OFFSETOF(_children), 0, 0},2155 {"_reserved_words", T_OBJECT, OFFSETOF(_reserved_words), 0, 0},
1766 {"_parents", T_OBJECT, OFFSETOF(_parents), 0, 0},2156 {"_children", T_OBJECT, OFFSETOF(_children), 0, 0},
1767 {NULL}2157 {"_parents", T_OBJECT, OFFSETOF(_parents), 0, 0},
1768};2158 {NULL}
1769#undef OFFSETOF2159};
17702160#undef OFFSETOF
1771statichere PyTypeObject Compile_Type = {2161
1772 PyObject_HEAD_INIT(NULL)2162statichere PyTypeObject Compile_Type = {
1773 0, /*ob_size*/2163 PyObject_HEAD_INIT(NULL)
1774 "storm.variables.Compile", /*tp_name*/2164 0, /*ob_size*/
1775 sizeof(CompileObject), /*tp_basicsize*/2165 "storm.variables.Compile", /*tp_name*/
1776 0, /*tp_itemsize*/2166 sizeof(CompileObject), /*tp_basicsize*/
1777 (destructor)Compile_dealloc, /*tp_dealloc*/2167 0, /*tp_itemsize*/
1778 0, /*tp_print*/2168 (destructor)Compile_dealloc, /*tp_dealloc*/
1779 0, /*tp_getattr*/2169 0, /*tp_print*/
1780 0, /*tp_setattr*/2170 0, /*tp_getattr*/
1781 0, /*tp_compare*/2171 0, /*tp_setattr*/
1782 0, /*tp_repr*/2172 0, /*tp_compare*/
1783 0, /*tp_as_number*/2173 0, /*tp_repr*/
1784 0, /*tp_as_sequence*/2174 0, /*tp_as_number*/
1785 0, /*tp_as_mapping*/2175 0, /*tp_as_sequence*/
1786 0, /*tp_hash*/2176 0, /*tp_as_mapping*/
1787 (ternaryfunc)Compile__call__, /*tp_call*/2177 0, /*tp_hash*/
1788 0, /*tp_str*/2178 (ternaryfunc)Compile__call__, /*tp_call*/
1789 PyObject_GenericGetAttr,/*tp_getattro*/2179 0, /*tp_str*/
1790 PyObject_GenericSetAttr,/*tp_setattro*/2180 PyObject_GenericGetAttr,/*tp_getattro*/
1791 0, /*tp_as_buffer*/2181 PyObject_GenericSetAttr,/*tp_setattro*/
1792 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/2182 0, /*tp_as_buffer*/
1793 0, /*tp_doc*/2183 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1794 (traverseproc)Compile_traverse, /*tp_traverse*/2184 0, /*tp_doc*/
1795 (inquiry)Compile_clear, /*tp_clear*/2185 (traverseproc)Compile_traverse, /*tp_traverse*/
1796 0, /*tp_richcompare*/2186 (inquiry)Compile_clear, /*tp_clear*/
1797 offsetof(CompileObject, __weakreflist), /*tp_weaklistoffset*/2187 0, /*tp_richcompare*/
1798 0, /*tp_iter*/2188 offsetof(CompileObject, __weakreflist), /*tp_weaklistoffset*/
1799 0, /*tp_iternext*/2189 0, /*tp_iter*/
1800 Compile_methods, /*tp_methods*/2190 0, /*tp_iternext*/
1801 Compile_members, /*tp_members*/2191 Compile_methods, /*tp_methods*/
1802 0, /*tp_getset*/2192 Compile_members, /*tp_members*/
1803 0, /*tp_base*/2193 0, /*tp_getset*/
1804 0, /*tp_dict*/2194 0, /*tp_base*/
1805 0, /*tp_descr_get*/2195 0, /*tp_dict*/
1806 0, /*tp_descr_set*/2196 0, /*tp_descr_get*/
1807 0, /*tp_dictoffset*/2197 0, /*tp_descr_set*/
1808 (initproc)Compile_init, /*tp_init*/2198 0, /*tp_dictoffset*/
1809 PyType_GenericAlloc, /*tp_alloc*/2199 (initproc)Compile_init, /*tp_init*/
1810 PyType_GenericNew, /*tp_new*/2200 PyType_GenericAlloc, /*tp_alloc*/
1811 PyObject_GC_Del, /*tp_free*/2201 PyType_GenericNew, /*tp_new*/
1812 0, /*tp_is_gc*/2202 PyObject_GC_Del, /*tp_free*/
1813};2203 0, /*tp_is_gc*/
18142204};
18152205
1816static PyObject *2206
2207static PyObject *
2208=======
2209Compile__update_cache(CompileObject *self, PyObject *args);
2210
2211static int
2212Compile_init(CompileObject *self, PyObject *args, PyObject *kwargs)
2213{
2214 static char *kwlist[] = {"parent", NULL};
2215
2216 PyObject *parent = Py_None;
2217
2218 PyObject *module = NULL;
2219 PyObject *WeakKeyDictionary = NULL;
2220
2221 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &parent))
2222 return -1;
2223
2224 /*
2225 self._local_dispatch_table = {}
2226 self._local_precedence = {}
2227 self._local_reserved_words = {}
2228 self._dispatch_table = {}
2229 self._precedence = {}
2230 self._reserved_words = {}
2231 */
2232 CATCH(NULL, self->_local_dispatch_table = PyDict_New());
2233 CATCH(NULL, self->_local_precedence = PyDict_New());
2234 CATCH(NULL, self->_local_reserved_words = PyDict_New());
2235 CATCH(NULL, self->_dispatch_table = PyDict_New());
2236 CATCH(NULL, self->_precedence = PyDict_New());
2237 CATCH(NULL, self->_reserved_words = PyDict_New());
2238
2239 /* self._children = WeakKeyDictionary() */
2240 CATCH(NULL, module = PyImport_ImportModule("weakref"));
2241 CATCH(NULL, WeakKeyDictionary = \
2242 PyObject_GetAttrString(module, "WeakKeyDictionary"));
2243 Py_CLEAR(module);
2244 CATCH(NULL, self->_children = \
2245 PyObject_CallFunctionObjArgs(WeakKeyDictionary, NULL));
2246 Py_CLEAR(WeakKeyDictionary);
2247
2248 /* self._parents = [] */
2249 CATCH(NULL, self->_parents = PyList_New(0));
2250
2251 /* if parent: */
2252 if (parent != Py_None) {
2253 PyObject *tmp;
2254
2255 /* self._parents.extend(parent._parents) */
2256 CompileObject *parent_object = (CompileObject *)parent;
2257 CATCH(-1, PyList_SetSlice(self->_parents, 0, 0,
2258 parent_object->_parents));
2259
2260 /* self._parents.append(parent) */
2261 CATCH(-1, PyList_Append(self->_parents, parent));
2262
2263 /* parent._children[self] = True */
2264 CATCH(-1, PyObject_SetItem(parent_object->_children,
2265 (PyObject *)self, Py_True));
2266
2267 /* self._update_cache() */
2268 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
2269 Py_DECREF(tmp);
2270 }
2271
2272 return 0;
2273
2274error:
2275 Py_XDECREF(module);
2276 Py_XDECREF(WeakKeyDictionary);
2277 return -1;
2278}
2279
2280static int
2281Compile_traverse(CompileObject *self, visitproc visit, void *arg)
2282{
2283 Py_VISIT(self->_local_dispatch_table);
2284 Py_VISIT(self->_local_precedence);
2285 Py_VISIT(self->_local_reserved_words);
2286 Py_VISIT(self->_dispatch_table);
2287 Py_VISIT(self->_precedence);
2288 Py_VISIT(self->_reserved_words);
2289 Py_VISIT(self->_children);
2290 Py_VISIT(self->_parents);
2291 return 0;
2292}
2293
2294static int
2295Compile_clear(CompileObject *self)
2296{
2297 if (self->__weakreflist)
2298 PyObject_ClearWeakRefs((PyObject *)self);
2299 Py_CLEAR(self->_local_dispatch_table);
2300 Py_CLEAR(self->_local_precedence);
2301 Py_CLEAR(self->_local_reserved_words);
2302 Py_CLEAR(self->_dispatch_table);
2303 Py_CLEAR(self->_precedence);
2304 Py_CLEAR(self->_reserved_words);
2305 Py_CLEAR(self->_children);
2306 Py_CLEAR(self->_parents);
2307 return 0;
2308}
2309
2310static void
2311Compile_dealloc(CompileObject *self)
2312{
2313 Compile_clear(self);
2314 self->ob_type->tp_free((PyObject *)self);
2315}
2316
2317static PyObject *
2318Compile__update_cache(CompileObject *self, PyObject *args)
2319{
2320 PyObject *iter = NULL;
2321 PyObject *child = NULL;
2322 Py_ssize_t size;
2323 int i;
2324
2325 /* for parent in self._parents: */
2326 size = PyList_GET_SIZE(self->_parents);
2327 for (i = 0; i != size; i++) {
2328 CompileObject *parent = \
2329 (CompileObject *)PyList_GET_ITEM(self->_parents, i);
2330 /* self._dispatch_table.update(parent._local_dispatch_table) */
2331 CATCH(-1, PyDict_Update(self->_dispatch_table,
2332 parent->_local_dispatch_table));
2333 /* self._precedence.update(parent._local_precedence) */
2334 CATCH(-1, PyDict_Update(self->_precedence,
2335 parent->_local_precedence));
2336 /* self._reserved_words.update(parent._local_reserved_words) */
2337 CATCH(-1, PyDict_Update(self->_reserved_words,
2338 parent->_local_reserved_words));
2339 }
2340 /* self._dispatch_table.update(self._local_dispatch_table) */
2341 CATCH(-1, PyDict_Update(self->_dispatch_table,
2342 self->_local_dispatch_table));
2343 /* self._precedence.update(self._local_precedence) */
2344 CATCH(-1, PyDict_Update(self->_precedence, self->_local_precedence));
2345 /* self._reserved_words.update(self._local_reserved_words) */
2346 CATCH(-1, PyDict_Update(self->_reserved_words,
2347 self->_local_reserved_words));
2348
2349 /* for child in self._children: */
2350 CATCH(NULL, iter = PyObject_GetIter(self->_children));
2351 while((child = PyIter_Next(iter))) {
2352 PyObject *tmp;
2353
2354 /* child._update_cache() */
2355 CATCH(NULL, tmp = Compile__update_cache((CompileObject *)child, NULL));
2356 Py_DECREF(tmp);
2357 Py_DECREF(child);
2358 }
2359 if (PyErr_Occurred())
2360 goto error;
2361 Py_CLEAR(iter);
2362
2363 Py_RETURN_NONE;
2364
2365error:
2366 Py_XDECREF(child);
2367 Py_XDECREF(iter);
2368 return NULL;
2369}
2370
2371static PyObject *
2372Compile_when(CompileObject *self, PyObject *types)
2373{
2374 PyObject *result = NULL;
2375 PyObject *module = PyImport_ImportModule("storm.expr");
2376 if (module) {
2377 PyObject *_when = PyObject_GetAttrString(module, "_when");
2378 if (_when) {
2379 result = PyObject_CallFunctionObjArgs(_when, self, types, NULL);
2380 Py_DECREF(_when);
2381 }
2382 Py_DECREF(module);
2383 }
2384 return result;
2385}
2386
2387static PyObject *
2388Compile_add_reserved_words(CompileObject *self, PyObject *words)
2389{
2390 PyObject *lower_word = NULL;
2391 PyObject *iter = NULL;
2392 PyObject *word = NULL;
2393 PyObject *tmp;
2394
2395 /* self._local_reserved_words.update((word.lower(), True)
2396 for word in words) */
2397 CATCH(NULL, iter = PyObject_GetIter(words));
2398 while ((word = PyIter_Next(iter))) {
2399 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
2400 CATCH(-1, PyDict_SetItem(self->_local_reserved_words,
2401 lower_word, Py_True));
2402 Py_CLEAR(lower_word);
2403 Py_DECREF(word);
2404 }
2405 if (PyErr_Occurred())
2406 goto error;
2407 Py_CLEAR(iter);
2408
2409 /* self._update_cache() */
2410 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
2411 Py_DECREF(tmp);
2412
2413 Py_RETURN_NONE;
2414
2415error:
2416 Py_XDECREF(lower_word);
2417 Py_XDECREF(word);
2418 Py_XDECREF(iter);
2419 return NULL;
2420}
2421
2422static PyObject *
2423Compile_remove_reserved_words(CompileObject *self, PyObject *words)
2424{
2425 PyObject *lower_word = NULL;
2426 PyObject *word = NULL;
2427 PyObject *iter = NULL;
2428 PyObject *tmp;
2429
2430 /* self._local_reserved_words.update((word.lower(), None)
2431 for word in words) */
2432 CATCH(NULL, iter = PyObject_GetIter(words));
2433 while ((word = PyIter_Next(iter))) {
2434 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
2435 CATCH(-1, PyDict_SetItem(self->_local_reserved_words,
2436 lower_word, Py_None));
2437 Py_CLEAR(lower_word);
2438 Py_DECREF(word);
2439 }
2440 if (PyErr_Occurred())
2441 goto error;
2442 Py_CLEAR(iter);
2443
2444 /* self._update_cache() */
2445 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
2446 Py_DECREF(tmp);
2447
2448 Py_RETURN_NONE;
2449
2450error:
2451 Py_XDECREF(lower_word);
2452 Py_XDECREF(word);
2453 Py_XDECREF(iter);
2454 return NULL;
2455}
2456
2457static PyObject *
2458Compile_is_reserved_word(CompileObject *self, PyObject *word)
2459{
2460 PyObject *lower_word = NULL;
2461 PyObject *result = Py_False;
2462 PyObject *item;
2463
2464 /* return self._reserved_words.get(word.lower()) is not None */
2465 CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
2466 item = PyDict_GetItem(self->_reserved_words, lower_word);
2467 if (item == NULL && PyErr_Occurred()) {
2468 goto error;
2469 } else if (item != NULL && item != Py_None) {
2470 result = Py_True;
2471 }
2472 Py_DECREF(lower_word);
2473 Py_INCREF(result);
2474 return result;
2475
2476error:
2477 Py_XDECREF(lower_word);
2478 return NULL;
2479}
2480
2481staticforward PyTypeObject Compile_Type;
2482
2483static PyObject *
2484Compile_create_child(CompileObject *self, PyObject *args)
2485{
2486 /* return self.__class__(self) */
2487 return PyObject_CallFunctionObjArgs((PyObject *)self->ob_type, self, NULL);
2488}
2489
2490static PyObject *
2491Compile_get_precedence(CompileObject *self, PyObject *type)
2492{
2493 /* return self._precedence.get(type, MAX_PRECEDENCE) */
2494 PyObject *result = PyDict_GetItem(self->_precedence, type);
2495 if (result == NULL && !PyErr_Occurred()) {
2496 /* That should be MAX_PRECEDENCE, defined in expr.py */
2497 return PyInt_FromLong(1000);
2498 }
2499 Py_INCREF(result);
2500 return result;
2501}
2502
2503static PyObject *
2504Compile_set_precedence(CompileObject *self, PyObject *args)
2505{
2506 Py_ssize_t size = PyTuple_GET_SIZE(args);
2507 PyObject *precedence = NULL;
2508 PyObject *tmp;
2509 int i;
2510
2511 if (size < 2) {
2512 PyErr_SetString(PyExc_TypeError,
2513 "set_precedence() takes at least 2 arguments.");
2514 return NULL;
2515 }
2516
2517 /* for type in types: */
2518 precedence = PyTuple_GET_ITEM(args, 0);
2519 for (i = 1; i != size; i++) {
2520 PyObject *type = PyTuple_GET_ITEM(args, i);
2521 /* self._local_precedence[type] = precedence */
2522 CATCH(-1, PyDict_SetItem(self->_local_precedence, type, precedence));
2523 }
2524
2525 /* self._update_cache() */
2526 CATCH(NULL, tmp = Compile__update_cache(self, NULL));
2527 Py_DECREF(tmp);
2528
2529 Py_RETURN_NONE;
2530error:
2531 return NULL;
2532}
2533
2534PyObject *
2535Compile_single(CompileObject *self,
2536 PyObject *expr, PyObject *state, PyObject *outer_precedence)
2537{
2538 PyObject *inner_precedence = NULL;
2539 PyObject *statement = NULL;
2540
2541 /* cls = expr.__class__ */
2542 PyObject *cls = (PyObject *)expr->ob_type;
2543
2544 /*
2545 dispatch_table = self._dispatch_table
2546 if cls in dispatch_table:
2547 handler = dispatch_table[cls]
2548 else:
2549 */
2550 PyObject *handler = PyDict_GetItem(self->_dispatch_table, cls);
2551 if (!handler) {
2552 PyObject *mro;
2553 Py_ssize_t size, i;
2554
2555 if (PyErr_Occurred())
2556 goto error;
2557
2558 /* for mro_cls in cls.__mro__: */
2559 mro = expr->ob_type->tp_mro;
2560 size = PyTuple_GET_SIZE(mro);
2561 for (i = 0; i != size; i++) {
2562 PyObject *mro_cls = PyTuple_GET_ITEM(mro, i);
2563 /*
2564 if mro_cls in dispatch_table:
2565 handler = dispatch_table[mro_cls]
2566 break
2567 */
2568 handler = PyDict_GetItem(self->_dispatch_table, mro_cls);
2569 if (handler)
2570 break;
2571
2572 if (PyErr_Occurred())
2573 goto error;
2574 }
2575 /* else: */
2576 if (i == size) {
2577 /*
2578 raise CompileError("Don't know how to compile type %r of %r"
2579 % (expr.__class__, expr))
2580 */
2581 PyObject *repr = PyObject_Repr(expr);
2582 if (repr) {
2583 PyErr_Format(CompileError,
2584 "Don't know how to compile type %s of %s",
2585 expr->ob_type->tp_name, PyString_AS_STRING(repr));
2586 Py_DECREF(repr);
2587 }
2588 goto error;
2589 }
2590 }
2591
2592 /*
2593 inner_precedence = state.precedence = \
2594 self._precedence.get(cls, MAX_PRECEDENCE)
2595 */
2596 CATCH(NULL, inner_precedence = Compile_get_precedence(self, cls));
2597 CATCH(-1, PyObject_SetAttrString(state, "precedence", inner_precedence));
2598
2599 /* statement = handler(self, expr, state) */
2600 CATCH(NULL, statement = PyObject_CallFunctionObjArgs(handler, self, expr,
2601 state, NULL));
2602
2603 /* if inner_precedence < outer_precedence: */
2604 if (PyObject_Compare(inner_precedence, outer_precedence) == -1) {
2605 PyObject *args, *tmp;
2606
2607 if (PyErr_Occurred())
2608 goto error;
2609
2610 /* return "(%s)" % statement */
2611 CATCH(NULL, args = PyTuple_Pack(1, statement));
2612 tmp = PyUnicode_Format(parenthesis_format, args);
2613 Py_DECREF(args);
2614 CATCH(NULL, tmp);
2615 Py_DECREF(statement);
2616 statement = tmp;
2617 }
2618
2619 Py_DECREF(inner_precedence);
2620
2621 return statement;
2622
2623error:
2624 Py_XDECREF(inner_precedence);
2625 Py_XDECREF(statement);
2626
2627 return NULL;
2628}
2629
2630PyObject *
2631Compile_one_or_many(CompileObject *self, PyObject *expr, PyObject *state,
2632 PyObject *join, int raw, int token)
2633{
2634 PyObject *outer_precedence = NULL;
2635 PyObject *compiled = NULL;
2636 PyObject *sequence = NULL;
2637 PyObject *statement = NULL;
2638 Py_ssize_t size, i;
2639
2640 Py_INCREF(expr);
2641
2642 /*
2643 expr_type = type(expr)
2644 if (expr_type is SQLRaw or
2645 raw and (expr_type is str or expr_type is unicode)):
2646 return expr
2647 */
2648 if ((PyObject *)expr->ob_type == SQLRaw ||
2649 (raw && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr)))) {
2650 /* Pass our reference on. */
2651 return expr;
2652 }
2653
2654 /*
2655 if token and (expr_type is str or expr_type is unicode):
2656 expr = SQLToken(expr)
2657 */
2658 if (token && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr))) {
2659 PyObject *tmp;
2660 CATCH(NULL, tmp = PyObject_CallFunctionObjArgs(SQLToken, expr, NULL));
2661 Py_DECREF(expr);
2662 expr = tmp;
2663 }
2664
2665 /*
2666 if state is None:
2667 state = State()
2668 */
2669 /* That's done in Compile__call__ just once. */
2670
2671 /* outer_precedence = state.precedence */
2672 CATCH(NULL, outer_precedence = PyObject_GetAttrString(state, "precedence"));
2673 /* if expr_type is tuple or expr_type is list: */
2674 if (PyTuple_CheckExact(expr) || PyList_CheckExact(expr)) {
2675 /* compiled = [] */
2676 CATCH(NULL, compiled = PyList_New(0));
2677
2678 /* for subexpr in expr: */
2679 sequence = PySequence_Fast(expr, "This can't actually fail! ;-)");
2680 size = PySequence_Fast_GET_SIZE(sequence);
2681 for (i = 0; i != size; i++) {
2682 PyObject *subexpr = PySequence_Fast_GET_ITEM(sequence, i);
2683 /*
2684 subexpr_type = type(subexpr)
2685 if subexpr_type is SQLRaw or raw and (subexpr_type is str or
2686 subexpr_type is unicode):
2687 */
2688 if ((PyObject *)subexpr->ob_type == (PyObject *)SQLRaw ||
2689 (raw && (PyString_CheckExact(subexpr) ||
2690 PyUnicode_CheckExact(subexpr)))) {
2691 /* statement = subexpr */
2692 Py_INCREF(subexpr);
2693 statement = subexpr;
2694 /* elif subexpr_type is tuple or subexpr_type is list: */
2695 } else if (PyTuple_CheckExact(subexpr) ||
2696 PyList_CheckExact(subexpr)) {
2697 /* state.precedence = outer_precedence */
2698 CATCH(-1, PyObject_SetAttrString(state, "precedence",
2699 outer_precedence));
2700 /* statement = self(subexpr, state, join, raw, token) */
2701 CATCH(NULL,
2702 statement = Compile_one_or_many(self, subexpr, state,
2703 join, raw, token));
2704 /* else: */
2705 } else {
2706 /*
2707 if token and (subexpr_type is unicode or
2708 subexpr_type is str):
2709 */
2710 if (token && (PyUnicode_CheckExact(subexpr) ||
2711 PyString_CheckExact(subexpr))) {
2712 /* subexpr = SQLToken(subexpr) */
2713 CATCH(NULL,
2714 subexpr = PyObject_CallFunctionObjArgs(SQLToken,
2715 subexpr,
2716 NULL));
2717 } else {
2718 Py_INCREF(subexpr);
2719 }
2720
2721 /*
2722 statement = self._compile_single(subexpr, state,
2723 outer_precedence)
2724 */
2725 statement = Compile_single(self, subexpr, state,
2726 outer_precedence);
2727 Py_DECREF(subexpr);
2728 CATCH(NULL, statement);
2729 }
2730
2731 /* compiled.append(statement) */
2732 CATCH(-1, PyList_Append(compiled, statement));
2733 Py_CLEAR(statement);
2734 }
2735 Py_CLEAR(sequence);
2736
2737 /* statement = join.join(compiled) */
2738 CATCH(NULL, statement = PyUnicode_Join(join, compiled));
2739 Py_CLEAR(compiled);
2740 } else {
2741 /* statement = self._compile_single(expr, state, outer_precedence) */
2742 CATCH(NULL, statement = Compile_single(self, expr, state,
2743 outer_precedence));
2744 }
2745
2746 /* state.precedence = outer_precedence */
2747 CATCH(-1, PyObject_SetAttrString(state, "precedence", outer_precedence));
2748 Py_CLEAR(outer_precedence);
2749
2750 Py_DECREF(expr);
2751
2752 return statement;
2753
2754error:
2755 Py_XDECREF(expr);
2756 Py_XDECREF(outer_precedence);
2757 Py_XDECREF(compiled);
2758 Py_XDECREF(sequence);
2759 Py_XDECREF(statement);
2760
2761 return NULL;
2762}
2763
2764static PyObject *
2765Compile__call__(CompileObject *self, PyObject *args, PyObject *kwargs)
2766{
2767 static char *kwlist[] = {"expr", "state", "join", "raw", "token", NULL};
2768 PyObject *expr = NULL;
2769 PyObject *state = Py_None;
2770 PyObject *join;
2771 char raw = 0;
2772 char token = 0;
2773
2774 PyObject *result = NULL;
2775
2776 if (!initialize_globals())
2777 return NULL;
2778
2779 join = default_compile_join;
2780
2781 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OSbb", kwlist,
2782 &expr, &state, &join, &raw, &token)) {
2783 return NULL;
2784 }
2785
2786 if (state == Py_None) {
2787 state = PyObject_CallFunctionObjArgs(State, NULL);
2788 } else {
2789 Py_INCREF(state);
2790 }
2791 if (state) {
2792 result = Compile_one_or_many(self, expr, state, join, raw, token);
2793 Py_DECREF(state);
2794 }
2795 return result;
2796}
2797
2798
2799static PyMethodDef Compile_methods[] = {
2800 {"_update_cache", (PyCFunction)Compile__update_cache, METH_NOARGS, NULL},
2801 {"when", (PyCFunction)Compile_when, METH_VARARGS, NULL},
2802 {"add_reserved_words", (PyCFunction)Compile_add_reserved_words,
2803 METH_O, NULL},
2804 {"remove_reserved_words", (PyCFunction)Compile_remove_reserved_words,
2805 METH_O, NULL},
2806 {"is_reserved_word", (PyCFunction)Compile_is_reserved_word, METH_O, NULL},
2807 {"create_child", (PyCFunction)Compile_create_child, METH_NOARGS, NULL},
2808 {"get_precedence", (PyCFunction)Compile_get_precedence, METH_O, NULL},
2809 {"set_precedence", (PyCFunction)Compile_set_precedence, METH_VARARGS, NULL},
2810 {NULL, NULL}
2811};
2812
2813#define OFFSETOF(x) offsetof(CompileObject, x)
2814static PyMemberDef Compile_members[] = {
2815 {"_local_dispatch_table", T_OBJECT, OFFSETOF(_local_dispatch_table), 0, 0},
2816 {"_local_precedence", T_OBJECT, OFFSETOF(_local_precedence), 0, 0},
2817 {"_local_reserved_words", T_OBJECT, OFFSETOF(_local_reserved_words), 0, 0},
2818 {"_dispatch_table", T_OBJECT, OFFSETOF(_dispatch_table), 0, 0},
2819 {"_precedence", T_OBJECT, OFFSETOF(_precedence), 0, 0},
2820 {"_reserved_words", T_OBJECT, OFFSETOF(_reserved_words), 0, 0},
2821 {"_children", T_OBJECT, OFFSETOF(_children), 0, 0},
2822 {"_parents", T_OBJECT, OFFSETOF(_parents), 0, 0},
2823 {NULL}
2824};
2825#undef OFFSETOF
2826
2827statichere PyTypeObject Compile_Type = {
2828 PyObject_HEAD_INIT(NULL)
2829 0, /*ob_size*/
2830 "storm.variables.Compile", /*tp_name*/
2831 sizeof(CompileObject), /*tp_basicsize*/
2832 0, /*tp_itemsize*/
2833 (destructor)Compile_dealloc, /*tp_dealloc*/
2834 0, /*tp_print*/
2835 0, /*tp_getattr*/
2836 0, /*tp_setattr*/
2837 0, /*tp_compare*/
2838 0, /*tp_repr*/
2839 0, /*tp_as_number*/
2840 0, /*tp_as_sequence*/
2841 0, /*tp_as_mapping*/
2842 0, /*tp_hash*/
2843 (ternaryfunc)Compile__call__, /*tp_call*/
2844 0, /*tp_str*/
2845 PyObject_GenericGetAttr,/*tp_getattro*/
2846 PyObject_GenericSetAttr,/*tp_setattro*/
2847 0, /*tp_as_buffer*/
2848 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2849 0, /*tp_doc*/
2850 (traverseproc)Compile_traverse, /*tp_traverse*/
2851 (inquiry)Compile_clear, /*tp_clear*/
2852 0, /*tp_richcompare*/
2853 offsetof(CompileObject, __weakreflist), /*tp_weaklistoffset*/
2854 0, /*tp_iter*/
2855 0, /*tp_iternext*/
2856 Compile_methods, /*tp_methods*/
2857 Compile_members, /*tp_members*/
2858 0, /*tp_getset*/
2859 0, /*tp_base*/
2860 0, /*tp_dict*/
2861 0, /*tp_descr_get*/
2862 0, /*tp_descr_set*/
2863 0, /*tp_dictoffset*/
2864 (initproc)Compile_init, /*tp_init*/
2865 PyType_GenericAlloc, /*tp_alloc*/
2866 PyType_GenericNew, /*tp_new*/
2867 PyObject_GC_Del, /*tp_free*/
2868 0, /*tp_is_gc*/
2869};
2870
2871
2872static PyObject *
2873>>>>>>> MERGE-SOURCE
1817ObjectInfo__emit_object_deleted(ObjectInfoObject *self, PyObject *args)2874ObjectInfo__emit_object_deleted(ObjectInfoObject *self, PyObject *args)
1818{2875{
1819 /* self.event.emit("object-deleted") */2876 /* self.event.emit("object-deleted") */
18202877
=== modified file 'storm/database.py'
=== modified file 'storm/databases/postgres.py'
--- storm/databases/postgres.py 2008-08-18 19:44:51 +0000
+++ storm/databases/postgres.py 2009-05-06 21:20:16 +0000
@@ -36,7 +36,7 @@
36from storm.variables import Variable, ListVariable, RawStrVariable36from storm.variables import Variable, ListVariable, RawStrVariable
37from storm.database import Database, Connection, Result37from storm.database import Database, Connection, Result
38from storm.exceptions import (38from storm.exceptions import (
39 install_exceptions, DatabaseError, DatabaseModuleError,39 install_exceptions, DatabaseError, DatabaseModuleError, InterfaceError,
40 OperationalError, ProgrammingError, TimeoutError)40 OperationalError, ProgrammingError, TimeoutError)
41from storm.tracer import TimeoutTracer41from storm.tracer import TimeoutTracer
4242
@@ -285,18 +285,28 @@
285 yield param285 yield param
286286
287 def is_disconnection_error(self, exc):287 def is_disconnection_error(self, exc):
288 if not isinstance(exc, (OperationalError, ProgrammingError)):288 if not isinstance(
289 exc, (InterfaceError, OperationalError, ProgrammingError)):
289 return False290 return False
290291
291 # XXX: 2007-09-17 jamesh292 # XXX: 2007-09-17 jamesh
292 # I have no idea why I am seeing the last exception message293 # I have no idea why I am seeing the last exception message
293 # after upgrading to Gutsy.294 # after upgrading to Gutsy.
294 msg = str(exc)295 msg = str(exc)
295 return ("server closed the connection unexpectedly" in msg or296<<<<<<< TREE
296 "could not connect to server" in msg or297 return ("server closed the connection unexpectedly" in msg or
297 "no connection to the server" in msg or298 "could not connect to server" in msg or
298 "connection not open" in msg or299 "no connection to the server" in msg or
299 "losed the connection unexpectedly" in msg)300 "connection not open" in msg or
301 "losed the connection unexpectedly" in msg)
302=======
303 return ("server closed the connection unexpectedly" in msg or
304 "could not connect to server" in msg or
305 "no connection to the server" in msg or
306 "connection not open" in msg or
307 "connection already closed" in msg or
308 "losed the connection unexpectedly" in msg)
309>>>>>>> MERGE-SOURCE
300310
301311
302class Postgres(Database):312class Postgres(Database):
303313
=== modified file 'storm/properties.py'
=== modified file 'storm/references.py'
=== modified file 'storm/sqlobject.py'
--- storm/sqlobject.py 2008-11-05 18:37:41 +0000
+++ storm/sqlobject.py 2009-05-06 21:20:16 +0000
@@ -552,8 +552,13 @@
552 return item in result_set552 return item in result_set
553553
554 def __nonzero__(self):554 def __nonzero__(self):
555<<<<<<< TREE
555 result_set = self._without_prejoins()._result_set556 result_set = self._without_prejoins()._result_set
556 return not result_set.is_empty()557 return not result_set.is_empty()
558=======
559 result_set = self._without_prejoins()._result_set
560 return result_set.any() is not None
561>>>>>>> MERGE-SOURCE
557562
558 def count(self):563 def count(self):
559 result_set = self._without_prejoins()._result_set564 result_set = self._without_prejoins()._result_set
560565
=== modified file 'storm/store.py'
--- storm/store.py 2009-02-16 10:44:31 +0000
+++ storm/store.py 2009-05-06 21:20:16 +0000
@@ -36,7 +36,8 @@
36 Union, Except, Intersect, Alias, SetExpr)36 Union, Except, Intersect, Alias, SetExpr)
37from storm.exceptions import (37from storm.exceptions import (
38 WrongStoreError, NotFlushedError, OrderLoopError, UnorderedError,38 WrongStoreError, NotFlushedError, OrderLoopError, UnorderedError,
39 NotOneError, FeatureError, CompileError, LostObjectError, ClassInfoError)39 NotOneError, FeatureError, CompileError, LostObjectError, ClassInfoError,
40 ExprError)
40from storm import Undef41from storm import Undef
41from storm.cache import Cache42from storm.cache import Cache
42from storm.event import EventSystem43from storm.event import EventSystem
@@ -439,7 +440,18 @@
439 normal flushing times are insufficient, such as when you want to440 normal flushing times are insufficient, such as when you want to
440 make sure a database trigger gets run at a particular time.441 make sure a database trigger gets run at a particular time.
441 """442 """
443<<<<<<< TREE
442 self._event.emit("flush")444 self._event.emit("flush")
445=======
446 # XXX 2008-06-19 jamesh bug=241267:
447 # This loop takes up 75% of flush()'s runtime in our tests,
448 # and probably more in cases with more live objects. As we
449 # don't use any property types that require the event, I've
450 # temporarily disabled it.
451
452 ##for obj_info in self._iter_alive():
453 ## obj_info.event.emit("flush")
454>>>>>>> MERGE-SOURCE
443455
444 # The _dirty list may change under us while we're running456 # The _dirty list may change under us while we're running
445 # the flush hooks, so we cannot just simply loop over it457 # the flush hooks, so we cannot just simply loop over it
@@ -1016,6 +1028,7 @@
10161028
1017 return self.copy().config(offset=offset, limit=limit)1029 return self.copy().config(offset=offset, limit=limit)
10181030
1031<<<<<<< TREE
1019 def __contains__(self, item):1032 def __contains__(self, item):
1020 """Check if an item is contained within the result set."""1033 """Check if an item is contained within the result set."""
1021 columns, values = self._find_spec.get_columns_and_values_for_item(item)1034 columns, values = self._find_spec.get_columns_and_values_for_item(item)
@@ -1047,6 +1060,31 @@
1047 result = self._store._connection.execute(select)1060 result = self._store._connection.execute(select)
1048 return (not result.get_one())1061 return (not result.get_one())
10491062
1063=======
1064 def __contains__(self, item):
1065 """Check if an item is contained within the result set."""
1066 columns, values = self._find_spec.get_columns_and_values_for_item(item)
1067
1068 if self._select is Undef and self._group_by is Undef:
1069 # No predefined select: adjust the where clause.
1070 dummy, default_tables = self._find_spec.get_columns_and_tables()
1071 where = [Eq(*pair) for pair in zip(columns, values)]
1072 if self._where is not Undef:
1073 where.append(self._where)
1074 select = Select(1, And(*where), self._tables,
1075 default_tables)
1076 else:
1077 # Rewrite the predefined query and use it as a subquery.
1078 aliased_columns = [Alias(column, "_key%d" % index)
1079 for (index, column) in enumerate(columns)]
1080 subquery = replace_columns(self._get_select(), aliased_columns)
1081 where = [Eq(*pair) for pair in zip(aliased_columns, values)]
1082 select = Select(1, And(*where), Alias(subquery, "_tmp"))
1083
1084 result = self._store._connection.execute(select)
1085 return result.get_one() is not None
1086
1087>>>>>>> MERGE-SOURCE
1050 def any(self):1088 def any(self):
1051 """Return a single item from the result set.1089 """Return a single item from the result set.
10521090
@@ -1438,12 +1476,18 @@
1438 def __getitem__(self, index):1476 def __getitem__(self, index):
1439 return self.copy()1477 return self.copy()
14401478
1479<<<<<<< TREE
1441 def __contains__(self, item):1480 def __contains__(self, item):
1442 return False1481 return False
14431482
1444 def is_empty(self):1483 def is_empty(self):
1445 return True1484 return True
14461485
1486=======
1487 def __contains__(self, item):
1488 return False
1489
1490>>>>>>> MERGE-SOURCE
1447 def any(self):1491 def any(self):
1448 return None1492 return None
14491493
14501494
=== modified file 'storm/tracer.py'
--- storm/tracer.py 2009-02-04 01:53:02 +0000
+++ storm/tracer.py 2009-05-06 21:20:16 +0000
@@ -14,6 +14,7 @@
1414
15 def connection_raw_execute(self, connection, raw_cursor, statement, params):15 def connection_raw_execute(self, connection, raw_cursor, statement, params):
16 time = datetime.now().isoformat()[11:]16 time = datetime.now().isoformat()[11:]
17<<<<<<< TREE
17 raw_params = []18 raw_params = []
18 for param in params:19 for param in params:
19 if isinstance(param, Variable):20 if isinstance(param, Variable):
@@ -23,6 +24,10 @@
23 raw_params = tuple(raw_params)24 raw_params = tuple(raw_params)
24 self._stream.write(25 self._stream.write(
25 "[%s] EXECUTE: %r, %r\n" % (time, statement, raw_params))26 "[%s] EXECUTE: %r, %r\n" % (time, statement, raw_params))
27=======
28 params = tuple(param.get() for param in params)
29 self._stream.write("[%s] EXECUTE: %r, %r\n" % (time, statement, params))
30>>>>>>> MERGE-SOURCE
26 self._stream.flush()31 self._stream.flush()
2732
28 def connection_raw_execute_error(self, connection, raw_cursor,33 def connection_raw_execute_error(self, connection, raw_cursor,
2934
=== modified file 'storm/variables.py'
--- storm/variables.py 2009-03-04 16:56:58 +0000
+++ storm/variables.py 2009-05-06 21:20:16 +0000
@@ -536,6 +536,7 @@
536 raise ValueError("Invalid enum value: %s" % repr(value))536 raise ValueError("Invalid enum value: %s" % repr(value))
537537
538538
539<<<<<<< TREE
539class MutableValueVariable(Variable):540class MutableValueVariable(Variable):
540 """541 """
541 A variable which contains a reference to mutable content. For this kind542 A variable which contains a reference to mutable content. For this kind
@@ -544,6 +545,10 @@
544 flushing current objects, to check if the state has changed.545 flushing current objects, to check if the state has changed.
545 """546 """
546 __slots__ = ("_event_system")547 __slots__ = ("_event_system")
548=======
549class PickleVariable(Variable):
550 __slots__ = ()
551>>>>>>> MERGE-SOURCE
547552
548 def __init__(self, *args, **kwargs):553 def __init__(self, *args, **kwargs):
549 self._event_system = None554 self._event_system = None
@@ -603,9 +608,21 @@
603 self._lazy_value = state[0]608 self._lazy_value = state[0]
604 self._value = pickle.loads(state[1])609 self._value = pickle.loads(state[1])
605610
611<<<<<<< TREE
606612
607class ListVariable(MutableValueVariable):613class ListVariable(MutableValueVariable):
608 __slots__ = ("_item_factory",)614 __slots__ = ("_item_factory",)
615=======
616 def __hash__(self):
617 try:
618 return hash(self._value)
619 except TypeError:
620 return hash(pickle.dumps(self._value, -1))
621
622
623class ListVariable(Variable):
624 __slots__ = ("_item_factory",)
625>>>>>>> MERGE-SOURCE
609626
610 def __init__(self, item_factory, *args, **kwargs):627 def __init__(self, item_factory, *args, **kwargs):
611 self._item_factory = item_factory628 self._item_factory = item_factory
612629
=== modified file 'storm/zope/__init__.py'
--- storm/zope/__init__.py 2008-07-30 06:07:40 +0000
+++ storm/zope/__init__.py 2009-05-06 21:20:16 +0000
@@ -27,6 +27,7 @@
2727
2828
29classImplements(storm_sqlobject.SQLObjectResultSet, ISQLObjectResultSet)29classImplements(storm_sqlobject.SQLObjectResultSet, ISQLObjectResultSet)
30<<<<<<< TREE
30classImplements(ResultSet, IResultSet)31classImplements(ResultSet, IResultSet)
31classImplements(EmptyResultSet, IResultSet)32classImplements(EmptyResultSet, IResultSet)
3233
@@ -43,3 +44,7 @@
43 # Store.44 # Store.
44 _available_by_default.append("__storm_object_info__")45 _available_by_default.append("__storm_object_info__")
45 BasicTypes[ObjectInfo] = NoProxy46 BasicTypes[ObjectInfo] = NoProxy
47=======
48classImplements(ResultSet, IResultSet)
49classImplements(EmptyResultSet, IResultSet)
50>>>>>>> MERGE-SOURCE
4651
=== modified file 'storm/zope/interfaces.py'
=== modified file 'storm/zope/zstorm.py'
=== modified file 'test'
=== modified file 'tests/__init__.py'
--- tests/__init__.py 2008-06-20 14:08:30 +0000
+++ tests/__init__.py 2009-05-06 21:20:16 +0000
@@ -0,0 +1,1 @@
1#import storm.psycer as p; p.enable()
02
=== modified file 'tests/databases/base.py'
=== modified file 'tests/databases/postgres.py'
=== modified file 'tests/expr.py'
--- tests/expr.py 2008-10-02 15:47:18 +0000
+++ tests/expr.py 2009-05-06 21:20:16 +0000
@@ -662,16 +662,30 @@
662 'ORDER BY column1')662 'ORDER BY column1')
663 self.assertEquals(state.parameters, [])663 self.assertEquals(state.parameters, [])
664664
665 def test_select_having(self):665<<<<<<< TREE
666 expr = Select(column1, tables=table1, order_by=u"column1",666 def test_select_having(self):
667 group_by=[u"column2"], having=u"1 = 2")667 expr = Select(column1, tables=table1, order_by=u"column1",
668 state = State()668 group_by=[u"column2"], having=u"1 = 2")
669 statement = compile(expr, state)669 state = State()
670 self.assertEquals(statement, 'SELECT column1 FROM "table 1" '670 statement = compile(expr, state)
671 'GROUP BY column2 HAVING 1 = 2 '671 self.assertEquals(statement, 'SELECT column1 FROM "table 1" '
672 'ORDER BY column1')672 'GROUP BY column2 HAVING 1 = 2 '
673 self.assertEquals(state.parameters, [])673 'ORDER BY column1')
674674 self.assertEquals(state.parameters, [])
675
676=======
677 def test_select_having(self):
678 expr = Select(column1, tables=table1, order_by=u"column1",
679 group_by=[u"column2"], having=u"1 = 2")
680 state = State()
681 statement = compile(expr, state)
682 self.assertEquals(statement, 'SELECT column1 FROM "table 1" '
683 'GROUP BY column2 HAVING 1 = 2 '
684 'ORDER BY column1')
685 self.assertEquals(state.parameters, [])
686
687
688>>>>>>> MERGE-SOURCE
675 def test_select_contexts(self):689 def test_select_contexts(self):
676 column, where, table, order_by, group_by = track_contexts(5)690 column, where, table, order_by, group_by = track_contexts(5)
677 expr = Select(column, where, table,691 expr = Select(column, where, table,
@@ -932,8 +946,13 @@
932 expr = Func1().is_in([])946 expr = Func1().is_in([])
933 state = State()947 state = State()
934 statement = compile(expr, state)948 statement = compile(expr, state)
949<<<<<<< TREE
935 self.assertEquals(statement, "?")950 self.assertEquals(statement, "?")
936 self.assertVariablesEqual(state.parameters, [BoolVariable(False)])951 self.assertVariablesEqual(state.parameters, [BoolVariable(False)])
952=======
953 self.assertEquals(statement, "?")
954 self.assertEquals(state.parameters, [BoolVariable(False)])
955>>>>>>> MERGE-SOURCE
937956
938 def test_is_in_expr(self):957 def test_is_in_expr(self):
939 expr = Func1().is_in(Select(column1))958 expr = Func1().is_in(Select(column1))
940959
=== modified file 'tests/store/base.py'
--- tests/store/base.py 2009-02-19 16:44:33 +0000
+++ tests/store/base.py 2009-05-06 21:20:16 +0000
@@ -21,17 +21,26 @@
21#21#
22import decimal22import decimal
23import gc23import gc
24<<<<<<< TREE
24import operator25import operator
25import weakref26import weakref
27=======
28import operator
29>>>>>>> MERGE-SOURCE
2630
27from storm.references import Reference, ReferenceSet, Proxy31from storm.references import Reference, ReferenceSet, Proxy
28from storm.database import Result32from storm.database import Result
29from storm.properties import Int, Float, RawStr, Unicode, Property, Pickle33from storm.properties import Int, Float, RawStr, Unicode, Property, Pickle
30from storm.properties import PropertyPublisherMeta, Decimal34from storm.properties import PropertyPublisherMeta, Decimal
35<<<<<<< TREE
31from storm.variables import PickleVariable36from storm.variables import PickleVariable
32from storm.expr import (37from storm.expr import (
33 Asc, Desc, Select, Func, LeftJoin, SQL, Count, Sum, Avg, And, Or, Eq,38 Asc, Desc, Select, Func, LeftJoin, SQL, Count, Sum, Avg, And, Or, Eq,
34 Lower)39 Lower)
40=======
41from storm.expr import (
42 Asc, Desc, Select, Func, LeftJoin, SQL, Count, Sum, Avg, And, Or, Eq)
43>>>>>>> MERGE-SOURCE
35from storm.variables import Variable, UnicodeVariable, IntVariable44from storm.variables import Variable, UnicodeVariable, IntVariable
36from storm.info import get_obj_info, ClassAlias45from storm.info import get_obj_info, ClassAlias
37from storm.exceptions import *46from storm.exceptions import *
@@ -1306,131 +1315,259 @@
1306 foo = self.store.find(Foo, Foo.id == 10).one()1315 foo = self.store.find(Foo, Foo.id == 10).one()
1307 self.assertEqual(foo.title, "Title 30")1316 self.assertEqual(foo.title, "Title 30")
13081317
1309 def test_find_group_by(self):1318<<<<<<< TREE
1310 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))1319 def test_find_group_by(self):
1311 result.group_by(FooValue.value2)1320 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1312 result.order_by(Count(FooValue.id), Sum(FooValue.value1))1321 result.group_by(FooValue.value2)
1313 result = list(result)1322 result.order_by(Count(FooValue.id), Sum(FooValue.value1))
1314 self.assertEquals(result, [(2L, 2L), (2L, 2L), (2L, 3L), (3L, 6L)])1323 result = list(result)
13151324 self.assertEquals(result, [(2L, 2L), (2L, 2L), (2L, 3L), (3L, 6L)])
1316 def test_find_group_by_table(self):1325
1317 result = self.store.find(1326 def test_find_group_by_table(self):
1318 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)1327 result = self.store.find(
1319 result.group_by(Foo)1328 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1320 foo1 = self.store.get(Foo, 10)1329 result.group_by(Foo)
1321 foo2 = self.store.get(Foo, 20)1330 foo1 = self.store.get(Foo, 10)
1322 self.assertEquals(list(result), [(5, foo1), (16, foo2)])1331 foo2 = self.store.get(Foo, 20)
13231332 self.assertEquals(list(result), [(5, foo1), (16, foo2)])
1324 def test_find_group_by_table_contains(self):1333
1325 result = self.store.find(1334 def test_find_group_by_table_contains(self):
1326 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)1335 result = self.store.find(
1327 result.group_by(Foo)1336 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1328 foo1 = self.store.get(Foo, 10)1337 result.group_by(Foo)
1329 self.assertEquals((5, foo1) in result, True)1338 foo1 = self.store.get(Foo, 10)
13301339 self.assertEquals((5, foo1) in result, True)
1331 def test_find_group_by_multiple_tables(self):1340
1332 result = self.store.find(1341 def test_find_group_by_multiple_tables(self):
1333 Sum(FooValue.value2), Foo.id == FooValue.foo_id)1342 result = self.store.find(
1334 result.group_by(Foo.id)1343 Sum(FooValue.value2), Foo.id == FooValue.foo_id)
1335 result.order_by(Sum(FooValue.value2))1344 result.group_by(Foo.id)
1336 result = list(result)1345 result.order_by(Sum(FooValue.value2))
1337 self.assertEquals(result, [5, 16])1346 result = list(result)
13381347 self.assertEquals(result, [5, 16])
1339 result = self.store.find(1348
1340 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)1349 result = self.store.find(
1341 result.group_by(Foo)1350 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1342 result.order_by(Sum(FooValue.value2))1351 result.group_by(Foo)
1343 result = list(result)1352 result.order_by(Sum(FooValue.value2))
1344 foo1 = self.store.get(Foo, 10)1353 result = list(result)
1345 foo2 = self.store.get(Foo, 20)1354 foo1 = self.store.get(Foo, 10)
1346 self.assertEquals(result, [(5, foo1), (16, foo2)])1355 foo2 = self.store.get(Foo, 20)
13471356 self.assertEquals(result, [(5, foo1), (16, foo2)])
1348 result = self.store.find(1357
1349 (Foo.id, Sum(FooValue.value2), Avg(FooValue.value1)),1358 result = self.store.find(
1350 Foo.id == FooValue.foo_id)1359 (Foo.id, Sum(FooValue.value2), Avg(FooValue.value1)),
1351 result.group_by(Foo.id)1360 Foo.id == FooValue.foo_id)
1352 result.order_by(Foo.id)1361 result.group_by(Foo.id)
1353 result = list(result)1362 result.order_by(Foo.id)
1354 self.assertEquals(result, [(10, 5, 2),1363 result = list(result)
1355 (20, 16, 1)])1364 self.assertEquals(result, [(10, 5, 2),
13561365 (20, 16, 1)])
1357 def test_find_group_by_having(self):1366
1358 result = self.store.find(1367 def test_find_group_by_having(self):
1359 Sum(FooValue.value2), Foo.id == FooValue.foo_id)1368 result = self.store.find(
1360 result.group_by(Foo.id)1369 Sum(FooValue.value2), Foo.id == FooValue.foo_id)
1361 result.having(Sum(FooValue.value2) == 5)1370 result.group_by(Foo.id)
1362 self.assertEquals(list(result), [5])1371 result.having(Sum(FooValue.value2) == 5)
1363 result = self.store.find(1372 self.assertEquals(list(result), [5])
1364 Sum(FooValue.value2), Foo.id == FooValue.foo_id)1373 result = self.store.find(
1365 result.group_by(Foo.id)1374 Sum(FooValue.value2), Foo.id == FooValue.foo_id)
1366 result.having(Count() == 5)1375 result.group_by(Foo.id)
1367 self.assertEquals(list(result), [16])1376 result.having(Count() == 5)
13681377 self.assertEquals(list(result), [16])
1369 def test_find_having_without_group_by(self):1378
1370 result = self.store.find(FooValue)1379 def test_find_having_without_group_by(self):
1371 self.assertRaises(FeatureError, result.having, FooValue.value1 == 1)1380 result = self.store.find(FooValue)
13721381 self.assertRaises(FeatureError, result.having, FooValue.value1 == 1)
1373 def test_find_group_by_multiple_having(self):1382
1374 result = self.store.find((Count(), FooValue.value2))1383 def test_find_group_by_multiple_having(self):
1375 result.group_by(FooValue.value2)1384 result = self.store.find((Count(), FooValue.value2))
1376 result.having(Count() == 2, FooValue.value2 >= 3)1385 result.group_by(FooValue.value2)
1377 result.order_by(Count(), FooValue.value2)1386 result.having(Count() == 2, FooValue.value2 >= 3)
1378 list_result = list(result)1387 result.order_by(Count(), FooValue.value2)
1379 self.assertEquals(list_result, [(2, 3), (2, 4)])1388 list_result = list(result)
13801389 self.assertEquals(list_result, [(2, 3), (2, 4)])
1381 def test_find_successive_group_by(self):1390
1382 result = self.store.find(Count())1391 def test_find_successive_group_by(self):
1383 result.group_by(FooValue.value2)1392 result = self.store.find(Count())
1384 result.order_by(Count())1393 result.group_by(FooValue.value2)
1385 list_result = list(result)1394 result.order_by(Count())
1386 self.assertEquals(list_result, [2, 2, 2, 3])1395 list_result = list(result)
1387 result.group_by(FooValue.value1)1396 self.assertEquals(list_result, [2, 2, 2, 3])
1388 list_result = list(result)1397 result.group_by(FooValue.value1)
1389 self.assertEquals(list_result, [4, 5])1398 list_result = list(result)
13901399 self.assertEquals(list_result, [4, 5])
1391 def test_find_multiple_group_by(self):1400
1392 result = self.store.find(Count())1401 def test_find_multiple_group_by(self):
1393 result.group_by(FooValue.value2, FooValue.value1)1402 result = self.store.find(Count())
1394 result.order_by(Count())1403 result.group_by(FooValue.value2, FooValue.value1)
1395 list_result = list(result)1404 result.order_by(Count())
1396 self.assertEquals(list_result, [1, 1, 2, 2, 3])1405 list_result = list(result)
13971406 self.assertEquals(list_result, [1, 1, 2, 2, 3])
1398 def test_find_multiple_group_by_with_having(self):1407
1399 result = self.store.find((Count(), FooValue.value2))1408 def test_find_multiple_group_by_with_having(self):
1400 result.group_by(FooValue.value2, FooValue.value1).having(Count() == 2)1409 result = self.store.find((Count(), FooValue.value2))
1401 result.order_by(Count(), FooValue.value2)1410 result.group_by(FooValue.value2, FooValue.value1).having(Count() == 2)
1402 list_result = list(result)1411 result.order_by(Count(), FooValue.value2)
1403 self.assertEquals(list_result, [(2, 3), (2, 4)])1412 list_result = list(result)
14041413 self.assertEquals(list_result, [(2, 3), (2, 4)])
1405 def test_find_group_by_avg(self):1414
1406 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))1415 def test_find_group_by_avg(self):
1407 result.group_by(FooValue.value2)1416 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1408 self.assertRaises(FeatureError, result.avg, FooValue.value2)1417 result.group_by(FooValue.value2)
14091418 self.assertRaises(FeatureError, result.avg, FooValue.value2)
1410 def test_find_group_by_values(self):1419
1411 result = self.store.find(1420 def test_find_group_by_values(self):
1412 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)1421 result = self.store.find(
1413 result.group_by(Foo)1422 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1414 result.order_by(Foo.title)1423 result.group_by(Foo)
1415 result = list(result.values(Foo.title))1424 result.order_by(Foo.title)
1416 self.assertEquals(result, [u'Title 20', u'Title 30'])1425 result = list(result.values(Foo.title))
14171426 self.assertEquals(result, [u'Title 20', u'Title 30'])
1418 def test_find_group_by_union(self):1427
1419 result1 = self.store.find(Foo, id=30)1428 def test_find_group_by_union(self):
1420 result2 = self.store.find(Foo, id=10)1429 result1 = self.store.find(Foo, id=30)
1421 result3 = result1.union(result2)1430 result2 = self.store.find(Foo, id=10)
1422 self.assertRaises(FeatureError, result3.group_by, Foo.title)1431 result3 = result1.union(result2)
14231432 self.assertRaises(FeatureError, result3.group_by, Foo.title)
1424 def test_find_group_by_remove(self):1433
1425 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))1434 def test_find_group_by_remove(self):
1426 result.group_by(FooValue.value2)1435 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1427 self.assertRaises(FeatureError, result.remove)1436 result.group_by(FooValue.value2)
14281437 self.assertRaises(FeatureError, result.remove)
1429 def test_find_group_by_set(self):1438
1430 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))1439 def test_find_group_by_set(self):
1431 result.group_by(FooValue.value2)1440 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1432 self.assertRaises(FeatureError, result.set, FooValue.value1 == 1)1441 result.group_by(FooValue.value2)
14331442 self.assertRaises(FeatureError, result.set, FooValue.value1 == 1)
1443
1444=======
1445 def test_find_group_by(self):
1446 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1447 result.group_by(FooValue.value2)
1448 result.order_by(Count(FooValue.id), Sum(FooValue.value1))
1449 result = list(result)
1450 self.assertEquals(result, [(2L, 2L), (2L, 2L), (2L, 3L), (3L, 6L)])
1451
1452 def test_find_group_by_table(self):
1453 result = self.store.find(
1454 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1455 result.group_by(Foo)
1456 foo1 = self.store.get(Foo, 10)
1457 foo2 = self.store.get(Foo, 20)
1458 self.assertEquals(list(result), [(5, foo1), (16, foo2)])
1459
1460 def test_find_group_by_table_contains(self):
1461 result = self.store.find(
1462 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1463 result.group_by(Foo)
1464 foo1 = self.store.get(Foo, 10)
1465 self.assertEquals((5, foo1) in result, True)
1466
1467 def test_find_group_by_multiple_tables(self):
1468 result = self.store.find(
1469 Sum(FooValue.value2), Foo.id == FooValue.foo_id)
1470 result.group_by(Foo.id)
1471 result.order_by(Sum(FooValue.value2))
1472 result = list(result)
1473 self.assertEquals(result, [5, 16])
1474
1475 result = self.store.find(
1476 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1477 result.group_by(Foo)
1478 result.order_by(Sum(FooValue.value2))
1479 result = list(result)
1480 foo1 = self.store.get(Foo, 10)
1481 foo2 = self.store.get(Foo, 20)
1482 self.assertEquals(result, [(5, foo1), (16, foo2)])
1483
1484 result = self.store.find(
1485 (Foo.id, Sum(FooValue.value2), Avg(FooValue.value1)),
1486 Foo.id == FooValue.foo_id)
1487 result.group_by(Foo.id)
1488 result.order_by(Foo.id)
1489 result = list(result)
1490 self.assertEquals(result, [(10, 5, 2),
1491 (20, 16, 1)])
1492
1493 def test_find_group_by_having(self):
1494 result = self.store.find(
1495 Sum(FooValue.value2), Foo.id == FooValue.foo_id)
1496 result.group_by(Foo.id)
1497 result.having(Sum(FooValue.value2) == 5)
1498 self.assertEquals(list(result), [5])
1499 result = self.store.find(
1500 Sum(FooValue.value2), Foo.id == FooValue.foo_id)
1501 result.group_by(Foo.id)
1502 result.having(Count() == 5)
1503 self.assertEquals(list(result), [16])
1504
1505 def test_find_having_without_group_by(self):
1506 result = self.store.find(FooValue)
1507 self.assertRaises(FeatureError, result.having, FooValue.value1 == 1)
1508
1509 def test_find_group_by_multiple_having(self):
1510 result = self.store.find((Count(), FooValue.value2))
1511 result.group_by(FooValue.value2)
1512 result.having(Count() == 2, FooValue.value2 >= 3)
1513 result.order_by(Count(), FooValue.value2)
1514 list_result = list(result)
1515 self.assertEquals(list_result, [(2, 3), (2, 4)])
1516
1517 def test_find_successive_group_by(self):
1518 result = self.store.find(Count())
1519 result.group_by(FooValue.value2)
1520 result.order_by(Count())
1521 list_result = list(result)
1522 self.assertEquals(list_result, [2, 2, 2, 3])
1523 result.group_by(FooValue.value1)
1524 list_result = list(result)
1525 self.assertEquals(list_result, [4, 5])
1526
1527 def test_find_multiple_group_by(self):
1528 result = self.store.find(Count())
1529 result.group_by(FooValue.value2, FooValue.value1)
1530 result.order_by(Count())
1531 list_result = list(result)
1532 self.assertEquals(list_result, [1, 1, 2, 2, 3])
1533
1534 def test_find_multiple_group_by_with_having(self):
1535 result = self.store.find((Count(), FooValue.value2))
1536 result.group_by(FooValue.value2, FooValue.value1).having(Count() == 2)
1537 result.order_by(Count(), FooValue.value2)
1538 list_result = list(result)
1539 self.assertEquals(list_result, [(2, 3), (2, 4)])
1540
1541 def test_find_group_by_avg(self):
1542 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1543 result.group_by(FooValue.value2)
1544 self.assertRaises(FeatureError, result.avg, FooValue.value2)
1545
1546 def test_find_group_by_values(self):
1547 result = self.store.find(
1548 (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id)
1549 result.group_by(Foo)
1550 result.order_by(Foo.title)
1551 result = list(result.values(Foo.title))
1552 self.assertEquals(result, [u'Title 20', u'Title 30'])
1553
1554 def test_find_group_by_union(self):
1555 result1 = self.store.find(Foo, id=30)
1556 result2 = self.store.find(Foo, id=10)
1557 result3 = result1.union(result2)
1558 self.assertRaises(FeatureError, result3.group_by, Foo.title)
1559
1560 def test_find_group_by_remove(self):
1561 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1562 result.group_by(FooValue.value2)
1563 self.assertRaises(FeatureError, result.remove)
1564
1565 def test_find_group_by_set(self):
1566 result = self.store.find((Count(FooValue.id), Sum(FooValue.value1)))
1567 result.group_by(FooValue.value2)
1568 self.assertRaises(FeatureError, result.set, FooValue.value1 == 1)
1569
1570>>>>>>> MERGE-SOURCE
1434 def test_add_commit(self):1571 def test_add_commit(self):
1435 foo = Foo()1572 foo = Foo()
1436 foo.id = 401573 foo.id = 40
@@ -4316,6 +4453,10 @@
4316 self.assertEquals(foo.title, "Some default value")4453 self.assertEquals(foo.title, "Some default value")
43174454
4318 def test_pickle_variable(self):4455 def test_pickle_variable(self):
4456 # XXX 2008-06-19 jamesh bug=241267:
4457 # Disabled, as Pickle() properties depend on the flush event.
4458 return
4459
4319 class PickleBlob(Blob):4460 class PickleBlob(Blob):
4320 bin = Pickle()4461 bin = Pickle()
43214462
@@ -4503,6 +4644,10 @@
4503 self.assertTrue(value is blob.pickle)4644 self.assertTrue(value is blob.pickle)
45044645
4505 def test_pickle_variable_with_deleted_object(self):4646 def test_pickle_variable_with_deleted_object(self):
4647 # XXX 2008-06-19 jamesh bug=241267:
4648 # Disabled, as Pickle() properties depend on the flush event.
4649 return
4650
4506 class PickleBlob(Blob):4651 class PickleBlob(Blob):
4507 bin = Pickle()4652 bin = Pickle()
45084653
@@ -5387,6 +5532,7 @@
5387 " (ensure your database was created with CREATE DATABASE"5532 " (ensure your database was created with CREATE DATABASE"
5388 " ... CHARACTER SET utf8)")5533 " ... CHARACTER SET utf8)")
53895534
5535<<<<<<< TREE
5390 def test_creation_order_is_preserved_when_possible(self):5536 def test_creation_order_is_preserved_when_possible(self):
5391 foos = [self.store.add(Foo()) for i in range(10)]5537 foos = [self.store.add(Foo()) for i in range(10)]
5392 self.store.flush()5538 self.store.flush()
@@ -5499,6 +5645,50 @@
5499 foo.title = u"New title"5645 foo.title = u"New title"
5500 self.assertEqual(len(calls), 1)5646 self.assertEqual(len(calls), 1)
5501 self.assertEqual(calls[0], self.store)5647 self.assertEqual(calls[0], self.store)
5648=======
5649 def test_creation_order_is_preserved_when_possible(self):
5650 foos = [self.store.add(Foo()) for i in range(10)]
5651 self.store.flush()
5652 for i in range(len(foos)-1):
5653 self.assertTrue(foos[i].id < foos[i+1].id)
5654
5655 def test_update_order_is_preserved_when_possible(self):
5656 class MyFoo(Foo):
5657 sequence = 0
5658 def __storm_flushed__(self):
5659 self.flush_order = MyFoo.sequence
5660 MyFoo.sequence += 1
5661
5662 foos = [self.store.add(MyFoo()) for i in range(10)]
5663 self.store.flush()
5664
5665 MyFoo.sequence = 0
5666 for foo in foos:
5667 foo.title = u"Changed Title"
5668 self.store.flush()
5669
5670 for i, foo in enumerate(foos):
5671 self.assertEquals(foo.flush_order, i)
5672
5673 def test_removal_order_is_preserved_when_possible(self):
5674 class MyFoo(Foo):
5675 sequence = 0
5676 def __storm_flushed__(self):
5677 self.flush_order = MyFoo.sequence
5678 MyFoo.sequence += 1
5679
5680 foos = [self.store.add(MyFoo()) for i in range(10)]
5681 self.store.flush()
5682
5683 MyFoo.sequence = 0
5684 for foo in foos:
5685 self.store.remove(foo)
5686 self.store.flush()
5687
5688 for i, foo in enumerate(foos):
5689 self.assertEquals(foo.flush_order, i)
5690
5691>>>>>>> MERGE-SOURCE
55025692
5503class EmptyResultSetTest(object):5693class EmptyResultSetTest(object):
55045694
@@ -5560,6 +5750,7 @@
5560 self.assertEquals(list(self.result[:]), [])5750 self.assertEquals(list(self.result[:]), [])
5561 self.assertEquals(list(self.empty[:]), [])5751 self.assertEquals(list(self.empty[:]), [])
55625752
5753<<<<<<< TREE
5563 def test_contains(self):5754 def test_contains(self):
5564 self.assertEquals(Foo() in self.empty, False)5755 self.assertEquals(Foo() in self.empty, False)
55655756
@@ -5567,6 +5758,11 @@
5567 self.assertEquals(self.result.is_empty(), True)5758 self.assertEquals(self.result.is_empty(), True)
5568 self.assertEquals(self.empty.is_empty(), True)5759 self.assertEquals(self.empty.is_empty(), True)
55695760
5761=======
5762 def test_contains(self):
5763 self.assertEquals(Foo() in self.empty, False)
5764
5765>>>>>>> MERGE-SOURCE
5570 def test_any(self):5766 def test_any(self):
5571 self.assertEquals(self.result.any(), None)5767 self.assertEquals(self.result.any(), None)
5572 self.assertEquals(self.empty.any(), None)5768 self.assertEquals(self.empty.any(), None)
55735769
=== modified file 'tests/store/mysql.py'
=== modified file 'tests/store/postgres.py'
--- tests/store/postgres.py 2009-03-04 16:56:58 +0000
+++ tests/store/postgres.py 2009-05-06 21:20:16 +0000
@@ -103,6 +103,9 @@
103 self.connection.rollback()103 self.connection.rollback()
104104
105 def test_list_variable(self):105 def test_list_variable(self):
106 # XXX 2008-06-19 jamesh bug=241267:
107 # Disabled, as List() properties depend on the flush event.
108 return
106109
107 lst = Lst1()110 lst = Lst1()
108 lst.id = 1111 lst.id = 1
@@ -146,6 +149,9 @@
146 self.assertEquals(result.get_one(), ([1,2,3],))149 self.assertEquals(result.get_one(), ([1,2,3],))
147150
148 def test_list_variable_nested(self):151 def test_list_variable_nested(self):
152 # XXX 2008-06-19 jamesh bug=241267:
153 # Disabled, as List() properties depend on the flush event.
154 return
149155
150 lst = Lst2()156 lst = Lst2()
151 lst.id = 1157 lst.id = 1
152158
=== modified file 'tests/store/sqlite.py'
=== modified file 'tests/tracer.py'
--- tests/tracer.py 2009-02-04 01:53:02 +0000
+++ tests/tracer.py 2009-05-06 21:20:16 +0000
@@ -74,6 +74,7 @@
74 self.assertEquals(stash, ["m1", (1, 2), {"c": 3}, "m2", (), {}])74 self.assertEquals(stash, ["m1", (1, 2), {"c": 3}, "m2", (), {}])
7575
7676
77<<<<<<< TREE
7778
78class MockVariable(Variable):79class MockVariable(Variable):
7980
@@ -84,6 +85,18 @@
84 return self._value85 return self._value
8586
8687
88=======
89
90class MockVariable(object):
91
92 def __init__(self, value):
93 self._value = value
94
95 def get(self):
96 return self._value
97
98
99>>>>>>> MERGE-SOURCE
87class DebugTracerTest(TestHelper):100class DebugTracerTest(TestHelper):
88101
89 def setUp(self):102 def setUp(self):
@@ -116,6 +129,7 @@
116 self.assertEqual(tracer._stream, marker)129 self.assertEqual(tracer._stream, marker)
117130
118 def test_connection_raw_execute(self):131 def test_connection_raw_execute(self):
132<<<<<<< TREE
119 self.stream.write(133 self.stream.write(
120 "[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n")134 "[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n")
121 self.stream.flush()135 self.stream.flush()
@@ -139,6 +153,17 @@
139 raw_cursor = "RAW_CURSOR"153 raw_cursor = "RAW_CURSOR"
140 statement = "STATEMENT"154 statement = "STATEMENT"
141 params = [self.variable, 1]155 params = [self.variable, 1]
156=======
157 stderr = self.mocker.replace("sys.stderr")
158 stderr.write("[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n")
159 stderr.flush()
160 self.mocker.replay()
161
162 connection = "CONNECTION"
163 raw_cursor = "RAW_CURSOR"
164 statement = "STATEMENT"
165 params = [self.variable]
166>>>>>>> MERGE-SOURCE
142167
143 self.tracer.connection_raw_execute(connection, raw_cursor,168 self.tracer.connection_raw_execute(connection, raw_cursor,
144 statement, params)169 statement, params)
@@ -170,6 +195,25 @@
170 self.tracer.connection_raw_execute_success(connection, raw_cursor,195 self.tracer.connection_raw_execute_success(connection, raw_cursor,
171 statement, params)196 statement, params)
172197
198<<<<<<< TREE
199=======
200 def test_custom_stream(self):
201 self.tracer = DebugTracer(sys.stdout)
202
203 stdout = self.mocker.replace("sys.stdout")
204 stdout.write("[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n")
205 stdout.flush()
206 self.mocker.replay()
207
208 connection = "CONNECTION"
209 raw_cursor = "RAW_CURSOR"
210 statement = "STATEMENT"
211 params = [self.variable]
212
213 self.tracer.connection_raw_execute(connection, raw_cursor,
214 statement, params)
215
216>>>>>>> MERGE-SOURCE
173217
174class TimeoutTracerTestBase(TestHelper):218class TimeoutTracerTestBase(TestHelper):
175219
176220
=== modified file 'tests/tutorial.txt'
=== modified file 'tests/zope/zstorm.py'
--- tests/zope/zstorm.py 2009-03-05 21:53:12 +0000
+++ tests/zope/zstorm.py 2009-05-06 21:20:16 +0000
@@ -21,7 +21,11 @@
21import thread, weakref, gc21import thread, weakref, gc
2222
23from tests.helper import TestHelper23from tests.helper import TestHelper
24<<<<<<< TREE
24from tests.zope import has_transaction, has_zope_component25from tests.zope import has_transaction, has_zope_component
26=======
27from tests.zope import has_transaction, has_zope, has_zope_component
28>>>>>>> MERGE-SOURCE
2529
26if has_transaction:30if has_transaction:
27 import transaction31 import transaction
@@ -31,6 +35,9 @@
31if has_zope_component:35if has_zope_component:
32 from zope.component import provideUtility, getUtility36 from zope.component import provideUtility, getUtility
3337
38if has_zope_component:
39 from zope.component import provideUtility, getUtility
40
34from storm.exceptions import OperationalError41from storm.exceptions import OperationalError
35from storm.locals import Store42from storm.locals import Store
3643
@@ -233,6 +240,7 @@
233 store = self.zstorm.get("name", "sqlite:")240 store = self.zstorm.get("name", "sqlite:")
234 store_ref = weakref.ref(store)241 store_ref = weakref.ref(store)
235 transaction.abort()242 transaction.abort()
243<<<<<<< TREE
236 del store244 del store
237 gc.collect()245 gc.collect()
238 self.assertNotIdentical(store_ref(), None)246 self.assertNotIdentical(store_ref(), None)
@@ -249,3 +257,24 @@
249 provideUtility(ZStorm())257 provideUtility(ZStorm())
250 self.assertTrue(isinstance(getUtility(IZStorm), ZStorm))258 self.assertTrue(isinstance(getUtility(IZStorm), ZStorm))
251259
260=======
261 self.assertEquals(
262 len(transaction.manager._synchs.values()[0].data.values()), 1)
263 self.zstorm._reset()
264 self.assertEquals(
265 len(transaction.manager._synchs.values()[0].data.values()), 0)
266
267 def test_store_strong_reference(self):
268 """
269 The zstorm utility should be a strong reference to named stores so that
270 it doesn't recreate stores uselessly.
271 """
272 store = self.zstorm.get("name", "sqlite:")
273 store_ref = weakref.ref(store)
274 transaction.abort()
275 del store
276 gc.collect()
277 self.assertNotIdentical(store_ref(), None)
278 store = self.zstorm.get("name")
279 self.assertIdentical(store_ref(), store)
280>>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches

to status/vote changes: