~jbaker/storm/nose_plugin

« back to all changes in this revision

Viewing changes to storm/cextensions.c

  • Committer: Gustavo Niemeyer
  • Date: 2008-06-26 11:57:22 UTC
  • mfrom: (235.2.24 need-for-speed-revenge)
  • Revision ID: gustavo@niemeyer.net-20080626115722-ekl4af6sx2pn08d0
Merging need-for-speed-revenge branch [a=niemeyer,jamesh,radix]
[r=jamesh,therve]

This branch introduces a number of fixes, optimizations, and extensions
on the cextensions module, with speedup purposes.  The module is now
built by default, but still disabled unless the STORM_CEXTENSIONS=1
environment variable is defined.

Besides these, Chris also provided a mechanism to cache ClassAliases,
to prevent the cost of rebuilding the ClassInfo for each alias.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
#
3
 
# Copyright (c) 2006, 2007 Canonical
 
3
# Copyright (c) 2006-2008 Canonical
4
4
#
5
5
# Written by Gustavo Niemeyer <gustavo@niemeyer.net>
6
6
#
24
24
#include <structmember.h>
25
25
 
26
26
 
 
27
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
 
28
typedef int Py_ssize_t;
 
29
#define PY_SSIZE_T_MAX INT_MAX
 
30
#define PY_SSIZE_T_MIN INT_MIN
 
31
#endif
 
32
 
 
33
 
 
34
#define CATCH(error_value, expression) \
 
35
        do { \
 
36
            if ((expression) == error_value) {\
 
37
                /*printf("GOT AN ERROR AT LINE %d!\n", __LINE__);*/ \
 
38
                goto error; \
 
39
            } \
 
40
        } while (0)
 
41
 
 
42
#define REPLACE(variable, new_value) \
 
43
        do { \
 
44
            PyObject *tmp = variable; \
 
45
            variable = new_value; \
 
46
            Py_DECREF(tmp); \
 
47
        } while(0)
 
48
 
 
49
 
 
50
/* Python 2.4 does not include the PySet_* API, so provide a minimal
 
51
   implementation for the calls we care about. */
 
52
#if PY_VERSION_HEX < 0x02050000 && !defined(PySet_GET_SIZE)
 
53
#  define PySet_GET_SIZE(so) \
 
54
     ((PyDictObject *)((PySetObject *)so)->data)->ma_used
 
55
static PyObject *
 
56
PySet_New(PyObject *p)
 
57
{
 
58
    return PyObject_CallObject((PyObject *)&PySet_Type, NULL);
 
59
}
 
60
 
 
61
static int
 
62
PySet_Add(PyObject *set, PyObject *key)
 
63
{
 
64
    PyObject *dict;
 
65
 
 
66
    if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
 
67
        PyErr_BadInternalCall();
 
68
        return -1;
 
69
    }
 
70
    dict = ((PySetObject *)set)->data;
 
71
    return PyDict_SetItem(dict, key, Py_True);
 
72
}
 
73
 
 
74
static int
 
75
PySet_Discard(PyObject *set, PyObject *key)
 
76
{
 
77
    PyObject *dict;
 
78
    int result;
 
79
 
 
80
    if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
 
81
        PyErr_BadInternalCall();
 
82
        return -1;
 
83
    }
 
84
    dict = ((PySetObject *)set)->data;
 
85
    result = PyDict_DelItem(dict, key);
 
86
    if (result == 0) {
 
87
        /* key found and removed */
 
88
        result = 1;
 
89
    } else {
 
90
        if (PyErr_ExceptionMatches(PyExc_KeyError)) {
 
91
            /* key not found */
 
92
            PyErr_Clear();
 
93
            result = 0;
 
94
        }
 
95
    }
 
96
    return result;
 
97
}
 
98
#endif
 
99
 
27
100
static PyObject *Undef = NULL;
28
101
static PyObject *LazyValue = NULL;
29
102
static PyObject *raise_none_error = NULL;
30
103
static PyObject *get_cls_info = NULL;
31
104
static PyObject *EventSystem = NULL;
32
 
 
 
105
static PyObject *SQLRaw = NULL;
 
106
static PyObject *SQLToken = NULL;
 
107
static PyObject *State = NULL;
 
108
static PyObject *CompileError = NULL;
 
109
static PyObject *parenthesis_format = NULL;
 
110
static PyObject *default_compile_join = NULL;
 
111
 
 
112
 
 
113
typedef struct {
 
114
    PyObject_HEAD
 
115
    PyObject *_owner_ref;
 
116
    PyObject *_hooks;
 
117
} EventSystemObject;
33
118
 
34
119
typedef struct {
35
120
    PyObject_HEAD
37
122
    PyObject *_lazy_value;
38
123
    PyObject *_checkpoint_state;
39
124
    PyObject *_allow_none;
 
125
    PyObject *_validator;
 
126
    PyObject *_validator_object_factory;
 
127
    PyObject *_validator_attribute;
40
128
    PyObject *column;
41
129
    PyObject *event;
42
130
} VariableObject;
43
131
 
44
132
typedef struct {
 
133
    PyObject_HEAD
 
134
    PyObject *__weakreflist;
 
135
    PyObject *_local_dispatch_table;
 
136
    PyObject *_local_precedence;
 
137
    PyObject *_local_reserved_words;
 
138
    PyObject *_dispatch_table;
 
139
    PyObject *_precedence;
 
140
    PyObject *_reserved_words;
 
141
    PyObject *_children;
 
142
    PyObject *_parents;
 
143
} CompileObject;
 
144
 
 
145
typedef struct {
45
146
    PyDictObject super;
46
147
    PyObject *__weakreflist;
47
148
    PyObject *__obj_ref;
64
165
 
65
166
    initialized = 1;
66
167
 
67
 
    {
68
 
        module = PyImport_ImportModule("storm");
69
 
        if (!module)
70
 
            return 0;
71
 
 
72
 
        Undef = PyObject_GetAttrString(module, "Undef");
73
 
        if (!Undef)
74
 
            return 0;
75
 
 
76
 
        Py_DECREF(module);
77
 
    }
78
 
 
79
 
    {
80
 
        module = PyImport_ImportModule("storm.variables");
81
 
        if (!module)
82
 
            return 0;
83
 
 
84
 
        raise_none_error = PyObject_GetAttrString(module, "raise_none_error");
85
 
        if (!raise_none_error)
86
 
            return 0;
87
 
 
88
 
        LazyValue = PyObject_GetAttrString(module, "LazyValue");
89
 
        if (!LazyValue)
90
 
            return 0;
91
 
 
92
 
        Py_DECREF(module);
93
 
    }
94
 
 
95
 
    {
96
 
        module = PyImport_ImportModule("storm.info");
97
 
        if (!module)
98
 
            return 0;
99
 
        
100
 
        get_cls_info = PyObject_GetAttrString(module, "get_cls_info");
101
 
        if (!get_cls_info)
102
 
            return 0;
103
 
 
104
 
        Py_DECREF(module);
105
 
    }
106
 
 
107
 
    {
108
 
        module = PyImport_ImportModule("storm.event");
109
 
        if (!module)
110
 
            return 0;
111
 
 
112
 
        EventSystem = PyObject_GetAttrString(module, "EventSystem");
113
 
        if (!EventSystem)
114
 
            return 0;
115
 
 
116
 
        Py_DECREF(module);
117
 
    }
 
168
    /* Import objects from storm module */
 
169
    module = PyImport_ImportModule("storm");
 
170
    if (!module)
 
171
        return 0;
 
172
 
 
173
    Undef = PyObject_GetAttrString(module, "Undef");
 
174
    if (!Undef)
 
175
        return 0;
 
176
 
 
177
    Py_DECREF(module);
 
178
 
 
179
    /* Import objects from storm.variables module */
 
180
    module = PyImport_ImportModule("storm.variables");
 
181
    if (!module)
 
182
        return 0;
 
183
 
 
184
    raise_none_error = PyObject_GetAttrString(module, "raise_none_error");
 
185
    if (!raise_none_error)
 
186
        return 0;
 
187
 
 
188
    LazyValue = PyObject_GetAttrString(module, "LazyValue");
 
189
    if (!LazyValue)
 
190
        return 0;
 
191
 
 
192
    Py_DECREF(module);
 
193
 
 
194
    /* Import objects from storm.info module */
 
195
    module = PyImport_ImportModule("storm.info");
 
196
    if (!module)
 
197
        return 0;
 
198
    
 
199
    get_cls_info = PyObject_GetAttrString(module, "get_cls_info");
 
200
    if (!get_cls_info)
 
201
        return 0;
 
202
 
 
203
    Py_DECREF(module);
 
204
 
 
205
    /* Import objects from storm.event module */
 
206
    module = PyImport_ImportModule("storm.event");
 
207
    if (!module)
 
208
        return 0;
 
209
 
 
210
    EventSystem = PyObject_GetAttrString(module, "EventSystem");
 
211
    if (!EventSystem)
 
212
        return 0;
 
213
 
 
214
    Py_DECREF(module);
 
215
 
 
216
    /* Import objects from storm.expr module */
 
217
    module = PyImport_ImportModule("storm.expr");
 
218
    if (!module)
 
219
        return 0;
 
220
 
 
221
    SQLRaw = PyObject_GetAttrString(module, "SQLRaw");
 
222
    if (!SQLRaw)
 
223
        return 0;
 
224
 
 
225
    SQLToken = PyObject_GetAttrString(module, "SQLToken");
 
226
    if (!SQLToken)
 
227
        return 0;
 
228
 
 
229
    State = PyObject_GetAttrString(module, "State");
 
230
    if (!State)
 
231
        return 0;
 
232
 
 
233
    CompileError = PyObject_GetAttrString(module, "CompileError");
 
234
    if (!CompileError)
 
235
        return 0;
 
236
 
 
237
    Py_DECREF(module);
 
238
 
 
239
    /* A few frequently used objects which are part of the fast path. */
 
240
 
 
241
    parenthesis_format = PyUnicode_DecodeASCII("(%s)", 4, "strict");
 
242
    default_compile_join = PyUnicode_DecodeASCII(", ", 2, "strict");
118
243
 
119
244
    return 1;
120
245
}
121
246
 
122
247
 
 
248
static int
 
249
EventSystem_init(EventSystemObject *self, PyObject *args, PyObject *kwargs)
 
250
{
 
251
    static char *kwlist[] = {"owner", NULL};
 
252
    PyObject *owner;
 
253
    int result = -1;
 
254
 
 
255
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &owner))
 
256
        return -1;
 
257
 
 
258
    /* self._owner_ref = weakref.ref(owner) */
 
259
    self->_owner_ref = PyWeakref_NewRef(owner, NULL);
 
260
    if (self->_owner_ref) {
 
261
        /* self._hooks = {} */
 
262
        self->_hooks = PyDict_New();
 
263
        if (self->_hooks) {
 
264
            result = 0;
 
265
        }
 
266
    }
 
267
 
 
268
    return result;
 
269
}
 
270
 
 
271
static int
 
272
EventSystem_traverse(EventSystemObject *self, visitproc visit, void *arg)
 
273
{
 
274
    Py_VISIT(self->_owner_ref);
 
275
    Py_VISIT(self->_hooks);
 
276
    return 0;
 
277
}
 
278
 
 
279
static int
 
280
EventSystem_clear(EventSystemObject *self)
 
281
{
 
282
    Py_CLEAR(self->_owner_ref);
 
283
    Py_CLEAR(self->_hooks);
 
284
    return 0;
 
285
}
 
286
 
 
287
static void
 
288
EventSystem_dealloc(EventSystemObject *self)
 
289
{
 
290
    EventSystem_clear(self);
 
291
    self->ob_type->tp_free((PyObject *)self);
 
292
}
 
293
 
 
294
static PyObject *
 
295
EventSystem_hook(EventSystemObject *self, PyObject *args)
 
296
{
 
297
    PyObject *result = NULL;
 
298
    PyObject *name, *callback, *data;
 
299
 
 
300
    if (PyTuple_GET_SIZE(args) < 2) {
 
301
        PyErr_SetString(PyExc_TypeError, "Invalid number of arguments");
 
302
        return NULL;
 
303
    }
 
304
 
 
305
    name = PyTuple_GET_ITEM(args, 0);
 
306
    callback = PyTuple_GET_ITEM(args, 1);
 
307
    data = PyTuple_GetSlice(args, 2, PyTuple_GET_SIZE(args));
 
308
    if (data) {
 
309
        /*
 
310
           callbacks = self._hooks.get(name)
 
311
           if callbacks is None:
 
312
               self._hooks.setdefault(name, set()).add((callback, data))
 
313
           else:
 
314
               callbacks.add((callback, data))
 
315
        */
 
316
        PyObject *callbacks = PyDict_GetItem(self->_hooks, name);
 
317
        if (!PyErr_Occurred()) {
 
318
            if (callbacks == NULL) {
 
319
                callbacks = PySet_New(NULL);
 
320
                if (callbacks &&
 
321
                    PyDict_SetItem(self->_hooks, name, callbacks) == -1) {
 
322
                    Py_DECREF(callbacks);
 
323
                    callbacks = NULL;
 
324
                }
 
325
            } else {
 
326
                Py_INCREF(callbacks);
 
327
            }
 
328
            if (callbacks) {
 
329
                PyObject *tuple = PyTuple_New(2);
 
330
                if (tuple) {
 
331
                    Py_INCREF(callback);
 
332
                    PyTuple_SET_ITEM(tuple, 0, callback);
 
333
                    Py_INCREF(data);
 
334
                    PyTuple_SET_ITEM(tuple, 1, data);
 
335
                    if (PySet_Add(callbacks, tuple) != -1) {
 
336
                        Py_INCREF(Py_None);
 
337
                        result = Py_None;
 
338
                    }
 
339
                    Py_DECREF(tuple);
 
340
                }
 
341
                Py_DECREF(callbacks);
 
342
            }
 
343
        }
 
344
        Py_DECREF(data);
 
345
    }
 
346
 
 
347
    return result;
 
348
}
 
349
 
 
350
static PyObject *
 
351
EventSystem_unhook(EventSystemObject *self, PyObject *args)
 
352
{
 
353
    PyObject *result = NULL;
 
354
    PyObject *name, *callback, *data;
 
355
 
 
356
    if (PyTuple_GET_SIZE(args) < 2) {
 
357
        PyErr_SetString(PyExc_TypeError, "Invalid number of arguments");
 
358
        return NULL;
 
359
    }
 
360
 
 
361
    name = PyTuple_GET_ITEM(args, 0);
 
362
    callback = PyTuple_GET_ITEM(args, 1);
 
363
    data = PyTuple_GetSlice(args, 2, PyTuple_GET_SIZE(args));
 
364
    if (data) {
 
365
        /* 
 
366
           callbacks = self._hooks.get(name)
 
367
           if callbacks is not None:
 
368
               callbacks.discard((callback, data))
 
369
        */
 
370
        PyObject *callbacks = PyDict_GetItem(self->_hooks, name);
 
371
        if (callbacks) {
 
372
            PyObject *tuple = PyTuple_New(2);
 
373
            if (tuple) {
 
374
                Py_INCREF(callback);
 
375
                PyTuple_SET_ITEM(tuple, 0, callback);
 
376
                Py_INCREF(data);
 
377
                PyTuple_SET_ITEM(tuple, 1, data);
 
378
                if (PySet_Discard(callbacks, tuple) != -1) {
 
379
                    Py_INCREF(Py_None);
 
380
                    result = Py_None;
 
381
                }
 
382
                Py_DECREF(tuple);
 
383
            }
 
384
        } else if (!PyErr_Occurred()) {
 
385
            Py_INCREF(Py_None);
 
386
            result = Py_None;
 
387
        }
 
388
        Py_DECREF(data);
 
389
    }
 
390
 
 
391
    return result;
 
392
}
 
393
 
 
394
static PyObject *
 
395
EventSystem__do_emit_call(PyObject *callback, PyObject *owner,
 
396
                          PyObject *args, PyObject *data)
 
397
{
 
398
    /* return callback(owner, *(args+data)) */
 
399
    PyObject *result = NULL;
 
400
    PyObject *tuple = PyTuple_New(PyTuple_GET_SIZE(args) +
 
401
                                  PyTuple_GET_SIZE(data) + 1);
 
402
    if (tuple) {
 
403
        Py_ssize_t i, tuple_i;
 
404
 
 
405
        Py_INCREF(owner);
 
406
        PyTuple_SET_ITEM(tuple, 0, owner);
 
407
        tuple_i = 1;
 
408
        for (i = 0; i != PyTuple_GET_SIZE(args); i++) {
 
409
            PyObject *item = PyTuple_GET_ITEM(args, i);
 
410
            Py_INCREF(item);
 
411
            PyTuple_SET_ITEM(tuple, tuple_i++, item);
 
412
        }
 
413
        for (i = 0; i != PyTuple_GET_SIZE(data); i++) {
 
414
            PyObject *item = PyTuple_GET_ITEM(data, i);
 
415
            Py_INCREF(item);
 
416
            PyTuple_SET_ITEM(tuple, tuple_i++, item);
 
417
        }
 
418
        result = PyObject_Call(callback, tuple, NULL);
 
419
        Py_DECREF(tuple);
 
420
    }
 
421
    return result;
 
422
}
 
423
 
 
424
static PyObject *
 
425
EventSystem_emit(EventSystemObject *self, PyObject *all_args)
 
426
{
 
427
    PyObject *result = NULL;
 
428
    PyObject *name, *args;
 
429
 
 
430
    if (PyTuple_GET_SIZE(all_args) == 0) {
 
431
        PyErr_SetString(PyExc_TypeError, "Invalid number of arguments");
 
432
        return NULL;
 
433
    }
 
434
 
 
435
    /* XXX In the following code we trust on the format inserted by
 
436
     *     the hook() method.  If it's hacked somehow, it may blow up. */
 
437
 
 
438
    name = PyTuple_GET_ITEM(all_args, 0);
 
439
    args = PyTuple_GetSlice(all_args, 1, PyTuple_GET_SIZE(all_args));
 
440
    if (args) {
 
441
        /* owner = self._owner_ref() */
 
442
        PyObject *owner = PyWeakref_GET_OBJECT(self->_owner_ref);
 
443
        /* if owner is not None: */
 
444
        if (owner != Py_None) {
 
445
            /* callbacks = self._hooks.get(name) */
 
446
            PyObject *callbacks = PyDict_GetItem(self->_hooks, name);
 
447
            Py_INCREF(owner);
 
448
            /* if callbacks: */
 
449
            if (callbacks && PySet_GET_SIZE(callbacks) != 0) {
 
450
                /* for callback, data in tuple(callbacks): */
 
451
                PyObject *sequence = \
 
452
                    PySequence_Fast(callbacks, "callbacks object isn't a set");
 
453
                if (sequence) {
 
454
                    int failed = 0;
 
455
                    Py_ssize_t i;
 
456
                    for (i = 0; i != PySequence_Fast_GET_SIZE(sequence); i++) {
 
457
                        PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
 
458
                        PyObject *callback = PyTuple_GET_ITEM(item, 0);
 
459
                        PyObject *data = PyTuple_GET_ITEM(item, 1);
 
460
                        PyObject *res;
 
461
                        /* 
 
462
                           if callback(owner, *(args+data)) is False:
 
463
                               callbacks.discard((callback, data))
 
464
                        */
 
465
                        res = EventSystem__do_emit_call(callback, owner,
 
466
                                                        args, data);
 
467
                        Py_XDECREF(res);
 
468
                        if (res == NULL ||
 
469
                            (res == Py_False &&
 
470
                             PySet_Discard(callbacks, item) == -1)) {
 
471
                            failed = 1;
 
472
                            break;
 
473
                        }
 
474
                    }
 
475
                    if (!failed) {
 
476
                        Py_INCREF(Py_None);
 
477
                        result = Py_None;
 
478
                    }
 
479
                    Py_DECREF(sequence);
 
480
                }
 
481
            } else if (!PyErr_Occurred()) {
 
482
                Py_INCREF(Py_None);
 
483
                result = Py_None;
 
484
            }
 
485
            Py_DECREF(owner);
 
486
        } else {
 
487
            Py_INCREF(Py_None);
 
488
            result = Py_None;
 
489
        }
 
490
        Py_DECREF(args);
 
491
    }
 
492
 
 
493
    return result;
 
494
}
 
495
 
 
496
 
 
497
static PyMethodDef EventSystem_methods[] = {
 
498
    {"hook", (PyCFunction)EventSystem_hook, METH_VARARGS, NULL},
 
499
    {"unhook", (PyCFunction)EventSystem_unhook, METH_VARARGS, NULL},
 
500
    {"emit", (PyCFunction)EventSystem_emit, METH_VARARGS, NULL},
 
501
    {NULL, NULL}
 
502
};
 
503
 
 
504
#define OFFSETOF(x) offsetof(EventSystemObject, x)
 
505
static PyMemberDef EventSystem_members[] = {
 
506
    {"_object_ref", T_OBJECT, OFFSETOF(_owner_ref), READONLY, 0},
 
507
    {"_hooks", T_OBJECT, OFFSETOF(_hooks), READONLY, 0},
 
508
    {NULL}
 
509
};
 
510
#undef OFFSETOF
 
511
 
 
512
statichere PyTypeObject EventSystem_Type = {
 
513
    PyObject_HEAD_INIT(NULL)
 
514
    0,            /*ob_size*/
 
515
    "storm.variables.EventSystem",    /*tp_name*/
 
516
    sizeof(EventSystemObject), /*tp_basicsize*/
 
517
    0,            /*tp_itemsize*/
 
518
    (destructor)EventSystem_dealloc, /*tp_dealloc*/
 
519
    0,            /*tp_print*/
 
520
    0,            /*tp_getattr*/
 
521
    0,            /*tp_setattr*/
 
522
    0,            /*tp_compare*/
 
523
    0,          /*tp_repr*/
 
524
    0,            /*tp_as_number*/
 
525
    0,            /*tp_as_sequence*/
 
526
    0,            /*tp_as_mapping*/
 
527
    0,                      /*tp_hash*/
 
528
    0,                      /*tp_call*/
 
529
    0,                      /*tp_str*/
 
530
    PyObject_GenericGetAttr,/*tp_getattro*/
 
531
    PyObject_GenericSetAttr,/*tp_setattro*/
 
532
    0,                      /*tp_as_buffer*/
 
533
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
 
534
    0,                      /*tp_doc*/
 
535
    (traverseproc)EventSystem_traverse,  /*tp_traverse*/
 
536
    (inquiry)EventSystem_clear,          /*tp_clear*/
 
537
    0,                      /*tp_richcompare*/
 
538
    0,                      /*tp_weaklistoffset*/
 
539
    0,                      /*tp_iter*/
 
540
    0,                      /*tp_iternext*/
 
541
    EventSystem_methods,        /*tp_methods*/
 
542
    EventSystem_members,        /*tp_members*/
 
543
    0,                      /*tp_getset*/
 
544
    0,                      /*tp_base*/
 
545
    0,                      /*tp_dict*/
 
546
    0,                      /*tp_descr_get*/
 
547
    0,                      /*tp_descr_set*/
 
548
    0,                      /*tp_dictoffset*/
 
549
    (initproc)EventSystem_init, /*tp_init*/
 
550
    PyType_GenericAlloc,    /*tp_alloc*/
 
551
    PyType_GenericNew,      /*tp_new*/
 
552
    PyObject_GC_Del,        /*tp_free*/
 
553
    0,                      /*tp_is_gc*/
 
554
};
 
555
 
 
556
 
123
557
static PyObject *
124
558
Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
125
559
{
149
583
static int
150
584
Variable_init(VariableObject *self, PyObject *args, PyObject *kwargs)
151
585
{
152
 
    static char *kwlist[] = {"value", "value_factory", "from_db", "allow_none",
153
 
                             "column", "event", NULL};
 
586
    static char *kwlist[] = {"value", "value_factory", "from_db",
 
587
                             "allow_none", "column", "event", "validator",
 
588
                             "validator_object_factory", "validator_attribute",
 
589
                             NULL};
154
590
 
155
591
    PyObject *value = Undef;
156
592
    PyObject *value_factory = Undef;
158
594
    PyObject *allow_none = Py_True;
159
595
    PyObject *column = Py_None;
160
596
    PyObject *event = Py_None;
161
 
    PyObject *result;
 
597
    PyObject *validator = Py_None;
 
598
    PyObject *validator_object_factory = Py_None;
 
599
    PyObject *validator_attribute = Py_None;
 
600
    PyObject *tmp;
162
601
 
163
 
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOOO", kwlist, &value,
 
602
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOOOOOO", kwlist, &value,
164
603
                                     &value_factory, &from_db, &allow_none,
165
 
                                     &column, &event))
 
604
                                     &column, &event, &validator,
 
605
                                     &validator_object_factory,
 
606
                                     &validator_attribute))
166
607
        return -1;
167
608
 
168
609
    /* if not allow_none: */
169
610
    if (allow_none != Py_True &&
170
611
        (allow_none == Py_False || !PyObject_IsTrue(allow_none))) {
171
 
          /* self._allow_none = False */
172
 
          Py_INCREF(Py_False);
173
 
          self->_allow_none = Py_False;
 
612
        /* self._allow_none = False */
 
613
        Py_INCREF(Py_False);
 
614
        REPLACE(self->_allow_none, Py_False);
174
615
    }
175
616
 
176
617
    /* if value is not Undef: */
177
618
    if (value != Undef) {
178
619
        /* self.set(value, from_db) */
179
 
        result = PyObject_CallMethod((PyObject *)self,
180
 
                                     "set", "OO", value, from_db);
181
 
        if (!result) return -1;
 
620
        CATCH(NULL, tmp = PyObject_CallMethod((PyObject *)self,
 
621
                                              "set", "OO", value, from_db));
 
622
        Py_DECREF(tmp);
182
623
    }
183
624
    /* elif value_factory is not Undef: */
184
625
    else if (value_factory != Undef) {
185
626
        /* self.set(value_factory(), from_db) */
186
 
        value = PyObject_CallFunctionObjArgs(value_factory, NULL);
187
 
        result = PyObject_CallMethod((PyObject *)self,
188
 
                                     "set", "OO", value, from_db);
189
 
        if (!result) return -1;
190
 
    }
191
 
    
 
627
        CATCH(NULL, value = PyObject_CallFunctionObjArgs(value_factory, NULL));
 
628
        tmp = PyObject_CallMethod((PyObject *)self,
 
629
                                  "set", "OO", value, from_db);
 
630
        Py_DECREF(value);
 
631
        CATCH(NULL, tmp);
 
632
        Py_DECREF(tmp);
 
633
    }
 
634
 
 
635
    /* if validator is not None: */
 
636
    if (validator != Py_None) {
 
637
        /* self._validator = validator */
 
638
        Py_INCREF(validator);
 
639
        self->_validator = validator;
 
640
        /* self._validator_object_factory = validator_object_factory */
 
641
        Py_INCREF(validator_object_factory);
 
642
        self->_validator_object_factory = validator_object_factory;
 
643
        /* self._validator_attribute = validator_attribute */
 
644
        Py_INCREF(validator_attribute);
 
645
        self->_validator_attribute = validator_attribute;
 
646
    }
 
647
 
192
648
    /* self.column = column */
 
649
    Py_DECREF(self->column);
193
650
    Py_INCREF(column);
194
651
    self->column = column;
195
652
 
196
653
    /* self.event = event */
 
654
    Py_DECREF(self->event);
197
655
    Py_INCREF(event);
198
656
    self->event = event;
199
657
 
200
658
    return 0;
 
659
 
 
660
error:
 
661
    return -1;
201
662
}
202
663
 
203
664
static int
207
668
    Py_VISIT(self->_lazy_value);
208
669
    Py_VISIT(self->_checkpoint_state);
209
670
    /* Py_VISIT(self->_allow_none); */
 
671
    Py_VISIT(self->_validator);
 
672
    Py_VISIT(self->_validator_object_factory);
 
673
    Py_VISIT(self->_validator_attribute);
210
674
    Py_VISIT(self->column);
211
675
    Py_VISIT(self->event);
212
676
    return 0;
219
683
    Py_CLEAR(self->_lazy_value);
220
684
    Py_CLEAR(self->_checkpoint_state);
221
685
    Py_CLEAR(self->_allow_none);
 
686
    Py_CLEAR(self->_validator);
 
687
    Py_CLEAR(self->_validator_object_factory);
 
688
    Py_CLEAR(self->_validator_attribute);
222
689
    Py_CLEAR(self->column);
223
690
    Py_CLEAR(self->event);
224
691
    return 0;
308
775
    static char *kwlist[] = {"default", "to_db", NULL};
309
776
    PyObject *default_ = Py_None;
310
777
    PyObject *to_db = Py_False;
311
 
    PyObject *result;
312
778
 
313
779
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:get", kwlist,
314
780
                                     &default_, &to_db))
316
782
 
317
783
    /* if self._lazy_value is not Undef and self.event is not None: */
318
784
    if (self->_lazy_value != Undef && self->event != Py_None) {
 
785
        PyObject *tmp;
319
786
        /* self.event.emit("resolve-lazy-value", self, self._lazy_value) */
320
 
        result = PyObject_CallMethod(self->event, "emit", "sOO",
321
 
                                     "resolve-lazy-value", self,
322
 
                                     self->_lazy_value);
323
 
        if (!result)
324
 
            return NULL;
325
 
        Py_DECREF(result);
 
787
        CATCH(NULL, tmp = PyObject_CallMethod(self->event, "emit", "sOO",
 
788
                                              "resolve-lazy-value", self,
 
789
                                              self->_lazy_value));
 
790
        Py_DECREF(tmp);
326
791
    }
327
792
 
328
793
    /* value = self->_value */
336
801
    /* if value is None: */
337
802
    if (self->_value == Py_None) {
338
803
        /* return None */
339
 
        Py_INCREF(Py_None);
340
 
        return Py_None;
 
804
        Py_RETURN_NONE;
341
805
    }
342
806
 
343
807
    /* return self.parse_get(value, to_db) */
344
808
    return PyObject_CallMethod((PyObject *)self, "parse_get",
345
809
                               "OO", self->_value, to_db);
 
810
 
 
811
error:
 
812
    return NULL;
346
813
}
347
814
 
348
815
static PyObject *
353
820
    PyObject *from_db = Py_False;
354
821
    PyObject *old_value = NULL;
355
822
    PyObject *new_value = NULL;
356
 
    PyObject *result;
 
823
    PyObject *tmp;
357
824
 
358
825
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:set", kwlist,
359
826
                                     &value, &from_db))
365
832
    if (PyObject_IsInstance(value, LazyValue)) {
366
833
        /* self._lazy_value = value */
367
834
        Py_INCREF(value);
368
 
        Py_DECREF(self->_lazy_value);
369
 
        self->_lazy_value = value;
 
835
        REPLACE(self->_lazy_value, value);
370
836
 
371
837
        /* new_value = Undef */
372
838
        Py_INCREF(Undef);
374
840
    }
375
841
    /* else: */
376
842
    else {
 
843
        /* if not from_db and self._validator is not None: */
 
844
        if (self->_validator && !PyObject_IsTrue(from_db)) {
 
845
            /* value = self._validator(self._validator_object_factory and
 
846
                                       self._validator_object_factory(),
 
847
                                       self._validator_attribute, value) */
 
848
            PyObject *validator_object, *tmp;
 
849
            if (self->_validator_object_factory == Py_None) {
 
850
                Py_INCREF(Py_None);
 
851
                validator_object = Py_None;
 
852
            } else {
 
853
                CATCH(NULL, validator_object = PyObject_CallFunctionObjArgs(
 
854
                                self->_validator_object_factory, NULL));
 
855
            }
 
856
            tmp = PyObject_CallFunctionObjArgs(self->_validator,
 
857
                                               validator_object,
 
858
                                               self->_validator_attribute,
 
859
                                               value, NULL);
 
860
            Py_DECREF(validator_object);
 
861
            CATCH(NULL, tmp);
 
862
 
 
863
            Py_DECREF(value);
 
864
            value = tmp;
 
865
        }
 
866
 
377
867
        /* self._lazy_value = Undef */
378
868
        Py_INCREF(Undef);
379
869
        Py_DECREF(self->_lazy_value);
384
874
            /* if self._allow_none is False: */
385
875
            if (self->_allow_none == Py_False) {
386
876
                /* raise_none_error(self.column) */
387
 
                result = PyObject_CallFunctionObjArgs(raise_none_error,
388
 
                                                      self->column, NULL);
389
 
                /* result should always be NULL here. */
390
 
                Py_XDECREF(result);
 
877
                tmp = PyObject_CallFunctionObjArgs(raise_none_error,
 
878
                                                   self->column, NULL);
 
879
                /* tmp should always be NULL here. */
 
880
                Py_XDECREF(tmp);
391
881
                goto error;
392
882
            }
393
883
 
398
888
        /* else: */
399
889
        else {
400
890
            /* new_value = self.parse_set(value, from_db) */
401
 
            new_value = PyObject_CallMethod((PyObject *)self, "parse_set",
402
 
                                            "OO", value, from_db);
403
 
            if (!new_value)
404
 
                goto error;
 
891
            CATCH(NULL,
 
892
                  new_value = PyObject_CallMethod((PyObject *)self, "parse_set",
 
893
                                                  "OO", value, from_db));
405
894
 
406
895
            /* if from_db: */
407
896
            if (PyObject_IsTrue(from_db)) {
408
897
                /* value = self.parse_get(new_value, False) */
409
898
                Py_DECREF(value);
410
 
                value = PyObject_CallMethod((PyObject *)self, "parse_get",
411
 
                                            "OO", new_value, Py_False);
412
 
                if (!value)
413
 
                    goto error;
 
899
                CATCH(NULL,
 
900
                      value = PyObject_CallMethod((PyObject *)self, "parse_get",
 
901
                                                  "OO", new_value, Py_False));
414
902
            }
415
903
        }
416
904
    }
432
920
        /* if old_value is not None and old_value is not Undef: */
433
921
        if (old_value != Py_None && old_value != Undef) {
434
922
            /* old_value = self.parse_get(old_value, False) */
435
 
            result = PyObject_CallMethod((PyObject *)self, "parse_get",
436
 
                                         "OO", old_value, Py_False);
437
 
            if (!result)
438
 
                goto error;
439
 
 
 
923
            CATCH(NULL, tmp = PyObject_CallMethod((PyObject *)self, "parse_get",
 
924
                                                  "OO", old_value, Py_False));
440
925
            Py_DECREF(old_value);
441
 
            old_value = result;
 
926
            old_value = tmp;
442
927
        }
443
928
        /* self.event.emit("changed", self, old_value, value, from_db) */
444
 
        result = PyObject_CallMethod((PyObject *)self->event, "emit", "sOOOO",
445
 
                                     "changed", self, old_value, value,
446
 
                                     from_db);
447
 
        if (!result)
448
 
            goto error;
449
 
        Py_DECREF(result);
 
929
        CATCH(NULL, tmp = PyObject_CallMethod((PyObject *)self->event, "emit",
 
930
                                              "sOOOO", "changed", self,
 
931
                                              old_value, value, from_db));
 
932
        Py_DECREF(tmp);
450
933
    }
451
934
 
452
935
    Py_DECREF(value);
453
936
    Py_DECREF(old_value);
454
937
    Py_DECREF(new_value);
455
 
    Py_INCREF(Py_None);
456
 
    return Py_None;
 
938
 
 
939
    Py_RETURN_NONE;
457
940
 
458
941
error:
459
942
    Py_XDECREF(value);
465
948
static PyObject *
466
949
Variable_delete(VariableObject *self, PyObject *args)
467
950
{
 
951
    PyObject *old_value;
 
952
    PyObject *tmp;
 
953
 
468
954
    /* old_value = self._value */
469
 
    PyObject *old_value = self->_value;
470
 
    PyObject *result;
 
955
    old_value = self->_value;
 
956
    Py_INCREF(old_value);
471
957
 
472
958
    /* if old_value is not Undef: */
473
959
    if (old_value != Undef) {
474
960
 
475
961
        /* self._value = Undef */
 
962
        Py_DECREF(self->_value);
476
963
        Py_INCREF(Undef);
477
964
        self->_value = Undef;
478
965
 
481
968
            /* if old_value is not None and old_value is not Undef: */
482
969
            if (old_value != Py_None && old_value != Undef) {
483
970
                /* old_value = self.parse_get(old_value, False) */
484
 
                result = PyObject_CallMethod((PyObject *)self, "parse_get",
485
 
                                             "OO", old_value, Py_False);
486
 
                if (!result)
487
 
                    return NULL;
488
 
 
 
971
                CATCH(NULL,
 
972
                      tmp = PyObject_CallMethod((PyObject *)self, "parse_get",
 
973
                                                "OO", old_value, Py_False));
489
974
                Py_DECREF(old_value);
490
 
                old_value = result;
 
975
                old_value = tmp;
491
976
            }
492
977
 
493
978
            /* self.event.emit("changed", self, old_value, Undef, False) */
494
 
            result = PyObject_CallMethod((PyObject *)self->event, "emit",
495
 
                                         "sOOOO", "changed", self, old_value,
496
 
                                         Undef, Py_False);
497
 
            if (!result)
498
 
                return NULL;
499
 
            Py_DECREF(result);
 
979
            CATCH(NULL,
 
980
                  tmp = PyObject_CallMethod((PyObject *)self->event, "emit",
 
981
                                            "sOOOO", "changed", self, old_value,
 
982
                                            Undef, Py_False));
 
983
            Py_DECREF(tmp);
500
984
        }
501
985
    }
502
986
 
503
987
    Py_DECREF(old_value);
504
 
    Py_INCREF(Py_None);
505
 
    return Py_None;
 
988
    Py_RETURN_NONE;
 
989
 
 
990
error:
 
991
    Py_XDECREF(old_value);
 
992
    return NULL;
506
993
}
507
994
 
508
995
static PyObject *
519
1006
               self.get_state() != self._checkpoint_state) */
520
1007
    PyObject *result = Py_True;
521
1008
    if (self->_lazy_value == Undef) {
522
 
        PyObject *state = PyObject_CallMethod((PyObject *)self,
523
 
                                              "get_state", NULL);
 
1009
        PyObject *state;
524
1010
        int res;
525
 
        if (state == NULL)
526
 
            return NULL;
 
1011
        CATCH(NULL, state = PyObject_CallMethod((PyObject *)self,
 
1012
                                                "get_state", NULL));
527
1013
        res = PyObject_RichCompareBool(state, self->_checkpoint_state, Py_EQ);
528
1014
        Py_DECREF(state);
529
 
        if (res == -1)
530
 
            return NULL;
 
1015
        CATCH(-1, res);
531
1016
        if (res)
532
1017
            result = Py_False;
533
1018
    }
534
1019
    Py_INCREF(result);
535
1020
    return result;
 
1021
 
 
1022
error:
 
1023
    return NULL;
536
1024
}
537
1025
 
538
1026
static PyObject *
539
1027
Variable_get_state(VariableObject *self, PyObject *args)
540
1028
{
541
 
    /* return self._value is not Undef */
542
 
    PyObject *result = PyTuple_New(2);
543
 
    if (!result)
544
 
        return NULL;
 
1029
    /* return (self._lazy_value, self._value) */
 
1030
    PyObject *result;
 
1031
    CATCH(NULL, result = PyTuple_New(2));
545
1032
    Py_INCREF(self->_lazy_value);
546
1033
    Py_INCREF(self->_value);
547
1034
    PyTuple_SET_ITEM(result, 0, self->_lazy_value);
548
1035
    PyTuple_SET_ITEM(result, 1, self->_value);
549
1036
    return result;
 
1037
error:
 
1038
    return NULL;
550
1039
}
551
1040
 
552
1041
static PyObject *
553
1042
Variable_set_state(VariableObject *self, PyObject *args)
554
1043
{
555
1044
    /* self._lazy_value, self._value = state */
556
 
    if (!PyArg_ParseTuple(args, "(OO):set_state",
557
 
                          &self->_lazy_value, &self->_value))
 
1045
    PyObject *lazy_value, *value;
 
1046
    if (!PyArg_ParseTuple(args, "(OO):set_state", &lazy_value, &value))
558
1047
        return NULL;
559
 
    Py_INCREF(self->_lazy_value);
560
 
    Py_INCREF(self->_value);
561
 
    Py_INCREF(Py_None);
562
 
    return Py_None;
 
1048
    Py_INCREF(lazy_value);
 
1049
    REPLACE(self->_lazy_value, lazy_value);
 
1050
    Py_INCREF(value);
 
1051
    REPLACE(self->_value, value);
 
1052
    Py_RETURN_NONE;
563
1053
}
564
1054
 
565
1055
static PyObject *
571
1061
        return NULL;
572
1062
    Py_DECREF(self->_checkpoint_state);
573
1063
    self->_checkpoint_state = state;
574
 
    Py_INCREF(Py_None);
575
 
    return Py_None;
 
1064
    Py_RETURN_NONE;
576
1065
}
577
1066
 
578
1067
static PyObject *
579
1068
Variable_copy(VariableObject *self, PyObject *args)
580
1069
{
581
 
    PyObject *noargs, *variable, *state, *result;
 
1070
    PyObject *noargs = NULL;
 
1071
    PyObject *variable = NULL;
 
1072
    PyObject *state = NULL;
 
1073
    PyObject *tmp;
 
1074
 
582
1075
    /* variable = self.__class__.__new__(self.__class__) */
583
1076
    noargs = PyTuple_New(0);
584
 
    variable = self->ob_type->tp_new(self->ob_type, noargs, NULL);
 
1077
    CATCH(NULL, variable = self->ob_type->tp_new(self->ob_type, noargs, NULL));
 
1078
 
 
1079
    /* variable.set_state(self.get_state()) */
 
1080
    CATCH(NULL,
 
1081
          state = PyObject_CallMethod((PyObject *)self, "get_state", NULL));
 
1082
 
 
1083
    CATCH(NULL, tmp = PyObject_CallMethod((PyObject *)variable,
 
1084
                                          "set_state", "(O)", state));
 
1085
    Py_DECREF(tmp);
 
1086
 
585
1087
    Py_DECREF(noargs);
586
 
    if (!variable)
587
 
        return NULL;
588
 
    /* variable.set_state(self.get_state()) */
589
 
    state = PyObject_CallMethod((PyObject *)self, "get_state", NULL);
590
 
    if (!state) {
591
 
        Py_DECREF(variable);
592
 
        return NULL;
593
 
    }
594
 
    result = PyObject_CallMethod((PyObject *)variable,
595
 
                                 "set_state", "(O)", state);
596
1088
    Py_DECREF(state);
597
 
    if (!result) {
598
 
        Py_DECREF(variable);
599
 
        return NULL;
600
 
    }
601
 
    Py_DECREF(result);
602
1089
    return variable;
 
1090
 
 
1091
error:
 
1092
    Py_XDECREF(noargs);
 
1093
    Py_XDECREF(state);
 
1094
    Py_XDECREF(variable);
 
1095
    return NULL;
603
1096
}
604
1097
 
605
1098
static PyMethodDef Variable_methods[] = {
678
1171
 
679
1172
 
680
1173
static PyObject *
 
1174
Compile__update_cache(CompileObject *self, PyObject *args);
 
1175
 
 
1176
static int
 
1177
Compile_init(CompileObject *self, PyObject *args, PyObject *kwargs)
 
1178
{
 
1179
    static char *kwlist[] = {"parent", NULL};
 
1180
 
 
1181
    PyObject *parent = Py_None;
 
1182
 
 
1183
    PyObject *module = NULL;
 
1184
    PyObject *WeakKeyDictionary = NULL;
 
1185
 
 
1186
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &parent))
 
1187
        return -1;
 
1188
 
 
1189
    /*
 
1190
       self._local_dispatch_table = {}
 
1191
       self._local_precedence = {}
 
1192
       self._local_reserved_words = {}
 
1193
       self._dispatch_table = {}
 
1194
       self._precedence = {}
 
1195
       self._reserved_words = {}
 
1196
    */
 
1197
    CATCH(NULL, self->_local_dispatch_table = PyDict_New());
 
1198
    CATCH(NULL, self->_local_precedence = PyDict_New());
 
1199
    CATCH(NULL, self->_local_reserved_words = PyDict_New());
 
1200
    CATCH(NULL, self->_dispatch_table = PyDict_New());
 
1201
    CATCH(NULL, self->_precedence = PyDict_New());
 
1202
    CATCH(NULL, self->_reserved_words = PyDict_New());
 
1203
 
 
1204
    /* self._children = WeakKeyDictionary() */
 
1205
    CATCH(NULL, module = PyImport_ImportModule("weakref"));
 
1206
    CATCH(NULL, WeakKeyDictionary = \
 
1207
                    PyObject_GetAttrString(module, "WeakKeyDictionary"));
 
1208
    Py_CLEAR(module);
 
1209
    CATCH(NULL, self->_children = \
 
1210
                    PyObject_CallFunctionObjArgs(WeakKeyDictionary, NULL));
 
1211
    Py_CLEAR(WeakKeyDictionary);
 
1212
 
 
1213
    /* self._parents = [] */
 
1214
    CATCH(NULL, self->_parents = PyList_New(0));
 
1215
 
 
1216
    /* if parent: */
 
1217
    if (parent != Py_None) {
 
1218
        PyObject *tmp;
 
1219
 
 
1220
        /* self._parents.extend(parent._parents) */
 
1221
        CompileObject *parent_object = (CompileObject *)parent;
 
1222
        CATCH(-1, PyList_SetSlice(self->_parents, 0, 0,
 
1223
                                  parent_object->_parents));
 
1224
 
 
1225
        /* self._parents.append(parent) */
 
1226
        CATCH(-1, PyList_Append(self->_parents, parent));
 
1227
 
 
1228
        /* parent._children[self] = True */
 
1229
        CATCH(-1, PyObject_SetItem(parent_object->_children,
 
1230
                                   (PyObject *)self, Py_True));
 
1231
 
 
1232
        /* self._update_cache() */
 
1233
        CATCH(NULL, tmp = Compile__update_cache(self, NULL));
 
1234
        Py_DECREF(tmp);
 
1235
    }
 
1236
 
 
1237
    return 0;
 
1238
 
 
1239
error:
 
1240
    Py_XDECREF(module);
 
1241
    Py_XDECREF(WeakKeyDictionary);
 
1242
    return -1;
 
1243
}
 
1244
 
 
1245
static int
 
1246
Compile_traverse(CompileObject *self, visitproc visit, void *arg)
 
1247
{
 
1248
    Py_VISIT(self->_local_dispatch_table);
 
1249
    Py_VISIT(self->_local_precedence);
 
1250
    Py_VISIT(self->_local_reserved_words);
 
1251
    Py_VISIT(self->_dispatch_table);
 
1252
    Py_VISIT(self->_precedence);
 
1253
    Py_VISIT(self->_reserved_words);
 
1254
    Py_VISIT(self->_children);
 
1255
    Py_VISIT(self->_parents);
 
1256
    return 0;
 
1257
}
 
1258
 
 
1259
static int
 
1260
Compile_clear(CompileObject *self)
 
1261
{
 
1262
    if (self->__weakreflist)
 
1263
        PyObject_ClearWeakRefs((PyObject *)self);
 
1264
    Py_CLEAR(self->_local_dispatch_table);
 
1265
    Py_CLEAR(self->_local_precedence);
 
1266
    Py_CLEAR(self->_local_reserved_words);
 
1267
    Py_CLEAR(self->_dispatch_table);
 
1268
    Py_CLEAR(self->_precedence);
 
1269
    Py_CLEAR(self->_reserved_words);
 
1270
    Py_CLEAR(self->_children);
 
1271
    Py_CLEAR(self->_parents);
 
1272
    return 0;
 
1273
}
 
1274
 
 
1275
static void
 
1276
Compile_dealloc(CompileObject *self)
 
1277
{
 
1278
    Compile_clear(self);
 
1279
    self->ob_type->tp_free((PyObject *)self);
 
1280
}
 
1281
 
 
1282
static PyObject *
 
1283
Compile__update_cache(CompileObject *self, PyObject *args)
 
1284
{
 
1285
    PyObject *iter = NULL;
 
1286
    PyObject *child = NULL;
 
1287
    Py_ssize_t size;
 
1288
    int i;
 
1289
 
 
1290
    /* for parent in self._parents: */
 
1291
    size = PyList_GET_SIZE(self->_parents);
 
1292
    for (i = 0; i != size; i++) {
 
1293
        CompileObject *parent = \
 
1294
            (CompileObject *)PyList_GET_ITEM(self->_parents, i);
 
1295
        /* self._dispatch_table.update(parent._local_dispatch_table) */
 
1296
        CATCH(-1, PyDict_Update(self->_dispatch_table,
 
1297
                                parent->_local_dispatch_table));
 
1298
        /* self._precedence.update(parent._local_precedence) */
 
1299
        CATCH(-1, PyDict_Update(self->_precedence,
 
1300
                                parent->_local_precedence));
 
1301
        /* self._reserved_words.update(parent._local_reserved_words) */
 
1302
        CATCH(-1, PyDict_Update(self->_reserved_words,
 
1303
                                parent->_local_reserved_words));
 
1304
    }
 
1305
    /* self._dispatch_table.update(self._local_dispatch_table) */
 
1306
    CATCH(-1, PyDict_Update(self->_dispatch_table,
 
1307
                            self->_local_dispatch_table));
 
1308
    /* self._precedence.update(self._local_precedence) */
 
1309
    CATCH(-1, PyDict_Update(self->_precedence, self->_local_precedence));
 
1310
    /* self._reserved_words.update(self._local_reserved_words) */
 
1311
    CATCH(-1, PyDict_Update(self->_reserved_words,
 
1312
                            self->_local_reserved_words));
 
1313
 
 
1314
    /* for child in self._children: */
 
1315
    CATCH(NULL, iter = PyObject_GetIter(self->_children));
 
1316
    while((child = PyIter_Next(iter))) {
 
1317
        PyObject *tmp;
 
1318
 
 
1319
        /* child._update_cache() */
 
1320
        CATCH(NULL, tmp = Compile__update_cache((CompileObject *)child, NULL));
 
1321
        Py_DECREF(tmp);
 
1322
        Py_DECREF(child);
 
1323
    }
 
1324
    if (PyErr_Occurred())
 
1325
        goto error;
 
1326
    Py_CLEAR(iter);
 
1327
 
 
1328
    Py_RETURN_NONE;
 
1329
 
 
1330
error:
 
1331
    Py_XDECREF(child);
 
1332
    Py_XDECREF(iter);
 
1333
    return NULL;
 
1334
}
 
1335
 
 
1336
static PyObject *
 
1337
Compile_when(CompileObject *self, PyObject *types)
 
1338
{
 
1339
    PyObject *result = NULL;
 
1340
    PyObject *module = PyImport_ImportModule("storm.expr");
 
1341
    if (module) {
 
1342
        PyObject *_when = PyObject_GetAttrString(module, "_when");
 
1343
        if (_when) {
 
1344
            result = PyObject_CallFunctionObjArgs(_when, self, types, NULL);
 
1345
            Py_DECREF(_when);
 
1346
        }
 
1347
        Py_DECREF(module);
 
1348
    }
 
1349
    return result;    
 
1350
}
 
1351
 
 
1352
static PyObject *
 
1353
Compile_add_reserved_words(CompileObject *self, PyObject *words)
 
1354
{
 
1355
    PyObject *lower_word = NULL;
 
1356
    PyObject *iter = NULL;
 
1357
    PyObject *word = NULL;
 
1358
    PyObject *tmp;
 
1359
 
 
1360
    /* self._local_reserved_words.update((word.lower(), True)
 
1361
                                         for word in words) */
 
1362
    CATCH(NULL, iter = PyObject_GetIter(words));
 
1363
    while ((word = PyIter_Next(iter))) {
 
1364
        CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
 
1365
        CATCH(-1, PyDict_SetItem(self->_local_reserved_words,
 
1366
                                 lower_word, Py_True));
 
1367
        Py_CLEAR(lower_word);
 
1368
        Py_DECREF(word);
 
1369
    }
 
1370
    if (PyErr_Occurred())
 
1371
        goto error;
 
1372
    Py_CLEAR(iter);
 
1373
 
 
1374
    /* self._update_cache() */
 
1375
    CATCH(NULL, tmp = Compile__update_cache(self, NULL));
 
1376
    Py_DECREF(tmp);
 
1377
 
 
1378
    Py_RETURN_NONE;
 
1379
 
 
1380
error:
 
1381
    Py_XDECREF(lower_word);
 
1382
    Py_XDECREF(word);
 
1383
    Py_XDECREF(iter);
 
1384
    return NULL;
 
1385
}
 
1386
 
 
1387
static PyObject *
 
1388
Compile_remove_reserved_words(CompileObject *self, PyObject *words)
 
1389
{
 
1390
    PyObject *lower_word = NULL;
 
1391
    PyObject *word = NULL;
 
1392
    PyObject *iter = NULL;
 
1393
    PyObject *tmp;
 
1394
 
 
1395
    /* self._local_reserved_words.update((word.lower(), None)
 
1396
                                         for word in words) */
 
1397
    CATCH(NULL, iter = PyObject_GetIter(words));
 
1398
    while ((word = PyIter_Next(iter))) {
 
1399
        CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
 
1400
        CATCH(-1, PyDict_SetItem(self->_local_reserved_words,
 
1401
                                 lower_word, Py_None));
 
1402
        Py_CLEAR(lower_word);
 
1403
        Py_DECREF(word);
 
1404
    }
 
1405
    if (PyErr_Occurred())
 
1406
        goto error;
 
1407
    Py_CLEAR(iter);
 
1408
 
 
1409
    /* self._update_cache() */
 
1410
    CATCH(NULL, tmp = Compile__update_cache(self, NULL));
 
1411
    Py_DECREF(tmp);
 
1412
 
 
1413
    Py_RETURN_NONE;
 
1414
 
 
1415
error:
 
1416
    Py_XDECREF(lower_word);
 
1417
    Py_XDECREF(word);
 
1418
    Py_XDECREF(iter);
 
1419
    return NULL;
 
1420
}
 
1421
 
 
1422
static PyObject *
 
1423
Compile_is_reserved_word(CompileObject *self, PyObject *word)
 
1424
{
 
1425
    PyObject *lower_word = NULL;
 
1426
    PyObject *result = Py_False;
 
1427
    PyObject *item;
 
1428
 
 
1429
    /* return self._reserved_words.get(word.lower()) is not None */
 
1430
    CATCH(NULL, lower_word = PyObject_CallMethod(word, "lower", NULL));
 
1431
    item = PyDict_GetItem(self->_reserved_words, lower_word);
 
1432
    if (item == NULL && PyErr_Occurred()) {
 
1433
        goto error; 
 
1434
    } else if (item != NULL && item != Py_None) {
 
1435
        result = Py_True;
 
1436
    }
 
1437
    Py_DECREF(lower_word);
 
1438
    Py_INCREF(result);
 
1439
    return result;
 
1440
 
 
1441
error:
 
1442
    Py_XDECREF(lower_word);
 
1443
    return NULL;
 
1444
}
 
1445
 
 
1446
staticforward PyTypeObject Compile_Type;
 
1447
 
 
1448
static PyObject *
 
1449
Compile_create_child(CompileObject *self, PyObject *args)
 
1450
{
 
1451
    /* return self.__class__(self) */
 
1452
    return PyObject_CallFunctionObjArgs((PyObject *)self->ob_type, self, NULL);
 
1453
}
 
1454
 
 
1455
static PyObject *
 
1456
Compile_get_precedence(CompileObject *self, PyObject *type)
 
1457
{
 
1458
    /* return self._precedence.get(type, MAX_PRECEDENCE) */
 
1459
    PyObject *result = PyDict_GetItem(self->_precedence, type);
 
1460
    if (result == NULL && !PyErr_Occurred()) {
 
1461
        /* That should be MAX_PRECEDENCE, defined in expr.py */
 
1462
        return PyInt_FromLong(1000);
 
1463
    }
 
1464
    Py_INCREF(result);
 
1465
    return result;
 
1466
}
 
1467
 
 
1468
static PyObject *
 
1469
Compile_set_precedence(CompileObject *self, PyObject *args)
 
1470
{
 
1471
    Py_ssize_t size = PyTuple_GET_SIZE(args);
 
1472
    PyObject *precedence = NULL;
 
1473
    PyObject *tmp;
 
1474
    int i;
 
1475
 
 
1476
    if (size < 2) {
 
1477
        PyErr_SetString(PyExc_TypeError,
 
1478
                        "set_precedence() takes at least 2 arguments.");
 
1479
        return NULL;
 
1480
    }
 
1481
 
 
1482
    /* for type in types: */
 
1483
    precedence = PyTuple_GET_ITEM(args, 0);
 
1484
    for (i = 1; i != size; i++) {
 
1485
        PyObject *type = PyTuple_GET_ITEM(args, i);
 
1486
        /* self._local_precedence[type] = precedence */
 
1487
        CATCH(-1, PyDict_SetItem(self->_local_precedence, type, precedence));
 
1488
    }
 
1489
 
 
1490
    /* self._update_cache() */
 
1491
    CATCH(NULL, tmp = Compile__update_cache(self, NULL));
 
1492
    Py_DECREF(tmp);
 
1493
 
 
1494
    Py_RETURN_NONE;
 
1495
error:
 
1496
    return NULL;
 
1497
}
 
1498
 
 
1499
PyObject *
 
1500
Compile_single(CompileObject *self,
 
1501
               PyObject *expr, PyObject *state, PyObject *outer_precedence)
 
1502
{
 
1503
    PyObject *inner_precedence = NULL;
 
1504
    PyObject *statement = NULL;
 
1505
 
 
1506
    /* cls = expr.__class__ */
 
1507
    PyObject *cls = (PyObject *)expr->ob_type;
 
1508
 
 
1509
    /*
 
1510
       dispatch_table = self._dispatch_table
 
1511
       if cls in dispatch_table:
 
1512
           handler = dispatch_table[cls]
 
1513
       else:
 
1514
    */
 
1515
    PyObject *handler = PyDict_GetItem(self->_dispatch_table, cls);
 
1516
    if (!handler) {
 
1517
        PyObject *mro;
 
1518
        Py_ssize_t size, i;
 
1519
 
 
1520
        if (PyErr_Occurred())
 
1521
            goto error;
 
1522
 
 
1523
        /* for mro_cls in cls.__mro__: */
 
1524
        mro = expr->ob_type->tp_mro;
 
1525
        size = PyTuple_GET_SIZE(mro);
 
1526
        for (i = 0; i != size; i++) {
 
1527
            PyObject *mro_cls = PyTuple_GET_ITEM(mro, i);
 
1528
            /*
 
1529
               if mro_cls in dispatch_table:
 
1530
                   handler = dispatch_table[mro_cls]
 
1531
                   break
 
1532
            */
 
1533
            handler = PyDict_GetItem(self->_dispatch_table, mro_cls);
 
1534
            if (handler)
 
1535
                break;
 
1536
 
 
1537
            if (PyErr_Occurred())
 
1538
                goto error;
 
1539
        }
 
1540
        /* else: */
 
1541
        if (i == size) {
 
1542
            /*
 
1543
               raise CompileError("Don't know how to compile type %r of %r"
 
1544
                                  % (expr.__class__, expr))
 
1545
            */
 
1546
            PyObject *repr = PyObject_Repr(expr);
 
1547
            if (repr) {
 
1548
                PyErr_Format(CompileError,
 
1549
                             "Don't know how to compile type %s of %s",
 
1550
                             expr->ob_type->tp_name, PyString_AS_STRING(repr));
 
1551
                Py_DECREF(repr);
 
1552
            }
 
1553
            goto error;
 
1554
        }
 
1555
    }
 
1556
 
 
1557
    /*
 
1558
       inner_precedence = state.precedence = \
 
1559
                          self._precedence.get(cls, MAX_PRECEDENCE)
 
1560
    */
 
1561
    CATCH(NULL, inner_precedence = Compile_get_precedence(self, cls));
 
1562
    CATCH(-1, PyObject_SetAttrString(state, "precedence", inner_precedence));
 
1563
 
 
1564
    /* statement = handler(self, expr, state) */
 
1565
    CATCH(NULL, statement = PyObject_CallFunctionObjArgs(handler, self, expr,
 
1566
                                                         state, NULL));
 
1567
 
 
1568
    /* if inner_precedence < outer_precedence: */
 
1569
    if (PyObject_Compare(inner_precedence, outer_precedence) == -1) {
 
1570
        PyObject *args, *tmp;
 
1571
 
 
1572
        if (PyErr_Occurred())
 
1573
            goto error;
 
1574
 
 
1575
        /* return "(%s)" % statement */
 
1576
        CATCH(NULL, args = PyTuple_Pack(1, statement));
 
1577
        tmp = PyUnicode_Format(parenthesis_format, args);
 
1578
        Py_DECREF(args);
 
1579
        CATCH(NULL, tmp);
 
1580
        Py_DECREF(statement);
 
1581
        statement = tmp;
 
1582
    }
 
1583
 
 
1584
    Py_DECREF(inner_precedence);
 
1585
 
 
1586
    return statement;
 
1587
 
 
1588
error:
 
1589
    Py_XDECREF(inner_precedence);
 
1590
    Py_XDECREF(statement);
 
1591
 
 
1592
    return NULL;
 
1593
}
 
1594
 
 
1595
PyObject *
 
1596
Compile_one_or_many(CompileObject *self, PyObject *expr, PyObject *state,
 
1597
                    PyObject *join, int raw, int token)
 
1598
{
 
1599
    PyObject *outer_precedence = NULL;
 
1600
    PyObject *compiled = NULL;
 
1601
    PyObject *sequence = NULL;
 
1602
    PyObject *statement = NULL;
 
1603
    Py_ssize_t size, i;
 
1604
 
 
1605
    Py_INCREF(expr);
 
1606
 
 
1607
    /*
 
1608
      expr_type = type(expr)
 
1609
      if (expr_type is SQLRaw or
 
1610
          raw and (expr_type is str or expr_type is unicode)):
 
1611
          return expr
 
1612
    */  
 
1613
    if ((PyObject *)expr->ob_type == SQLRaw ||
 
1614
        (raw && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr)))) {
 
1615
        /* Pass our reference on. */
 
1616
        return expr;
 
1617
    }
 
1618
 
 
1619
    /*
 
1620
       if token and (expr_type is str or expr_type is unicode):
 
1621
           expr = SQLToken(expr)
 
1622
    */
 
1623
    if (token && (PyString_CheckExact(expr) || PyUnicode_CheckExact(expr))) {
 
1624
        PyObject *tmp;
 
1625
        CATCH(NULL, tmp = PyObject_CallFunctionObjArgs(SQLToken, expr, NULL));
 
1626
        Py_DECREF(expr);
 
1627
        expr = tmp;
 
1628
    }
 
1629
 
 
1630
    /*
 
1631
       if state is None:
 
1632
           state = State()
 
1633
    */
 
1634
    /* That's done in Compile__call__ just once. */
 
1635
 
 
1636
    /* outer_precedence = state.precedence */
 
1637
    CATCH(NULL, outer_precedence = PyObject_GetAttrString(state, "precedence"));
 
1638
    /* if expr_type is tuple or expr_type is list: */
 
1639
    if (PyTuple_CheckExact(expr) || PyList_CheckExact(expr)) {
 
1640
        /* compiled = [] */
 
1641
        CATCH(NULL, compiled = PyList_New(0));
 
1642
 
 
1643
        /* for subexpr in expr: */
 
1644
        sequence = PySequence_Fast(expr, "This can't actually fail! ;-)");
 
1645
        size = PySequence_Fast_GET_SIZE(sequence);
 
1646
        for (i = 0; i != size; i++) {
 
1647
            PyObject *subexpr = PySequence_Fast_GET_ITEM(sequence, i);
 
1648
            /*
 
1649
               subexpr_type = type(subexpr)
 
1650
               if subexpr_type is SQLRaw or raw and (subexpr_type is str or
 
1651
                                                     subexpr_type is unicode):
 
1652
            */
 
1653
            if ((PyObject *)subexpr->ob_type == (PyObject *)SQLRaw ||
 
1654
                (raw && (PyString_CheckExact(subexpr) ||
 
1655
                         PyUnicode_CheckExact(subexpr)))) {
 
1656
                /* statement = subexpr */
 
1657
                Py_INCREF(subexpr);
 
1658
                statement = subexpr;
 
1659
            /* elif subexpr_type is tuple or subexpr_type is list: */
 
1660
            } else if (PyTuple_CheckExact(subexpr) ||
 
1661
                       PyList_CheckExact(subexpr)) {
 
1662
                /* state.precedence = outer_precedence */
 
1663
                CATCH(-1, PyObject_SetAttrString(state, "precedence",
 
1664
                                                 outer_precedence));
 
1665
                /* statement = self(subexpr, state, join, raw, token) */
 
1666
                CATCH(NULL,
 
1667
                      statement = Compile_one_or_many(self, subexpr, state,
 
1668
                                                      join, raw, token));
 
1669
            /* else: */
 
1670
            } else {
 
1671
                /*
 
1672
                   if token and (subexpr_type is unicode or
 
1673
                                 subexpr_type is str):
 
1674
                */
 
1675
                if (token && (PyUnicode_CheckExact(subexpr) ||
 
1676
                              PyString_CheckExact(subexpr))) {
 
1677
                    /* subexpr = SQLToken(subexpr) */
 
1678
                    CATCH(NULL,
 
1679
                          subexpr = PyObject_CallFunctionObjArgs(SQLToken,
 
1680
                                                                 subexpr,
 
1681
                                                                 NULL));
 
1682
                } else {
 
1683
                    Py_INCREF(subexpr);
 
1684
                }
 
1685
 
 
1686
                /* 
 
1687
                   statement = self._compile_single(subexpr, state,
 
1688
                                                    outer_precedence)
 
1689
                */
 
1690
                statement = Compile_single(self, subexpr, state,
 
1691
                                           outer_precedence);
 
1692
                Py_DECREF(subexpr);
 
1693
                CATCH(NULL, statement);
 
1694
            }
 
1695
            
 
1696
            /* compiled.append(statement) */
 
1697
            CATCH(-1, PyList_Append(compiled, statement));
 
1698
            Py_CLEAR(statement);
 
1699
        }
 
1700
        Py_CLEAR(sequence);
 
1701
 
 
1702
        /* statement = join.join(compiled) */
 
1703
        CATCH(NULL, statement = PyUnicode_Join(join, compiled));
 
1704
        Py_CLEAR(compiled);
 
1705
    } else {
 
1706
        /* statement = self._compile_single(expr, state, outer_precedence) */
 
1707
        CATCH(NULL, statement = Compile_single(self, expr, state,
 
1708
                                               outer_precedence));
 
1709
    }
 
1710
 
 
1711
    /* state.precedence = outer_precedence */
 
1712
    CATCH(-1, PyObject_SetAttrString(state, "precedence", outer_precedence));
 
1713
    Py_CLEAR(outer_precedence);
 
1714
 
 
1715
    Py_DECREF(expr);
 
1716
 
 
1717
    return statement;
 
1718
 
 
1719
error:
 
1720
    Py_XDECREF(expr);
 
1721
    Py_XDECREF(outer_precedence);
 
1722
    Py_XDECREF(compiled);
 
1723
    Py_XDECREF(sequence);
 
1724
    Py_XDECREF(statement);
 
1725
 
 
1726
    return NULL;
 
1727
}
 
1728
 
 
1729
static PyObject *
 
1730
Compile__call__(CompileObject *self, PyObject *args, PyObject *kwargs)
 
1731
{
 
1732
    static char *kwlist[] = {"expr", "state", "join", "raw", "token", NULL};
 
1733
    PyObject *expr = NULL;
 
1734
    PyObject *state = Py_None;
 
1735
    PyObject *join;
 
1736
    char raw = 0;
 
1737
    char token = 0;
 
1738
 
 
1739
    PyObject *result = NULL;
 
1740
 
 
1741
    if (!initialize_globals())
 
1742
        return NULL;
 
1743
 
 
1744
    join = default_compile_join;
 
1745
 
 
1746
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OSbb", kwlist,
 
1747
                                     &expr, &state, &join, &raw, &token)) {
 
1748
        return NULL;
 
1749
    }
 
1750
 
 
1751
    if (state == Py_None) {
 
1752
        state = PyObject_CallFunctionObjArgs(State, NULL);
 
1753
    } else {
 
1754
        Py_INCREF(state);
 
1755
    }
 
1756
    if (state) {
 
1757
        result = Compile_one_or_many(self, expr, state, join, raw, token);
 
1758
        Py_DECREF(state);
 
1759
    }
 
1760
    return result;
 
1761
}
 
1762
 
 
1763
 
 
1764
static PyMethodDef Compile_methods[] = {
 
1765
    {"_update_cache", (PyCFunction)Compile__update_cache, METH_NOARGS, NULL},
 
1766
    {"when", (PyCFunction)Compile_when, METH_VARARGS, NULL},
 
1767
    {"add_reserved_words", (PyCFunction)Compile_add_reserved_words,
 
1768
        METH_O, NULL},
 
1769
    {"remove_reserved_words", (PyCFunction)Compile_remove_reserved_words,
 
1770
        METH_O, NULL},
 
1771
    {"is_reserved_word", (PyCFunction)Compile_is_reserved_word, METH_O, NULL},
 
1772
    {"create_child", (PyCFunction)Compile_create_child, METH_NOARGS, NULL},
 
1773
    {"get_precedence", (PyCFunction)Compile_get_precedence, METH_O, NULL},
 
1774
    {"set_precedence", (PyCFunction)Compile_set_precedence, METH_VARARGS, NULL},
 
1775
    {NULL, NULL}
 
1776
};
 
1777
 
 
1778
#define OFFSETOF(x) offsetof(CompileObject, x)
 
1779
static PyMemberDef Compile_members[] = {
 
1780
    {"_local_dispatch_table", T_OBJECT, OFFSETOF(_local_dispatch_table), 0, 0},
 
1781
    {"_local_precedence", T_OBJECT, OFFSETOF(_local_precedence), 0, 0},
 
1782
    {"_local_reserved_words", T_OBJECT, OFFSETOF(_local_reserved_words), 0, 0},
 
1783
    {"_dispatch_table", T_OBJECT, OFFSETOF(_dispatch_table), 0, 0},
 
1784
    {"_precedence", T_OBJECT, OFFSETOF(_precedence), 0, 0},
 
1785
    {"_reserved_words", T_OBJECT, OFFSETOF(_reserved_words), 0, 0},
 
1786
    {"_children", T_OBJECT, OFFSETOF(_children), 0, 0},
 
1787
    {"_parents", T_OBJECT, OFFSETOF(_parents), 0, 0},
 
1788
    {NULL}
 
1789
};
 
1790
#undef OFFSETOF
 
1791
 
 
1792
statichere PyTypeObject Compile_Type = {
 
1793
    PyObject_HEAD_INIT(NULL)
 
1794
    0,            /*ob_size*/
 
1795
    "storm.variables.Compile",    /*tp_name*/
 
1796
    sizeof(CompileObject), /*tp_basicsize*/
 
1797
    0,            /*tp_itemsize*/
 
1798
    (destructor)Compile_dealloc, /*tp_dealloc*/
 
1799
    0,            /*tp_print*/
 
1800
    0,            /*tp_getattr*/
 
1801
    0,            /*tp_setattr*/
 
1802
    0,            /*tp_compare*/
 
1803
    0,          /*tp_repr*/
 
1804
    0,            /*tp_as_number*/
 
1805
    0,            /*tp_as_sequence*/
 
1806
    0,            /*tp_as_mapping*/
 
1807
    0,                      /*tp_hash*/
 
1808
    (ternaryfunc)Compile__call__, /*tp_call*/
 
1809
    0,                      /*tp_str*/
 
1810
    PyObject_GenericGetAttr,/*tp_getattro*/
 
1811
    PyObject_GenericSetAttr,/*tp_setattro*/
 
1812
    0,                      /*tp_as_buffer*/
 
1813
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
 
1814
    0,                      /*tp_doc*/
 
1815
    (traverseproc)Compile_traverse,  /*tp_traverse*/
 
1816
    (inquiry)Compile_clear,          /*tp_clear*/
 
1817
    0,                      /*tp_richcompare*/
 
1818
    offsetof(CompileObject, __weakreflist), /*tp_weaklistoffset*/
 
1819
    0,                      /*tp_iter*/
 
1820
    0,                      /*tp_iternext*/
 
1821
    Compile_methods,        /*tp_methods*/
 
1822
    Compile_members,        /*tp_members*/
 
1823
    0,                      /*tp_getset*/
 
1824
    0,                      /*tp_base*/
 
1825
    0,                      /*tp_dict*/
 
1826
    0,                      /*tp_descr_get*/
 
1827
    0,                      /*tp_descr_set*/
 
1828
    0,                      /*tp_dictoffset*/
 
1829
    (initproc)Compile_init, /*tp_init*/
 
1830
    PyType_GenericAlloc,    /*tp_alloc*/
 
1831
    PyType_GenericNew,      /*tp_new*/
 
1832
    PyObject_GC_Del,        /*tp_free*/
 
1833
    0,                      /*tp_is_gc*/
 
1834
};
 
1835
 
 
1836
 
 
1837
static PyObject *
681
1838
ObjectInfo__emit_object_deleted(ObjectInfoObject *self, PyObject *args)
682
1839
{
683
1840
    /* self.event.emit("object-deleted") */
691
1848
static int
692
1849
ObjectInfo_init(ObjectInfoObject *self, PyObject *args)
693
1850
{
 
1851
    PyObject *self_get_obj = NULL;
694
1852
    PyObject *empty_args = NULL;
695
1853
    PyObject *factory_kwargs = NULL;
696
1854
    PyObject *columns = NULL;
699
1857
    Py_ssize_t i;
700
1858
 
701
1859
    empty_args = PyTuple_New(0);
702
 
    if (!empty_args)
703
 
        goto error;
704
 
 
705
 
    if (PyDict_Type.tp_init((PyObject *)self, empty_args, NULL) == -1)
706
 
        goto error;
707
 
 
708
 
    if (!initialize_globals())
709
 
        goto error;
 
1860
 
 
1861
    CATCH(-1, PyDict_Type.tp_init((PyObject *)self, empty_args, NULL));
 
1862
 
 
1863
    CATCH(0, initialize_globals());
710
1864
 
711
1865
    if (!PyArg_ParseTuple(args, "O", &obj))
712
1866
        goto error;
713
1867
 
714
1868
    /* self.cls_info = get_cls_info(type(obj)) */
715
 
    self->cls_info = PyObject_CallFunctionObjArgs(get_cls_info, obj->ob_type,
716
 
                                                  NULL);
717
 
    if (!self->cls_info)
718
 
        goto error;
 
1869
    CATCH(NULL, self->cls_info = PyObject_CallFunctionObjArgs(get_cls_info,
 
1870
                                                              obj->ob_type,
 
1871
                                                              NULL));
719
1872
 
720
1873
    /* self.set_obj(obj) */
721
 
    /* This is slightly different. get_obj() is an actual method. */
722
 
    self->__obj_ref_callback = PyCFunction_NewEx(&ObjectInfo_deleted_callback,
723
 
                                                 (PyObject *)self, NULL);
724
 
    if (!self->__obj_ref_callback)
725
 
        goto error;
 
1874
    CATCH(NULL, self->__obj_ref_callback =
 
1875
                    PyCFunction_NewEx(&ObjectInfo_deleted_callback,
 
1876
                                      (PyObject *)self, NULL));
726
1877
 
727
 
    self->__obj_ref = PyWeakref_NewRef(obj, self->__obj_ref_callback);
728
 
    if (!self->__obj_ref)
729
 
        goto error;
 
1878
    CATCH(NULL,
 
1879
          self->__obj_ref = PyWeakref_NewRef(obj, self->__obj_ref_callback));
730
1880
 
731
1881
    /* self.event = event = EventSystem(self) */
732
 
    self->event = PyObject_CallFunctionObjArgs(EventSystem, self, NULL);
733
 
    if (!self->event)
734
 
        goto error;
 
1882
    CATCH(NULL,
 
1883
          self->event = PyObject_CallFunctionObjArgs(EventSystem, self, NULL));
735
1884
 
736
1885
    /* self->variables = variables = {} */
737
 
    self->variables = PyDict_New();
738
 
    if (!self->variables)
739
 
        goto error;
740
 
 
741
 
    factory_kwargs = PyDict_New();
742
 
    if (!factory_kwargs)
743
 
        goto error;
744
 
 
745
 
    if (PyDict_SetItemString(factory_kwargs, "event", self->event) == -1)
746
 
        goto error;
 
1886
    CATCH(NULL, self->variables = PyDict_New());
 
1887
 
 
1888
    CATCH(NULL, self_get_obj = PyObject_GetAttrString((PyObject *)self,
 
1889
                                                      "get_obj"));
 
1890
    CATCH(NULL, factory_kwargs = PyDict_New());
 
1891
    CATCH(-1, PyDict_SetItemString(factory_kwargs, "event", self->event));
 
1892
    CATCH(-1, PyDict_SetItemString(factory_kwargs, "validator_object_factory",
 
1893
                                   self_get_obj));
747
1894
 
748
1895
    /* for column in self.cls_info.columns: */
749
 
    columns = PyObject_GetAttrString(self->cls_info, "columns");
750
 
    if (!columns)
751
 
        goto error;
 
1896
    CATCH(NULL, columns = PyObject_GetAttrString(self->cls_info, "columns"));
752
1897
    for (i = 0; i != PyTuple_GET_SIZE(columns); i++) {
753
 
        /* variables[column] = column.variable_factory(column=column,
754
 
                                                       event=event) */
 
1898
        /*
 
1899
           variables[column] = \
 
1900
               column.variable_factory(column=column,
 
1901
                                       event=event,
 
1902
                                       validator_object_factory=self.get_obj)
 
1903
        */
755
1904
        PyObject *column = PyTuple_GET_ITEM(columns, i);
756
1905
        PyObject *variable, *factory;
757
 
        if (PyDict_SetItemString(factory_kwargs, "column", column) == -1)
758
 
            goto error;
759
 
        factory = PyObject_GetAttrString(column, "variable_factory");
760
 
        if (!factory)
761
 
            goto error;
 
1906
        CATCH(-1, PyDict_SetItemString(factory_kwargs, "column", column));
 
1907
        CATCH(NULL, factory = PyObject_GetAttrString(column,
 
1908
                                                     "variable_factory"));
762
1909
        variable = PyObject_Call(factory, empty_args, factory_kwargs);
763
1910
        Py_DECREF(factory);
764
 
        if (!variable)
765
 
            goto error;
 
1911
        CATCH(NULL, variable);
766
1912
        if (PyDict_SetItem(self->variables, column, variable) == -1) {
767
1913
            Py_DECREF(variable);
768
1914
            goto error;
772
1918
 
773
1919
    /* self.primary_vars = tuple(variables[column]
774
1920
                                 for column in self.cls_info.primary_key) */
775
 
    primary_key = PyObject_GetAttrString((PyObject *)self->cls_info,
776
 
                                         "primary_key");
777
 
    if (!primary_key)
778
 
        goto error;
 
1921
    CATCH(NULL, primary_key = PyObject_GetAttrString((PyObject *)self->cls_info,
 
1922
                                                     "primary_key"));
 
1923
 
779
1924
    /* XXX Check primary_key type here. */
780
 
    self->primary_vars = PyTuple_New(PyTuple_GET_SIZE(primary_key));
781
 
    if (!self->primary_vars)
782
 
        goto error;
 
1925
    CATCH(NULL,
 
1926
          self->primary_vars = PyTuple_New(PyTuple_GET_SIZE(primary_key)));
783
1927
    for (i = 0; i != PyTuple_GET_SIZE(primary_key); i++) {
784
1928
        PyObject *column = PyTuple_GET_ITEM(primary_key, i);
785
1929
        PyObject *variable = PyDict_GetItem(self->variables, column);
787
1931
        PyTuple_SET_ITEM(self->primary_vars, i, variable);
788
1932
    }
789
1933
 
 
1934
    Py_DECREF(self_get_obj);
790
1935
    Py_DECREF(empty_args);
791
1936
    Py_DECREF(factory_kwargs);
792
1937
    Py_DECREF(columns);
794
1939
    return 0;
795
1940
 
796
1941
error:
 
1942
    Py_XDECREF(self_get_obj);
797
1943
    Py_XDECREF(empty_args);
798
1944
    Py_XDECREF(factory_kwargs);
799
1945
    Py_XDECREF(columns);
814
1960
{
815
1961
    PyObject *obj;
816
1962
 
817
 
    /* self.get_obj = ref(obj, self._emit_object_deleted) */
818
 
    /* This is slightly different. get_obj() is an actual method. */
 
1963
    /* self._ref = ref(obj, self._emit_object_deleted) */
819
1964
    if (!PyArg_ParseTuple(args, "O", &obj))
820
1965
        return NULL;
821
1966
 
824
1969
    if (!self->__obj_ref)
825
1970
        return NULL;
826
1971
 
827
 
    Py_INCREF(Py_None);
828
 
    return Py_None;
 
1972
    Py_RETURN_NONE;
829
1973
}
830
1974
 
831
1975
static PyObject *
832
1976
ObjectInfo_checkpoint(ObjectInfoObject *self, PyObject *args)
833
1977
{
834
 
    PyObject *column, *variable, *result;
 
1978
    PyObject *column, *variable, *tmp;
835
1979
    Py_ssize_t i = 0;
836
1980
 
837
1981
    /* for variable in self.variables.itervalues(): */
838
1982
    while (PyDict_Next(self->variables, &i, &column, &variable)) {
839
1983
        /* variable.checkpoint() */
840
 
        result = PyObject_CallMethod(variable, "checkpoint", NULL);
841
 
        if (!result) return NULL;
 
1984
        CATCH(NULL, tmp = PyObject_CallMethod(variable, "checkpoint", NULL));
 
1985
        Py_DECREF(tmp);
842
1986
    }
843
 
    Py_INCREF(Py_None);
844
 
    return Py_None;
 
1987
    Py_RETURN_NONE;
 
1988
error:
 
1989
    return NULL;
845
1990
}
846
1991
 
847
1992
static PyObject *
887
2032
    Py_CLEAR(self->event);
888
2033
    Py_CLEAR(self->variables);
889
2034
    Py_CLEAR(self->primary_vars);
890
 
    return PyDict_Type.tp_dealloc((PyObject *)self);
 
2035
    PyDict_Type.tp_dealloc((PyObject *)self);
891
2036
}
892
2037
 
893
2038
static PyMethodDef ObjectInfo_methods[] = {
1006
2151
{
1007
2152
    PyObject *module;
1008
2153
 
 
2154
    PyType_Ready(&EventSystem_Type);
1009
2155
    PyType_Ready(&Variable_Type);
 
2156
    PyType_Ready(&Compile_Type);
1010
2157
 
1011
2158
    ObjectInfo_Type.tp_base = &PyDict_Type;
1012
2159
    PyType_Ready(&ObjectInfo_Type);
1022
2169
 
1023
2170
    REGISTER_TYPE(Variable);
1024
2171
    REGISTER_TYPE(ObjectInfo);
 
2172
    REGISTER_TYPE(Compile);
 
2173
    REGISTER_TYPE(EventSystem);
1025
2174
}
1026
2175
 
1027
2176
/* vim:ts=4:sw=4:et