root/Cheetah/_namemapper.c

Revision f17b49bd2a9cb5c693518283252cdbca4d04136b, 13.3 kB (checked in by Jason Michalski <armooo@armooo.net>, 2 years ago)

Lets try the import again

  • Property mode set to 100644
Line 
1 /* ***************************************************************************
2 This is the C language version of NameMapper.py.  See the comments and
3 DocStrings in NameMapper for details on the purpose and interface of this
4 module.
5
6 ===============================================================================
7 $Id: _namemapper.c,v 1.31 2005/01/06 15:13:16 tavis_rudd Exp $
8 Authors: Tavis Rudd <tavis@damnsimple.com>
9 Version: $Revision: 1.31 $
10 Start Date: 2001/08/07
11 Last Revision Date: $Date: 2005/01/06 15:13:16 $
12 */
13
14 /* *************************************************************************** */
15 #include "Python.h"             /* Python header files */
16 #include <string.h>
17 #include <stdlib.h>
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23
24 static PyObject *NotFound;   /* locally-raised exception */
25 static PyObject *TooManyPeriods;   /* locally-raised exception */
26 static PyObject* pprintMod_pformat; /* used for exception formatting */
27 #define MAXCHUNKS 15            /* max num of nameChunks for the arrays */
28 #define TRUE 1
29 #define FALSE 0
30
31 #define ALLOW_WRAPPING_OF_NOTFOUND_EXCEPTIONS 1
32 #define INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS 0
33
34 # define createNameCopyAndChunks() {\
35   nameCopy = malloc(strlen(name) + 1);\
36   tmpPntr1 = name; \
37   tmpPntr2 = nameCopy;\
38   while ((*tmpPntr2++ = *tmpPntr1++)); \
39   numChunks = getNameChunks(nameChunks, name, nameCopy); \
40   if (PyErr_Occurred()) {       /* there might have been TooManyPeriods */\
41     free(nameCopy);\
42     return NULL;\
43   }\
44 }
45
46 #define OLD_checkForNameInNameSpaceAndReturnIfFound() { \
47     if ( PyNamemapper_hasKey(nameSpace, nameChunks[0]) ) {\
48       theValue = PyNamemapper_valueForName(nameSpace, nameChunks, numChunks, executeCallables);\
49       free(nameCopy);\
50       if (wrapInternalNotFoundException(name, nameSpace)) {\
51         theValue = NULL;\
52       }\
53       return theValue;\
54     }\
55 }
56
57 #define checkForNameInNameSpaceAndReturnIfFound(namespace_decref) { \
58     if ( PyNamemapper_hasKey(nameSpace, nameChunks[0]) ) {\
59       theValue = PyNamemapper_valueForName(nameSpace, nameChunks, numChunks, executeCallables);\
60       if (namespace_decref) {\
61         Py_DECREF(nameSpace);\
62       }\
63       if (wrapInternalNotFoundException(name, nameSpace)) {\
64         theValue = NULL;\
65       }\
66       goto done;\
67     }\
68 }
69
70 /* *************************************************************************** */
71 /* First the c versions of the functions */
72 /* *************************************************************************** */
73
74 static void
75 setNotFoundException(char *key, PyObject *namespace)
76 {
77
78
79   PyObject *exceptionStr = NULL;
80   exceptionStr = Py_BuildValue("s","cannot find '");
81   PyString_ConcatAndDel(&exceptionStr, Py_BuildValue("s", key));
82   PyString_ConcatAndDel(&exceptionStr, Py_BuildValue("s", "'"));
83   if (INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS) {
84     PyString_ConcatAndDel(&exceptionStr, Py_BuildValue("s", " in the namespace "));
85     PyString_ConcatAndDel(&exceptionStr,
86                           PyObject_CallFunctionObjArgs(pprintMod_pformat, namespace, NULL));
87   }
88   PyErr_SetObject(NotFound, exceptionStr);
89   Py_DECREF(exceptionStr);
90 }
91
92 static int
93 wrapInternalNotFoundException(char *fullName, PyObject *namespace)
94 {
95   PyObject *excType, *excValue, *excTraceback, *isAlreadyWrapped = NULL;
96   if (!ALLOW_WRAPPING_OF_NOTFOUND_EXCEPTIONS) {
97     return 0;
98   }
99   if (PyErr_Occurred() && PyErr_GivenExceptionMatches(PyErr_Occurred(), NotFound)) {
100     PyErr_Fetch(&excType, &excValue, &excTraceback);
101     isAlreadyWrapped = PyObject_CallMethod(excValue, "find", "s", "while searching");
102     if (PyInt_AsLong(isAlreadyWrapped)==-1) { /* only wrap once */
103       PyString_ConcatAndDel(&excValue, Py_BuildValue("s", " while searching for '"));
104       PyString_ConcatAndDel(&excValue, Py_BuildValue("s", fullName));
105       PyString_ConcatAndDel(&excValue, Py_BuildValue("s", "'"));
106       if (INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS) {
107         PyString_ConcatAndDel(&excValue, Py_BuildValue("s", " in "));
108         PyString_ConcatAndDel(&excValue, Py_BuildValue("s", "the top-level namespace "));
109         PyString_ConcatAndDel(&excValue,
110                               PyObject_CallFunctionObjArgs(pprintMod_pformat, namespace, NULL));
111       }
112     }
113     Py_DECREF(isAlreadyWrapped);
114     PyErr_Restore(excType, excValue, excTraceback);
115     return -1;
116   } else {
117     return 0;
118   }
119 }
120
121 static int getNameChunks(char *nameChunks[], char *name, char *nameCopy)
122 {
123   char c;
124   char *currChunk;
125   int currChunkNum = 0;
126  
127   currChunk = nameCopy;
128   while ('\0' != (c = *nameCopy)){
129     if ('.' == c) {
130       if (currChunkNum >= (MAXCHUNKS-2)) { /* avoid overflowing nameChunks[] */
131         PyErr_SetString(TooManyPeriods, name);
132         return 0;
133       }
134
135       *nameCopy ='\0';
136       nameChunks[currChunkNum++] = currChunk;
137       nameCopy++;
138       currChunk = nameCopy;
139     } else
140       nameCopy++;
141   }
142   if (nameCopy > currChunk) {
143     nameChunks[currChunkNum++] = currChunk;
144   }
145   return currChunkNum;
146 }
147
148
149 static int
150 PyNamemapper_hasKey(PyObject *obj, char *key)
151 {
152   if (PyMapping_Check(obj) && PyMapping_HasKeyString(obj, key)) {
153     return TRUE;
154   } else if (PyObject_HasAttrString(obj, key)) {
155     return TRUE;
156   } else {
157     return FALSE;
158   }
159 }
160
161
162 static PyObject *
163 PyNamemapper_valueForKey(PyObject *obj, char *key)
164 {
165   PyObject *theValue = NULL;
166
167   if (PyMapping_Check(obj) && PyMapping_HasKeyString(obj, key)) {
168     theValue = PyMapping_GetItemString(obj, key);
169   } else if (PyObject_HasAttrString(obj, key)) {
170     theValue = PyObject_GetAttrString(obj, key);
171
172   } else {
173     setNotFoundException(key, obj);
174   }
175
176   return theValue;
177 }
178
179 static PyObject *
180 PyNamemapper_valueForName(PyObject *obj, char *nameChunks[],
181                           int numChunks,
182                           int executeCallables)
183 {
184   int i;
185   char *currentKey;
186   PyObject *currentVal = NULL;
187   PyObject *nextVal = NULL;
188
189   currentVal = obj;
190   for (i=0; i < numChunks;i++) {
191     currentKey = nameChunks[i];
192     if (PyErr_CheckSignals()) { /* not sure if I really need to do this here, but what the hell */
193       if (i>0) {
194         Py_DECREF(currentVal);
195       }
196       return NULL;
197     }
198    
199     if (PyMapping_Check(currentVal) && PyMapping_HasKeyString(currentVal, currentKey)) {
200       nextVal = PyMapping_GetItemString(currentVal, currentKey);
201     } else if (PyObject_HasAttrString(currentVal, currentKey)) {
202       nextVal = PyObject_GetAttrString(currentVal, currentKey);
203     } else {
204       setNotFoundException(currentKey, currentVal);
205       if (i>0) {
206         Py_DECREF(currentVal);
207       }
208       return NULL;
209     }
210     if (i>0) {
211       Py_DECREF(currentVal);
212     }
213     if (executeCallables && PyCallable_Check(nextVal) && (!PyInstance_Check(nextVal))
214         && (!PyClass_Check(nextVal)) && (!PyType_Check(nextVal)) ) {
215       if (!(currentVal = PyObject_CallObject(nextVal, NULL))){
216         Py_DECREF(nextVal);
217         return NULL;
218       };
219       Py_DECREF(nextVal);
220     } else {
221       currentVal = nextVal;
222     }
223   }
224
225   return currentVal;
226 }
227
228
229 /* *************************************************************************** */
230 /* Now the wrapper functions to export into the Python module */
231 /* *************************************************************************** */
232
233
234 static PyObject *
235 namemapper_valueForKey(PyObject *self, PyObject *args)
236 {
237   PyObject *obj;
238   char *key;
239
240   if (!PyArg_ParseTuple(args, "Os", &obj, &key)) {
241     return NULL;
242   }
243
244   return PyNamemapper_valueForKey(obj, key);
245
246 }
247
248 static PyObject *
249 namemapper_valueForName(PyObject *self, PyObject *args, PyObject *keywds)
250 {
251
252
253   PyObject *obj;
254   char *name;
255   int executeCallables = 0;
256
257   char *nameCopy = NULL;
258   char *tmpPntr1 = NULL;
259   char *tmpPntr2 = NULL;
260   char *nameChunks[MAXCHUNKS];
261   int numChunks;
262
263   PyObject *theValue;
264
265   static char *kwlist[] = {"obj", "name", "executeCallables", NULL};
266
267   if (!PyArg_ParseTupleAndKeywords(args, keywds, "Os|i", kwlist,  &obj, &name, &executeCallables)) {
268     return NULL;
269   }
270
271   createNameCopyAndChunks(); 
272
273   theValue = PyNamemapper_valueForName(obj, nameChunks, numChunks, executeCallables);
274   free(nameCopy);
275   if (wrapInternalNotFoundException(name, obj)) {
276     theValue = NULL;
277   }
278   return theValue;
279
280 }
281
282 static PyObject *
283 namemapper_valueFromSearchList(PyObject *self, PyObject *args, PyObject *keywds)
284 {
285
286   PyObject *searchList;
287   char *name;
288   int executeCallables = 0;
289
290   char *nameCopy = NULL;
291   char *tmpPntr1 = NULL;
292   char *tmpPntr2 = NULL;
293   char *nameChunks[MAXCHUNKS];
294   int numChunks;
295
296   PyObject *nameSpace = NULL;
297   PyObject *theValue = NULL;
298   PyObject *iterator = NULL;
299
300   static char *kwlist[] = {"searchList", "name", "executeCallables", NULL};
301
302   if (!PyArg_ParseTupleAndKeywords(args, keywds, "Os|i", kwlist,  &searchList, &name,
303                                    &executeCallables)) {
304     return NULL;
305   }
306
307   createNameCopyAndChunks();
308
309   iterator = PyObject_GetIter(searchList);
310   if (iterator == NULL) {
311     PyErr_SetString(PyExc_TypeError,"This searchList is not iterable!");
312     goto done;
313   }
314
315   while ( (nameSpace = PyIter_Next(iterator)) ) {
316     checkForNameInNameSpaceAndReturnIfFound(TRUE);
317     Py_DECREF(nameSpace);
318     if(PyErr_CheckSignals()) {
319       theValue = NULL;
320       goto done;
321     }
322   }
323   if (PyErr_Occurred()) {
324     theValue = NULL;
325     goto done;
326   }
327
328   setNotFoundException(nameChunks[0], searchList);
329  done:
330   Py_XDECREF(iterator);
331   free(nameCopy);
332   return theValue;
333 }
334
335 static PyObject *
336 namemapper_valueFromFrameOrSearchList(PyObject *self, PyObject *args, PyObject *keywds)
337 {
338
339   /* python function args */
340   char *name;
341   int executeCallables = 0;
342   PyObject *searchList = NULL;
343
344   /* locals */
345   char *nameCopy = NULL;
346   char *tmpPntr1 = NULL;
347   char *tmpPntr2 = NULL;
348   char *nameChunks[MAXCHUNKS];
349   int numChunks;
350
351   PyObject *nameSpace = NULL;
352   PyObject *theValue = NULL;
353   PyObject *excString = NULL;
354   PyObject *iterator = NULL;
355
356   static char *kwlist[] = {"searchList", "name", "executeCallables", NULL};
357
358   if (!PyArg_ParseTupleAndKeywords(args, keywds, "Os|i", kwlist,  &searchList, &name,
359                                    &executeCallables)) {
360     return NULL;
361   }
362
363   createNameCopyAndChunks();
364  
365   nameSpace = PyEval_GetLocals();
366   checkForNameInNameSpaceAndReturnIfFound(FALSE); 
367
368   iterator = PyObject_GetIter(searchList);
369   if (iterator == NULL) {
370     PyErr_SetString(PyExc_TypeError,"This searchList is not iterable!");
371     goto done;
372   }
373   while ( (nameSpace = PyIter_Next(iterator)) ) {
374     checkForNameInNameSpaceAndReturnIfFound(TRUE);
375     Py_DECREF(nameSpace);
376     if(PyErr_CheckSignals()) {
377       theValue = NULL;
378       goto done;
379     }
380   }
381   if (PyErr_Occurred()) {
382     theValue = NULL;
383     goto done;
384   }
385
386   nameSpace = PyEval_GetGlobals();
387   checkForNameInNameSpaceAndReturnIfFound(FALSE);
388
389   nameSpace = PyEval_GetBuiltins();
390   checkForNameInNameSpaceAndReturnIfFound(FALSE);
391
392   excString = Py_BuildValue("s", "[locals()]+searchList+[globals(), __builtins__]");
393   setNotFoundException(nameChunks[0], excString);
394   Py_DECREF(excString);
395
396  done:
397   Py_XDECREF(iterator);
398   free(nameCopy);
399   return theValue;
400 }
401
402 static PyObject *
403 namemapper_valueFromFrame(PyObject *self, PyObject *args, PyObject *keywds)
404 {
405
406   /* python function args */
407   char *name;
408   int executeCallables = 0;
409
410   /* locals */
411   char *tmpPntr1 = NULL;
412   char *tmpPntr2 = NULL;
413
414   char *nameCopy = NULL;
415   char *nameChunks[MAXCHUNKS];
416   int numChunks;
417
418   PyObject *nameSpace = NULL;
419   PyObject *theValue = NULL;
420   PyObject *excString = NULL;
421
422   static char *kwlist[] = {"name", "executeCallables", NULL};
423
424   if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &name, &executeCallables)) {
425     return NULL;
426   }
427
428   createNameCopyAndChunks();
429  
430   nameSpace = PyEval_GetLocals();
431   checkForNameInNameSpaceAndReturnIfFound(FALSE);
432  
433   nameSpace = PyEval_GetGlobals();
434   checkForNameInNameSpaceAndReturnIfFound(FALSE);
435
436   nameSpace = PyEval_GetBuiltins();
437   checkForNameInNameSpaceAndReturnIfFound(FALSE);
438
439   excString = Py_BuildValue("s", "[locals(), globals(), __builtins__]");
440   setNotFoundException(nameChunks[0], excString);
441   Py_DECREF(excString);
442  done:
443   free(nameCopy);
444   return theValue;
445 }
446
447 /* *************************************************************************** */
448 /* Method registration table: name-string -> function-pointer */
449
450 static struct PyMethodDef namemapper_methods[] = {
451   {"valueForKey", namemapper_valueForKey,  1},
452   {"valueForName", (PyCFunction)namemapper_valueForName,  METH_VARARGS|METH_KEYWORDS},
453   {"valueFromSearchList", (PyCFunction)namemapper_valueFromSearchList,  METH_VARARGS|METH_KEYWORDS},
454   {"valueFromFrame", (PyCFunction)namemapper_valueFromFrame,  METH_VARARGS|METH_KEYWORDS},
455   {"valueFromFrameOrSearchList", (PyCFunction)namemapper_valueFromFrameOrSearchList,  METH_VARARGS|METH_KEYWORDS},
456   {NULL,         NULL}
457 };
458
459
460 /* *************************************************************************** */
461 /* Initialization function (import-time) */
462
463 DL_EXPORT(void)
464 init_namemapper(void)
465 {
466   PyObject *m, *d, *pprintMod;
467
468   /* create the module and add the functions */
469   m = Py_InitModule("_namemapper", namemapper_methods);        /* registration hook */
470  
471   /* add symbolic constants to the module */
472   d = PyModule_GetDict(m);
473   NotFound = PyErr_NewException("NameMapper.NotFound",PyExc_LookupError,NULL);
474   TooManyPeriods = PyErr_NewException("NameMapper.TooManyPeriodsInName",NULL,NULL);
475   PyDict_SetItemString(d, "NotFound", NotFound);
476   PyDict_SetItemString(d, "TooManyPeriodsInName", TooManyPeriods);
477   pprintMod = PyImport_ImportModule("pprint"); /* error check this */
478   pprintMod_pformat = PyObject_GetAttrString(pprintMod, "pformat");
479   Py_DECREF(pprintMod);
480   /* check for errors */
481   if (PyErr_Occurred())
482     Py_FatalError("Can't initialize module _namemapper");
483 }
484
485 #ifdef __cplusplus
486 }
487 #endif
Note: See TracBrowser for help on using the browser.