Merge lp:~flacoste/storm/bug-360846 into lp:storm
- bug-360846
- Merge into trunk
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Henstridge | Needs Resubmitting | ||
Review via email: mp+6271@code.launchpad.net |
Commit message
Description of the change
Francis J. Lacoste (flacoste) wrote : | # |
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.
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 SQLObjectResult
Set.__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 PostgresConnect
ion.is_ disconnection_ error() to
accept some forms that weren't being caught
Preview Diff
1 | === modified file 'Makefile' |
2 | --- Makefile 2008-11-19 18:22:29 +0000 |
3 | +++ Makefile 2009-05-06 21:20:15 +0000 |
4 | @@ -1,3 +1,4 @@ |
5 | +<<<<<<< TREE |
6 | PYTHON ?= python |
7 | |
8 | TEST_COMMAND = $(PYTHON) test |
9 | @@ -28,3 +29,29 @@ |
10 | find . -name "*~" -type f -exec rm -f {} \; |
11 | |
12 | .PHONY: all build test |
13 | +======= |
14 | +PYTHON = python |
15 | + |
16 | +TEST_COMMAND = $(PYTHON) test |
17 | + |
18 | +STORM_POSTGRES_URI = postgres:storm_test |
19 | +STORM_POSTGRES_HOST_URI = postgres://localhost/storm_test |
20 | +STORM_MYSQL_URI = mysql:storm_test |
21 | +STORM_MYSQL_HOST_URI = mysql://localhost/storm_test |
22 | + |
23 | +export STORM_POSTGRES_URI |
24 | +export STORM_POSTGRES_HOST_URI |
25 | +export STORM_MYSQL_URI |
26 | +export STORM_MYSQL_HOST_URI |
27 | + |
28 | +all: build |
29 | + |
30 | +build: |
31 | + $(PYTHON) setup.py build_ext -i |
32 | + |
33 | +check: build |
34 | + # Run the tests once with cextensions and once without them. |
35 | + $(TEST_COMMAND) && STORM_CEXTENSIONS=1 $(TEST_COMMAND) |
36 | + |
37 | +.PHONY: all build test |
38 | +>>>>>>> MERGE-SOURCE |
39 | |
40 | === modified file 'NEWS' |
41 | --- NEWS 2009-03-18 07:11:14 +0000 |
42 | +++ NEWS 2009-05-06 21:20:15 +0000 |
43 | @@ -1,3 +1,4 @@ |
44 | +<<<<<<< TREE |
45 | 0.15 (2009-XX-XX) |
46 | ================= |
47 | |
48 | @@ -67,6 +68,17 @@ |
49 | the "GROUP BY" and "HAVING" statements. |
50 | - Change tests/store to keep the connection during the tests to make it |
51 | faster. |
52 | +======= |
53 | +0.13 (2008-XX-XX) |
54 | +================= |
55 | + |
56 | +Improvements |
57 | +------------ |
58 | + - Add group_by/having methods on ResultSet objects, to allow access to |
59 | + the "GROUP BY" and "HAVING" statements. |
60 | + - Change tests/store to keep the connection during the tests to make it |
61 | + faster. |
62 | +>>>>>>> MERGE-SOURCE |
63 | - Implemented support for plugging generic "tracers". Statement |
64 | debugging is now implemented using a tracer, and easily enabled |
65 | with storm.tracer.debug(True) (storm.database.DEBUG = True is gone). |
66 | @@ -76,6 +88,7 @@ |
67 | the property. The value assigned to the property is the result |
68 | of the validator, so the original value should be returned if |
69 | changing it isn't intended. |
70 | +<<<<<<< TREE |
71 | - Expressions can be passed to Store.find() as well as classes. This |
72 | makes it possible to request individual columns from a table, |
73 | computed expressions or aggregates. |
74 | @@ -97,6 +110,26 @@ |
75 | zope.interface and transaction packages installed. This makes it |
76 | easier to reuse the per-thread store management and global |
77 | transaction handling from other web frameworks. |
78 | +======= |
79 | + - Expressions can be passed to Store.find() as well as classes. This |
80 | + makes it possible to request individual columns from a table, |
81 | + computed expressions or aggregates. |
82 | + - Objects will be flushed in the order they become dirty by default. |
83 | + This means that generally the order in which Python operations are |
84 | + performed will be used to define the order in which flushes are done, |
85 | + which is generally the most expected. |
86 | + - The cextensions module was fixed, optimized, and improved. It's now |
87 | + built by default, but to actually enable it the environment variable |
88 | + STORM_CEXTENSIONS=1 must be defined at runtime. The module will |
89 | + likely be enabled by default on a future release. |
90 | + - ClassAlias will now cache all explicitly named aliases, to prevent |
91 | + the cost of rebuilding it. |
92 | + - Result sets and reference sets now have a __contains__() method. |
93 | + While code like "item in set" was previously possible, it involved |
94 | + iterating over the result set, which is expensive for large |
95 | + databases. |
96 | + |
97 | +>>>>>>> MERGE-SOURCE |
98 | |
99 | Bug fixes |
100 | --------- |
101 | @@ -115,10 +148,15 @@ |
102 | previously raise OrderLoopError. |
103 | - If the remote object in a back reference is removed, the reference |
104 | will now be broken. |
105 | +<<<<<<< TREE |
106 | - Fixed a race condition when two threads try to initialize the |
107 | ClassInfo for a given class at the same time. |
108 | - Improve handling of AUTO INCREMENT columns in the MySQL backend to |
109 | remove an unnecessary query when adding objects to a store. |
110 | +======= |
111 | + - Fixed a race condition when two threads try to initialize the |
112 | + ClassInfo for a given class at the same time. |
113 | +>>>>>>> MERGE-SOURCE |
114 | |
115 | |
116 | 0.12 (2008-01-28) |
117 | |
118 | === modified file 'storm/__init__.py' |
119 | --- storm/__init__.py 2009-01-09 17:40:25 +0000 |
120 | +++ storm/__init__.py 2009-05-06 21:20:16 +0000 |
121 | @@ -19,10 +19,17 @@ |
122 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
123 | # |
124 | |
125 | +<<<<<<< TREE |
126 | import os |
127 | |
128 | |
129 | version = "0.14" |
130 | +======= |
131 | +import os |
132 | + |
133 | + |
134 | +version = "0.12" |
135 | +>>>>>>> MERGE-SOURCE |
136 | version_info = tuple([int(x) for x in version.split(".")]) |
137 | |
138 | |
139 | |
140 | === modified file 'storm/cextensions.c' |
141 | --- storm/cextensions.c 2009-02-09 16:59:07 +0000 |
142 | +++ storm/cextensions.c 2009-05-06 21:20:16 +0000 |
143 | @@ -165,86 +165,165 @@ |
144 | |
145 | initialized = 1; |
146 | |
147 | - /* Import objects from storm module */ |
148 | - module = PyImport_ImportModule("storm"); |
149 | - if (!module) |
150 | - return 0; |
151 | - |
152 | - Undef = PyObject_GetAttrString(module, "Undef"); |
153 | - if (!Undef) |
154 | - return 0; |
155 | - |
156 | - Py_DECREF(module); |
157 | - |
158 | - /* Import objects from storm.variables module */ |
159 | - module = PyImport_ImportModule("storm.variables"); |
160 | - if (!module) |
161 | - return 0; |
162 | - |
163 | - raise_none_error = PyObject_GetAttrString(module, "raise_none_error"); |
164 | - if (!raise_none_error) |
165 | - return 0; |
166 | - |
167 | - LazyValue = PyObject_GetAttrString(module, "LazyValue"); |
168 | - if (!LazyValue) |
169 | - return 0; |
170 | - |
171 | - Py_DECREF(module); |
172 | - |
173 | - /* Import objects from storm.info module */ |
174 | - module = PyImport_ImportModule("storm.info"); |
175 | - if (!module) |
176 | - return 0; |
177 | - |
178 | - get_cls_info = PyObject_GetAttrString(module, "get_cls_info"); |
179 | - if (!get_cls_info) |
180 | - return 0; |
181 | - |
182 | - Py_DECREF(module); |
183 | - |
184 | - /* Import objects from storm.event module */ |
185 | - module = PyImport_ImportModule("storm.event"); |
186 | - if (!module) |
187 | - return 0; |
188 | - |
189 | - EventSystem = PyObject_GetAttrString(module, "EventSystem"); |
190 | - if (!EventSystem) |
191 | - return 0; |
192 | - |
193 | - Py_DECREF(module); |
194 | - |
195 | - /* Import objects from storm.expr module */ |
196 | - module = PyImport_ImportModule("storm.expr"); |
197 | - if (!module) |
198 | - return 0; |
199 | - |
200 | - SQLRaw = PyObject_GetAttrString(module, "SQLRaw"); |
201 | - if (!SQLRaw) |
202 | - return 0; |
203 | - |
204 | - SQLToken = PyObject_GetAttrString(module, "SQLToken"); |
205 | - if (!SQLToken) |
206 | - return 0; |
207 | - |
208 | - State = PyObject_GetAttrString(module, "State"); |
209 | - if (!State) |
210 | - return 0; |
211 | - |
212 | - CompileError = PyObject_GetAttrString(module, "CompileError"); |
213 | - if (!CompileError) |
214 | - return 0; |
215 | - |
216 | - Py_DECREF(module); |
217 | - |
218 | - /* A few frequently used objects which are part of the fast path. */ |
219 | - |
220 | - parenthesis_format = PyUnicode_DecodeASCII("(%s)", 4, "strict"); |
221 | - default_compile_join = PyUnicode_DecodeASCII(", ", 2, "strict"); |
222 | +<<<<<<< TREE |
223 | + /* Import objects from storm module */ |
224 | + module = PyImport_ImportModule("storm"); |
225 | + if (!module) |
226 | + return 0; |
227 | + |
228 | + Undef = PyObject_GetAttrString(module, "Undef"); |
229 | + if (!Undef) |
230 | + return 0; |
231 | + |
232 | + Py_DECREF(module); |
233 | + |
234 | + /* Import objects from storm.variables module */ |
235 | + module = PyImport_ImportModule("storm.variables"); |
236 | + if (!module) |
237 | + return 0; |
238 | + |
239 | + raise_none_error = PyObject_GetAttrString(module, "raise_none_error"); |
240 | + if (!raise_none_error) |
241 | + return 0; |
242 | + |
243 | + LazyValue = PyObject_GetAttrString(module, "LazyValue"); |
244 | + if (!LazyValue) |
245 | + return 0; |
246 | + |
247 | + Py_DECREF(module); |
248 | + |
249 | + /* Import objects from storm.info module */ |
250 | + module = PyImport_ImportModule("storm.info"); |
251 | + if (!module) |
252 | + return 0; |
253 | + |
254 | + get_cls_info = PyObject_GetAttrString(module, "get_cls_info"); |
255 | + if (!get_cls_info) |
256 | + return 0; |
257 | + |
258 | + Py_DECREF(module); |
259 | + |
260 | + /* Import objects from storm.event module */ |
261 | + module = PyImport_ImportModule("storm.event"); |
262 | + if (!module) |
263 | + return 0; |
264 | + |
265 | + EventSystem = PyObject_GetAttrString(module, "EventSystem"); |
266 | + if (!EventSystem) |
267 | + return 0; |
268 | + |
269 | + Py_DECREF(module); |
270 | + |
271 | + /* Import objects from storm.expr module */ |
272 | + module = PyImport_ImportModule("storm.expr"); |
273 | + if (!module) |
274 | + return 0; |
275 | + |
276 | + SQLRaw = PyObject_GetAttrString(module, "SQLRaw"); |
277 | + if (!SQLRaw) |
278 | + return 0; |
279 | + |
280 | + SQLToken = PyObject_GetAttrString(module, "SQLToken"); |
281 | + if (!SQLToken) |
282 | + return 0; |
283 | + |
284 | + State = PyObject_GetAttrString(module, "State"); |
285 | + if (!State) |
286 | + return 0; |
287 | + |
288 | + CompileError = PyObject_GetAttrString(module, "CompileError"); |
289 | + if (!CompileError) |
290 | + return 0; |
291 | + |
292 | + Py_DECREF(module); |
293 | + |
294 | + /* A few frequently used objects which are part of the fast path. */ |
295 | + |
296 | + parenthesis_format = PyUnicode_DecodeASCII("(%s)", 4, "strict"); |
297 | + default_compile_join = PyUnicode_DecodeASCII(", ", 2, "strict"); |
298 | +======= |
299 | + /* Import objects from storm module */ |
300 | + module = PyImport_ImportModule("storm"); |
301 | + if (!module) |
302 | + return 0; |
303 | + |
304 | + Undef = PyObject_GetAttrString(module, "Undef"); |
305 | + if (!Undef) |
306 | + return 0; |
307 | + |
308 | + Py_DECREF(module); |
309 | + |
310 | + /* Import objects from storm.variables module */ |
311 | + module = PyImport_ImportModule("storm.variables"); |
312 | + if (!module) |
313 | + return 0; |
314 | + |
315 | + raise_none_error = PyObject_GetAttrString(module, "raise_none_error"); |
316 | + if (!raise_none_error) |
317 | + return 0; |
318 | + |
319 | + LazyValue = PyObject_GetAttrString(module, "LazyValue"); |
320 | + if (!LazyValue) |
321 | + return 0; |
322 | + |
323 | + Py_DECREF(module); |
324 | + |
325 | + /* Import objects from storm.info module */ |
326 | + module = PyImport_ImportModule("storm.info"); |
327 | + if (!module) |
328 | + return 0; |
329 | + |
330 | + get_cls_info = PyObject_GetAttrString(module, "get_cls_info"); |
331 | + if (!get_cls_info) |
332 | + return 0; |
333 | + |
334 | + Py_DECREF(module); |
335 | + |
336 | + /* Import objects from storm.event module */ |
337 | + module = PyImport_ImportModule("storm.event"); |
338 | + if (!module) |
339 | + return 0; |
340 | + |
341 | + EventSystem = PyObject_GetAttrString(module, "EventSystem"); |
342 | + if (!EventSystem) |
343 | + return 0; |
344 | + |
345 | + Py_DECREF(module); |
346 | + |
347 | + /* Import objects from storm.expr module */ |
348 | + module = PyImport_ImportModule("storm.expr"); |
349 | + if (!module) |
350 | + return 0; |
351 | + |
352 | + SQLRaw = PyObject_GetAttrString(module, "SQLRaw"); |
353 | + if (!SQLRaw) |
354 | + return 0; |
355 | + |
356 | + SQLToken = PyObject_GetAttrString(module, "SQLToken"); |
357 | + if (!SQLToken) |
358 | + return 0; |
359 | + |
360 | + State = PyObject_GetAttrString(module, "State"); |
361 | + if (!State) |
362 | + return 0; |
363 | + |
364 | + CompileError = PyObject_GetAttrString(module, "CompileError"); |
365 | + if (!CompileError) |
366 | + return 0; |
367 | + |
368 | + Py_DECREF(module); |
369 | + |
370 | + /* A few frequently used objects which are part of the fast path. */ |
371 | + |
372 | + parenthesis_format = PyUnicode_DecodeASCII("(%s)", 4, "strict"); |
373 | + default_compile_join = PyUnicode_DecodeASCII(", ", 2, "strict"); |
374 | +>>>>>>> MERGE-SOURCE |
375 | |
376 | return 1; |
377 | } |
378 | |
379 | |
380 | +<<<<<<< TREE |
381 | static int |
382 | EventSystem_init(EventSystemObject *self, PyObject *args, PyObject *kwargs) |
383 | { |
384 | @@ -554,6 +633,317 @@ |
385 | }; |
386 | |
387 | |
388 | +======= |
389 | +static int |
390 | +EventSystem_init(EventSystemObject *self, PyObject *args, PyObject *kwargs) |
391 | +{ |
392 | + static char *kwlist[] = {"owner", NULL}; |
393 | + PyObject *owner; |
394 | + int result = -1; |
395 | + |
396 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &owner)) |
397 | + return -1; |
398 | + |
399 | + /* self._owner_ref = weakref.ref(owner) */ |
400 | + self->_owner_ref = PyWeakref_NewRef(owner, NULL); |
401 | + if (self->_owner_ref) { |
402 | + /* self._hooks = {} */ |
403 | + self->_hooks = PyDict_New(); |
404 | + if (self->_hooks) { |
405 | + result = 0; |
406 | + } |
407 | + } |
408 | + |
409 | + return result; |
410 | +} |
411 | + |
412 | +static int |
413 | +EventSystem_traverse(EventSystemObject *self, visitproc visit, void *arg) |
414 | +{ |
415 | + Py_VISIT(self->_owner_ref); |
416 | + Py_VISIT(self->_hooks); |
417 | + return 0; |
418 | +} |
419 | + |
420 | +static int |
421 | +EventSystem_clear(EventSystemObject *self) |
422 | +{ |
423 | + Py_CLEAR(self->_owner_ref); |
424 | + Py_CLEAR(self->_hooks); |
425 | + return 0; |
426 | +} |
427 | + |
428 | +static void |
429 | +EventSystem_dealloc(EventSystemObject *self) |
430 | +{ |
431 | + EventSystem_clear(self); |
432 | + self->ob_type->tp_free((PyObject *)self); |
433 | +} |
434 | + |
435 | +static PyObject * |
436 | +EventSystem_hook(EventSystemObject *self, PyObject *args) |
437 | +{ |
438 | + PyObject *result = NULL; |
439 | + PyObject *name, *callback, *data; |
440 | + |
441 | + if (PyTuple_GET_SIZE(args) < 2) { |
442 | + PyErr_SetString(PyExc_TypeError, "Invalid number of arguments"); |
443 | + return NULL; |
444 | + } |
445 | + |
446 | + name = PyTuple_GET_ITEM(args, 0); |
447 | + callback = PyTuple_GET_ITEM(args, 1); |
448 | + data = PyTuple_GetSlice(args, 2, PyTuple_GET_SIZE(args)); |
449 | + if (data) { |
450 | + /* |
451 | + callbacks = self._hooks.get(name) |
452 | + if callbacks is None: |
453 | + self._hooks.setdefault(name, set()).add((callback, data)) |
454 | + else: |
455 | + callbacks.add((callback, data)) |
456 | + */ |
457 | + PyObject *callbacks = PyDict_GetItem(self->_hooks, name); |
458 | + if (!PyErr_Occurred()) { |
459 | + if (callbacks == NULL) { |
460 | + callbacks = PySet_New(NULL); |
461 | + if (callbacks && |
462 | + PyDict_SetItem(self->_hooks, name, callbacks) == -1) { |
463 | + Py_DECREF(callbacks); |
464 | + callbacks = NULL; |
465 | + } |
466 | + } else { |
467 | + Py_INCREF(callbacks); |
468 | + } |
469 | + if (callbacks) { |
470 | + PyObject *tuple = PyTuple_New(2); |
471 | + if (tuple) { |
472 | + Py_INCREF(callback); |
473 | + PyTuple_SET_ITEM(tuple, 0, callback); |
474 | + Py_INCREF(data); |
475 | + PyTuple_SET_ITEM(tuple, 1, data); |
476 | + if (PySet_Add(callbacks, tuple) != -1) { |
477 | + Py_INCREF(Py_None); |
478 | + result = Py_None; |
479 | + } |
480 | + Py_DECREF(tuple); |
481 | + } |
482 | + Py_DECREF(callbacks); |
483 | + } |
484 | + } |
485 | + Py_DECREF(data); |
486 | + } |
487 | + |
488 | + return result; |
489 | +} |
490 | + |
491 | +static PyObject * |
492 | +EventSystem_unhook(EventSystemObject *self, PyObject *args) |
493 | +{ |
494 | + PyObject *result = NULL; |
495 | + PyObject *name, *callback, *data; |
496 | + |
497 | + if (PyTuple_GET_SIZE(args) < 2) { |
498 | + PyErr_SetString(PyExc_TypeError, "Invalid number of arguments"); |
499 | + return NULL; |
500 | + } |
501 | + |
502 | + name = PyTuple_GET_ITEM(args, 0); |
503 | + callback = PyTuple_GET_ITEM(args, 1); |
504 | + data = PyTuple_GetSlice(args, 2, PyTuple_GET_SIZE(args)); |
505 | + if (data) { |
506 | + /* |
507 | + callbacks = self._hooks.get(name) |
508 | + if callbacks is not None: |
509 | + callbacks.discard((callback, data)) |
510 | + */ |
511 | + PyObject *callbacks = PyDict_GetItem(self->_hooks, name); |
512 | + if (callbacks) { |
513 | + PyObject *tuple = PyTuple_New(2); |
514 | + if (tuple) { |
515 | + Py_INCREF(callback); |
516 | + PyTuple_SET_ITEM(tuple, 0, callback); |
517 | + Py_INCREF(data); |
518 | + PyTuple_SET_ITEM(tuple, 1, data); |
519 | + if (PySet_Discard(callbacks, tuple) != -1) { |
520 | + Py_INCREF(Py_None); |
521 | + result = Py_None; |
522 | + } |
523 | + Py_DECREF(tuple); |
524 | + } |
525 | + } else if (!PyErr_Occurred()) { |
526 | + Py_INCREF(Py_None); |
527 | + result = Py_None; |
528 | + } |
529 | + Py_DECREF(data); |
530 | + } |
531 | + |
532 | + return result; |
533 | +} |
534 | + |
535 | +static PyObject * |
536 | +EventSystem__do_emit_call(PyObject *callback, PyObject *owner, |
537 | + PyObject *args, PyObject *data) |
538 | +{ |
539 | + /* return callback(owner, *(args+data)) */ |
540 | + PyObject *result = NULL; |
541 | + PyObject *tuple = PyTuple_New(PyTuple_GET_SIZE(args) + |
542 | + PyTuple_GET_SIZE(data) + 1); |
543 | + if (tuple) { |
544 | + Py_ssize_t i, tuple_i; |
545 | + |
546 | + Py_INCREF(owner); |
547 | + PyTuple_SET_ITEM(tuple, 0, owner); |
548 | + tuple_i = 1; |
549 | + for (i = 0; i != PyTuple_GET_SIZE(args); i++) { |
550 | + PyObject *item = PyTuple_GET_ITEM(args, i); |
551 | + Py_INCREF(item); |
552 | + PyTuple_SET_ITEM(tuple, tuple_i++, item); |
553 | + } |
554 | + for (i = 0; i != PyTuple_GET_SIZE(data); i++) { |
555 | + PyObject *item = PyTuple_GET_ITEM(data, i); |
556 | + Py_INCREF(item); |
557 | + PyTuple_SET_ITEM(tuple, tuple_i++, item); |
558 | + } |
559 | + result = PyObject_Call(callback, tuple, NULL); |
560 | + Py_DECREF(tuple); |
561 | + } |
562 | + return result; |
563 | +} |
564 | + |
565 | +static PyObject * |
566 | +EventSystem_emit(EventSystemObject *self, PyObject *all_args) |
567 | +{ |
568 | + PyObject *result = NULL; |
569 | + PyObject *name, *args; |
570 | + |
571 | + if (PyTuple_GET_SIZE(all_args) == 0) { |
572 | + PyErr_SetString(PyExc_TypeError, "Invalid number of arguments"); |
573 | + return NULL; |
574 | + } |
575 | + |
576 | + /* XXX In the following code we trust on the format inserted by |
577 | + * the hook() method. If it's hacked somehow, it may blow up. */ |
578 | + |
579 | + name = PyTuple_GET_ITEM(all_args, 0); |
580 | + args = PyTuple_GetSlice(all_args, 1, PyTuple_GET_SIZE(all_args)); |
581 | + if (args) { |
582 | + /* owner = self._owner_ref() */ |
583 | + PyObject *owner = PyWeakref_GET_OBJECT(self->_owner_ref); |
584 | + /* if owner is not None: */ |
585 | + if (owner != Py_None) { |
586 | + /* callbacks = self._hooks.get(name) */ |
587 | + PyObject *callbacks = PyDict_GetItem(self->_hooks, name); |
588 | + Py_INCREF(owner); |
589 | + /* if callbacks: */ |
590 | + if (callbacks && PySet_GET_SIZE(callbacks) != 0) { |
591 | + /* for callback, data in tuple(callbacks): */ |
592 | + PyObject *sequence = \ |
593 | + PySequence_Fast(callbacks, "callbacks object isn't a set"); |
594 | + if (sequence) { |
595 | + int failed = 0; |
596 | + Py_ssize_t i; |
597 | + for (i = 0; i != PySequence_Fast_GET_SIZE(sequence); i++) { |
598 | + PyObject *item = PySequence_Fast_GET_ITEM(sequence, i); |
599 | + PyObject *callback = PyTuple_GET_ITEM(item, 0); |
600 | + PyObject *data = PyTuple_GET_ITEM(item, 1); |
601 | + PyObject *res; |
602 | + /* |
603 | + if callback(owner, *(args+data)) is False: |
604 | + callbacks.discard((callback, data)) |
605 | + */ |
606 | + res = EventSystem__do_emit_call(callback, owner, |
607 | + args, data); |
608 | + Py_XDECREF(res); |
609 | + if (res == NULL || |
610 | + (res == Py_False && |
611 | + PySet_Discard(callbacks, item) == -1)) { |
612 | + failed = 1; |
613 | + break; |
614 | + } |
615 | + } |
616 | + if (!failed) { |
617 | + Py_INCREF(Py_None); |
618 | + result = Py_None; |
619 | + } |
620 | + Py_DECREF(sequence); |
621 | + } |
622 | + } else if (!PyErr_Occurred()) { |
623 | + Py_INCREF(Py_None); |
624 | + result = Py_None; |
625 | + } |
626 | + Py_DECREF(owner); |
627 | + } else { |
628 | + Py_INCREF(Py_None); |
629 | + result = Py_None; |
630 | + } |
631 | + Py_DECREF(args); |
632 | + } |
633 | + |
634 | + return result; |
635 | +} |
636 | + |
637 | + |
638 | +static PyMethodDef EventSystem_methods[] = { |
639 | + {"hook", (PyCFunction)EventSystem_hook, METH_VARARGS, NULL}, |
640 | + {"unhook", (PyCFunction)EventSystem_unhook, METH_VARARGS, NULL}, |
641 | + {"emit", (PyCFunction)EventSystem_emit, METH_VARARGS, NULL}, |
642 | + {NULL, NULL} |
643 | +}; |
644 | + |
645 | +#define OFFSETOF(x) offsetof(EventSystemObject, x) |
646 | +static PyMemberDef EventSystem_members[] = { |
647 | + {"_object_ref", T_OBJECT, OFFSETOF(_owner_ref), READONLY, 0}, |
648 | + {"_hooks", T_OBJECT, OFFSETOF(_hooks), READONLY, 0}, |
649 | + {NULL} |
650 | +}; |
651 | +#undef OFFSETOF |
652 | + |
653 | +statichere PyTypeObject EventSystem_Type = { |
654 | + PyObject_HEAD_INIT(NULL) |
655 | + 0, /*ob_size*/ |
656 | + "storm.variables.EventSystem", /*tp_name*/ |
657 | + sizeof(EventSystemObject), /*tp_basicsize*/ |
658 | + 0, /*tp_itemsize*/ |
659 | + (destructor)EventSystem_dealloc, /*tp_dealloc*/ |
660 | + 0, /*tp_print*/ |
661 | + 0, /*tp_getattr*/ |
662 | + 0, /*tp_setattr*/ |
663 | + 0, /*tp_compare*/ |
664 | + 0, /*tp_repr*/ |
665 | + 0, /*tp_as_number*/ |
666 | + 0, /*tp_as_sequence*/ |
667 | + 0, /*tp_as_mapping*/ |
668 | + 0, /*tp_hash*/ |
669 | + 0, /*tp_call*/ |
670 | + 0, /*tp_str*/ |
671 | + PyObject_GenericGetAttr,/*tp_getattro*/ |
672 | + PyObject_GenericSetAttr,/*tp_setattro*/ |
673 | + 0, /*tp_as_buffer*/ |
674 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ |
675 | + 0, /*tp_doc*/ |
676 | + (traverseproc)EventSystem_traverse, /*tp_traverse*/ |
677 | + (inquiry)EventSystem_clear, /*tp_clear*/ |
678 | + 0, /*tp_richcompare*/ |
679 | + 0, /*tp_weaklistoffset*/ |
680 | + 0, /*tp_iter*/ |
681 | + 0, /*tp_iternext*/ |
682 | + EventSystem_methods, /*tp_methods*/ |
683 | + EventSystem_members, /*tp_members*/ |
684 | + 0, /*tp_getset*/ |
685 | + 0, /*tp_base*/ |
686 | + 0, /*tp_dict*/ |
687 | + 0, /*tp_descr_get*/ |
688 | + 0, /*tp_descr_set*/ |
689 | + 0, /*tp_dictoffset*/ |
690 | + (initproc)EventSystem_init, /*tp_init*/ |
691 | + PyType_GenericAlloc, /*tp_alloc*/ |
692 | + PyType_GenericNew, /*tp_new*/ |
693 | + PyObject_GC_Del, /*tp_free*/ |
694 | + 0, /*tp_is_gc*/ |
695 | +}; |
696 | + |
697 | + |
698 | +>>>>>>> MERGE-SOURCE |
699 | static PyObject * |
700 | Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) |
701 | { |
702 | @@ -1150,670 +1540,1337 @@ |
703 | |
704 | |
705 | static PyObject * |
706 | -Compile__update_cache(CompileObject *self, PyObject *args); |
707 | - |
708 | -static int |
709 | -Compile_init(CompileObject *self, PyObject *args, PyObject *kwargs) |
710 | -{ |
711 | - static char *kwlist[] = {"parent", NULL}; |
712 | - |
713 | - PyObject *parent = Py_None; |
714 | - |
715 | - PyObject *module = NULL; |
716 | - PyObject *WeakKeyDictionary = NULL; |
717 | - |
718 | - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &parent)) |
719 | - return -1; |
720 | - |
721 | - /* |
722 | - self._local_dispatch_table = {} |
723 | - self._local_precedence = {} |
724 | - self._local_reserved_words = {} |
725 | - self._dispatch_table = {} |
726 | - self._precedence = {} |
727 | - self._reserved_words = {} |
728 | - */ |
729 | - CATCH(NULL, self->_local_dispatch_table = PyDict_New()); |
730 | - CATCH(NULL, self->_local_precedence = PyDict_New()); |
731 | - CATCH(NULL, self->_local_reserved_words = PyDict_New()); |
732 | - CATCH(NULL, self->_dispatch_table = PyDict_New()); |
733 | - CATCH(NULL, self->_precedence = PyDict_New()); |
734 | - CATCH(NULL, self->_reserved_words = PyDict_New()); |
735 | - |
736 | - /* self._children = WeakKeyDictionary() */ |
737 | - CATCH(NULL, module = PyImport_ImportModule("weakref")); |
738 | - CATCH(NULL, WeakKeyDictionary = \ |
739 | - PyObject_GetAttrString(module, "WeakKeyDictionary")); |
740 | - Py_CLEAR(module); |
741 | - CATCH(NULL, self->_children = \ |
742 | - PyObject_CallFunctionObjArgs(WeakKeyDictionary, NULL)); |
743 | - Py_CLEAR(WeakKeyDictionary); |
744 | - |
745 | - /* self._parents = [] */ |
746 | - CATCH(NULL, self->_parents = PyList_New(0)); |
747 | - |
748 | - /* if parent: */ |
749 | - if (parent != Py_None) { |
750 | - PyObject *tmp; |
751 | - |
752 | - /* self._parents.extend(parent._parents) */ |
753 | - CompileObject *parent_object = (CompileObject *)parent; |
754 | - CATCH(-1, PyList_SetSlice(self->_parents, 0, 0, |
755 | - parent_object->_parents)); |
756 | - |
757 | - /* self._parents.append(parent) */ |
758 | - CATCH(-1, PyList_Append(self->_parents, parent)); |
759 | - |
760 | - /* parent._children[self] = True */ |
761 | - CATCH(-1, PyObject_SetItem(parent_object->_children, |
762 | - (PyObject *)self, Py_True)); |
763 | - |
764 | - /* self._update_cache() */ |
765 | - CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
766 | - Py_DECREF(tmp); |
767 | - } |
768 | - |
769 | - return 0; |
770 | - |
771 | -error: |
772 | - Py_XDECREF(module); |
773 | - Py_XDECREF(WeakKeyDictionary); |
774 | - return -1; |
775 | -} |
776 | - |
777 | -static int |
778 | -Compile_traverse(CompileObject *self, visitproc visit, void *arg) |
779 | -{ |
780 | - Py_VISIT(self->_local_dispatch_table); |
781 | - Py_VISIT(self->_local_precedence); |
782 | - Py_VISIT(self->_local_reserved_words); |
783 | - Py_VISIT(self->_dispatch_table); |
784 | - Py_VISIT(self->_precedence); |
785 | - Py_VISIT(self->_reserved_words); |
786 | - Py_VISIT(self->_children); |
787 | - Py_VISIT(self->_parents); |
788 | - return 0; |
789 | -} |
790 | - |
791 | -static int |
792 | -Compile_clear(CompileObject *self) |
793 | -{ |
794 | - if (self->__weakreflist) |
795 | - PyObject_ClearWeakRefs((PyObject *)self); |
796 | - Py_CLEAR(self->_local_dispatch_table); |
797 | - Py_CLEAR(self->_local_precedence); |
798 | - Py_CLEAR(self->_local_reserved_words); |
799 | - Py_CLEAR(self->_dispatch_table); |
800 | - Py_CLEAR(self->_precedence); |
801 | - Py_CLEAR(self->_reserved_words); |
802 | - Py_CLEAR(self->_children); |
803 | - Py_CLEAR(self->_parents); |
804 | - return 0; |
805 | -} |
806 | - |
807 | -static void |
808 | -Compile_dealloc(CompileObject *self) |
809 | -{ |
810 | - Compile_clear(self); |
811 | - self->ob_type->tp_free((PyObject *)self); |
812 | -} |
813 | - |
814 | -static PyObject * |
815 | -Compile__update_cache(CompileObject *self, PyObject *args) |
816 | -{ |
817 | - PyObject *iter = NULL; |
818 | - PyObject *child = NULL; |
819 | - Py_ssize_t size; |
820 | - int i; |
821 | - |
822 | - /* for parent in self._parents: */ |
823 | - size = PyList_GET_SIZE(self->_parents); |
824 | - for (i = 0; i != size; i++) { |
825 | - CompileObject *parent = \ |
826 | - (CompileObject *)PyList_GET_ITEM(self->_parents, i); |
827 | - /* self._dispatch_table.update(parent._local_dispatch_table) */ |
828 | - CATCH(-1, PyDict_Update(self->_dispatch_table, |
829 | - parent->_local_dispatch_table)); |
830 | - /* self._precedence.update(parent._local_precedence) */ |
831 | - CATCH(-1, PyDict_Update(self->_precedence, |
832 | - parent->_local_precedence)); |
833 | - /* self._reserved_words.update(parent._local_reserved_words) */ |
834 | - CATCH(-1, PyDict_Update(self->_reserved_words, |
835 | - parent->_local_reserved_words)); |
836 | - } |
837 | - /* self._dispatch_table.update(self._local_dispatch_table) */ |
838 | - CATCH(-1, PyDict_Update(self->_dispatch_table, |
839 | - self->_local_dispatch_table)); |
840 | - /* self._precedence.update(self._local_precedence) */ |
841 | - CATCH(-1, PyDict_Update(self->_precedence, self->_local_precedence)); |
842 | - /* self._reserved_words.update(self._local_reserved_words) */ |
843 | - CATCH(-1, PyDict_Update(self->_reserved_words, |
844 | - self->_local_reserved_words)); |
845 | - |
846 | - /* for child in self._children: */ |
847 | - CATCH(NULL, iter = PyObject_GetIter(self->_children)); |
848 | - while((child = PyIter_Next(iter))) { |
849 | - PyObject *tmp; |
850 | - |
851 | - /* child._update_cache() */ |
852 | - CATCH(NULL, tmp = Compile__update_cache((CompileObject *)child, NULL)); |
853 | - Py_DECREF(tmp); |
854 | - Py_DECREF(child); |
855 | - } |
856 | - if (PyErr_Occurred()) |
857 | - goto error; |
858 | - Py_CLEAR(iter); |
859 | - |
860 | - Py_RETURN_NONE; |
861 | - |
862 | -error: |
863 | - Py_XDECREF(child); |
864 | - Py_XDECREF(iter); |
865 | - return NULL; |
866 | -} |
867 | - |
868 | -static PyObject * |
869 | -Compile_when(CompileObject *self, PyObject *types) |
870 | -{ |
871 | - PyObject *result = NULL; |
872 | - PyObject *module = PyImport_ImportModule("storm.expr"); |
873 | - if (module) { |
874 | - PyObject *_when = PyObject_GetAttrString(module, "_when"); |
875 | - if (_when) { |
876 | - result = PyObject_CallFunctionObjArgs(_when, self, types, NULL); |
877 | - Py_DECREF(_when); |
878 | - } |
879 | - Py_DECREF(module); |
880 | - } |
881 | - return result; |
882 | -} |
883 | - |
884 | -static PyObject * |
885 | -Compile_add_reserved_words(CompileObject *self, PyObject *words) |
886 | -{ |
887 | - PyObject *lower_word = NULL; |
888 | - PyObject *iter = NULL; |
889 | - PyObject *word = NULL; |
890 | - PyObject *tmp; |
891 | - |
892 | - /* self._local_reserved_words.update((word.lower(), True) |
893 | - for word in words) */ |
894 | - CATCH(NULL, iter = PyObject_GetIter(words)); |
895 | - while ((word = PyIter_Next(iter))) { |
896 | - CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
897 | - CATCH(-1, PyDict_SetItem(self->_local_reserved_words, |
898 | - lower_word, Py_True)); |
899 | - Py_CLEAR(lower_word); |
900 | - Py_DECREF(word); |
901 | - } |
902 | - if (PyErr_Occurred()) |
903 | - goto error; |
904 | - Py_CLEAR(iter); |
905 | - |
906 | - /* self._update_cache() */ |
907 | - CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
908 | - Py_DECREF(tmp); |
909 | - |
910 | - Py_RETURN_NONE; |
911 | - |
912 | -error: |
913 | - Py_XDECREF(lower_word); |
914 | - Py_XDECREF(word); |
915 | - Py_XDECREF(iter); |
916 | - return NULL; |
917 | -} |
918 | - |
919 | -static PyObject * |
920 | -Compile_remove_reserved_words(CompileObject *self, PyObject *words) |
921 | -{ |
922 | - PyObject *lower_word = NULL; |
923 | - PyObject *word = NULL; |
924 | - PyObject *iter = NULL; |
925 | - PyObject *tmp; |
926 | - |
927 | - /* self._local_reserved_words.update((word.lower(), None) |
928 | - for word in words) */ |
929 | - CATCH(NULL, iter = PyObject_GetIter(words)); |
930 | - while ((word = PyIter_Next(iter))) { |
931 | - CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
932 | - CATCH(-1, PyDict_SetItem(self->_local_reserved_words, |
933 | - lower_word, Py_None)); |
934 | - Py_CLEAR(lower_word); |
935 | - Py_DECREF(word); |
936 | - } |
937 | - if (PyErr_Occurred()) |
938 | - goto error; |
939 | - Py_CLEAR(iter); |
940 | - |
941 | - /* self._update_cache() */ |
942 | - CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
943 | - Py_DECREF(tmp); |
944 | - |
945 | - Py_RETURN_NONE; |
946 | - |
947 | -error: |
948 | - Py_XDECREF(lower_word); |
949 | - Py_XDECREF(word); |
950 | - Py_XDECREF(iter); |
951 | - return NULL; |
952 | -} |
953 | - |
954 | -static PyObject * |
955 | -Compile_is_reserved_word(CompileObject *self, PyObject *word) |
956 | -{ |
957 | - PyObject *lower_word = NULL; |
958 | - PyObject *result = Py_False; |
959 | - PyObject *item; |
960 | - |
961 | - /* return self._reserved_words.get(word.lower()) is not None */ |
962 | - CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
963 | - item = PyDict_GetItem(self->_reserved_words, lower_word); |
964 | - if (item == NULL && PyErr_Occurred()) { |
965 | - goto error; |
966 | - } else if (item != NULL && item != Py_None) { |
967 | - result = Py_True; |
968 | - } |
969 | - Py_DECREF(lower_word); |
970 | - Py_INCREF(result); |
971 | - return result; |
972 | - |
973 | -error: |
974 | - Py_XDECREF(lower_word); |
975 | - return NULL; |
976 | -} |
977 | - |
978 | -staticforward PyTypeObject Compile_Type; |
979 | - |
980 | -static PyObject * |
981 | -Compile_create_child(CompileObject *self, PyObject *args) |
982 | -{ |
983 | - /* return self.__class__(self) */ |
984 | - return PyObject_CallFunctionObjArgs((PyObject *)self->ob_type, self, NULL); |
985 | -} |
986 | - |
987 | -static PyObject * |
988 | -Compile_get_precedence(CompileObject *self, PyObject *type) |
989 | -{ |
990 | - /* return self._precedence.get(type, MAX_PRECEDENCE) */ |
991 | - PyObject *result = PyDict_GetItem(self->_precedence, type); |
992 | - if (result == NULL && !PyErr_Occurred()) { |
993 | - /* That should be MAX_PRECEDENCE, defined in expr.py */ |
994 | - return PyInt_FromLong(1000); |
995 | - } |
996 | - Py_INCREF(result); |
997 | - return result; |
998 | -} |
999 | - |
1000 | -static PyObject * |
1001 | -Compile_set_precedence(CompileObject *self, PyObject *args) |
1002 | -{ |
1003 | - Py_ssize_t size = PyTuple_GET_SIZE(args); |
1004 | - PyObject *precedence = NULL; |
1005 | - PyObject *tmp; |
1006 | - int i; |
1007 | - |
1008 | - if (size < 2) { |
1009 | - PyErr_SetString(PyExc_TypeError, |
1010 | - "set_precedence() takes at least 2 arguments."); |
1011 | - return NULL; |
1012 | - } |
1013 | - |
1014 | - /* for type in types: */ |
1015 | - precedence = PyTuple_GET_ITEM(args, 0); |
1016 | - for (i = 1; i != size; i++) { |
1017 | - PyObject *type = PyTuple_GET_ITEM(args, i); |
1018 | - /* self._local_precedence[type] = precedence */ |
1019 | - CATCH(-1, PyDict_SetItem(self->_local_precedence, type, precedence)); |
1020 | - } |
1021 | - |
1022 | - /* self._update_cache() */ |
1023 | - CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
1024 | - Py_DECREF(tmp); |
1025 | - |
1026 | - Py_RETURN_NONE; |
1027 | -error: |
1028 | - return NULL; |
1029 | -} |
1030 | - |
1031 | -PyObject * |
1032 | -Compile_single(CompileObject *self, |
1033 | - PyObject *expr, PyObject *state, PyObject *outer_precedence) |
1034 | -{ |
1035 | - PyObject *inner_precedence = NULL; |
1036 | - PyObject *statement = NULL; |
1037 | - |
1038 | - /* cls = expr.__class__ */ |
1039 | - PyObject *cls = (PyObject *)expr->ob_type; |
1040 | - |
1041 | - /* |
1042 | - dispatch_table = self._dispatch_table |
1043 | - if cls in dispatch_table: |
1044 | - handler = dispatch_table[cls] |
1045 | - else: |
1046 | - */ |
1047 | - PyObject *handler = PyDict_GetItem(self->_dispatch_table, cls); |
1048 | - if (!handler) { |
1049 | - PyObject *mro; |
1050 | - Py_ssize_t size, i; |
1051 | - |
1052 | - if (PyErr_Occurred()) |
1053 | - goto error; |
1054 | - |
1055 | - /* for mro_cls in cls.__mro__: */ |
1056 | - mro = expr->ob_type->tp_mro; |
1057 | - size = PyTuple_GET_SIZE(mro); |
1058 | - for (i = 0; i != size; i++) { |
1059 | - PyObject *mro_cls = PyTuple_GET_ITEM(mro, i); |
1060 | - /* |
1061 | - if mro_cls in dispatch_table: |
1062 | - handler = dispatch_table[mro_cls] |
1063 | - break |
1064 | - */ |
1065 | - handler = PyDict_GetItem(self->_dispatch_table, mro_cls); |
1066 | - if (handler) |
1067 | - break; |
1068 | - |
1069 | - if (PyErr_Occurred()) |
1070 | - goto error; |
1071 | - } |
1072 | - /* else: */ |
1073 | - if (i == size) { |
1074 | - /* |
1075 | - raise CompileError("Don't know how to compile type %r of %r" |
1076 | - % (expr.__class__, expr)) |
1077 | - */ |
1078 | - PyObject *repr = PyObject_Repr(expr); |
1079 | - if (repr) { |
1080 | - PyErr_Format(CompileError, |
1081 | - "Don't know how to compile type %s of %s", |
1082 | - expr->ob_type->tp_name, PyString_AS_STRING(repr)); |
1083 | - Py_DECREF(repr); |
1084 | - } |
1085 | - goto error; |
1086 | - } |
1087 | - } |
1088 | - |
1089 | - /* |
1090 | - inner_precedence = state.precedence = \ |
1091 | - self._precedence.get(cls, MAX_PRECEDENCE) |
1092 | - */ |
1093 | - CATCH(NULL, inner_precedence = Compile_get_precedence(self, cls)); |
1094 | - CATCH(-1, PyObject_SetAttrString(state, "precedence", inner_precedence)); |
1095 | - |
1096 | - /* statement = handler(self, expr, state) */ |
1097 | - CATCH(NULL, statement = PyObject_CallFunctionObjArgs(handler, self, expr, |
1098 | - state, NULL)); |
1099 | - |
1100 | - /* if inner_precedence < outer_precedence: */ |
1101 | - if (PyObject_Compare(inner_precedence, outer_precedence) == -1) { |
1102 | - PyObject *args, *tmp; |
1103 | - |
1104 | - if (PyErr_Occurred()) |
1105 | - goto error; |
1106 | - |
1107 | - /* return "(%s)" % statement */ |
1108 | - CATCH(NULL, args = PyTuple_Pack(1, statement)); |
1109 | - tmp = PyUnicode_Format(parenthesis_format, args); |
1110 | - Py_DECREF(args); |
1111 | - CATCH(NULL, tmp); |
1112 | - Py_DECREF(statement); |
1113 | - statement = tmp; |
1114 | - } |
1115 | - |
1116 | - Py_DECREF(inner_precedence); |
1117 | - |
1118 | - return statement; |
1119 | - |
1120 | -error: |
1121 | - Py_XDECREF(inner_precedence); |
1122 | - Py_XDECREF(statement); |
1123 | - |
1124 | - return NULL; |
1125 | -} |
1126 | - |
1127 | -PyObject * |
1128 | -Compile_one_or_many(CompileObject *self, PyObject *expr, PyObject *state, |
1129 | - PyObject *join, int raw, int token) |
1130 | -{ |
1131 | - PyObject *outer_precedence = NULL; |
1132 | - PyObject *compiled = NULL; |
1133 | - PyObject *sequence = NULL; |
1134 | - PyObject *statement = NULL; |
1135 | - Py_ssize_t size, i; |
1136 | - |
1137 | - Py_INCREF(expr); |
1138 | - |
1139 | - /* |
1140 | - expr_type = type(expr) |
1141 | - if (expr_type is SQLRaw or |
1142 | - raw and (expr_type is str or expr_type is unicode)): |
1143 | - return expr |
1144 | - */ |
1145 | - if ((PyObject *)expr->ob_type == SQLRaw || |
1146 | - (raw && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr)))) { |
1147 | - /* Pass our reference on. */ |
1148 | - return expr; |
1149 | - } |
1150 | - |
1151 | - /* |
1152 | - if token and (expr_type is str or expr_type is unicode): |
1153 | - expr = SQLToken(expr) |
1154 | - */ |
1155 | - if (token && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr))) { |
1156 | - PyObject *tmp; |
1157 | - CATCH(NULL, tmp = PyObject_CallFunctionObjArgs(SQLToken, expr, NULL)); |
1158 | - Py_DECREF(expr); |
1159 | - expr = tmp; |
1160 | - } |
1161 | - |
1162 | - /* |
1163 | - if state is None: |
1164 | - state = State() |
1165 | - */ |
1166 | - /* That's done in Compile__call__ just once. */ |
1167 | - |
1168 | - /* outer_precedence = state.precedence */ |
1169 | - CATCH(NULL, outer_precedence = PyObject_GetAttrString(state, "precedence")); |
1170 | - /* if expr_type is tuple or expr_type is list: */ |
1171 | - if (PyTuple_CheckExact(expr) || PyList_CheckExact(expr)) { |
1172 | - /* compiled = [] */ |
1173 | - CATCH(NULL, compiled = PyList_New(0)); |
1174 | - |
1175 | - /* for subexpr in expr: */ |
1176 | - sequence = PySequence_Fast(expr, "This can't actually fail! ;-)"); |
1177 | - size = PySequence_Fast_GET_SIZE(sequence); |
1178 | - for (i = 0; i != size; i++) { |
1179 | - PyObject *subexpr = PySequence_Fast_GET_ITEM(sequence, i); |
1180 | - /* |
1181 | - subexpr_type = type(subexpr) |
1182 | - if subexpr_type is SQLRaw or raw and (subexpr_type is str or |
1183 | - subexpr_type is unicode): |
1184 | - */ |
1185 | - if ((PyObject *)subexpr->ob_type == (PyObject *)SQLRaw || |
1186 | - (raw && (PyString_CheckExact(subexpr) || |
1187 | - PyUnicode_CheckExact(subexpr)))) { |
1188 | - /* statement = subexpr */ |
1189 | - Py_INCREF(subexpr); |
1190 | - statement = subexpr; |
1191 | - /* elif subexpr_type is tuple or subexpr_type is list: */ |
1192 | - } else if (PyTuple_CheckExact(subexpr) || |
1193 | - PyList_CheckExact(subexpr)) { |
1194 | - /* state.precedence = outer_precedence */ |
1195 | - CATCH(-1, PyObject_SetAttrString(state, "precedence", |
1196 | - outer_precedence)); |
1197 | - /* statement = self(subexpr, state, join, raw, token) */ |
1198 | - CATCH(NULL, |
1199 | - statement = Compile_one_or_many(self, subexpr, state, |
1200 | - join, raw, token)); |
1201 | - /* else: */ |
1202 | - } else { |
1203 | - /* |
1204 | - if token and (subexpr_type is unicode or |
1205 | - subexpr_type is str): |
1206 | - */ |
1207 | - if (token && (PyUnicode_CheckExact(subexpr) || |
1208 | - PyString_CheckExact(subexpr))) { |
1209 | - /* subexpr = SQLToken(subexpr) */ |
1210 | - CATCH(NULL, |
1211 | - subexpr = PyObject_CallFunctionObjArgs(SQLToken, |
1212 | - subexpr, |
1213 | - NULL)); |
1214 | - } else { |
1215 | - Py_INCREF(subexpr); |
1216 | - } |
1217 | - |
1218 | - /* |
1219 | - statement = self._compile_single(subexpr, state, |
1220 | - outer_precedence) |
1221 | - */ |
1222 | - statement = Compile_single(self, subexpr, state, |
1223 | - outer_precedence); |
1224 | - Py_DECREF(subexpr); |
1225 | - CATCH(NULL, statement); |
1226 | - } |
1227 | - |
1228 | - /* compiled.append(statement) */ |
1229 | - CATCH(-1, PyList_Append(compiled, statement)); |
1230 | - Py_CLEAR(statement); |
1231 | - } |
1232 | - Py_CLEAR(sequence); |
1233 | - |
1234 | - /* statement = join.join(compiled) */ |
1235 | - CATCH(NULL, statement = PyUnicode_Join(join, compiled)); |
1236 | - Py_CLEAR(compiled); |
1237 | - } else { |
1238 | - /* statement = self._compile_single(expr, state, outer_precedence) */ |
1239 | - CATCH(NULL, statement = Compile_single(self, expr, state, |
1240 | - outer_precedence)); |
1241 | - } |
1242 | - |
1243 | - /* state.precedence = outer_precedence */ |
1244 | - CATCH(-1, PyObject_SetAttrString(state, "precedence", outer_precedence)); |
1245 | - Py_CLEAR(outer_precedence); |
1246 | - |
1247 | - Py_DECREF(expr); |
1248 | - |
1249 | - return statement; |
1250 | - |
1251 | -error: |
1252 | - Py_XDECREF(expr); |
1253 | - Py_XDECREF(outer_precedence); |
1254 | - Py_XDECREF(compiled); |
1255 | - Py_XDECREF(sequence); |
1256 | - Py_XDECREF(statement); |
1257 | - |
1258 | - return NULL; |
1259 | -} |
1260 | - |
1261 | -static PyObject * |
1262 | -Compile__call__(CompileObject *self, PyObject *args, PyObject *kwargs) |
1263 | -{ |
1264 | - static char *kwlist[] = {"expr", "state", "join", "raw", "token", NULL}; |
1265 | - PyObject *expr = NULL; |
1266 | - PyObject *state = Py_None; |
1267 | - PyObject *join; |
1268 | - char raw = 0; |
1269 | - char token = 0; |
1270 | - |
1271 | - PyObject *result = NULL; |
1272 | - |
1273 | - if (!initialize_globals()) |
1274 | - return NULL; |
1275 | - |
1276 | - join = default_compile_join; |
1277 | - |
1278 | - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OSbb", kwlist, |
1279 | - &expr, &state, &join, &raw, &token)) { |
1280 | - return NULL; |
1281 | - } |
1282 | - |
1283 | - if (state == Py_None) { |
1284 | - state = PyObject_CallFunctionObjArgs(State, NULL); |
1285 | - } else { |
1286 | - Py_INCREF(state); |
1287 | - } |
1288 | - if (state) { |
1289 | - result = Compile_one_or_many(self, expr, state, join, raw, token); |
1290 | - Py_DECREF(state); |
1291 | - } |
1292 | - return result; |
1293 | -} |
1294 | - |
1295 | - |
1296 | -static PyMethodDef Compile_methods[] = { |
1297 | - {"_update_cache", (PyCFunction)Compile__update_cache, METH_NOARGS, NULL}, |
1298 | - {"when", (PyCFunction)Compile_when, METH_VARARGS, NULL}, |
1299 | - {"add_reserved_words", (PyCFunction)Compile_add_reserved_words, |
1300 | - METH_O, NULL}, |
1301 | - {"remove_reserved_words", (PyCFunction)Compile_remove_reserved_words, |
1302 | - METH_O, NULL}, |
1303 | - {"is_reserved_word", (PyCFunction)Compile_is_reserved_word, METH_O, NULL}, |
1304 | - {"create_child", (PyCFunction)Compile_create_child, METH_NOARGS, NULL}, |
1305 | - {"get_precedence", (PyCFunction)Compile_get_precedence, METH_O, NULL}, |
1306 | - {"set_precedence", (PyCFunction)Compile_set_precedence, METH_VARARGS, NULL}, |
1307 | - {NULL, NULL} |
1308 | -}; |
1309 | - |
1310 | -#define OFFSETOF(x) offsetof(CompileObject, x) |
1311 | -static PyMemberDef Compile_members[] = { |
1312 | - {"_local_dispatch_table", T_OBJECT, OFFSETOF(_local_dispatch_table), 0, 0}, |
1313 | - {"_local_precedence", T_OBJECT, OFFSETOF(_local_precedence), 0, 0}, |
1314 | - {"_local_reserved_words", T_OBJECT, OFFSETOF(_local_reserved_words), 0, 0}, |
1315 | - {"_dispatch_table", T_OBJECT, OFFSETOF(_dispatch_table), 0, 0}, |
1316 | - {"_precedence", T_OBJECT, OFFSETOF(_precedence), 0, 0}, |
1317 | - {"_reserved_words", T_OBJECT, OFFSETOF(_reserved_words), 0, 0}, |
1318 | - {"_children", T_OBJECT, OFFSETOF(_children), 0, 0}, |
1319 | - {"_parents", T_OBJECT, OFFSETOF(_parents), 0, 0}, |
1320 | - {NULL} |
1321 | -}; |
1322 | -#undef OFFSETOF |
1323 | - |
1324 | -statichere PyTypeObject Compile_Type = { |
1325 | - PyObject_HEAD_INIT(NULL) |
1326 | - 0, /*ob_size*/ |
1327 | - "storm.variables.Compile", /*tp_name*/ |
1328 | - sizeof(CompileObject), /*tp_basicsize*/ |
1329 | - 0, /*tp_itemsize*/ |
1330 | - (destructor)Compile_dealloc, /*tp_dealloc*/ |
1331 | - 0, /*tp_print*/ |
1332 | - 0, /*tp_getattr*/ |
1333 | - 0, /*tp_setattr*/ |
1334 | - 0, /*tp_compare*/ |
1335 | - 0, /*tp_repr*/ |
1336 | - 0, /*tp_as_number*/ |
1337 | - 0, /*tp_as_sequence*/ |
1338 | - 0, /*tp_as_mapping*/ |
1339 | - 0, /*tp_hash*/ |
1340 | - (ternaryfunc)Compile__call__, /*tp_call*/ |
1341 | - 0, /*tp_str*/ |
1342 | - PyObject_GenericGetAttr,/*tp_getattro*/ |
1343 | - PyObject_GenericSetAttr,/*tp_setattro*/ |
1344 | - 0, /*tp_as_buffer*/ |
1345 | - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ |
1346 | - 0, /*tp_doc*/ |
1347 | - (traverseproc)Compile_traverse, /*tp_traverse*/ |
1348 | - (inquiry)Compile_clear, /*tp_clear*/ |
1349 | - 0, /*tp_richcompare*/ |
1350 | - offsetof(CompileObject, __weakreflist), /*tp_weaklistoffset*/ |
1351 | - 0, /*tp_iter*/ |
1352 | - 0, /*tp_iternext*/ |
1353 | - Compile_methods, /*tp_methods*/ |
1354 | - Compile_members, /*tp_members*/ |
1355 | - 0, /*tp_getset*/ |
1356 | - 0, /*tp_base*/ |
1357 | - 0, /*tp_dict*/ |
1358 | - 0, /*tp_descr_get*/ |
1359 | - 0, /*tp_descr_set*/ |
1360 | - 0, /*tp_dictoffset*/ |
1361 | - (initproc)Compile_init, /*tp_init*/ |
1362 | - PyType_GenericAlloc, /*tp_alloc*/ |
1363 | - PyType_GenericNew, /*tp_new*/ |
1364 | - PyObject_GC_Del, /*tp_free*/ |
1365 | - 0, /*tp_is_gc*/ |
1366 | -}; |
1367 | - |
1368 | - |
1369 | -static PyObject * |
1370 | +<<<<<<< TREE |
1371 | +Compile__update_cache(CompileObject *self, PyObject *args); |
1372 | + |
1373 | +static int |
1374 | +Compile_init(CompileObject *self, PyObject *args, PyObject *kwargs) |
1375 | +{ |
1376 | + static char *kwlist[] = {"parent", NULL}; |
1377 | + |
1378 | + PyObject *parent = Py_None; |
1379 | + |
1380 | + PyObject *module = NULL; |
1381 | + PyObject *WeakKeyDictionary = NULL; |
1382 | + |
1383 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &parent)) |
1384 | + return -1; |
1385 | + |
1386 | + /* |
1387 | + self._local_dispatch_table = {} |
1388 | + self._local_precedence = {} |
1389 | + self._local_reserved_words = {} |
1390 | + self._dispatch_table = {} |
1391 | + self._precedence = {} |
1392 | + self._reserved_words = {} |
1393 | + */ |
1394 | + CATCH(NULL, self->_local_dispatch_table = PyDict_New()); |
1395 | + CATCH(NULL, self->_local_precedence = PyDict_New()); |
1396 | + CATCH(NULL, self->_local_reserved_words = PyDict_New()); |
1397 | + CATCH(NULL, self->_dispatch_table = PyDict_New()); |
1398 | + CATCH(NULL, self->_precedence = PyDict_New()); |
1399 | + CATCH(NULL, self->_reserved_words = PyDict_New()); |
1400 | + |
1401 | + /* self._children = WeakKeyDictionary() */ |
1402 | + CATCH(NULL, module = PyImport_ImportModule("weakref")); |
1403 | + CATCH(NULL, WeakKeyDictionary = \ |
1404 | + PyObject_GetAttrString(module, "WeakKeyDictionary")); |
1405 | + Py_CLEAR(module); |
1406 | + CATCH(NULL, self->_children = \ |
1407 | + PyObject_CallFunctionObjArgs(WeakKeyDictionary, NULL)); |
1408 | + Py_CLEAR(WeakKeyDictionary); |
1409 | + |
1410 | + /* self._parents = [] */ |
1411 | + CATCH(NULL, self->_parents = PyList_New(0)); |
1412 | + |
1413 | + /* if parent: */ |
1414 | + if (parent != Py_None) { |
1415 | + PyObject *tmp; |
1416 | + |
1417 | + /* self._parents.extend(parent._parents) */ |
1418 | + CompileObject *parent_object = (CompileObject *)parent; |
1419 | + CATCH(-1, PyList_SetSlice(self->_parents, 0, 0, |
1420 | + parent_object->_parents)); |
1421 | + |
1422 | + /* self._parents.append(parent) */ |
1423 | + CATCH(-1, PyList_Append(self->_parents, parent)); |
1424 | + |
1425 | + /* parent._children[self] = True */ |
1426 | + CATCH(-1, PyObject_SetItem(parent_object->_children, |
1427 | + (PyObject *)self, Py_True)); |
1428 | + |
1429 | + /* self._update_cache() */ |
1430 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
1431 | + Py_DECREF(tmp); |
1432 | + } |
1433 | + |
1434 | + return 0; |
1435 | + |
1436 | +error: |
1437 | + Py_XDECREF(module); |
1438 | + Py_XDECREF(WeakKeyDictionary); |
1439 | + return -1; |
1440 | +} |
1441 | + |
1442 | +static int |
1443 | +Compile_traverse(CompileObject *self, visitproc visit, void *arg) |
1444 | +{ |
1445 | + Py_VISIT(self->_local_dispatch_table); |
1446 | + Py_VISIT(self->_local_precedence); |
1447 | + Py_VISIT(self->_local_reserved_words); |
1448 | + Py_VISIT(self->_dispatch_table); |
1449 | + Py_VISIT(self->_precedence); |
1450 | + Py_VISIT(self->_reserved_words); |
1451 | + Py_VISIT(self->_children); |
1452 | + Py_VISIT(self->_parents); |
1453 | + return 0; |
1454 | +} |
1455 | + |
1456 | +static int |
1457 | +Compile_clear(CompileObject *self) |
1458 | +{ |
1459 | + if (self->__weakreflist) |
1460 | + PyObject_ClearWeakRefs((PyObject *)self); |
1461 | + Py_CLEAR(self->_local_dispatch_table); |
1462 | + Py_CLEAR(self->_local_precedence); |
1463 | + Py_CLEAR(self->_local_reserved_words); |
1464 | + Py_CLEAR(self->_dispatch_table); |
1465 | + Py_CLEAR(self->_precedence); |
1466 | + Py_CLEAR(self->_reserved_words); |
1467 | + Py_CLEAR(self->_children); |
1468 | + Py_CLEAR(self->_parents); |
1469 | + return 0; |
1470 | +} |
1471 | + |
1472 | +static void |
1473 | +Compile_dealloc(CompileObject *self) |
1474 | +{ |
1475 | + Compile_clear(self); |
1476 | + self->ob_type->tp_free((PyObject *)self); |
1477 | +} |
1478 | + |
1479 | +static PyObject * |
1480 | +Compile__update_cache(CompileObject *self, PyObject *args) |
1481 | +{ |
1482 | + PyObject *iter = NULL; |
1483 | + PyObject *child = NULL; |
1484 | + Py_ssize_t size; |
1485 | + int i; |
1486 | + |
1487 | + /* for parent in self._parents: */ |
1488 | + size = PyList_GET_SIZE(self->_parents); |
1489 | + for (i = 0; i != size; i++) { |
1490 | + CompileObject *parent = \ |
1491 | + (CompileObject *)PyList_GET_ITEM(self->_parents, i); |
1492 | + /* self._dispatch_table.update(parent._local_dispatch_table) */ |
1493 | + CATCH(-1, PyDict_Update(self->_dispatch_table, |
1494 | + parent->_local_dispatch_table)); |
1495 | + /* self._precedence.update(parent._local_precedence) */ |
1496 | + CATCH(-1, PyDict_Update(self->_precedence, |
1497 | + parent->_local_precedence)); |
1498 | + /* self._reserved_words.update(parent._local_reserved_words) */ |
1499 | + CATCH(-1, PyDict_Update(self->_reserved_words, |
1500 | + parent->_local_reserved_words)); |
1501 | + } |
1502 | + /* self._dispatch_table.update(self._local_dispatch_table) */ |
1503 | + CATCH(-1, PyDict_Update(self->_dispatch_table, |
1504 | + self->_local_dispatch_table)); |
1505 | + /* self._precedence.update(self._local_precedence) */ |
1506 | + CATCH(-1, PyDict_Update(self->_precedence, self->_local_precedence)); |
1507 | + /* self._reserved_words.update(self._local_reserved_words) */ |
1508 | + CATCH(-1, PyDict_Update(self->_reserved_words, |
1509 | + self->_local_reserved_words)); |
1510 | + |
1511 | + /* for child in self._children: */ |
1512 | + CATCH(NULL, iter = PyObject_GetIter(self->_children)); |
1513 | + while((child = PyIter_Next(iter))) { |
1514 | + PyObject *tmp; |
1515 | + |
1516 | + /* child._update_cache() */ |
1517 | + CATCH(NULL, tmp = Compile__update_cache((CompileObject *)child, NULL)); |
1518 | + Py_DECREF(tmp); |
1519 | + Py_DECREF(child); |
1520 | + } |
1521 | + if (PyErr_Occurred()) |
1522 | + goto error; |
1523 | + Py_CLEAR(iter); |
1524 | + |
1525 | + Py_RETURN_NONE; |
1526 | + |
1527 | +error: |
1528 | + Py_XDECREF(child); |
1529 | + Py_XDECREF(iter); |
1530 | + return NULL; |
1531 | +} |
1532 | + |
1533 | +static PyObject * |
1534 | +Compile_when(CompileObject *self, PyObject *types) |
1535 | +{ |
1536 | + PyObject *result = NULL; |
1537 | + PyObject *module = PyImport_ImportModule("storm.expr"); |
1538 | + if (module) { |
1539 | + PyObject *_when = PyObject_GetAttrString(module, "_when"); |
1540 | + if (_when) { |
1541 | + result = PyObject_CallFunctionObjArgs(_when, self, types, NULL); |
1542 | + Py_DECREF(_when); |
1543 | + } |
1544 | + Py_DECREF(module); |
1545 | + } |
1546 | + return result; |
1547 | +} |
1548 | + |
1549 | +static PyObject * |
1550 | +Compile_add_reserved_words(CompileObject *self, PyObject *words) |
1551 | +{ |
1552 | + PyObject *lower_word = NULL; |
1553 | + PyObject *iter = NULL; |
1554 | + PyObject *word = NULL; |
1555 | + PyObject *tmp; |
1556 | + |
1557 | + /* self._local_reserved_words.update((word.lower(), True) |
1558 | + for word in words) */ |
1559 | + CATCH(NULL, iter = PyObject_GetIter(words)); |
1560 | + while ((word = PyIter_Next(iter))) { |
1561 | + CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
1562 | + CATCH(-1, PyDict_SetItem(self->_local_reserved_words, |
1563 | + lower_word, Py_True)); |
1564 | + Py_CLEAR(lower_word); |
1565 | + Py_DECREF(word); |
1566 | + } |
1567 | + if (PyErr_Occurred()) |
1568 | + goto error; |
1569 | + Py_CLEAR(iter); |
1570 | + |
1571 | + /* self._update_cache() */ |
1572 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
1573 | + Py_DECREF(tmp); |
1574 | + |
1575 | + Py_RETURN_NONE; |
1576 | + |
1577 | +error: |
1578 | + Py_XDECREF(lower_word); |
1579 | + Py_XDECREF(word); |
1580 | + Py_XDECREF(iter); |
1581 | + return NULL; |
1582 | +} |
1583 | + |
1584 | +static PyObject * |
1585 | +Compile_remove_reserved_words(CompileObject *self, PyObject *words) |
1586 | +{ |
1587 | + PyObject *lower_word = NULL; |
1588 | + PyObject *word = NULL; |
1589 | + PyObject *iter = NULL; |
1590 | + PyObject *tmp; |
1591 | + |
1592 | + /* self._local_reserved_words.update((word.lower(), None) |
1593 | + for word in words) */ |
1594 | + CATCH(NULL, iter = PyObject_GetIter(words)); |
1595 | + while ((word = PyIter_Next(iter))) { |
1596 | + CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
1597 | + CATCH(-1, PyDict_SetItem(self->_local_reserved_words, |
1598 | + lower_word, Py_None)); |
1599 | + Py_CLEAR(lower_word); |
1600 | + Py_DECREF(word); |
1601 | + } |
1602 | + if (PyErr_Occurred()) |
1603 | + goto error; |
1604 | + Py_CLEAR(iter); |
1605 | + |
1606 | + /* self._update_cache() */ |
1607 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
1608 | + Py_DECREF(tmp); |
1609 | + |
1610 | + Py_RETURN_NONE; |
1611 | + |
1612 | +error: |
1613 | + Py_XDECREF(lower_word); |
1614 | + Py_XDECREF(word); |
1615 | + Py_XDECREF(iter); |
1616 | + return NULL; |
1617 | +} |
1618 | + |
1619 | +static PyObject * |
1620 | +Compile_is_reserved_word(CompileObject *self, PyObject *word) |
1621 | +{ |
1622 | + PyObject *lower_word = NULL; |
1623 | + PyObject *result = Py_False; |
1624 | + PyObject *item; |
1625 | + |
1626 | + /* return self._reserved_words.get(word.lower()) is not None */ |
1627 | + CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
1628 | + item = PyDict_GetItem(self->_reserved_words, lower_word); |
1629 | + if (item == NULL && PyErr_Occurred()) { |
1630 | + goto error; |
1631 | + } else if (item != NULL && item != Py_None) { |
1632 | + result = Py_True; |
1633 | + } |
1634 | + Py_DECREF(lower_word); |
1635 | + Py_INCREF(result); |
1636 | + return result; |
1637 | + |
1638 | +error: |
1639 | + Py_XDECREF(lower_word); |
1640 | + return NULL; |
1641 | +} |
1642 | + |
1643 | +staticforward PyTypeObject Compile_Type; |
1644 | + |
1645 | +static PyObject * |
1646 | +Compile_create_child(CompileObject *self, PyObject *args) |
1647 | +{ |
1648 | + /* return self.__class__(self) */ |
1649 | + return PyObject_CallFunctionObjArgs((PyObject *)self->ob_type, self, NULL); |
1650 | +} |
1651 | + |
1652 | +static PyObject * |
1653 | +Compile_get_precedence(CompileObject *self, PyObject *type) |
1654 | +{ |
1655 | + /* return self._precedence.get(type, MAX_PRECEDENCE) */ |
1656 | + PyObject *result = PyDict_GetItem(self->_precedence, type); |
1657 | + if (result == NULL && !PyErr_Occurred()) { |
1658 | + /* That should be MAX_PRECEDENCE, defined in expr.py */ |
1659 | + return PyInt_FromLong(1000); |
1660 | + } |
1661 | + Py_INCREF(result); |
1662 | + return result; |
1663 | +} |
1664 | + |
1665 | +static PyObject * |
1666 | +Compile_set_precedence(CompileObject *self, PyObject *args) |
1667 | +{ |
1668 | + Py_ssize_t size = PyTuple_GET_SIZE(args); |
1669 | + PyObject *precedence = NULL; |
1670 | + PyObject *tmp; |
1671 | + int i; |
1672 | + |
1673 | + if (size < 2) { |
1674 | + PyErr_SetString(PyExc_TypeError, |
1675 | + "set_precedence() takes at least 2 arguments."); |
1676 | + return NULL; |
1677 | + } |
1678 | + |
1679 | + /* for type in types: */ |
1680 | + precedence = PyTuple_GET_ITEM(args, 0); |
1681 | + for (i = 1; i != size; i++) { |
1682 | + PyObject *type = PyTuple_GET_ITEM(args, i); |
1683 | + /* self._local_precedence[type] = precedence */ |
1684 | + CATCH(-1, PyDict_SetItem(self->_local_precedence, type, precedence)); |
1685 | + } |
1686 | + |
1687 | + /* self._update_cache() */ |
1688 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
1689 | + Py_DECREF(tmp); |
1690 | + |
1691 | + Py_RETURN_NONE; |
1692 | +error: |
1693 | + return NULL; |
1694 | +} |
1695 | + |
1696 | +PyObject * |
1697 | +Compile_single(CompileObject *self, |
1698 | + PyObject *expr, PyObject *state, PyObject *outer_precedence) |
1699 | +{ |
1700 | + PyObject *inner_precedence = NULL; |
1701 | + PyObject *statement = NULL; |
1702 | + |
1703 | + /* cls = expr.__class__ */ |
1704 | + PyObject *cls = (PyObject *)expr->ob_type; |
1705 | + |
1706 | + /* |
1707 | + dispatch_table = self._dispatch_table |
1708 | + if cls in dispatch_table: |
1709 | + handler = dispatch_table[cls] |
1710 | + else: |
1711 | + */ |
1712 | + PyObject *handler = PyDict_GetItem(self->_dispatch_table, cls); |
1713 | + if (!handler) { |
1714 | + PyObject *mro; |
1715 | + Py_ssize_t size, i; |
1716 | + |
1717 | + if (PyErr_Occurred()) |
1718 | + goto error; |
1719 | + |
1720 | + /* for mro_cls in cls.__mro__: */ |
1721 | + mro = expr->ob_type->tp_mro; |
1722 | + size = PyTuple_GET_SIZE(mro); |
1723 | + for (i = 0; i != size; i++) { |
1724 | + PyObject *mro_cls = PyTuple_GET_ITEM(mro, i); |
1725 | + /* |
1726 | + if mro_cls in dispatch_table: |
1727 | + handler = dispatch_table[mro_cls] |
1728 | + break |
1729 | + */ |
1730 | + handler = PyDict_GetItem(self->_dispatch_table, mro_cls); |
1731 | + if (handler) |
1732 | + break; |
1733 | + |
1734 | + if (PyErr_Occurred()) |
1735 | + goto error; |
1736 | + } |
1737 | + /* else: */ |
1738 | + if (i == size) { |
1739 | + /* |
1740 | + raise CompileError("Don't know how to compile type %r of %r" |
1741 | + % (expr.__class__, expr)) |
1742 | + */ |
1743 | + PyObject *repr = PyObject_Repr(expr); |
1744 | + if (repr) { |
1745 | + PyErr_Format(CompileError, |
1746 | + "Don't know how to compile type %s of %s", |
1747 | + expr->ob_type->tp_name, PyString_AS_STRING(repr)); |
1748 | + Py_DECREF(repr); |
1749 | + } |
1750 | + goto error; |
1751 | + } |
1752 | + } |
1753 | + |
1754 | + /* |
1755 | + inner_precedence = state.precedence = \ |
1756 | + self._precedence.get(cls, MAX_PRECEDENCE) |
1757 | + */ |
1758 | + CATCH(NULL, inner_precedence = Compile_get_precedence(self, cls)); |
1759 | + CATCH(-1, PyObject_SetAttrString(state, "precedence", inner_precedence)); |
1760 | + |
1761 | + /* statement = handler(self, expr, state) */ |
1762 | + CATCH(NULL, statement = PyObject_CallFunctionObjArgs(handler, self, expr, |
1763 | + state, NULL)); |
1764 | + |
1765 | + /* if inner_precedence < outer_precedence: */ |
1766 | + if (PyObject_Compare(inner_precedence, outer_precedence) == -1) { |
1767 | + PyObject *args, *tmp; |
1768 | + |
1769 | + if (PyErr_Occurred()) |
1770 | + goto error; |
1771 | + |
1772 | + /* return "(%s)" % statement */ |
1773 | + CATCH(NULL, args = PyTuple_Pack(1, statement)); |
1774 | + tmp = PyUnicode_Format(parenthesis_format, args); |
1775 | + Py_DECREF(args); |
1776 | + CATCH(NULL, tmp); |
1777 | + Py_DECREF(statement); |
1778 | + statement = tmp; |
1779 | + } |
1780 | + |
1781 | + Py_DECREF(inner_precedence); |
1782 | + |
1783 | + return statement; |
1784 | + |
1785 | +error: |
1786 | + Py_XDECREF(inner_precedence); |
1787 | + Py_XDECREF(statement); |
1788 | + |
1789 | + return NULL; |
1790 | +} |
1791 | + |
1792 | +PyObject * |
1793 | +Compile_one_or_many(CompileObject *self, PyObject *expr, PyObject *state, |
1794 | + PyObject *join, int raw, int token) |
1795 | +{ |
1796 | + PyObject *outer_precedence = NULL; |
1797 | + PyObject *compiled = NULL; |
1798 | + PyObject *sequence = NULL; |
1799 | + PyObject *statement = NULL; |
1800 | + Py_ssize_t size, i; |
1801 | + |
1802 | + Py_INCREF(expr); |
1803 | + |
1804 | + /* |
1805 | + expr_type = type(expr) |
1806 | + if (expr_type is SQLRaw or |
1807 | + raw and (expr_type is str or expr_type is unicode)): |
1808 | + return expr |
1809 | + */ |
1810 | + if ((PyObject *)expr->ob_type == SQLRaw || |
1811 | + (raw && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr)))) { |
1812 | + /* Pass our reference on. */ |
1813 | + return expr; |
1814 | + } |
1815 | + |
1816 | + /* |
1817 | + if token and (expr_type is str or expr_type is unicode): |
1818 | + expr = SQLToken(expr) |
1819 | + */ |
1820 | + if (token && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr))) { |
1821 | + PyObject *tmp; |
1822 | + CATCH(NULL, tmp = PyObject_CallFunctionObjArgs(SQLToken, expr, NULL)); |
1823 | + Py_DECREF(expr); |
1824 | + expr = tmp; |
1825 | + } |
1826 | + |
1827 | + /* |
1828 | + if state is None: |
1829 | + state = State() |
1830 | + */ |
1831 | + /* That's done in Compile__call__ just once. */ |
1832 | + |
1833 | + /* outer_precedence = state.precedence */ |
1834 | + CATCH(NULL, outer_precedence = PyObject_GetAttrString(state, "precedence")); |
1835 | + /* if expr_type is tuple or expr_type is list: */ |
1836 | + if (PyTuple_CheckExact(expr) || PyList_CheckExact(expr)) { |
1837 | + /* compiled = [] */ |
1838 | + CATCH(NULL, compiled = PyList_New(0)); |
1839 | + |
1840 | + /* for subexpr in expr: */ |
1841 | + sequence = PySequence_Fast(expr, "This can't actually fail! ;-)"); |
1842 | + size = PySequence_Fast_GET_SIZE(sequence); |
1843 | + for (i = 0; i != size; i++) { |
1844 | + PyObject *subexpr = PySequence_Fast_GET_ITEM(sequence, i); |
1845 | + /* |
1846 | + subexpr_type = type(subexpr) |
1847 | + if subexpr_type is SQLRaw or raw and (subexpr_type is str or |
1848 | + subexpr_type is unicode): |
1849 | + */ |
1850 | + if ((PyObject *)subexpr->ob_type == (PyObject *)SQLRaw || |
1851 | + (raw && (PyString_CheckExact(subexpr) || |
1852 | + PyUnicode_CheckExact(subexpr)))) { |
1853 | + /* statement = subexpr */ |
1854 | + Py_INCREF(subexpr); |
1855 | + statement = subexpr; |
1856 | + /* elif subexpr_type is tuple or subexpr_type is list: */ |
1857 | + } else if (PyTuple_CheckExact(subexpr) || |
1858 | + PyList_CheckExact(subexpr)) { |
1859 | + /* state.precedence = outer_precedence */ |
1860 | + CATCH(-1, PyObject_SetAttrString(state, "precedence", |
1861 | + outer_precedence)); |
1862 | + /* statement = self(subexpr, state, join, raw, token) */ |
1863 | + CATCH(NULL, |
1864 | + statement = Compile_one_or_many(self, subexpr, state, |
1865 | + join, raw, token)); |
1866 | + /* else: */ |
1867 | + } else { |
1868 | + /* |
1869 | + if token and (subexpr_type is unicode or |
1870 | + subexpr_type is str): |
1871 | + */ |
1872 | + if (token && (PyUnicode_CheckExact(subexpr) || |
1873 | + PyString_CheckExact(subexpr))) { |
1874 | + /* subexpr = SQLToken(subexpr) */ |
1875 | + CATCH(NULL, |
1876 | + subexpr = PyObject_CallFunctionObjArgs(SQLToken, |
1877 | + subexpr, |
1878 | + NULL)); |
1879 | + } else { |
1880 | + Py_INCREF(subexpr); |
1881 | + } |
1882 | + |
1883 | + /* |
1884 | + statement = self._compile_single(subexpr, state, |
1885 | + outer_precedence) |
1886 | + */ |
1887 | + statement = Compile_single(self, subexpr, state, |
1888 | + outer_precedence); |
1889 | + Py_DECREF(subexpr); |
1890 | + CATCH(NULL, statement); |
1891 | + } |
1892 | + |
1893 | + /* compiled.append(statement) */ |
1894 | + CATCH(-1, PyList_Append(compiled, statement)); |
1895 | + Py_CLEAR(statement); |
1896 | + } |
1897 | + Py_CLEAR(sequence); |
1898 | + |
1899 | + /* statement = join.join(compiled) */ |
1900 | + CATCH(NULL, statement = PyUnicode_Join(join, compiled)); |
1901 | + Py_CLEAR(compiled); |
1902 | + } else { |
1903 | + /* statement = self._compile_single(expr, state, outer_precedence) */ |
1904 | + CATCH(NULL, statement = Compile_single(self, expr, state, |
1905 | + outer_precedence)); |
1906 | + } |
1907 | + |
1908 | + /* state.precedence = outer_precedence */ |
1909 | + CATCH(-1, PyObject_SetAttrString(state, "precedence", outer_precedence)); |
1910 | + Py_CLEAR(outer_precedence); |
1911 | + |
1912 | + Py_DECREF(expr); |
1913 | + |
1914 | + return statement; |
1915 | + |
1916 | +error: |
1917 | + Py_XDECREF(expr); |
1918 | + Py_XDECREF(outer_precedence); |
1919 | + Py_XDECREF(compiled); |
1920 | + Py_XDECREF(sequence); |
1921 | + Py_XDECREF(statement); |
1922 | + |
1923 | + return NULL; |
1924 | +} |
1925 | + |
1926 | +static PyObject * |
1927 | +Compile__call__(CompileObject *self, PyObject *args, PyObject *kwargs) |
1928 | +{ |
1929 | + static char *kwlist[] = {"expr", "state", "join", "raw", "token", NULL}; |
1930 | + PyObject *expr = NULL; |
1931 | + PyObject *state = Py_None; |
1932 | + PyObject *join; |
1933 | + char raw = 0; |
1934 | + char token = 0; |
1935 | + |
1936 | + PyObject *result = NULL; |
1937 | + |
1938 | + if (!initialize_globals()) |
1939 | + return NULL; |
1940 | + |
1941 | + join = default_compile_join; |
1942 | + |
1943 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OSbb", kwlist, |
1944 | + &expr, &state, &join, &raw, &token)) { |
1945 | + return NULL; |
1946 | + } |
1947 | + |
1948 | + if (state == Py_None) { |
1949 | + state = PyObject_CallFunctionObjArgs(State, NULL); |
1950 | + } else { |
1951 | + Py_INCREF(state); |
1952 | + } |
1953 | + if (state) { |
1954 | + result = Compile_one_or_many(self, expr, state, join, raw, token); |
1955 | + Py_DECREF(state); |
1956 | + } |
1957 | + return result; |
1958 | +} |
1959 | + |
1960 | + |
1961 | +static PyMethodDef Compile_methods[] = { |
1962 | + {"_update_cache", (PyCFunction)Compile__update_cache, METH_NOARGS, NULL}, |
1963 | + {"when", (PyCFunction)Compile_when, METH_VARARGS, NULL}, |
1964 | + {"add_reserved_words", (PyCFunction)Compile_add_reserved_words, |
1965 | + METH_O, NULL}, |
1966 | + {"remove_reserved_words", (PyCFunction)Compile_remove_reserved_words, |
1967 | + METH_O, NULL}, |
1968 | + {"is_reserved_word", (PyCFunction)Compile_is_reserved_word, METH_O, NULL}, |
1969 | + {"create_child", (PyCFunction)Compile_create_child, METH_NOARGS, NULL}, |
1970 | + {"get_precedence", (PyCFunction)Compile_get_precedence, METH_O, NULL}, |
1971 | + {"set_precedence", (PyCFunction)Compile_set_precedence, METH_VARARGS, NULL}, |
1972 | + {NULL, NULL} |
1973 | +}; |
1974 | + |
1975 | +#define OFFSETOF(x) offsetof(CompileObject, x) |
1976 | +static PyMemberDef Compile_members[] = { |
1977 | + {"_local_dispatch_table", T_OBJECT, OFFSETOF(_local_dispatch_table), 0, 0}, |
1978 | + {"_local_precedence", T_OBJECT, OFFSETOF(_local_precedence), 0, 0}, |
1979 | + {"_local_reserved_words", T_OBJECT, OFFSETOF(_local_reserved_words), 0, 0}, |
1980 | + {"_dispatch_table", T_OBJECT, OFFSETOF(_dispatch_table), 0, 0}, |
1981 | + {"_precedence", T_OBJECT, OFFSETOF(_precedence), 0, 0}, |
1982 | + {"_reserved_words", T_OBJECT, OFFSETOF(_reserved_words), 0, 0}, |
1983 | + {"_children", T_OBJECT, OFFSETOF(_children), 0, 0}, |
1984 | + {"_parents", T_OBJECT, OFFSETOF(_parents), 0, 0}, |
1985 | + {NULL} |
1986 | +}; |
1987 | +#undef OFFSETOF |
1988 | + |
1989 | +statichere PyTypeObject Compile_Type = { |
1990 | + PyObject_HEAD_INIT(NULL) |
1991 | + 0, /*ob_size*/ |
1992 | + "storm.variables.Compile", /*tp_name*/ |
1993 | + sizeof(CompileObject), /*tp_basicsize*/ |
1994 | + 0, /*tp_itemsize*/ |
1995 | + (destructor)Compile_dealloc, /*tp_dealloc*/ |
1996 | + 0, /*tp_print*/ |
1997 | + 0, /*tp_getattr*/ |
1998 | + 0, /*tp_setattr*/ |
1999 | + 0, /*tp_compare*/ |
2000 | + 0, /*tp_repr*/ |
2001 | + 0, /*tp_as_number*/ |
2002 | + 0, /*tp_as_sequence*/ |
2003 | + 0, /*tp_as_mapping*/ |
2004 | + 0, /*tp_hash*/ |
2005 | + (ternaryfunc)Compile__call__, /*tp_call*/ |
2006 | + 0, /*tp_str*/ |
2007 | + PyObject_GenericGetAttr,/*tp_getattro*/ |
2008 | + PyObject_GenericSetAttr,/*tp_setattro*/ |
2009 | + 0, /*tp_as_buffer*/ |
2010 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ |
2011 | + 0, /*tp_doc*/ |
2012 | + (traverseproc)Compile_traverse, /*tp_traverse*/ |
2013 | + (inquiry)Compile_clear, /*tp_clear*/ |
2014 | + 0, /*tp_richcompare*/ |
2015 | + offsetof(CompileObject, __weakreflist), /*tp_weaklistoffset*/ |
2016 | + 0, /*tp_iter*/ |
2017 | + 0, /*tp_iternext*/ |
2018 | + Compile_methods, /*tp_methods*/ |
2019 | + Compile_members, /*tp_members*/ |
2020 | + 0, /*tp_getset*/ |
2021 | + 0, /*tp_base*/ |
2022 | + 0, /*tp_dict*/ |
2023 | + 0, /*tp_descr_get*/ |
2024 | + 0, /*tp_descr_set*/ |
2025 | + 0, /*tp_dictoffset*/ |
2026 | + (initproc)Compile_init, /*tp_init*/ |
2027 | + PyType_GenericAlloc, /*tp_alloc*/ |
2028 | + PyType_GenericNew, /*tp_new*/ |
2029 | + PyObject_GC_Del, /*tp_free*/ |
2030 | + 0, /*tp_is_gc*/ |
2031 | +}; |
2032 | + |
2033 | + |
2034 | +static PyObject * |
2035 | +======= |
2036 | +Compile__update_cache(CompileObject *self, PyObject *args); |
2037 | + |
2038 | +static int |
2039 | +Compile_init(CompileObject *self, PyObject *args, PyObject *kwargs) |
2040 | +{ |
2041 | + static char *kwlist[] = {"parent", NULL}; |
2042 | + |
2043 | + PyObject *parent = Py_None; |
2044 | + |
2045 | + PyObject *module = NULL; |
2046 | + PyObject *WeakKeyDictionary = NULL; |
2047 | + |
2048 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &parent)) |
2049 | + return -1; |
2050 | + |
2051 | + /* |
2052 | + self._local_dispatch_table = {} |
2053 | + self._local_precedence = {} |
2054 | + self._local_reserved_words = {} |
2055 | + self._dispatch_table = {} |
2056 | + self._precedence = {} |
2057 | + self._reserved_words = {} |
2058 | + */ |
2059 | + CATCH(NULL, self->_local_dispatch_table = PyDict_New()); |
2060 | + CATCH(NULL, self->_local_precedence = PyDict_New()); |
2061 | + CATCH(NULL, self->_local_reserved_words = PyDict_New()); |
2062 | + CATCH(NULL, self->_dispatch_table = PyDict_New()); |
2063 | + CATCH(NULL, self->_precedence = PyDict_New()); |
2064 | + CATCH(NULL, self->_reserved_words = PyDict_New()); |
2065 | + |
2066 | + /* self._children = WeakKeyDictionary() */ |
2067 | + CATCH(NULL, module = PyImport_ImportModule("weakref")); |
2068 | + CATCH(NULL, WeakKeyDictionary = \ |
2069 | + PyObject_GetAttrString(module, "WeakKeyDictionary")); |
2070 | + Py_CLEAR(module); |
2071 | + CATCH(NULL, self->_children = \ |
2072 | + PyObject_CallFunctionObjArgs(WeakKeyDictionary, NULL)); |
2073 | + Py_CLEAR(WeakKeyDictionary); |
2074 | + |
2075 | + /* self._parents = [] */ |
2076 | + CATCH(NULL, self->_parents = PyList_New(0)); |
2077 | + |
2078 | + /* if parent: */ |
2079 | + if (parent != Py_None) { |
2080 | + PyObject *tmp; |
2081 | + |
2082 | + /* self._parents.extend(parent._parents) */ |
2083 | + CompileObject *parent_object = (CompileObject *)parent; |
2084 | + CATCH(-1, PyList_SetSlice(self->_parents, 0, 0, |
2085 | + parent_object->_parents)); |
2086 | + |
2087 | + /* self._parents.append(parent) */ |
2088 | + CATCH(-1, PyList_Append(self->_parents, parent)); |
2089 | + |
2090 | + /* parent._children[self] = True */ |
2091 | + CATCH(-1, PyObject_SetItem(parent_object->_children, |
2092 | + (PyObject *)self, Py_True)); |
2093 | + |
2094 | + /* self._update_cache() */ |
2095 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
2096 | + Py_DECREF(tmp); |
2097 | + } |
2098 | + |
2099 | + return 0; |
2100 | + |
2101 | +error: |
2102 | + Py_XDECREF(module); |
2103 | + Py_XDECREF(WeakKeyDictionary); |
2104 | + return -1; |
2105 | +} |
2106 | + |
2107 | +static int |
2108 | +Compile_traverse(CompileObject *self, visitproc visit, void *arg) |
2109 | +{ |
2110 | + Py_VISIT(self->_local_dispatch_table); |
2111 | + Py_VISIT(self->_local_precedence); |
2112 | + Py_VISIT(self->_local_reserved_words); |
2113 | + Py_VISIT(self->_dispatch_table); |
2114 | + Py_VISIT(self->_precedence); |
2115 | + Py_VISIT(self->_reserved_words); |
2116 | + Py_VISIT(self->_children); |
2117 | + Py_VISIT(self->_parents); |
2118 | + return 0; |
2119 | +} |
2120 | + |
2121 | +static int |
2122 | +Compile_clear(CompileObject *self) |
2123 | +{ |
2124 | + if (self->__weakreflist) |
2125 | + PyObject_ClearWeakRefs((PyObject *)self); |
2126 | + Py_CLEAR(self->_local_dispatch_table); |
2127 | + Py_CLEAR(self->_local_precedence); |
2128 | + Py_CLEAR(self->_local_reserved_words); |
2129 | + Py_CLEAR(self->_dispatch_table); |
2130 | + Py_CLEAR(self->_precedence); |
2131 | + Py_CLEAR(self->_reserved_words); |
2132 | + Py_CLEAR(self->_children); |
2133 | + Py_CLEAR(self->_parents); |
2134 | + return 0; |
2135 | +} |
2136 | + |
2137 | +static void |
2138 | +Compile_dealloc(CompileObject *self) |
2139 | +{ |
2140 | + Compile_clear(self); |
2141 | + self->ob_type->tp_free((PyObject *)self); |
2142 | +} |
2143 | + |
2144 | +static PyObject * |
2145 | +Compile__update_cache(CompileObject *self, PyObject *args) |
2146 | +{ |
2147 | + PyObject *iter = NULL; |
2148 | + PyObject *child = NULL; |
2149 | + Py_ssize_t size; |
2150 | + int i; |
2151 | + |
2152 | + /* for parent in self._parents: */ |
2153 | + size = PyList_GET_SIZE(self->_parents); |
2154 | + for (i = 0; i != size; i++) { |
2155 | + CompileObject *parent = \ |
2156 | + (CompileObject *)PyList_GET_ITEM(self->_parents, i); |
2157 | + /* self._dispatch_table.update(parent._local_dispatch_table) */ |
2158 | + CATCH(-1, PyDict_Update(self->_dispatch_table, |
2159 | + parent->_local_dispatch_table)); |
2160 | + /* self._precedence.update(parent._local_precedence) */ |
2161 | + CATCH(-1, PyDict_Update(self->_precedence, |
2162 | + parent->_local_precedence)); |
2163 | + /* self._reserved_words.update(parent._local_reserved_words) */ |
2164 | + CATCH(-1, PyDict_Update(self->_reserved_words, |
2165 | + parent->_local_reserved_words)); |
2166 | + } |
2167 | + /* self._dispatch_table.update(self._local_dispatch_table) */ |
2168 | + CATCH(-1, PyDict_Update(self->_dispatch_table, |
2169 | + self->_local_dispatch_table)); |
2170 | + /* self._precedence.update(self._local_precedence) */ |
2171 | + CATCH(-1, PyDict_Update(self->_precedence, self->_local_precedence)); |
2172 | + /* self._reserved_words.update(self._local_reserved_words) */ |
2173 | + CATCH(-1, PyDict_Update(self->_reserved_words, |
2174 | + self->_local_reserved_words)); |
2175 | + |
2176 | + /* for child in self._children: */ |
2177 | + CATCH(NULL, iter = PyObject_GetIter(self->_children)); |
2178 | + while((child = PyIter_Next(iter))) { |
2179 | + PyObject *tmp; |
2180 | + |
2181 | + /* child._update_cache() */ |
2182 | + CATCH(NULL, tmp = Compile__update_cache((CompileObject *)child, NULL)); |
2183 | + Py_DECREF(tmp); |
2184 | + Py_DECREF(child); |
2185 | + } |
2186 | + if (PyErr_Occurred()) |
2187 | + goto error; |
2188 | + Py_CLEAR(iter); |
2189 | + |
2190 | + Py_RETURN_NONE; |
2191 | + |
2192 | +error: |
2193 | + Py_XDECREF(child); |
2194 | + Py_XDECREF(iter); |
2195 | + return NULL; |
2196 | +} |
2197 | + |
2198 | +static PyObject * |
2199 | +Compile_when(CompileObject *self, PyObject *types) |
2200 | +{ |
2201 | + PyObject *result = NULL; |
2202 | + PyObject *module = PyImport_ImportModule("storm.expr"); |
2203 | + if (module) { |
2204 | + PyObject *_when = PyObject_GetAttrString(module, "_when"); |
2205 | + if (_when) { |
2206 | + result = PyObject_CallFunctionObjArgs(_when, self, types, NULL); |
2207 | + Py_DECREF(_when); |
2208 | + } |
2209 | + Py_DECREF(module); |
2210 | + } |
2211 | + return result; |
2212 | +} |
2213 | + |
2214 | +static PyObject * |
2215 | +Compile_add_reserved_words(CompileObject *self, PyObject *words) |
2216 | +{ |
2217 | + PyObject *lower_word = NULL; |
2218 | + PyObject *iter = NULL; |
2219 | + PyObject *word = NULL; |
2220 | + PyObject *tmp; |
2221 | + |
2222 | + /* self._local_reserved_words.update((word.lower(), True) |
2223 | + for word in words) */ |
2224 | + CATCH(NULL, iter = PyObject_GetIter(words)); |
2225 | + while ((word = PyIter_Next(iter))) { |
2226 | + CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
2227 | + CATCH(-1, PyDict_SetItem(self->_local_reserved_words, |
2228 | + lower_word, Py_True)); |
2229 | + Py_CLEAR(lower_word); |
2230 | + Py_DECREF(word); |
2231 | + } |
2232 | + if (PyErr_Occurred()) |
2233 | + goto error; |
2234 | + Py_CLEAR(iter); |
2235 | + |
2236 | + /* self._update_cache() */ |
2237 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
2238 | + Py_DECREF(tmp); |
2239 | + |
2240 | + Py_RETURN_NONE; |
2241 | + |
2242 | +error: |
2243 | + Py_XDECREF(lower_word); |
2244 | + Py_XDECREF(word); |
2245 | + Py_XDECREF(iter); |
2246 | + return NULL; |
2247 | +} |
2248 | + |
2249 | +static PyObject * |
2250 | +Compile_remove_reserved_words(CompileObject *self, PyObject *words) |
2251 | +{ |
2252 | + PyObject *lower_word = NULL; |
2253 | + PyObject *word = NULL; |
2254 | + PyObject *iter = NULL; |
2255 | + PyObject *tmp; |
2256 | + |
2257 | + /* self._local_reserved_words.update((word.lower(), None) |
2258 | + for word in words) */ |
2259 | + CATCH(NULL, iter = PyObject_GetIter(words)); |
2260 | + while ((word = PyIter_Next(iter))) { |
2261 | + CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
2262 | + CATCH(-1, PyDict_SetItem(self->_local_reserved_words, |
2263 | + lower_word, Py_None)); |
2264 | + Py_CLEAR(lower_word); |
2265 | + Py_DECREF(word); |
2266 | + } |
2267 | + if (PyErr_Occurred()) |
2268 | + goto error; |
2269 | + Py_CLEAR(iter); |
2270 | + |
2271 | + /* self._update_cache() */ |
2272 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
2273 | + Py_DECREF(tmp); |
2274 | + |
2275 | + Py_RETURN_NONE; |
2276 | + |
2277 | +error: |
2278 | + Py_XDECREF(lower_word); |
2279 | + Py_XDECREF(word); |
2280 | + Py_XDECREF(iter); |
2281 | + return NULL; |
2282 | +} |
2283 | + |
2284 | +static PyObject * |
2285 | +Compile_is_reserved_word(CompileObject *self, PyObject *word) |
2286 | +{ |
2287 | + PyObject *lower_word = NULL; |
2288 | + PyObject *result = Py_False; |
2289 | + PyObject *item; |
2290 | + |
2291 | + /* return self._reserved_words.get(word.lower()) is not None */ |
2292 | + CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL)); |
2293 | + item = PyDict_GetItem(self->_reserved_words, lower_word); |
2294 | + if (item == NULL && PyErr_Occurred()) { |
2295 | + goto error; |
2296 | + } else if (item != NULL && item != Py_None) { |
2297 | + result = Py_True; |
2298 | + } |
2299 | + Py_DECREF(lower_word); |
2300 | + Py_INCREF(result); |
2301 | + return result; |
2302 | + |
2303 | +error: |
2304 | + Py_XDECREF(lower_word); |
2305 | + return NULL; |
2306 | +} |
2307 | + |
2308 | +staticforward PyTypeObject Compile_Type; |
2309 | + |
2310 | +static PyObject * |
2311 | +Compile_create_child(CompileObject *self, PyObject *args) |
2312 | +{ |
2313 | + /* return self.__class__(self) */ |
2314 | + return PyObject_CallFunctionObjArgs((PyObject *)self->ob_type, self, NULL); |
2315 | +} |
2316 | + |
2317 | +static PyObject * |
2318 | +Compile_get_precedence(CompileObject *self, PyObject *type) |
2319 | +{ |
2320 | + /* return self._precedence.get(type, MAX_PRECEDENCE) */ |
2321 | + PyObject *result = PyDict_GetItem(self->_precedence, type); |
2322 | + if (result == NULL && !PyErr_Occurred()) { |
2323 | + /* That should be MAX_PRECEDENCE, defined in expr.py */ |
2324 | + return PyInt_FromLong(1000); |
2325 | + } |
2326 | + Py_INCREF(result); |
2327 | + return result; |
2328 | +} |
2329 | + |
2330 | +static PyObject * |
2331 | +Compile_set_precedence(CompileObject *self, PyObject *args) |
2332 | +{ |
2333 | + Py_ssize_t size = PyTuple_GET_SIZE(args); |
2334 | + PyObject *precedence = NULL; |
2335 | + PyObject *tmp; |
2336 | + int i; |
2337 | + |
2338 | + if (size < 2) { |
2339 | + PyErr_SetString(PyExc_TypeError, |
2340 | + "set_precedence() takes at least 2 arguments."); |
2341 | + return NULL; |
2342 | + } |
2343 | + |
2344 | + /* for type in types: */ |
2345 | + precedence = PyTuple_GET_ITEM(args, 0); |
2346 | + for (i = 1; i != size; i++) { |
2347 | + PyObject *type = PyTuple_GET_ITEM(args, i); |
2348 | + /* self._local_precedence[type] = precedence */ |
2349 | + CATCH(-1, PyDict_SetItem(self->_local_precedence, type, precedence)); |
2350 | + } |
2351 | + |
2352 | + /* self._update_cache() */ |
2353 | + CATCH(NULL, tmp = Compile__update_cache(self, NULL)); |
2354 | + Py_DECREF(tmp); |
2355 | + |
2356 | + Py_RETURN_NONE; |
2357 | +error: |
2358 | + return NULL; |
2359 | +} |
2360 | + |
2361 | +PyObject * |
2362 | +Compile_single(CompileObject *self, |
2363 | + PyObject *expr, PyObject *state, PyObject *outer_precedence) |
2364 | +{ |
2365 | + PyObject *inner_precedence = NULL; |
2366 | + PyObject *statement = NULL; |
2367 | + |
2368 | + /* cls = expr.__class__ */ |
2369 | + PyObject *cls = (PyObject *)expr->ob_type; |
2370 | + |
2371 | + /* |
2372 | + dispatch_table = self._dispatch_table |
2373 | + if cls in dispatch_table: |
2374 | + handler = dispatch_table[cls] |
2375 | + else: |
2376 | + */ |
2377 | + PyObject *handler = PyDict_GetItem(self->_dispatch_table, cls); |
2378 | + if (!handler) { |
2379 | + PyObject *mro; |
2380 | + Py_ssize_t size, i; |
2381 | + |
2382 | + if (PyErr_Occurred()) |
2383 | + goto error; |
2384 | + |
2385 | + /* for mro_cls in cls.__mro__: */ |
2386 | + mro = expr->ob_type->tp_mro; |
2387 | + size = PyTuple_GET_SIZE(mro); |
2388 | + for (i = 0; i != size; i++) { |
2389 | + PyObject *mro_cls = PyTuple_GET_ITEM(mro, i); |
2390 | + /* |
2391 | + if mro_cls in dispatch_table: |
2392 | + handler = dispatch_table[mro_cls] |
2393 | + break |
2394 | + */ |
2395 | + handler = PyDict_GetItem(self->_dispatch_table, mro_cls); |
2396 | + if (handler) |
2397 | + break; |
2398 | + |
2399 | + if (PyErr_Occurred()) |
2400 | + goto error; |
2401 | + } |
2402 | + /* else: */ |
2403 | + if (i == size) { |
2404 | + /* |
2405 | + raise CompileError("Don't know how to compile type %r of %r" |
2406 | + % (expr.__class__, expr)) |
2407 | + */ |
2408 | + PyObject *repr = PyObject_Repr(expr); |
2409 | + if (repr) { |
2410 | + PyErr_Format(CompileError, |
2411 | + "Don't know how to compile type %s of %s", |
2412 | + expr->ob_type->tp_name, PyString_AS_STRING(repr)); |
2413 | + Py_DECREF(repr); |
2414 | + } |
2415 | + goto error; |
2416 | + } |
2417 | + } |
2418 | + |
2419 | + /* |
2420 | + inner_precedence = state.precedence = \ |
2421 | + self._precedence.get(cls, MAX_PRECEDENCE) |
2422 | + */ |
2423 | + CATCH(NULL, inner_precedence = Compile_get_precedence(self, cls)); |
2424 | + CATCH(-1, PyObject_SetAttrString(state, "precedence", inner_precedence)); |
2425 | + |
2426 | + /* statement = handler(self, expr, state) */ |
2427 | + CATCH(NULL, statement = PyObject_CallFunctionObjArgs(handler, self, expr, |
2428 | + state, NULL)); |
2429 | + |
2430 | + /* if inner_precedence < outer_precedence: */ |
2431 | + if (PyObject_Compare(inner_precedence, outer_precedence) == -1) { |
2432 | + PyObject *args, *tmp; |
2433 | + |
2434 | + if (PyErr_Occurred()) |
2435 | + goto error; |
2436 | + |
2437 | + /* return "(%s)" % statement */ |
2438 | + CATCH(NULL, args = PyTuple_Pack(1, statement)); |
2439 | + tmp = PyUnicode_Format(parenthesis_format, args); |
2440 | + Py_DECREF(args); |
2441 | + CATCH(NULL, tmp); |
2442 | + Py_DECREF(statement); |
2443 | + statement = tmp; |
2444 | + } |
2445 | + |
2446 | + Py_DECREF(inner_precedence); |
2447 | + |
2448 | + return statement; |
2449 | + |
2450 | +error: |
2451 | + Py_XDECREF(inner_precedence); |
2452 | + Py_XDECREF(statement); |
2453 | + |
2454 | + return NULL; |
2455 | +} |
2456 | + |
2457 | +PyObject * |
2458 | +Compile_one_or_many(CompileObject *self, PyObject *expr, PyObject *state, |
2459 | + PyObject *join, int raw, int token) |
2460 | +{ |
2461 | + PyObject *outer_precedence = NULL; |
2462 | + PyObject *compiled = NULL; |
2463 | + PyObject *sequence = NULL; |
2464 | + PyObject *statement = NULL; |
2465 | + Py_ssize_t size, i; |
2466 | + |
2467 | + Py_INCREF(expr); |
2468 | + |
2469 | + /* |
2470 | + expr_type = type(expr) |
2471 | + if (expr_type is SQLRaw or |
2472 | + raw and (expr_type is str or expr_type is unicode)): |
2473 | + return expr |
2474 | + */ |
2475 | + if ((PyObject *)expr->ob_type == SQLRaw || |
2476 | + (raw && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr)))) { |
2477 | + /* Pass our reference on. */ |
2478 | + return expr; |
2479 | + } |
2480 | + |
2481 | + /* |
2482 | + if token and (expr_type is str or expr_type is unicode): |
2483 | + expr = SQLToken(expr) |
2484 | + */ |
2485 | + if (token && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr))) { |
2486 | + PyObject *tmp; |
2487 | + CATCH(NULL, tmp = PyObject_CallFunctionObjArgs(SQLToken, expr, NULL)); |
2488 | + Py_DECREF(expr); |
2489 | + expr = tmp; |
2490 | + } |
2491 | + |
2492 | + /* |
2493 | + if state is None: |
2494 | + state = State() |
2495 | + */ |
2496 | + /* That's done in Compile__call__ just once. */ |
2497 | + |
2498 | + /* outer_precedence = state.precedence */ |
2499 | + CATCH(NULL, outer_precedence = PyObject_GetAttrString(state, "precedence")); |
2500 | + /* if expr_type is tuple or expr_type is list: */ |
2501 | + if (PyTuple_CheckExact(expr) || PyList_CheckExact(expr)) { |
2502 | + /* compiled = [] */ |
2503 | + CATCH(NULL, compiled = PyList_New(0)); |
2504 | + |
2505 | + /* for subexpr in expr: */ |
2506 | + sequence = PySequence_Fast(expr, "This can't actually fail! ;-)"); |
2507 | + size = PySequence_Fast_GET_SIZE(sequence); |
2508 | + for (i = 0; i != size; i++) { |
2509 | + PyObject *subexpr = PySequence_Fast_GET_ITEM(sequence, i); |
2510 | + /* |
2511 | + subexpr_type = type(subexpr) |
2512 | + if subexpr_type is SQLRaw or raw and (subexpr_type is str or |
2513 | + subexpr_type is unicode): |
2514 | + */ |
2515 | + if ((PyObject *)subexpr->ob_type == (PyObject *)SQLRaw || |
2516 | + (raw && (PyString_CheckExact(subexpr) || |
2517 | + PyUnicode_CheckExact(subexpr)))) { |
2518 | + /* statement = subexpr */ |
2519 | + Py_INCREF(subexpr); |
2520 | + statement = subexpr; |
2521 | + /* elif subexpr_type is tuple or subexpr_type is list: */ |
2522 | + } else if (PyTuple_CheckExact(subexpr) || |
2523 | + PyList_CheckExact(subexpr)) { |
2524 | + /* state.precedence = outer_precedence */ |
2525 | + CATCH(-1, PyObject_SetAttrString(state, "precedence", |
2526 | + outer_precedence)); |
2527 | + /* statement = self(subexpr, state, join, raw, token) */ |
2528 | + CATCH(NULL, |
2529 | + statement = Compile_one_or_many(self, subexpr, state, |
2530 | + join, raw, token)); |
2531 | + /* else: */ |
2532 | + } else { |
2533 | + /* |
2534 | + if token and (subexpr_type is unicode or |
2535 | + subexpr_type is str): |
2536 | + */ |
2537 | + if (token && (PyUnicode_CheckExact(subexpr) || |
2538 | + PyString_CheckExact(subexpr))) { |
2539 | + /* subexpr = SQLToken(subexpr) */ |
2540 | + CATCH(NULL, |
2541 | + subexpr = PyObject_CallFunctionObjArgs(SQLToken, |
2542 | + subexpr, |
2543 | + NULL)); |
2544 | + } else { |
2545 | + Py_INCREF(subexpr); |
2546 | + } |
2547 | + |
2548 | + /* |
2549 | + statement = self._compile_single(subexpr, state, |
2550 | + outer_precedence) |
2551 | + */ |
2552 | + statement = Compile_single(self, subexpr, state, |
2553 | + outer_precedence); |
2554 | + Py_DECREF(subexpr); |
2555 | + CATCH(NULL, statement); |
2556 | + } |
2557 | + |
2558 | + /* compiled.append(statement) */ |
2559 | + CATCH(-1, PyList_Append(compiled, statement)); |
2560 | + Py_CLEAR(statement); |
2561 | + } |
2562 | + Py_CLEAR(sequence); |
2563 | + |
2564 | + /* statement = join.join(compiled) */ |
2565 | + CATCH(NULL, statement = PyUnicode_Join(join, compiled)); |
2566 | + Py_CLEAR(compiled); |
2567 | + } else { |
2568 | + /* statement = self._compile_single(expr, state, outer_precedence) */ |
2569 | + CATCH(NULL, statement = Compile_single(self, expr, state, |
2570 | + outer_precedence)); |
2571 | + } |
2572 | + |
2573 | + /* state.precedence = outer_precedence */ |
2574 | + CATCH(-1, PyObject_SetAttrString(state, "precedence", outer_precedence)); |
2575 | + Py_CLEAR(outer_precedence); |
2576 | + |
2577 | + Py_DECREF(expr); |
2578 | + |
2579 | + return statement; |
2580 | + |
2581 | +error: |
2582 | + Py_XDECREF(expr); |
2583 | + Py_XDECREF(outer_precedence); |
2584 | + Py_XDECREF(compiled); |
2585 | + Py_XDECREF(sequence); |
2586 | + Py_XDECREF(statement); |
2587 | + |
2588 | + return NULL; |
2589 | +} |
2590 | + |
2591 | +static PyObject * |
2592 | +Compile__call__(CompileObject *self, PyObject *args, PyObject *kwargs) |
2593 | +{ |
2594 | + static char *kwlist[] = {"expr", "state", "join", "raw", "token", NULL}; |
2595 | + PyObject *expr = NULL; |
2596 | + PyObject *state = Py_None; |
2597 | + PyObject *join; |
2598 | + char raw = 0; |
2599 | + char token = 0; |
2600 | + |
2601 | + PyObject *result = NULL; |
2602 | + |
2603 | + if (!initialize_globals()) |
2604 | + return NULL; |
2605 | + |
2606 | + join = default_compile_join; |
2607 | + |
2608 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OSbb", kwlist, |
2609 | + &expr, &state, &join, &raw, &token)) { |
2610 | + return NULL; |
2611 | + } |
2612 | + |
2613 | + if (state == Py_None) { |
2614 | + state = PyObject_CallFunctionObjArgs(State, NULL); |
2615 | + } else { |
2616 | + Py_INCREF(state); |
2617 | + } |
2618 | + if (state) { |
2619 | + result = Compile_one_or_many(self, expr, state, join, raw, token); |
2620 | + Py_DECREF(state); |
2621 | + } |
2622 | + return result; |
2623 | +} |
2624 | + |
2625 | + |
2626 | +static PyMethodDef Compile_methods[] = { |
2627 | + {"_update_cache", (PyCFunction)Compile__update_cache, METH_NOARGS, NULL}, |
2628 | + {"when", (PyCFunction)Compile_when, METH_VARARGS, NULL}, |
2629 | + {"add_reserved_words", (PyCFunction)Compile_add_reserved_words, |
2630 | + METH_O, NULL}, |
2631 | + {"remove_reserved_words", (PyCFunction)Compile_remove_reserved_words, |
2632 | + METH_O, NULL}, |
2633 | + {"is_reserved_word", (PyCFunction)Compile_is_reserved_word, METH_O, NULL}, |
2634 | + {"create_child", (PyCFunction)Compile_create_child, METH_NOARGS, NULL}, |
2635 | + {"get_precedence", (PyCFunction)Compile_get_precedence, METH_O, NULL}, |
2636 | + {"set_precedence", (PyCFunction)Compile_set_precedence, METH_VARARGS, NULL}, |
2637 | + {NULL, NULL} |
2638 | +}; |
2639 | + |
2640 | +#define OFFSETOF(x) offsetof(CompileObject, x) |
2641 | +static PyMemberDef Compile_members[] = { |
2642 | + {"_local_dispatch_table", T_OBJECT, OFFSETOF(_local_dispatch_table), 0, 0}, |
2643 | + {"_local_precedence", T_OBJECT, OFFSETOF(_local_precedence), 0, 0}, |
2644 | + {"_local_reserved_words", T_OBJECT, OFFSETOF(_local_reserved_words), 0, 0}, |
2645 | + {"_dispatch_table", T_OBJECT, OFFSETOF(_dispatch_table), 0, 0}, |
2646 | + {"_precedence", T_OBJECT, OFFSETOF(_precedence), 0, 0}, |
2647 | + {"_reserved_words", T_OBJECT, OFFSETOF(_reserved_words), 0, 0}, |
2648 | + {"_children", T_OBJECT, OFFSETOF(_children), 0, 0}, |
2649 | + {"_parents", T_OBJECT, OFFSETOF(_parents), 0, 0}, |
2650 | + {NULL} |
2651 | +}; |
2652 | +#undef OFFSETOF |
2653 | + |
2654 | +statichere PyTypeObject Compile_Type = { |
2655 | + PyObject_HEAD_INIT(NULL) |
2656 | + 0, /*ob_size*/ |
2657 | + "storm.variables.Compile", /*tp_name*/ |
2658 | + sizeof(CompileObject), /*tp_basicsize*/ |
2659 | + 0, /*tp_itemsize*/ |
2660 | + (destructor)Compile_dealloc, /*tp_dealloc*/ |
2661 | + 0, /*tp_print*/ |
2662 | + 0, /*tp_getattr*/ |
2663 | + 0, /*tp_setattr*/ |
2664 | + 0, /*tp_compare*/ |
2665 | + 0, /*tp_repr*/ |
2666 | + 0, /*tp_as_number*/ |
2667 | + 0, /*tp_as_sequence*/ |
2668 | + 0, /*tp_as_mapping*/ |
2669 | + 0, /*tp_hash*/ |
2670 | + (ternaryfunc)Compile__call__, /*tp_call*/ |
2671 | + 0, /*tp_str*/ |
2672 | + PyObject_GenericGetAttr,/*tp_getattro*/ |
2673 | + PyObject_GenericSetAttr,/*tp_setattro*/ |
2674 | + 0, /*tp_as_buffer*/ |
2675 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ |
2676 | + 0, /*tp_doc*/ |
2677 | + (traverseproc)Compile_traverse, /*tp_traverse*/ |
2678 | + (inquiry)Compile_clear, /*tp_clear*/ |
2679 | + 0, /*tp_richcompare*/ |
2680 | + offsetof(CompileObject, __weakreflist), /*tp_weaklistoffset*/ |
2681 | + 0, /*tp_iter*/ |
2682 | + 0, /*tp_iternext*/ |
2683 | + Compile_methods, /*tp_methods*/ |
2684 | + Compile_members, /*tp_members*/ |
2685 | + 0, /*tp_getset*/ |
2686 | + 0, /*tp_base*/ |
2687 | + 0, /*tp_dict*/ |
2688 | + 0, /*tp_descr_get*/ |
2689 | + 0, /*tp_descr_set*/ |
2690 | + 0, /*tp_dictoffset*/ |
2691 | + (initproc)Compile_init, /*tp_init*/ |
2692 | + PyType_GenericAlloc, /*tp_alloc*/ |
2693 | + PyType_GenericNew, /*tp_new*/ |
2694 | + PyObject_GC_Del, /*tp_free*/ |
2695 | + 0, /*tp_is_gc*/ |
2696 | +}; |
2697 | + |
2698 | + |
2699 | +static PyObject * |
2700 | +>>>>>>> MERGE-SOURCE |
2701 | ObjectInfo__emit_object_deleted(ObjectInfoObject *self, PyObject *args) |
2702 | { |
2703 | /* self.event.emit("object-deleted") */ |
2704 | |
2705 | === modified file 'storm/database.py' |
2706 | === modified file 'storm/databases/postgres.py' |
2707 | --- storm/databases/postgres.py 2008-08-18 19:44:51 +0000 |
2708 | +++ storm/databases/postgres.py 2009-05-06 21:20:16 +0000 |
2709 | @@ -36,7 +36,7 @@ |
2710 | from storm.variables import Variable, ListVariable, RawStrVariable |
2711 | from storm.database import Database, Connection, Result |
2712 | from storm.exceptions import ( |
2713 | - install_exceptions, DatabaseError, DatabaseModuleError, |
2714 | + install_exceptions, DatabaseError, DatabaseModuleError, InterfaceError, |
2715 | OperationalError, ProgrammingError, TimeoutError) |
2716 | from storm.tracer import TimeoutTracer |
2717 | |
2718 | @@ -285,18 +285,28 @@ |
2719 | yield param |
2720 | |
2721 | def is_disconnection_error(self, exc): |
2722 | - if not isinstance(exc, (OperationalError, ProgrammingError)): |
2723 | + if not isinstance( |
2724 | + exc, (InterfaceError, OperationalError, ProgrammingError)): |
2725 | return False |
2726 | |
2727 | # XXX: 2007-09-17 jamesh |
2728 | # I have no idea why I am seeing the last exception message |
2729 | # after upgrading to Gutsy. |
2730 | msg = str(exc) |
2731 | - return ("server closed the connection unexpectedly" in msg or |
2732 | - "could not connect to server" in msg or |
2733 | - "no connection to the server" in msg or |
2734 | - "connection not open" in msg or |
2735 | - "losed the connection unexpectedly" in msg) |
2736 | +<<<<<<< TREE |
2737 | + return ("server closed the connection unexpectedly" in msg or |
2738 | + "could not connect to server" in msg or |
2739 | + "no connection to the server" in msg or |
2740 | + "connection not open" in msg or |
2741 | + "losed the connection unexpectedly" in msg) |
2742 | +======= |
2743 | + return ("server closed the connection unexpectedly" in msg or |
2744 | + "could not connect to server" in msg or |
2745 | + "no connection to the server" in msg or |
2746 | + "connection not open" in msg or |
2747 | + "connection already closed" in msg or |
2748 | + "losed the connection unexpectedly" in msg) |
2749 | +>>>>>>> MERGE-SOURCE |
2750 | |
2751 | |
2752 | class Postgres(Database): |
2753 | |
2754 | === modified file 'storm/properties.py' |
2755 | === modified file 'storm/references.py' |
2756 | === modified file 'storm/sqlobject.py' |
2757 | --- storm/sqlobject.py 2008-11-05 18:37:41 +0000 |
2758 | +++ storm/sqlobject.py 2009-05-06 21:20:16 +0000 |
2759 | @@ -552,8 +552,13 @@ |
2760 | return item in result_set |
2761 | |
2762 | def __nonzero__(self): |
2763 | +<<<<<<< TREE |
2764 | result_set = self._without_prejoins()._result_set |
2765 | return not result_set.is_empty() |
2766 | +======= |
2767 | + result_set = self._without_prejoins()._result_set |
2768 | + return result_set.any() is not None |
2769 | +>>>>>>> MERGE-SOURCE |
2770 | |
2771 | def count(self): |
2772 | result_set = self._without_prejoins()._result_set |
2773 | |
2774 | === modified file 'storm/store.py' |
2775 | --- storm/store.py 2009-02-16 10:44:31 +0000 |
2776 | +++ storm/store.py 2009-05-06 21:20:16 +0000 |
2777 | @@ -36,7 +36,8 @@ |
2778 | Union, Except, Intersect, Alias, SetExpr) |
2779 | from storm.exceptions import ( |
2780 | WrongStoreError, NotFlushedError, OrderLoopError, UnorderedError, |
2781 | - NotOneError, FeatureError, CompileError, LostObjectError, ClassInfoError) |
2782 | + NotOneError, FeatureError, CompileError, LostObjectError, ClassInfoError, |
2783 | + ExprError) |
2784 | from storm import Undef |
2785 | from storm.cache import Cache |
2786 | from storm.event import EventSystem |
2787 | @@ -439,7 +440,18 @@ |
2788 | normal flushing times are insufficient, such as when you want to |
2789 | make sure a database trigger gets run at a particular time. |
2790 | """ |
2791 | +<<<<<<< TREE |
2792 | self._event.emit("flush") |
2793 | +======= |
2794 | + # XXX 2008-06-19 jamesh bug=241267: |
2795 | + # This loop takes up 75% of flush()'s runtime in our tests, |
2796 | + # and probably more in cases with more live objects. As we |
2797 | + # don't use any property types that require the event, I've |
2798 | + # temporarily disabled it. |
2799 | + |
2800 | + ##for obj_info in self._iter_alive(): |
2801 | + ## obj_info.event.emit("flush") |
2802 | +>>>>>>> MERGE-SOURCE |
2803 | |
2804 | # The _dirty list may change under us while we're running |
2805 | # the flush hooks, so we cannot just simply loop over it |
2806 | @@ -1016,6 +1028,7 @@ |
2807 | |
2808 | return self.copy().config(offset=offset, limit=limit) |
2809 | |
2810 | +<<<<<<< TREE |
2811 | def __contains__(self, item): |
2812 | """Check if an item is contained within the result set.""" |
2813 | columns, values = self._find_spec.get_columns_and_values_for_item(item) |
2814 | @@ -1047,6 +1060,31 @@ |
2815 | result = self._store._connection.execute(select) |
2816 | return (not result.get_one()) |
2817 | |
2818 | +======= |
2819 | + def __contains__(self, item): |
2820 | + """Check if an item is contained within the result set.""" |
2821 | + columns, values = self._find_spec.get_columns_and_values_for_item(item) |
2822 | + |
2823 | + if self._select is Undef and self._group_by is Undef: |
2824 | + # No predefined select: adjust the where clause. |
2825 | + dummy, default_tables = self._find_spec.get_columns_and_tables() |
2826 | + where = [Eq(*pair) for pair in zip(columns, values)] |
2827 | + if self._where is not Undef: |
2828 | + where.append(self._where) |
2829 | + select = Select(1, And(*where), self._tables, |
2830 | + default_tables) |
2831 | + else: |
2832 | + # Rewrite the predefined query and use it as a subquery. |
2833 | + aliased_columns = [Alias(column, "_key%d" % index) |
2834 | + for (index, column) in enumerate(columns)] |
2835 | + subquery = replace_columns(self._get_select(), aliased_columns) |
2836 | + where = [Eq(*pair) for pair in zip(aliased_columns, values)] |
2837 | + select = Select(1, And(*where), Alias(subquery, "_tmp")) |
2838 | + |
2839 | + result = self._store._connection.execute(select) |
2840 | + return result.get_one() is not None |
2841 | + |
2842 | +>>>>>>> MERGE-SOURCE |
2843 | def any(self): |
2844 | """Return a single item from the result set. |
2845 | |
2846 | @@ -1438,12 +1476,18 @@ |
2847 | def __getitem__(self, index): |
2848 | return self.copy() |
2849 | |
2850 | +<<<<<<< TREE |
2851 | def __contains__(self, item): |
2852 | return False |
2853 | |
2854 | def is_empty(self): |
2855 | return True |
2856 | |
2857 | +======= |
2858 | + def __contains__(self, item): |
2859 | + return False |
2860 | + |
2861 | +>>>>>>> MERGE-SOURCE |
2862 | def any(self): |
2863 | return None |
2864 | |
2865 | |
2866 | === modified file 'storm/tracer.py' |
2867 | --- storm/tracer.py 2009-02-04 01:53:02 +0000 |
2868 | +++ storm/tracer.py 2009-05-06 21:20:16 +0000 |
2869 | @@ -14,6 +14,7 @@ |
2870 | |
2871 | def connection_raw_execute(self, connection, raw_cursor, statement, params): |
2872 | time = datetime.now().isoformat()[11:] |
2873 | +<<<<<<< TREE |
2874 | raw_params = [] |
2875 | for param in params: |
2876 | if isinstance(param, Variable): |
2877 | @@ -23,6 +24,10 @@ |
2878 | raw_params = tuple(raw_params) |
2879 | self._stream.write( |
2880 | "[%s] EXECUTE: %r, %r\n" % (time, statement, raw_params)) |
2881 | +======= |
2882 | + params = tuple(param.get() for param in params) |
2883 | + self._stream.write("[%s] EXECUTE: %r, %r\n" % (time, statement, params)) |
2884 | +>>>>>>> MERGE-SOURCE |
2885 | self._stream.flush() |
2886 | |
2887 | def connection_raw_execute_error(self, connection, raw_cursor, |
2888 | |
2889 | === modified file 'storm/variables.py' |
2890 | --- storm/variables.py 2009-03-04 16:56:58 +0000 |
2891 | +++ storm/variables.py 2009-05-06 21:20:16 +0000 |
2892 | @@ -536,6 +536,7 @@ |
2893 | raise ValueError("Invalid enum value: %s" % repr(value)) |
2894 | |
2895 | |
2896 | +<<<<<<< TREE |
2897 | class MutableValueVariable(Variable): |
2898 | """ |
2899 | A variable which contains a reference to mutable content. For this kind |
2900 | @@ -544,6 +545,10 @@ |
2901 | flushing current objects, to check if the state has changed. |
2902 | """ |
2903 | __slots__ = ("_event_system") |
2904 | +======= |
2905 | +class PickleVariable(Variable): |
2906 | + __slots__ = () |
2907 | +>>>>>>> MERGE-SOURCE |
2908 | |
2909 | def __init__(self, *args, **kwargs): |
2910 | self._event_system = None |
2911 | @@ -603,9 +608,21 @@ |
2912 | self._lazy_value = state[0] |
2913 | self._value = pickle.loads(state[1]) |
2914 | |
2915 | +<<<<<<< TREE |
2916 | |
2917 | class ListVariable(MutableValueVariable): |
2918 | __slots__ = ("_item_factory",) |
2919 | +======= |
2920 | + def __hash__(self): |
2921 | + try: |
2922 | + return hash(self._value) |
2923 | + except TypeError: |
2924 | + return hash(pickle.dumps(self._value, -1)) |
2925 | + |
2926 | + |
2927 | +class ListVariable(Variable): |
2928 | + __slots__ = ("_item_factory",) |
2929 | +>>>>>>> MERGE-SOURCE |
2930 | |
2931 | def __init__(self, item_factory, *args, **kwargs): |
2932 | self._item_factory = item_factory |
2933 | |
2934 | === modified file 'storm/zope/__init__.py' |
2935 | --- storm/zope/__init__.py 2008-07-30 06:07:40 +0000 |
2936 | +++ storm/zope/__init__.py 2009-05-06 21:20:16 +0000 |
2937 | @@ -27,6 +27,7 @@ |
2938 | |
2939 | |
2940 | classImplements(storm_sqlobject.SQLObjectResultSet, ISQLObjectResultSet) |
2941 | +<<<<<<< TREE |
2942 | classImplements(ResultSet, IResultSet) |
2943 | classImplements(EmptyResultSet, IResultSet) |
2944 | |
2945 | @@ -43,3 +44,7 @@ |
2946 | # Store. |
2947 | _available_by_default.append("__storm_object_info__") |
2948 | BasicTypes[ObjectInfo] = NoProxy |
2949 | +======= |
2950 | +classImplements(ResultSet, IResultSet) |
2951 | +classImplements(EmptyResultSet, IResultSet) |
2952 | +>>>>>>> MERGE-SOURCE |
2953 | |
2954 | === modified file 'storm/zope/interfaces.py' |
2955 | === modified file 'storm/zope/zstorm.py' |
2956 | === modified file 'test' |
2957 | === modified file 'tests/__init__.py' |
2958 | --- tests/__init__.py 2008-06-20 14:08:30 +0000 |
2959 | +++ tests/__init__.py 2009-05-06 21:20:16 +0000 |
2960 | @@ -0,0 +1,1 @@ |
2961 | +#import storm.psycer as p; p.enable() |
2962 | |
2963 | === modified file 'tests/databases/base.py' |
2964 | === modified file 'tests/databases/postgres.py' |
2965 | === modified file 'tests/expr.py' |
2966 | --- tests/expr.py 2008-10-02 15:47:18 +0000 |
2967 | +++ tests/expr.py 2009-05-06 21:20:16 +0000 |
2968 | @@ -662,16 +662,30 @@ |
2969 | 'ORDER BY column1') |
2970 | self.assertEquals(state.parameters, []) |
2971 | |
2972 | - def test_select_having(self): |
2973 | - expr = Select(column1, tables=table1, order_by=u"column1", |
2974 | - group_by=[u"column2"], having=u"1 = 2") |
2975 | - state = State() |
2976 | - statement = compile(expr, state) |
2977 | - self.assertEquals(statement, 'SELECT column1 FROM "table 1" ' |
2978 | - 'GROUP BY column2 HAVING 1 = 2 ' |
2979 | - 'ORDER BY column1') |
2980 | - self.assertEquals(state.parameters, []) |
2981 | - |
2982 | +<<<<<<< TREE |
2983 | + def test_select_having(self): |
2984 | + expr = Select(column1, tables=table1, order_by=u"column1", |
2985 | + group_by=[u"column2"], having=u"1 = 2") |
2986 | + state = State() |
2987 | + statement = compile(expr, state) |
2988 | + self.assertEquals(statement, 'SELECT column1 FROM "table 1" ' |
2989 | + 'GROUP BY column2 HAVING 1 = 2 ' |
2990 | + 'ORDER BY column1') |
2991 | + self.assertEquals(state.parameters, []) |
2992 | + |
2993 | +======= |
2994 | + def test_select_having(self): |
2995 | + expr = Select(column1, tables=table1, order_by=u"column1", |
2996 | + group_by=[u"column2"], having=u"1 = 2") |
2997 | + state = State() |
2998 | + statement = compile(expr, state) |
2999 | + self.assertEquals(statement, 'SELECT column1 FROM "table 1" ' |
3000 | + 'GROUP BY column2 HAVING 1 = 2 ' |
3001 | + 'ORDER BY column1') |
3002 | + self.assertEquals(state.parameters, []) |
3003 | + |
3004 | + |
3005 | +>>>>>>> MERGE-SOURCE |
3006 | def test_select_contexts(self): |
3007 | column, where, table, order_by, group_by = track_contexts(5) |
3008 | expr = Select(column, where, table, |
3009 | @@ -932,8 +946,13 @@ |
3010 | expr = Func1().is_in([]) |
3011 | state = State() |
3012 | statement = compile(expr, state) |
3013 | +<<<<<<< TREE |
3014 | self.assertEquals(statement, "?") |
3015 | self.assertVariablesEqual(state.parameters, [BoolVariable(False)]) |
3016 | +======= |
3017 | + self.assertEquals(statement, "?") |
3018 | + self.assertEquals(state.parameters, [BoolVariable(False)]) |
3019 | +>>>>>>> MERGE-SOURCE |
3020 | |
3021 | def test_is_in_expr(self): |
3022 | expr = Func1().is_in(Select(column1)) |
3023 | |
3024 | === modified file 'tests/store/base.py' |
3025 | --- tests/store/base.py 2009-02-19 16:44:33 +0000 |
3026 | +++ tests/store/base.py 2009-05-06 21:20:16 +0000 |
3027 | @@ -21,17 +21,26 @@ |
3028 | # |
3029 | import decimal |
3030 | import gc |
3031 | +<<<<<<< TREE |
3032 | import operator |
3033 | import weakref |
3034 | +======= |
3035 | +import operator |
3036 | +>>>>>>> MERGE-SOURCE |
3037 | |
3038 | from storm.references import Reference, ReferenceSet, Proxy |
3039 | from storm.database import Result |
3040 | from storm.properties import Int, Float, RawStr, Unicode, Property, Pickle |
3041 | from storm.properties import PropertyPublisherMeta, Decimal |
3042 | +<<<<<<< TREE |
3043 | from storm.variables import PickleVariable |
3044 | from storm.expr import ( |
3045 | Asc, Desc, Select, Func, LeftJoin, SQL, Count, Sum, Avg, And, Or, Eq, |
3046 | Lower) |
3047 | +======= |
3048 | +from storm.expr import ( |
3049 | + Asc, Desc, Select, Func, LeftJoin, SQL, Count, Sum, Avg, And, Or, Eq) |
3050 | +>>>>>>> MERGE-SOURCE |
3051 | from storm.variables import Variable, UnicodeVariable, IntVariable |
3052 | from storm.info import get_obj_info, ClassAlias |
3053 | from storm.exceptions import * |
3054 | @@ -1306,131 +1315,259 @@ |
3055 | foo = self.store.find(Foo, Foo.id == 10).one() |
3056 | self.assertEqual(foo.title, "Title 30") |
3057 | |
3058 | - def test_find_group_by(self): |
3059 | - result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3060 | - result.group_by(FooValue.value2) |
3061 | - result.order_by(Count(FooValue.id), Sum(FooValue.value1)) |
3062 | - result = list(result) |
3063 | - self.assertEquals(result, [(2L, 2L), (2L, 2L), (2L, 3L), (3L, 6L)]) |
3064 | - |
3065 | - def test_find_group_by_table(self): |
3066 | - result = self.store.find( |
3067 | - (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3068 | - result.group_by(Foo) |
3069 | - foo1 = self.store.get(Foo, 10) |
3070 | - foo2 = self.store.get(Foo, 20) |
3071 | - self.assertEquals(list(result), [(5, foo1), (16, foo2)]) |
3072 | - |
3073 | - def test_find_group_by_table_contains(self): |
3074 | - result = self.store.find( |
3075 | - (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3076 | - result.group_by(Foo) |
3077 | - foo1 = self.store.get(Foo, 10) |
3078 | - self.assertEquals((5, foo1) in result, True) |
3079 | - |
3080 | - def test_find_group_by_multiple_tables(self): |
3081 | - result = self.store.find( |
3082 | - Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3083 | - result.group_by(Foo.id) |
3084 | - result.order_by(Sum(FooValue.value2)) |
3085 | - result = list(result) |
3086 | - self.assertEquals(result, [5, 16]) |
3087 | - |
3088 | - result = self.store.find( |
3089 | - (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3090 | - result.group_by(Foo) |
3091 | - result.order_by(Sum(FooValue.value2)) |
3092 | - result = list(result) |
3093 | - foo1 = self.store.get(Foo, 10) |
3094 | - foo2 = self.store.get(Foo, 20) |
3095 | - self.assertEquals(result, [(5, foo1), (16, foo2)]) |
3096 | - |
3097 | - result = self.store.find( |
3098 | - (Foo.id, Sum(FooValue.value2), Avg(FooValue.value1)), |
3099 | - Foo.id == FooValue.foo_id) |
3100 | - result.group_by(Foo.id) |
3101 | - result.order_by(Foo.id) |
3102 | - result = list(result) |
3103 | - self.assertEquals(result, [(10, 5, 2), |
3104 | - (20, 16, 1)]) |
3105 | - |
3106 | - def test_find_group_by_having(self): |
3107 | - result = self.store.find( |
3108 | - Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3109 | - result.group_by(Foo.id) |
3110 | - result.having(Sum(FooValue.value2) == 5) |
3111 | - self.assertEquals(list(result), [5]) |
3112 | - result = self.store.find( |
3113 | - Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3114 | - result.group_by(Foo.id) |
3115 | - result.having(Count() == 5) |
3116 | - self.assertEquals(list(result), [16]) |
3117 | - |
3118 | - def test_find_having_without_group_by(self): |
3119 | - result = self.store.find(FooValue) |
3120 | - self.assertRaises(FeatureError, result.having, FooValue.value1 == 1) |
3121 | - |
3122 | - def test_find_group_by_multiple_having(self): |
3123 | - result = self.store.find((Count(), FooValue.value2)) |
3124 | - result.group_by(FooValue.value2) |
3125 | - result.having(Count() == 2, FooValue.value2 >= 3) |
3126 | - result.order_by(Count(), FooValue.value2) |
3127 | - list_result = list(result) |
3128 | - self.assertEquals(list_result, [(2, 3), (2, 4)]) |
3129 | - |
3130 | - def test_find_successive_group_by(self): |
3131 | - result = self.store.find(Count()) |
3132 | - result.group_by(FooValue.value2) |
3133 | - result.order_by(Count()) |
3134 | - list_result = list(result) |
3135 | - self.assertEquals(list_result, [2, 2, 2, 3]) |
3136 | - result.group_by(FooValue.value1) |
3137 | - list_result = list(result) |
3138 | - self.assertEquals(list_result, [4, 5]) |
3139 | - |
3140 | - def test_find_multiple_group_by(self): |
3141 | - result = self.store.find(Count()) |
3142 | - result.group_by(FooValue.value2, FooValue.value1) |
3143 | - result.order_by(Count()) |
3144 | - list_result = list(result) |
3145 | - self.assertEquals(list_result, [1, 1, 2, 2, 3]) |
3146 | - |
3147 | - def test_find_multiple_group_by_with_having(self): |
3148 | - result = self.store.find((Count(), FooValue.value2)) |
3149 | - result.group_by(FooValue.value2, FooValue.value1).having(Count() == 2) |
3150 | - result.order_by(Count(), FooValue.value2) |
3151 | - list_result = list(result) |
3152 | - self.assertEquals(list_result, [(2, 3), (2, 4)]) |
3153 | - |
3154 | - def test_find_group_by_avg(self): |
3155 | - result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3156 | - result.group_by(FooValue.value2) |
3157 | - self.assertRaises(FeatureError, result.avg, FooValue.value2) |
3158 | - |
3159 | - def test_find_group_by_values(self): |
3160 | - result = self.store.find( |
3161 | - (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3162 | - result.group_by(Foo) |
3163 | - result.order_by(Foo.title) |
3164 | - result = list(result.values(Foo.title)) |
3165 | - self.assertEquals(result, [u'Title 20', u'Title 30']) |
3166 | - |
3167 | - def test_find_group_by_union(self): |
3168 | - result1 = self.store.find(Foo, id=30) |
3169 | - result2 = self.store.find(Foo, id=10) |
3170 | - result3 = result1.union(result2) |
3171 | - self.assertRaises(FeatureError, result3.group_by, Foo.title) |
3172 | - |
3173 | - def test_find_group_by_remove(self): |
3174 | - result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3175 | - result.group_by(FooValue.value2) |
3176 | - self.assertRaises(FeatureError, result.remove) |
3177 | - |
3178 | - def test_find_group_by_set(self): |
3179 | - result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3180 | - result.group_by(FooValue.value2) |
3181 | - self.assertRaises(FeatureError, result.set, FooValue.value1 == 1) |
3182 | - |
3183 | +<<<<<<< TREE |
3184 | + def test_find_group_by(self): |
3185 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3186 | + result.group_by(FooValue.value2) |
3187 | + result.order_by(Count(FooValue.id), Sum(FooValue.value1)) |
3188 | + result = list(result) |
3189 | + self.assertEquals(result, [(2L, 2L), (2L, 2L), (2L, 3L), (3L, 6L)]) |
3190 | + |
3191 | + def test_find_group_by_table(self): |
3192 | + result = self.store.find( |
3193 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3194 | + result.group_by(Foo) |
3195 | + foo1 = self.store.get(Foo, 10) |
3196 | + foo2 = self.store.get(Foo, 20) |
3197 | + self.assertEquals(list(result), [(5, foo1), (16, foo2)]) |
3198 | + |
3199 | + def test_find_group_by_table_contains(self): |
3200 | + result = self.store.find( |
3201 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3202 | + result.group_by(Foo) |
3203 | + foo1 = self.store.get(Foo, 10) |
3204 | + self.assertEquals((5, foo1) in result, True) |
3205 | + |
3206 | + def test_find_group_by_multiple_tables(self): |
3207 | + result = self.store.find( |
3208 | + Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3209 | + result.group_by(Foo.id) |
3210 | + result.order_by(Sum(FooValue.value2)) |
3211 | + result = list(result) |
3212 | + self.assertEquals(result, [5, 16]) |
3213 | + |
3214 | + result = self.store.find( |
3215 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3216 | + result.group_by(Foo) |
3217 | + result.order_by(Sum(FooValue.value2)) |
3218 | + result = list(result) |
3219 | + foo1 = self.store.get(Foo, 10) |
3220 | + foo2 = self.store.get(Foo, 20) |
3221 | + self.assertEquals(result, [(5, foo1), (16, foo2)]) |
3222 | + |
3223 | + result = self.store.find( |
3224 | + (Foo.id, Sum(FooValue.value2), Avg(FooValue.value1)), |
3225 | + Foo.id == FooValue.foo_id) |
3226 | + result.group_by(Foo.id) |
3227 | + result.order_by(Foo.id) |
3228 | + result = list(result) |
3229 | + self.assertEquals(result, [(10, 5, 2), |
3230 | + (20, 16, 1)]) |
3231 | + |
3232 | + def test_find_group_by_having(self): |
3233 | + result = self.store.find( |
3234 | + Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3235 | + result.group_by(Foo.id) |
3236 | + result.having(Sum(FooValue.value2) == 5) |
3237 | + self.assertEquals(list(result), [5]) |
3238 | + result = self.store.find( |
3239 | + Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3240 | + result.group_by(Foo.id) |
3241 | + result.having(Count() == 5) |
3242 | + self.assertEquals(list(result), [16]) |
3243 | + |
3244 | + def test_find_having_without_group_by(self): |
3245 | + result = self.store.find(FooValue) |
3246 | + self.assertRaises(FeatureError, result.having, FooValue.value1 == 1) |
3247 | + |
3248 | + def test_find_group_by_multiple_having(self): |
3249 | + result = self.store.find((Count(), FooValue.value2)) |
3250 | + result.group_by(FooValue.value2) |
3251 | + result.having(Count() == 2, FooValue.value2 >= 3) |
3252 | + result.order_by(Count(), FooValue.value2) |
3253 | + list_result = list(result) |
3254 | + self.assertEquals(list_result, [(2, 3), (2, 4)]) |
3255 | + |
3256 | + def test_find_successive_group_by(self): |
3257 | + result = self.store.find(Count()) |
3258 | + result.group_by(FooValue.value2) |
3259 | + result.order_by(Count()) |
3260 | + list_result = list(result) |
3261 | + self.assertEquals(list_result, [2, 2, 2, 3]) |
3262 | + result.group_by(FooValue.value1) |
3263 | + list_result = list(result) |
3264 | + self.assertEquals(list_result, [4, 5]) |
3265 | + |
3266 | + def test_find_multiple_group_by(self): |
3267 | + result = self.store.find(Count()) |
3268 | + result.group_by(FooValue.value2, FooValue.value1) |
3269 | + result.order_by(Count()) |
3270 | + list_result = list(result) |
3271 | + self.assertEquals(list_result, [1, 1, 2, 2, 3]) |
3272 | + |
3273 | + def test_find_multiple_group_by_with_having(self): |
3274 | + result = self.store.find((Count(), FooValue.value2)) |
3275 | + result.group_by(FooValue.value2, FooValue.value1).having(Count() == 2) |
3276 | + result.order_by(Count(), FooValue.value2) |
3277 | + list_result = list(result) |
3278 | + self.assertEquals(list_result, [(2, 3), (2, 4)]) |
3279 | + |
3280 | + def test_find_group_by_avg(self): |
3281 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3282 | + result.group_by(FooValue.value2) |
3283 | + self.assertRaises(FeatureError, result.avg, FooValue.value2) |
3284 | + |
3285 | + def test_find_group_by_values(self): |
3286 | + result = self.store.find( |
3287 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3288 | + result.group_by(Foo) |
3289 | + result.order_by(Foo.title) |
3290 | + result = list(result.values(Foo.title)) |
3291 | + self.assertEquals(result, [u'Title 20', u'Title 30']) |
3292 | + |
3293 | + def test_find_group_by_union(self): |
3294 | + result1 = self.store.find(Foo, id=30) |
3295 | + result2 = self.store.find(Foo, id=10) |
3296 | + result3 = result1.union(result2) |
3297 | + self.assertRaises(FeatureError, result3.group_by, Foo.title) |
3298 | + |
3299 | + def test_find_group_by_remove(self): |
3300 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3301 | + result.group_by(FooValue.value2) |
3302 | + self.assertRaises(FeatureError, result.remove) |
3303 | + |
3304 | + def test_find_group_by_set(self): |
3305 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3306 | + result.group_by(FooValue.value2) |
3307 | + self.assertRaises(FeatureError, result.set, FooValue.value1 == 1) |
3308 | + |
3309 | +======= |
3310 | + def test_find_group_by(self): |
3311 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3312 | + result.group_by(FooValue.value2) |
3313 | + result.order_by(Count(FooValue.id), Sum(FooValue.value1)) |
3314 | + result = list(result) |
3315 | + self.assertEquals(result, [(2L, 2L), (2L, 2L), (2L, 3L), (3L, 6L)]) |
3316 | + |
3317 | + def test_find_group_by_table(self): |
3318 | + result = self.store.find( |
3319 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3320 | + result.group_by(Foo) |
3321 | + foo1 = self.store.get(Foo, 10) |
3322 | + foo2 = self.store.get(Foo, 20) |
3323 | + self.assertEquals(list(result), [(5, foo1), (16, foo2)]) |
3324 | + |
3325 | + def test_find_group_by_table_contains(self): |
3326 | + result = self.store.find( |
3327 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3328 | + result.group_by(Foo) |
3329 | + foo1 = self.store.get(Foo, 10) |
3330 | + self.assertEquals((5, foo1) in result, True) |
3331 | + |
3332 | + def test_find_group_by_multiple_tables(self): |
3333 | + result = self.store.find( |
3334 | + Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3335 | + result.group_by(Foo.id) |
3336 | + result.order_by(Sum(FooValue.value2)) |
3337 | + result = list(result) |
3338 | + self.assertEquals(result, [5, 16]) |
3339 | + |
3340 | + result = self.store.find( |
3341 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3342 | + result.group_by(Foo) |
3343 | + result.order_by(Sum(FooValue.value2)) |
3344 | + result = list(result) |
3345 | + foo1 = self.store.get(Foo, 10) |
3346 | + foo2 = self.store.get(Foo, 20) |
3347 | + self.assertEquals(result, [(5, foo1), (16, foo2)]) |
3348 | + |
3349 | + result = self.store.find( |
3350 | + (Foo.id, Sum(FooValue.value2), Avg(FooValue.value1)), |
3351 | + Foo.id == FooValue.foo_id) |
3352 | + result.group_by(Foo.id) |
3353 | + result.order_by(Foo.id) |
3354 | + result = list(result) |
3355 | + self.assertEquals(result, [(10, 5, 2), |
3356 | + (20, 16, 1)]) |
3357 | + |
3358 | + def test_find_group_by_having(self): |
3359 | + result = self.store.find( |
3360 | + Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3361 | + result.group_by(Foo.id) |
3362 | + result.having(Sum(FooValue.value2) == 5) |
3363 | + self.assertEquals(list(result), [5]) |
3364 | + result = self.store.find( |
3365 | + Sum(FooValue.value2), Foo.id == FooValue.foo_id) |
3366 | + result.group_by(Foo.id) |
3367 | + result.having(Count() == 5) |
3368 | + self.assertEquals(list(result), [16]) |
3369 | + |
3370 | + def test_find_having_without_group_by(self): |
3371 | + result = self.store.find(FooValue) |
3372 | + self.assertRaises(FeatureError, result.having, FooValue.value1 == 1) |
3373 | + |
3374 | + def test_find_group_by_multiple_having(self): |
3375 | + result = self.store.find((Count(), FooValue.value2)) |
3376 | + result.group_by(FooValue.value2) |
3377 | + result.having(Count() == 2, FooValue.value2 >= 3) |
3378 | + result.order_by(Count(), FooValue.value2) |
3379 | + list_result = list(result) |
3380 | + self.assertEquals(list_result, [(2, 3), (2, 4)]) |
3381 | + |
3382 | + def test_find_successive_group_by(self): |
3383 | + result = self.store.find(Count()) |
3384 | + result.group_by(FooValue.value2) |
3385 | + result.order_by(Count()) |
3386 | + list_result = list(result) |
3387 | + self.assertEquals(list_result, [2, 2, 2, 3]) |
3388 | + result.group_by(FooValue.value1) |
3389 | + list_result = list(result) |
3390 | + self.assertEquals(list_result, [4, 5]) |
3391 | + |
3392 | + def test_find_multiple_group_by(self): |
3393 | + result = self.store.find(Count()) |
3394 | + result.group_by(FooValue.value2, FooValue.value1) |
3395 | + result.order_by(Count()) |
3396 | + list_result = list(result) |
3397 | + self.assertEquals(list_result, [1, 1, 2, 2, 3]) |
3398 | + |
3399 | + def test_find_multiple_group_by_with_having(self): |
3400 | + result = self.store.find((Count(), FooValue.value2)) |
3401 | + result.group_by(FooValue.value2, FooValue.value1).having(Count() == 2) |
3402 | + result.order_by(Count(), FooValue.value2) |
3403 | + list_result = list(result) |
3404 | + self.assertEquals(list_result, [(2, 3), (2, 4)]) |
3405 | + |
3406 | + def test_find_group_by_avg(self): |
3407 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3408 | + result.group_by(FooValue.value2) |
3409 | + self.assertRaises(FeatureError, result.avg, FooValue.value2) |
3410 | + |
3411 | + def test_find_group_by_values(self): |
3412 | + result = self.store.find( |
3413 | + (Sum(FooValue.value2), Foo), Foo.id == FooValue.foo_id) |
3414 | + result.group_by(Foo) |
3415 | + result.order_by(Foo.title) |
3416 | + result = list(result.values(Foo.title)) |
3417 | + self.assertEquals(result, [u'Title 20', u'Title 30']) |
3418 | + |
3419 | + def test_find_group_by_union(self): |
3420 | + result1 = self.store.find(Foo, id=30) |
3421 | + result2 = self.store.find(Foo, id=10) |
3422 | + result3 = result1.union(result2) |
3423 | + self.assertRaises(FeatureError, result3.group_by, Foo.title) |
3424 | + |
3425 | + def test_find_group_by_remove(self): |
3426 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3427 | + result.group_by(FooValue.value2) |
3428 | + self.assertRaises(FeatureError, result.remove) |
3429 | + |
3430 | + def test_find_group_by_set(self): |
3431 | + result = self.store.find((Count(FooValue.id), Sum(FooValue.value1))) |
3432 | + result.group_by(FooValue.value2) |
3433 | + self.assertRaises(FeatureError, result.set, FooValue.value1 == 1) |
3434 | + |
3435 | +>>>>>>> MERGE-SOURCE |
3436 | def test_add_commit(self): |
3437 | foo = Foo() |
3438 | foo.id = 40 |
3439 | @@ -4316,6 +4453,10 @@ |
3440 | self.assertEquals(foo.title, "Some default value") |
3441 | |
3442 | def test_pickle_variable(self): |
3443 | + # XXX 2008-06-19 jamesh bug=241267: |
3444 | + # Disabled, as Pickle() properties depend on the flush event. |
3445 | + return |
3446 | + |
3447 | class PickleBlob(Blob): |
3448 | bin = Pickle() |
3449 | |
3450 | @@ -4503,6 +4644,10 @@ |
3451 | self.assertTrue(value is blob.pickle) |
3452 | |
3453 | def test_pickle_variable_with_deleted_object(self): |
3454 | + # XXX 2008-06-19 jamesh bug=241267: |
3455 | + # Disabled, as Pickle() properties depend on the flush event. |
3456 | + return |
3457 | + |
3458 | class PickleBlob(Blob): |
3459 | bin = Pickle() |
3460 | |
3461 | @@ -5387,6 +5532,7 @@ |
3462 | " (ensure your database was created with CREATE DATABASE" |
3463 | " ... CHARACTER SET utf8)") |
3464 | |
3465 | +<<<<<<< TREE |
3466 | def test_creation_order_is_preserved_when_possible(self): |
3467 | foos = [self.store.add(Foo()) for i in range(10)] |
3468 | self.store.flush() |
3469 | @@ -5499,6 +5645,50 @@ |
3470 | foo.title = u"New title" |
3471 | self.assertEqual(len(calls), 1) |
3472 | self.assertEqual(calls[0], self.store) |
3473 | +======= |
3474 | + def test_creation_order_is_preserved_when_possible(self): |
3475 | + foos = [self.store.add(Foo()) for i in range(10)] |
3476 | + self.store.flush() |
3477 | + for i in range(len(foos)-1): |
3478 | + self.assertTrue(foos[i].id < foos[i+1].id) |
3479 | + |
3480 | + def test_update_order_is_preserved_when_possible(self): |
3481 | + class MyFoo(Foo): |
3482 | + sequence = 0 |
3483 | + def __storm_flushed__(self): |
3484 | + self.flush_order = MyFoo.sequence |
3485 | + MyFoo.sequence += 1 |
3486 | + |
3487 | + foos = [self.store.add(MyFoo()) for i in range(10)] |
3488 | + self.store.flush() |
3489 | + |
3490 | + MyFoo.sequence = 0 |
3491 | + for foo in foos: |
3492 | + foo.title = u"Changed Title" |
3493 | + self.store.flush() |
3494 | + |
3495 | + for i, foo in enumerate(foos): |
3496 | + self.assertEquals(foo.flush_order, i) |
3497 | + |
3498 | + def test_removal_order_is_preserved_when_possible(self): |
3499 | + class MyFoo(Foo): |
3500 | + sequence = 0 |
3501 | + def __storm_flushed__(self): |
3502 | + self.flush_order = MyFoo.sequence |
3503 | + MyFoo.sequence += 1 |
3504 | + |
3505 | + foos = [self.store.add(MyFoo()) for i in range(10)] |
3506 | + self.store.flush() |
3507 | + |
3508 | + MyFoo.sequence = 0 |
3509 | + for foo in foos: |
3510 | + self.store.remove(foo) |
3511 | + self.store.flush() |
3512 | + |
3513 | + for i, foo in enumerate(foos): |
3514 | + self.assertEquals(foo.flush_order, i) |
3515 | + |
3516 | +>>>>>>> MERGE-SOURCE |
3517 | |
3518 | class EmptyResultSetTest(object): |
3519 | |
3520 | @@ -5560,6 +5750,7 @@ |
3521 | self.assertEquals(list(self.result[:]), []) |
3522 | self.assertEquals(list(self.empty[:]), []) |
3523 | |
3524 | +<<<<<<< TREE |
3525 | def test_contains(self): |
3526 | self.assertEquals(Foo() in self.empty, False) |
3527 | |
3528 | @@ -5567,6 +5758,11 @@ |
3529 | self.assertEquals(self.result.is_empty(), True) |
3530 | self.assertEquals(self.empty.is_empty(), True) |
3531 | |
3532 | +======= |
3533 | + def test_contains(self): |
3534 | + self.assertEquals(Foo() in self.empty, False) |
3535 | + |
3536 | +>>>>>>> MERGE-SOURCE |
3537 | def test_any(self): |
3538 | self.assertEquals(self.result.any(), None) |
3539 | self.assertEquals(self.empty.any(), None) |
3540 | |
3541 | === modified file 'tests/store/mysql.py' |
3542 | === modified file 'tests/store/postgres.py' |
3543 | --- tests/store/postgres.py 2009-03-04 16:56:58 +0000 |
3544 | +++ tests/store/postgres.py 2009-05-06 21:20:16 +0000 |
3545 | @@ -103,6 +103,9 @@ |
3546 | self.connection.rollback() |
3547 | |
3548 | def test_list_variable(self): |
3549 | + # XXX 2008-06-19 jamesh bug=241267: |
3550 | + # Disabled, as List() properties depend on the flush event. |
3551 | + return |
3552 | |
3553 | lst = Lst1() |
3554 | lst.id = 1 |
3555 | @@ -146,6 +149,9 @@ |
3556 | self.assertEquals(result.get_one(), ([1,2,3],)) |
3557 | |
3558 | def test_list_variable_nested(self): |
3559 | + # XXX 2008-06-19 jamesh bug=241267: |
3560 | + # Disabled, as List() properties depend on the flush event. |
3561 | + return |
3562 | |
3563 | lst = Lst2() |
3564 | lst.id = 1 |
3565 | |
3566 | === modified file 'tests/store/sqlite.py' |
3567 | === modified file 'tests/tracer.py' |
3568 | --- tests/tracer.py 2009-02-04 01:53:02 +0000 |
3569 | +++ tests/tracer.py 2009-05-06 21:20:16 +0000 |
3570 | @@ -74,6 +74,7 @@ |
3571 | self.assertEquals(stash, ["m1", (1, 2), {"c": 3}, "m2", (), {}]) |
3572 | |
3573 | |
3574 | +<<<<<<< TREE |
3575 | |
3576 | class MockVariable(Variable): |
3577 | |
3578 | @@ -84,6 +85,18 @@ |
3579 | return self._value |
3580 | |
3581 | |
3582 | +======= |
3583 | + |
3584 | +class MockVariable(object): |
3585 | + |
3586 | + def __init__(self, value): |
3587 | + self._value = value |
3588 | + |
3589 | + def get(self): |
3590 | + return self._value |
3591 | + |
3592 | + |
3593 | +>>>>>>> MERGE-SOURCE |
3594 | class DebugTracerTest(TestHelper): |
3595 | |
3596 | def setUp(self): |
3597 | @@ -116,6 +129,7 @@ |
3598 | self.assertEqual(tracer._stream, marker) |
3599 | |
3600 | def test_connection_raw_execute(self): |
3601 | +<<<<<<< TREE |
3602 | self.stream.write( |
3603 | "[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n") |
3604 | self.stream.flush() |
3605 | @@ -139,6 +153,17 @@ |
3606 | raw_cursor = "RAW_CURSOR" |
3607 | statement = "STATEMENT" |
3608 | params = [self.variable, 1] |
3609 | +======= |
3610 | + stderr = self.mocker.replace("sys.stderr") |
3611 | + stderr.write("[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n") |
3612 | + stderr.flush() |
3613 | + self.mocker.replay() |
3614 | + |
3615 | + connection = "CONNECTION" |
3616 | + raw_cursor = "RAW_CURSOR" |
3617 | + statement = "STATEMENT" |
3618 | + params = [self.variable] |
3619 | +>>>>>>> MERGE-SOURCE |
3620 | |
3621 | self.tracer.connection_raw_execute(connection, raw_cursor, |
3622 | statement, params) |
3623 | @@ -170,6 +195,25 @@ |
3624 | self.tracer.connection_raw_execute_success(connection, raw_cursor, |
3625 | statement, params) |
3626 | |
3627 | +<<<<<<< TREE |
3628 | +======= |
3629 | + def test_custom_stream(self): |
3630 | + self.tracer = DebugTracer(sys.stdout) |
3631 | + |
3632 | + stdout = self.mocker.replace("sys.stdout") |
3633 | + stdout.write("[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n") |
3634 | + stdout.flush() |
3635 | + self.mocker.replay() |
3636 | + |
3637 | + connection = "CONNECTION" |
3638 | + raw_cursor = "RAW_CURSOR" |
3639 | + statement = "STATEMENT" |
3640 | + params = [self.variable] |
3641 | + |
3642 | + self.tracer.connection_raw_execute(connection, raw_cursor, |
3643 | + statement, params) |
3644 | + |
3645 | +>>>>>>> MERGE-SOURCE |
3646 | |
3647 | class TimeoutTracerTestBase(TestHelper): |
3648 | |
3649 | |
3650 | === modified file 'tests/tutorial.txt' |
3651 | === modified file 'tests/zope/zstorm.py' |
3652 | --- tests/zope/zstorm.py 2009-03-05 21:53:12 +0000 |
3653 | +++ tests/zope/zstorm.py 2009-05-06 21:20:16 +0000 |
3654 | @@ -21,7 +21,11 @@ |
3655 | import thread, weakref, gc |
3656 | |
3657 | from tests.helper import TestHelper |
3658 | +<<<<<<< TREE |
3659 | from tests.zope import has_transaction, has_zope_component |
3660 | +======= |
3661 | +from tests.zope import has_transaction, has_zope, has_zope_component |
3662 | +>>>>>>> MERGE-SOURCE |
3663 | |
3664 | if has_transaction: |
3665 | import transaction |
3666 | @@ -31,6 +35,9 @@ |
3667 | if has_zope_component: |
3668 | from zope.component import provideUtility, getUtility |
3669 | |
3670 | +if has_zope_component: |
3671 | + from zope.component import provideUtility, getUtility |
3672 | + |
3673 | from storm.exceptions import OperationalError |
3674 | from storm.locals import Store |
3675 | |
3676 | @@ -233,6 +240,7 @@ |
3677 | store = self.zstorm.get("name", "sqlite:") |
3678 | store_ref = weakref.ref(store) |
3679 | transaction.abort() |
3680 | +<<<<<<< TREE |
3681 | del store |
3682 | gc.collect() |
3683 | self.assertNotIdentical(store_ref(), None) |
3684 | @@ -249,3 +257,24 @@ |
3685 | provideUtility(ZStorm()) |
3686 | self.assertTrue(isinstance(getUtility(IZStorm), ZStorm)) |
3687 | |
3688 | +======= |
3689 | + self.assertEquals( |
3690 | + len(transaction.manager._synchs.values()[0].data.values()), 1) |
3691 | + self.zstorm._reset() |
3692 | + self.assertEquals( |
3693 | + len(transaction.manager._synchs.values()[0].data.values()), 0) |
3694 | + |
3695 | + def test_store_strong_reference(self): |
3696 | + """ |
3697 | + The zstorm utility should be a strong reference to named stores so that |
3698 | + it doesn't recreate stores uselessly. |
3699 | + """ |
3700 | + store = self.zstorm.get("name", "sqlite:") |
3701 | + store_ref = weakref.ref(store) |
3702 | + transaction.abort() |
3703 | + del store |
3704 | + gc.collect() |
3705 | + self.assertNotIdentical(store_ref(), None) |
3706 | + store = self.zstorm.get("name") |
3707 | + self.assertIdentical(store_ref(), store) |
3708 | +>>>>>>> MERGE-SOURCE |
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.