source: trunk/lang/python/Rappture/PyRpLibrary.cc @ 3114

Last change on this file since 3114 was 3114, checked in by gah, 12 years ago
File size: 31.5 KB
Line 
1
2/*
3 * ======================================================================
4 *  AUTHOR:  Derrick S. Kearney, Purdue University
5 *  Copyright (c) 2004-2008  Purdue Research Foundation
6 *
7 *  See the file "license.terms" for information on usage and
8 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9 * ======================================================================
10 */
11#include <Python.h>
12#include <RpLibrary.h>
13#include <ctype.h>
14
15#define TRUE 1
16#define FALSE 0
17
18#define RP_OK   0
19#define RP_ERROR 1
20
21#ifndef Py_RETURN_NONE
22#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
23#endif
24
25/*
26 * As suggested by PEP353
27 * http://www.python.org/dev/peps/pep-0353/
28 */
29
30#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
31typedef int Py_ssize_t;
32#define PY_SSIZE_T_MAX INT_MAX
33#define PY_SSIZE_T_MIN INT_MIN
34#endif
35
36static PyObject *ErrorObject;
37static RpLibrary * RpLibraryObject_AsLibrary(PyObject *lib);
38static PyObject * RpLibraryObject_FromLibrary(RpLibrary *lib);
39static int boolAsInt(const char *inVal, int *outVal);
40static int boolIntFromPyObject (PyObject *inPyObj, const char *defaultVal,
41        const char *argName, int *boolVal);
42static int getArgCount(PyObject *args, PyObject *keywds, int *argc);
43
44typedef struct {
45    PyObject_HEAD
46    RpLibrary *lib;
47} RpLibraryObject;
48
49/*
50 * Check to see if this object is a Rappture.library object.
51 * This does not check to see if the object is correctly
52 * initialized. To check for correct object type and
53 * correct initialization, use RpLibraryObject_IsValid.
54 */
55static int
56RpLibraryObject_Check(PyObject *objPtr)
57{
58    if (objPtr == NULL) {
59        return FALSE;
60    }
61    if (strcmp(objPtr->ob_type->tp_name, "Rappture.library") != 0) {
62        return FALSE;
63    }
64    return TRUE;
65}
66
67/*
68 * Check to see if this object is a Rappture.library object
69 * and is correctly initialized
70 *
71 * This function calls RpLibraryObject_Check internally, and is used
72 * in most of the internal functions to check if an object being passed
73 * in by the user is a valid Rappture.library object
74 */
75static int
76RpLibraryObject_IsValid(PyObject *objPtr)
77{
78    if (objPtr == NULL) {
79        return FALSE;                   // Passed a NULL pointer. Should
80                                        // probably segfault.
81    }
82    if (!RpLibraryObject_Check(objPtr)) {
83        return FALSE;                   // Not a rappture library object type.
84    }
85    if (((RpLibraryObject *)objPtr)->lib == NULL) {
86        return FALSE;                   // Is a rappture library object, but
87                                        // doesn't contain a valid library.
88    }
89    return TRUE;
90}
91
92static PyObject *
93RpLibraryObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
94{
95    RpLibraryObject *self = NULL;
96
97    self = (RpLibraryObject *)type->tp_alloc(type,0);
98    if (self != NULL) {
99        self->lib = NULL;
100    }
101    else {
102        PyErr_SetString(PyExc_RuntimeError,
103                "trouble creating new RpLibraryObject");
104    }
105    return (PyObject *)self;
106}
107
108static int
109RpLibraryObject_init(RpLibraryObject *self, PyObject *args, PyObject *kwds)
110{
111    PyObject *inObj = NULL;
112    char *filename = NULL;
113    int retVal = 1;
114
115    if (!PyArg_ParseTuple(args, "|O", &inObj)) {
116        PyErr_Format(PyExc_TypeError,
117            "library() takes at most 1 argument, a file name or a Rappture Library Object");
118        return -1;
119    }
120
121    if (inObj != NULL) {
122        if (PyString_Check(inObj)) {
123            filename = PyString_AsString(inObj);
124            if (filename == NULL) {
125                PyErr_Format(PyExc_ValueError,"a file name is required");
126            }
127            self->lib = new RpLibrary(std::string(filename));
128        }
129        else if (RpLibraryObject_IsValid(inObj)) {
130            self->lib = new RpLibrary( *(RpLibraryObject_AsLibrary(inObj)) );
131        }
132        else if (RpLibraryObject_Check(inObj)) {
133            self->lib = new RpLibrary();
134        }
135        else {
136            PyErr_Format(PyExc_TypeError,"unrecognized object type");
137            return -1;
138        }
139    }
140    else {
141        self->lib = new RpLibrary();
142    }
143
144    return retVal;
145}
146
147static void
148RpLibraryObject_dealloc(RpLibraryObject *self)
149{
150    if (self) {
151        if (self->lib){
152            delete(self->lib);
153        }
154        self->ob_type->tp_free((PyObject *) self);
155    }
156}
157
158PyDoc_STRVAR(RpLibraryObject_copy_doc,
159"copy (topath, frompath [, fromobj=$self]) -> None, copies data\n\
160\n\
161Copy an xml element to \'topath\' of the current this object\n\
162from \'frompath\' of the Rappture Library Object \'fromobj\'.\n\
163\n\
164\'topath\' is the path (in this object) where the data should\n\
165be copied to\n\
166\'frompath\' is an path (in fromobj) where the data should be\n\
167copied from\n\
168\'fromobj\' is the Rappture Library Object to copy the data from\n\
169if fromobj is not set, the data is copied from the same object\n\
170the data will be copied to (this object).\n\
171\n\
172");
173
174static PyObject *
175RpLibraryObject_copy(RpLibraryObject *self, PyObject *args, PyObject *keywds)
176{
177    char *topath = (char *)"";
178    char *frompath = (char *)"";
179    int argc = 0;
180    PyObject *fromobj = (PyObject *) self;
181
182    static char *kwlist[] = {
183        (char *)"topath",
184        (char *)"frompath",
185        (char *)"fromobj",
186        NULL
187    };
188
189    if (self->lib == NULL) {
190        PyErr_SetString(PyExc_RuntimeError,
191            "self is uninitialized Rappture Library Object");
192        return NULL;
193    }
194
195    if (getArgCount(args,keywds,&argc) != RP_OK) {
196        // trouble ensues
197        // error message was set in getArgCount()
198        return NULL;
199    }
200
201    if (argc > 3) {
202        // tested with CopyTests.testArguments_TooManyArgs()
203        PyErr_Format(PyExc_TypeError,
204            "copy() takes at most 3 arguments (%i given)",argc);
205        return NULL;
206    }
207
208    if (argc < 2) {
209        // tested with CopyTests.testArguments_NotEnoughArgs()
210        PyErr_Format(PyExc_TypeError,
211            "copy() takes at least 2 arguments (%i given)",argc);
212        return NULL;
213    }
214
215    if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|O",
216            kwlist, &topath, &frompath, &fromobj)) {
217        // tested with CopyTests.testArguments_ArgsWrongType2()
218        PyErr_Format(PyExc_TypeError,
219            "copy() takes 2 sting and 1 Rappture Library Object as arguments");
220        return NULL;
221    }
222
223    if (!RpLibraryObject_IsValid(fromobj)) {
224        // tested with CopyTests.testArguments_ArgsWrongType3()
225        PyErr_SetString(PyExc_RuntimeError,
226            "incorrectly initialized Rappture Library Object");
227        return NULL;
228    }
229
230    self->lib->copy(std::string(topath),
231        RpLibraryObject_AsLibrary(fromobj),
232        std::string(frompath));
233
234    Py_RETURN_NONE;
235}
236
237PyDoc_STRVAR(RpLibraryObject_element_doc,
238"element ([path=\'\'][, as=\'object\']) -> returns string or Rappture Library Object\n\
239\n\
240Clients use this to query a particular element within the \n\
241entire data structure.  The path is a string of the form \n\
242\"structure.box(source).corner\".  This example represents \n\
243the tag <corner> within a tag <box id=\"source\"> within a \n\
244a tag <structure>, which must be found at the top level \n\
245within this document. \n\
246\n\
247By default, this method returns an object representing the \n\
248DOM node referenced by the path.  This is changed by setting \n\
249the \"as\" argument to \"id\" (for name of the tail element), \n\
250to \"type\" (for the type of the tail element), to \"component\" \n\
251(for the component name \"type(id)\"), or to \"object\" \n\
252for the default (an object representing the tail element).\n\
253");
254
255static PyObject *
256RpLibraryObject_element(RpLibraryObject *self, PyObject *args, PyObject *keywds)
257{
258    char* path = (char *)"";
259    char* as = (char *)"object";
260    RpLibrary* retlib = NULL;
261    PyObject* retVal = NULL;
262    int argc = 0;
263
264    static char *kwlist[] = {
265        (char *)"path",
266        (char *)"as",
267        NULL
268    };
269
270    if (self->lib == NULL) {
271        PyErr_Format(PyExc_RuntimeError,
272            "self is uninitialized Rappture Library Object");
273        return retVal;
274    }
275
276    if (getArgCount(args,keywds,&argc) != RP_OK) {
277        // trouble ensues
278        // error message was set in getArgCount()
279        return NULL;
280    }
281
282    if (argc > 2) {
283        // tested with ElementTests.testArguments_TooManyArgs()
284        PyErr_Format(PyExc_TypeError,
285            "element() takes at most 2 arguments (%i given)", argc);
286        return retVal;
287    }
288
289    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|ss",
290                kwlist, &path, &as)) {
291        /* incorrect input values */
292        // tested with ElementTests.testArguments_ArgsWrongType2()
293        PyErr_Format(PyExc_TypeError,"element ([path=\'\'][, as=\'object\'])");
294        return retVal;
295    }
296
297    retlib = self->lib->element(std::string(path));
298
299    if (retlib != NULL) {
300        if (   (as == NULL)
301            || ((*as == 'o') && (strcmp("object",as) == 0)) ) {
302            // tested with ElementTests.testArguments_PathArg()
303            retVal = RpLibraryObject_FromLibrary(retlib);
304        }
305        else if ((*as == 'c') && (strcmp("component",as) == 0)) {
306            // tested with ElementTests.testArguments_TwoArgs()
307            retVal = PyString_FromString(retlib->nodeComp().c_str());
308        }
309        else if ((*as == 'i') && (strcmp("id",as) == 0)) {
310            // tested with ElementTests.testArguments_AsId()
311            retVal = PyString_FromString(retlib->nodeId().c_str());
312        }
313        else if ((*as == 't') && (strcmp("type",as) == 0)) {
314            // tested with ElementTests.testArguments_AsKeywordArgs()
315            retVal = PyString_FromString(retlib->nodeType().c_str());
316        }
317        else if ((*as == 'p') && (strcmp("path",as) == 0)) {
318            // tested with ElementTests.testArguments_TwoKeywordArgs()
319            retVal = PyString_FromString(retlib->nodePath().c_str());
320        }
321        else {
322            // tested with ElementTests.testArguments_UnrecognizedAs()
323            PyErr_Format(PyExc_ValueError,
324                "element() \'as\' arg must be \'object\' or \'component\' or \'id\' or \'type\' or \'path\'");
325        }
326    }
327
328    return (PyObject *)retVal;
329}
330
331
332PyDoc_STRVAR(RpLibraryObject_get_doc,
333"get ([path=\'\'][, decode=\'True\']) -> returns data at \'path\' as string\n\
334\n\
335Clients use this to query the value of a node.  If the path\n\
336is not specified, it returns the value associated with the\n\
337root node.  Otherwise, it returns the value for the element\n\
338specified by the path.\n\
339");
340
341static PyObject *
342RpLibraryObject_get(RpLibraryObject *self, PyObject *args, PyObject *keywds)
343{
344    char* path = (char *)"";
345
346    PyObject* decode = NULL;
347    int decodeVal = FALSE;
348
349    PyObject* retVal = NULL;
350    std::string retValStr = "";
351    Rappture::Buffer retValBuf;
352
353    int argc = 0;
354
355    static char *kwlist[] = {
356        (char *)"path",
357        (char *)"decode",
358        NULL
359    };
360
361    if (self->lib == NULL) {
362        PyErr_SetString(PyExc_RuntimeError,
363            "self uninitialized Rappture Library Object");
364        return NULL;
365    }
366
367    if (getArgCount(args,keywds,&argc) != RP_OK) {
368        // trouble ensues
369        // error message was set in getArgCount()
370        return NULL;
371    }
372
373    if (argc > 2) {
374        // tested with GetTests.testArguments_TooManyArgs()
375        PyErr_Format(PyExc_TypeError,
376            "get() takes at most 2 arguments (%i given)",argc);
377        return NULL;
378    }
379
380    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sO",
381            kwlist, &path, &decode)) {
382        // tested with GetTests.testArguments_ArgsWrongType2()
383        PyErr_Format(PyExc_TypeError,"get ([path=\'\'][, decode=\'True\'])");
384        return NULL;
385    }
386    if (boolIntFromPyObject(decode,"yes", "decode", &decodeVal) != RP_OK) {
387        // tested with GetTests.testArgumentsDecodeError()
388        return NULL;
389    }
390
391    if (decodeVal) {
392        // tested with GetTests.testArgumentsDecode()
393        // tested with GetTests.testArgumentsDecodeYes()
394        // tested with GetTests.testArgumentsDecodeTrue)
395        // tested with GetTests.testArgumentsDecodeOn()
396        // tested with GetTests.testArgumentsDecode1Str()
397        // tested with GetTests.testArgumentsDecode1Int()
398        retValStr = self->lib->get(std::string(path));
399        retVal = PyString_FromStringAndSize(retValStr.c_str(),retValStr.size());
400    }
401    else {
402        // tested with GetTests.testArgumentsNoDecodeNo()
403        // tested with GetTests.testArgumentsNoDecodeFalse()
404        // tested with GetTests.testArgumentsNoDecodeOff()
405        // tested with GetTests.testArgumentsNoDecode0Str()
406        // tested with GetTests.testArgumentsNoDecode0Int()
407        retValBuf = self->lib->getData(std::string(path));
408        retVal = PyString_FromStringAndSize(retValBuf.bytes(),retValBuf.size());
409    }
410    return (PyObject *)retVal;
411}
412
413PyDoc_STRVAR(RpLibraryObject_parent_doc,
414"parent ([path=\'\'][, as=\'object\']) -> returns string or Rappture Library Object\n\
415\n\
416Clients use this to query the parent of a particular element \n\
417This is just like the \'element()\' method, but it returns the parent \n\
418of the element instead of the element itself. \n\
419\n\
420By default, this method returns an object representing the \n\
421DOM node referenced by the path.  This is changed by setting \n\
422the \"as\" argument to \"id\" (for name of the tail element), \n\
423to \"type\" (for the type of the tail element), to \"component\" \n\
424(for the component name \"type(id)\"), or to \"object\" \n\
425for the default (an object representing the tail element).\n\
426");
427
428static PyObject *
429RpLibraryObject_parent(RpLibraryObject *self, PyObject *args, PyObject *keywds)
430{
431    char* path = (char *)"";
432    char* as = (char *)"object";
433    RpLibrary* retlib = NULL;
434    PyObject* retVal = NULL;
435    int argc = 0;
436
437    static char *kwlist[] = {
438        (char *)"path",
439        (char *)"as",
440        NULL
441    };
442
443    if (getArgCount(args,keywds,&argc) != RP_OK) {
444        // trouble ensues
445        // error message was set in getArgCount()
446        return NULL;
447    }
448
449    if (argc > 3) {
450        PyErr_SetString(PyExc_TypeError,"parent() takes at most 2 arguments");
451        return NULL;
452    }
453    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|ss",
454            kwlist, &path, &as)) {
455        /* incorrect input values */
456        PyErr_SetString(PyExc_TypeError,
457                        "parent ([path=\'\'][, as=\'object\'])");
458        return NULL;
459    }
460    if (self->lib) {
461        retlib = self->lib->parent(std::string(path));
462    } else {
463        PyErr_SetString(PyExc_RuntimeError,
464            "incorrectly initialized Rappture Library Object");
465        return NULL;
466    }
467
468    if (retlib != NULL) {
469        if ((as == NULL) || ((*as == 'o') && (strcmp("object",as) == 0))) {
470            retVal = RpLibraryObject_FromLibrary(retlib);
471        } else if ((*as == 'c') && (strcmp("component",as) == 0)) {
472            retVal = PyString_FromString(retlib->nodeComp().c_str());
473        } else if ((*as == 'i') && (strcmp("id",as) == 0)) {
474            retVal = PyString_FromString(retlib->nodeId().c_str());
475        } else if ((*as == 't') && (strcmp("type",as) == 0)) {
476            retVal = PyString_FromString(retlib->nodeType().c_str());
477        } else if ((*as == 'p') && (strcmp("path",as) == 0)) {
478            retVal = PyString_FromString(retlib->nodePath().c_str());
479        } else {
480            PyErr_Format(PyExc_ValueError,
481                "parent() \'as\' arg must be \'object\' or \'component\' or \'id\' or \'type\' or \'path\'");
482        }
483    }
484    return (PyObject *)retVal;
485}
486
487PyDoc_STRVAR(RpLibraryObject_put_doc,
488"put (path=\'\', value=\'\'[,id=None][,append=False][,type=\'string\'][,compress=False]) -> None\n\
489\n\
490Clients use this to set the value of a node.  If the path\n\
491is not specified, it sets the value for the root node.\n\
492Otherwise, it sets the value for the element specified\n\
493by the path.  If the value is a string, then it is treated\n\
494as the text within the tag at the tail of the path.  If it\n\
495is a DOM node or a library, then it is inserted into the\n\
496tree at the specified path.\n\
497\n\
498The optional id input has no effect and is available for\n\
499backwards compatibility.\n\
500\n\
501If the optional append flag is specified, then the value\n\
502is appended to the current value. Otherwise, the value\n\
503replaces the current value.\n\
504\n\
505The optional type flag specifies whether the value should be\n\
506treated as string data (type=\"string\"), or the name of a\n\
507file (type=\"file\"). The default behavior is to treat the\n\
508value as string data.\n\
509\n\
510If the optional compress flag is specified, then the append\n\
511flag will be evaluated upon the data at path and the result\n\
512will be compressed.\n\
513");
514
515static PyObject *
516RpLibraryObject_put(RpLibraryObject *self, PyObject *args, PyObject *keywds)
517{
518    char *path = (char *)"";
519
520    PyObject *value = NULL;
521    PyObject *valueStrObj = NULL;
522    char *value_char = NULL;
523    Py_ssize_t value_len = 0;
524
525    char *id = NULL;
526
527    PyObject* append = NULL;
528    int appendInt = FALSE;
529
530    char *type = (char *)"string";
531
532    PyObject* compress = NULL;
533    int compressInt = FALSE;
534
535    int argc = 0;
536    int status = 0;
537
538    static char *kwlist[] = {
539        (char *)"path",
540        (char *)"value",
541        (char *)"id",
542        (char *)"append",
543        (char *)"type",
544        (char *)"compress",
545        NULL
546    };
547
548    if (self->lib == NULL) {
549        PyErr_Format(PyExc_RuntimeError,
550            "self uninitialized Rappture Library Object");
551        return NULL;
552    }
553
554    status = getArgCount(args,keywds,&argc);
555    if (status != 0) {
556        // trouble ensues
557        // error message was set in getArgCount()
558        return NULL;
559    }
560
561    if (argc > 6) {
562        // tested with PutTests.testArguments_TooManyArgs()
563        PyErr_Format(PyExc_TypeError,
564            "put() takes at most 6 arguments (%i given)",argc);
565        return NULL;
566    }
567
568    if (argc < 2) {
569        // tested with PutTests.testArguments_NotEnoughArgs()
570        PyErr_Format(PyExc_TypeError,
571            "put() takes at least 2 arguments (%i given)",argc);
572        return NULL;
573    }
574
575    if (!PyArg_ParseTupleAndKeywords(args, keywds, "sO|sOsO",
576            kwlist, &path, &value, &id, &append, &type, &compress)) {
577        // tested with PutTests.testArguments_ArgsWrongType2()
578        PyErr_Format(PyExc_TypeError, "incorrect arguments: put(path=\'\',value=\'\'[,id=None][,append=False][,type=\'string\'][,compress=False])");
579        return NULL;
580    }
581
582    if (value == NULL) {
583        PyErr_Format(PyExc_ValueError, "put()'s \'value\' arg is required");
584        return NULL;
585    }
586
587    valueStrObj = PyObject_Str(value);
588
589    status = boolIntFromPyObject(append,"no","append",&appendInt);
590    if (status != 0) {
591        // error message set inside of boolIntFromPyObject
592        // tested with PutTests.testArguments_AppendValError()
593        return NULL;
594    }
595    status = boolIntFromPyObject(compress,"no","compress",&compressInt);
596    if (status != 0) {
597        // error message set inside of boolIntFromPyObject
598        // tested with PutTests.testArguments_CompressValError()
599        return NULL;
600    }
601
602    if (RpLibraryObject_IsValid(value)) {
603        // tested with PutTests.testPutObject()
604        self->lib->put( std::string(path),
605                        RpLibraryObject_AsLibrary(value), "", appendInt);
606    }
607    else if (valueStrObj != NULL) {
608
609        if (PyString_AsStringAndSize(valueStrObj, &value_char, &value_len) == -1) {
610            // user passed in an improper string
611            // exception raised within fxn
612            return NULL;
613        }
614
615        if (   ( type == NULL )
616            || ( (*type == 's') && (strcmp("string", type) == 0) ) ) {
617            if (compress == 0) {
618                // tested with PutTests.testArgumentsCheckAppend()
619                // tested with PutTests.testArgumentsCheckAppendYes()
620                self->lib->put( std::string(path),
621                                std::string(value_char), "", appendInt);
622            }
623            else {
624                // tested with PutTests.testArgumentsCheckTypeStringCompressYes()
625                self->lib->putData( std::string(path),
626                                    value_char, value_len, appendInt);
627            }
628        }
629        else if ( (*type == 'f') && (strcmp("file",type) == 0) ) {
630            // tested with PutTests.testArgumentsCheckTypeFile()
631            // tested with PutTests.testArgumentsCheckTypeFileCompressTrue()
632            // tested with PutTests.testArgumentsCheckTypeFileCompressTrueNoDecode()
633            self->lib->putFile( std::string(path),
634                                std::string(PyString_AsString(valueStrObj)),
635                                compressInt,appendInt);
636        }
637        else {
638            // tested with PutTests.testArgumentsCheckTypeError()
639            PyErr_Format(PyExc_ValueError,
640                "\'type\' arg must be \'string\' or \'file\'");
641            return NULL;
642        }
643    }
644    else {
645        PyErr_Format(PyExc_TypeError,
646            "put()'s \'value\' arg must be a string or Rappture Library Object");
647        return NULL;
648    }
649
650    Py_RETURN_NONE;
651}
652
653PyDoc_STRVAR(RpLibraryObject_xml_doc,
654"xml () -> returns xml string\n\
655\n\
656Clients use this to query the XML representation for this\n\
657object.\n\
658");
659
660static PyObject*
661RpLibraryObject_xml(RpLibraryObject *self)
662{
663    PyObject *retStr = NULL;
664
665    if (self->lib == NULL) {
666        PyErr_Format(PyExc_RuntimeError,
667            "self uninitialized Rappture Library Object");
668    }
669
670    retStr = PyString_FromString(self->lib->xml().c_str());
671
672    return (PyObject *)retStr;
673}
674
675PyDoc_STRVAR(RpLibraryObject_result_doc,
676"result ([status=0]) -> None, send results back to graphical user interface\n\
677\n\
678Use this function to report the result of a Rappture simulation.\n\
679Pass in the optional exit status. Default is 0\n\
680");
681
682static PyObject*
683RpLibraryObject_result(RpLibraryObject *self, PyObject *args, PyObject *keywds)
684{
685    int argc = 0;
686    int status = 0;
687
688    static char *kwlist[] = {
689        (char *)"status",
690        NULL
691    };
692
693    if (self->lib == NULL) {
694        PyErr_Format(PyExc_RuntimeError,
695            "self uninitialized Rappture Library Object");
696        return NULL;
697    }
698
699    status = getArgCount(args,keywds,&argc);
700    if (status != 0) {
701        // trouble ensues
702        // error message was set in getArgCount()
703        return NULL;
704    }
705
706    if (argc > 2) {
707        PyErr_Format(PyExc_TypeError,
708            "result() takes at most 1 argument (%i given)",argc);
709        return NULL;
710    }
711
712    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|i", kwlist, &status)) {
713        // tested with ResultTests.testArguments_InvalidStatusArg()
714        PyErr_Format(PyExc_TypeError, "an integer is required");
715        return NULL;
716    }
717
718    self->lib->put("tool.version.rappture.language","python");
719    self->lib->result(status);
720
721    Py_RETURN_NONE;
722}
723
724static PyMethodDef RpLibraryObject_methods[] = {
725
726    {"copy", (PyCFunction)RpLibraryObject_copy, METH_VARARGS|METH_KEYWORDS,
727        RpLibraryObject_copy_doc},
728
729/*
730    {"children", (PyCFunction)RpLibraryObject_children, METH_VARARGS|METH_KEYWORDS,
731        RpLibraryObject_children_doc},
732*/
733
734    {"element", (PyCFunction)RpLibraryObject_element, METH_VARARGS|METH_KEYWORDS,
735        RpLibraryObject_element_doc},
736
737    {"get", (PyCFunction)RpLibraryObject_get, METH_VARARGS|METH_KEYWORDS,
738        RpLibraryObject_get_doc},
739
740/*
741    {"parent", (PyCFunction)RpLibraryObject_parent, METH_VARARGS|METH_KEYWORDS,
742        RpLibraryObject_put_doc},
743*/
744
745    {"put", (PyCFunction)RpLibraryObject_put, METH_VARARGS|METH_KEYWORDS,
746        RpLibraryObject_put_doc},
747
748/*
749    {"remove", (PyCFunction)RpLibraryObject_remove, METH_VARARGS|METH_KEYWORDS,
750        RpLibraryObject_remove_doc},
751*/
752
753    {"xml", (PyCFunction)RpLibraryObject_xml, METH_NOARGS,
754        RpLibraryObject_xml_doc},
755
756    {"result", (PyCFunction)RpLibraryObject_result, METH_VARARGS|METH_KEYWORDS,
757        RpLibraryObject_result_doc},
758
759    {NULL,        NULL}        /* sentinel */
760};
761
762static PyTypeObject RpLibraryObjectType = {
763    /* The ob_type field must be initialized in the module init function
764     * to be portable to Windows without using C++. */
765    PyObject_HEAD_INIT(NULL)
766    0,                                    /*ob_size*/
767    "Rappture.library",                   /*tp_name*/
768    sizeof(RpLibraryObject),              /*tp_basicsize*/
769    0,                                    /*tp_itemsize*/
770    /* methods */
771    (destructor)RpLibraryObject_dealloc,  /*tp_dealloc*/
772    0,                                    /*tp_print*/
773    0,                                    /*tp_getattr*/
774    0,                                    /*tp_setattr*/
775    0,                                    /*tp_compare*/
776    0,                                    /*tp_repr*/
777    0,                                    /*tp_as_number*/
778    0,                                    /*tp_as_sequence*/
779    0,                                    /*tp_as_mapping*/
780    0,                                    /*tp_hash*/
781    0,                                    /*tp_call*/
782    0,                                    /*tp_str*/
783    0,                                    /*tp_getattro*/
784    0,                                    /*tp_setattro*/
785    0,                                    /*tp_as_buffer*/
786    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /*tp_flags*/
787    "Rappture.library Object",            /*tp_doc*/
788    0,                                    /*tp_traverse*/
789    0,                                    /*tp_clear*/
790    0,                                    /*tp_richcompare*/
791    0,                                    /*tp_weaklistoffset*/
792    0,                                    /*tp_iter*/
793    0,                                    /*tp_iternext*/
794    RpLibraryObject_methods,              /* tp_methods */
795    0,                                    /*tp_members*/
796    0,                                    /*tp_getset*/
797    0,                                    /*tp_base*/
798    0,                                    /*tp_dict*/
799    0,                                    /*tp_descr_get*/
800    0,                                    /*tp_descr_set*/
801    0,                                    /*tp_dictoffset*/
802    (initproc)RpLibraryObject_init,       /*tp_init*/
803    0,                                    /*tp_alloc*/
804    RpLibraryObject_new,                  /*tp_new*/
805    0,                                    /*tp_new*/
806};
807
808/*
809 * used to create a RpLibrary object from a PyObject
810 */
811static RpLibrary *
812RpLibraryObject_AsLibrary(PyObject *lib)
813{
814    RpLibrary *retval = NULL;
815
816    if (lib != NULL) {
817        if (RpLibraryObject_IsValid(lib)) {
818            retval = ((RpLibraryObject *)lib)->lib;
819        }
820    }
821    return retval;
822}
823
824/*
825 * used to create a PyObject from a RpLibrary object
826 */
827PyObject *
828RpLibraryObject_FromLibrary(RpLibrary *lib)
829{
830    RpLibraryObject *self = NULL;
831
832    if (lib != NULL) {
833        self = PyObject_New(RpLibraryObject, &RpLibraryObjectType);
834        if (self != NULL) {
835            self->lib = lib;
836        }
837        else {
838            // raise error
839            PyErr_SetString(PyExc_RuntimeError,
840                            "trouble creating new RpLibraryObject");
841        }
842    }
843
844    return (PyObject *)self;
845}
846
847/*
848 *  int boolAsInt (inVal, outVal)
849 *
850 *  represent a boolean string as an integer.
851 *
852 *  outVal set to 1 if the boolean value inVal could
853 *  be associated with any of the following strings:
854 *  "yes", "on", "true", "1".
855 *
856 *  outVal set to 0 if the boolean value inVal could
857 *  be associated with any of the following strings:
858 *  "no", "off", "false", "0".
859 *
860 *  returns a status integer to tell if the operation
861 *  was successful (0) of if there was an error (!0)
862 *
863 *  note: string comparisons are case insensitive.
864 */
865
866static int
867boolAsInt(const char *string, int *resultPtr)
868{
869    char c;
870
871    if ((string == NULL) || (resultPtr == NULL) ) {
872        PyErr_Format(PyExc_TypeError,
873                     "incorrect use of boolAsInt(inVal,outVal)");
874        return RP_ERROR;
875    }
876    c = tolower(string[0]);
877    if ((c == 'y') && (strcasecmp(string, "yes") == 0)) {
878        *resultPtr = TRUE;
879    } else if ((c == 'n') && (strcasecmp(string, "no") == 0)) {
880        *resultPtr = FALSE;
881    } else if ((c == 'o') && (strcasecmp(string, "on") == 0)) {
882        *resultPtr = TRUE;
883    } else if ((c == 'o') && (strcasecmp(string, "off") == 0)) {
884        *resultPtr = FALSE;
885    } else if ((c == 't') && (strcasecmp(string, "true") == 0)) {
886        *resultPtr = TRUE;
887    } else if ((c == 'f') && (strcasecmp(string, "false") == 0)) {
888        *resultPtr = FALSE;
889    } else if ((c == '1') && (strcasecmp(string, "1") == 0)) {
890        *resultPtr = TRUE;
891    } else if ((c == '0') && (strcasecmp(string, "0") == 0)) {
892        *resultPtr = FALSE;
893    } else {
894        PyErr_Format(PyExc_ValueError,
895            "unrecognized input: %s: should be one of: \'yes\',\'true\',\'on\',\'1\',1,True,\'no\',\'false\',\'off\',\'0\',0,False", string);
896        return RP_ERROR;
897    }
898    return RP_OK;
899}
900
901static int
902boolIntFromPyObject (PyObject *objPtr, const char *defValue,
903                     const char *argName, int *resultPtr)
904{
905    int value;
906
907    value = FALSE;                      // Suppress compiler warning.
908    if ((defValue == NULL) || (argName == NULL) || (resultPtr == NULL)) {
909        // incorrect use of function
910        PyErr_Format(PyExc_ValueError,
911            "boolIntFromPyObject(): defValue or argName or resultPtr is NULL");
912        return RP_ERROR;
913    }
914    if (objPtr == NULL) {
915        return boolAsInt(defValue, resultPtr);
916    }
917    if (PyBool_Check(objPtr)) {
918        value = PyObject_IsTrue(objPtr);
919        if (value < 0) {
920             PyErr_Format(PyExc_ValueError,
921                "boolIntFromPyObject(): bad boolean object");
922            return RP_ERROR;
923        }
924    } else if (PyLong_Check(objPtr)) {
925        long l;
926
927        l = PyLong_AsLong(objPtr);
928        value = (l == 0) ? FALSE : TRUE;
929    } else if (PyFloat_Check(objPtr)) {
930        double d;
931
932        d = PyFloat_AS_DOUBLE(objPtr);
933        value = (d == 0.0) ? FALSE : TRUE;
934    } else if (PyString_Check(objPtr)) {
935        const char *string;
936       
937        string = PyString_AsString(objPtr);
938        if (string == NULL) {
939            PyErr_Format(PyExc_TypeError,
940                "bad value: %s: cannot convert to string",argName);
941            return RP_ERROR;
942        }
943        return boolAsInt(string, resultPtr);
944    }
945    *resultPtr = value;
946    return RP_OK;
947}
948
949static int
950getArgCount (PyObject *args, PyObject *keywds, int *argc)
951{
952    int args_cnt = 0;
953    int keywds_cnt = 0;
954
955    if (argc == NULL) {
956        // incorrect use of function
957        // argc cannot be null
958        PyErr_Format(PyExc_ValueError,"getArgCount(): argc is NULL");
959        return RP_ERROR;
960    }
961    if (args != NULL) {
962        if (!PyTuple_Check(args)) {
963            PyErr_Format(PyExc_TypeError,
964                "getArgCount(): \'args\' should be a PyTuple");
965            return RP_ERROR;
966        }
967        args_cnt = PyTuple_Size(args);
968    }
969    if (keywds != NULL) {
970        if (!PyDict_Check(keywds)) {
971            PyErr_Format(PyExc_TypeError,
972                "getArgCount(): \'keywds\' should be a PyDict");
973            return RP_ERROR;
974        }
975        keywds_cnt = PyDict_Size(keywds);
976    }
977    *argc = args_cnt + keywds_cnt;
978    return RP_OK;
979}
980
981/* ---------- */
982
983/* List of functions defined in the module */
984
985static PyMethodDef Library_Methods[] = {
986    {NULL,        NULL}        /* sentinel */
987};
988
989PyDoc_STRVAR(module_doc, "Rappture Library Module for Python.");
990
991/* Initialization function for the module */
992
993PyMODINIT_FUNC
994initlibrary(void)
995{
996    PyObject *m;
997
998    /* Finalize the type object including setting type of the new type
999     * object; doing it here is required for portability to Windows
1000     * without requiring C++. */
1001    if (PyType_Ready(&RpLibraryObjectType) < 0)
1002        return;
1003
1004    /* Create the module and add the functions */
1005    m = Py_InitModule3("library", Library_Methods, module_doc);
1006
1007    /* Add some symbolic constants to the module */
1008    if (ErrorObject == NULL) {
1009        ErrorObject = PyErr_NewException((char *)"RpLibrary.error", NULL, NULL);
1010        if (ErrorObject == NULL)
1011            return;
1012    }
1013
1014    Py_INCREF(&RpLibraryObjectType);
1015    PyModule_AddObject(m, "library", (PyObject*) &RpLibraryObjectType);
1016
1017    Py_XINCREF(ErrorObject);
1018    PyModule_AddObject(m, "error", ErrorObject);
1019
1020}
Note: See TracBrowser for help on using the repository browser.