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

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