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

Last change on this file since 4346 was 3638, checked in by gah, 9 years ago

fix ruby getstring for binary strings

File size: 28.8 KB
Line 
1
2/*
3 * ======================================================================
4 *  AUTHOR:  Derrick S. Kearney, Purdue University
5 *  Copyright (c) 2004-2012  HUBzero Foundation, LLC
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
50static int
51getArgCount(PyObject *args, PyObject *keywds, int *argc)
52{
53    int args_cnt = 0;
54    int keywds_cnt = 0;
55
56    if (argc == NULL) {
57        // incorrect use of function
58        // argc cannot be null
59        PyErr_Format(PyExc_ValueError,"getArgCount(): argc is NULL");
60        return RP_ERROR;
61    }
62    if (args != NULL) {
63        if (!PyTuple_Check(args)) {
64            PyErr_Format(PyExc_TypeError,
65                "getArgCount(): \'args\' should be a PyTuple");
66            return RP_ERROR;
67        }
68        args_cnt = PyTuple_Size(args);
69    }
70    if (keywds != NULL) {
71        if (!PyDict_Check(keywds)) {
72            PyErr_Format(PyExc_TypeError,
73                "getArgCount(): \'keywds\' should be a PyDict");
74            return RP_ERROR;
75        }
76        keywds_cnt = PyDict_Size(keywds);
77    }
78    *argc = args_cnt + keywds_cnt;
79    return RP_OK;
80}
81
82/*
83 *  StringToBoolean --
84 *
85 *  represent a boolean string as an integer.
86 *
87 *  outVal set to 1 if the boolean value inVal could
88 *  be associated with any of the following strings:
89 *  "yes", "on", "true", "1".
90 *
91 *  outVal set to 0 if the boolean value inVal could
92 *  be associated with any of the following strings:
93 *  "no", "off", "false", "0".
94 *
95 *  returns a status integer to tell if the operation
96 *  was successful (0) of if there was an error (!0)
97 *
98 *  note: string comparisons are case insensitive.
99 */
100
101static int
102StringToBoolean(const char *string, int *resultPtr)
103{
104    char c;
105
106    if ((string == NULL) || (resultPtr == NULL) ) {
107        PyErr_Format(PyExc_TypeError,
108                     "incorrect use of StringToBoolean(inVal,outVal)");
109        return RP_ERROR;
110    }
111    c = tolower(string[0]);
112    if (((c == 'y') && (strcasecmp(string, "yes") == 0)) ||
113        ((c == 'o') && (strcasecmp(string, "on") == 0)) ||
114        ((c == 't') && (strcasecmp(string, "true") == 0)) ||
115        ((c == '1') && (strcasecmp(string, "1") == 0))) {
116        *resultPtr = TRUE;
117    } else if (((c == 'n') && (strcasecmp(string, "no") == 0)) ||
118               ((c == 'o') && (strcasecmp(string, "off") == 0)) ||
119               ((c == 'f') && (strcasecmp(string, "false") == 0)) ||
120               ((c == '0') && (strcasecmp(string, "0") == 0))) {
121        *resultPtr = FALSE;
122    } else {
123        PyErr_Format(PyExc_ValueError,
124            "unrecognized input: %s: should be one of: \'yes\',\'true\',\'on\',\'1\',1,True,\'no\',\'false\',\'off\',\'0\',0,False", string);
125        return RP_ERROR;
126    }
127    return RP_OK;
128}
129
130static int
131PyObjectToBoolean(PyObject *objPtr, const char *defValue, const char *argName,
132                  int *resultPtr)
133{
134    int value;
135
136    value = FALSE;                      // Suppress compiler warning.
137    if ((defValue == NULL) || (argName == NULL) || (resultPtr == NULL)) {
138        // incorrect use of function
139        PyErr_Format(PyExc_ValueError,
140            "PyObjectToBoolean: defValue or argName or resultPtr is NULL");
141        return RP_ERROR;
142    }
143    if (objPtr == NULL) {
144        return StringToBoolean(defValue, resultPtr);
145    }
146    if (PyBool_Check(objPtr)) {
147        value = PyObject_IsTrue(objPtr);
148        if (value < 0) {
149             PyErr_Format(PyExc_ValueError,
150                "PyObjectToBoolean: bad boolean object");
151            return RP_ERROR;
152        }
153    } else if (PyLong_Check(objPtr)) {
154        long l;
155
156        l = PyLong_AsLong(objPtr);
157        value = (l == 0) ? FALSE : TRUE;
158    } else if (PyInt_Check(objPtr)) {
159        long l;
160
161        l = PyInt_AsLong(objPtr);
162        value = (l == 0) ? FALSE : TRUE;
163    } else if (PyFloat_Check(objPtr)) {
164        double d;
165
166        d = PyFloat_AS_DOUBLE(objPtr);
167        value = (d == 0.0) ? FALSE : TRUE;
168    } else if (PyString_Check(objPtr)) {
169        const char *string;
170       
171        string = PyString_AsString(objPtr);
172        if (string == NULL) {
173            PyErr_Format(PyExc_TypeError,
174                "bad value: %s: cannot convert to string",argName);
175            return RP_ERROR;
176        }
177        return StringToBoolean(string, resultPtr);
178    } else {
179        PyErr_Format(PyExc_TypeError,
180                "unknown python type for %s", argName);
181        return RP_ERROR;
182    }
183    *resultPtr = value;
184    return RP_OK;
185}
186
187/*
188 * Check to see if this object is a Rappture.library object.
189 * This does not check to see if the object is correctly
190 * initialized. To check for correct object type and
191 * correct initialization, use RpLibraryObject_IsValid.
192 */
193static int
194RpLibraryObject_Check(PyObject *objPtr)
195{
196    if (objPtr == NULL) {
197        return FALSE;
198    }
199    if (strcmp(objPtr->ob_type->tp_name, "Rappture.library") != 0) {
200        return FALSE;
201    }
202    return TRUE;
203}
204
205/*
206 * Check to see if this object is a Rappture.library object
207 * and is correctly initialized
208 *
209 * This function calls RpLibraryObject_Check internally, and is used
210 * in most of the internal functions to check if an object being passed
211 * in by the user is a valid Rappture.library object
212 */
213static int
214RpLibraryObject_IsValid(PyObject *objPtr)
215{
216    if (objPtr == NULL) {
217        return FALSE;                   // Passed a NULL pointer. Should
218                                        // probably segfault.
219    }
220    if (!RpLibraryObject_Check(objPtr)) {
221        return FALSE;                   // Not a rappture library object type.
222    }
223    if (((RpLibraryObject *)objPtr)->lib == NULL) {
224        return FALSE;                   // Is a rappture library object, but
225                                        // doesn't contain a valid library.
226    }
227    return TRUE;
228}
229
230static PyObject *
231NewProc(PyTypeObject *type, PyObject *args, PyObject *kwds)
232{
233    RpLibraryObject *self = NULL;
234
235    self = (RpLibraryObject *)type->tp_alloc(type,0);
236    if (self != NULL) {
237        self->lib = NULL;
238    } else {
239        PyErr_SetString(PyExc_RuntimeError,
240                "trouble creating new RpLibraryObject");
241    }
242    return (PyObject *)self;
243}
244
245static int
246InitProc(RpLibraryObject *self, PyObject *args, PyObject *kwds)
247{
248    PyObject *objPtr;
249
250    objPtr = NULL;
251    if (!PyArg_ParseTuple(args, "|O", &objPtr)) {
252        PyErr_Format(PyExc_TypeError,
253            "library() takes at most 1 argument, a file name or a Rappture Library Object");
254        return -1;
255    }
256
257    if (objPtr != NULL) {
258        if (PyString_Check(objPtr)) {
259            char *filename;
260
261            filename = PyString_AsString(objPtr);
262            if (filename == NULL) {
263                PyErr_Format(PyExc_ValueError,"a file name is required");
264            }
265            self->lib = new RpLibrary(std::string(filename));
266        } else if (RpLibraryObject_IsValid(objPtr)) {
267            self->lib = new RpLibrary( *(RpLibraryObject_AsLibrary(objPtr)) );
268        } else if (RpLibraryObject_Check(objPtr)) {
269            self->lib = new RpLibrary();
270        } else {
271            PyErr_Format(PyExc_TypeError,"unrecognized object type");
272            return -1;
273        }
274    } else {
275        self->lib = new RpLibrary();
276    }
277
278    return 1;
279}
280
281static void
282FreeProc(RpLibraryObject *self)
283{
284    if (self) {
285        if (self->lib){
286            delete(self->lib);
287        }
288        self->ob_type->tp_free((PyObject *) self);
289    }
290}
291
292PyDoc_STRVAR(CopyProcDoc,
293"copy (topath, frompath [, fromobj=$self]) -> None, copies data\n\
294\n\
295Copy an xml element to \'topath\' of the current this object\n\
296from \'frompath\' of the Rappture Library Object \'fromobj\'.\n\
297\n\
298\'topath\' is the path (in this object) where the data should\n\
299be copied to\n\
300\'frompath\' is an path (in fromobj) where the data should be\n\
301copied from\n\
302\'fromobj\' is the Rappture Library Object to copy the data from\n\
303if fromobj is not set, the data is copied from the same object\n\
304the data will be copied to (this object).\n\
305\n\
306");
307
308static PyObject *
309CopyProc(RpLibraryObject *self, PyObject *args, PyObject *keywds)
310{
311    char *topath = (char *)"";
312    char *frompath = (char *)"";
313    int argc = 0;
314    PyObject *fromobj = (PyObject *) self;
315
316    static char *kwlist[] = {
317        (char *)"topath",
318        (char *)"frompath",
319        (char *)"fromobj",
320        NULL
321    };
322
323    if (self->lib == NULL) {
324        PyErr_SetString(PyExc_RuntimeError,
325            "self is uninitialized Rappture Library Object");
326        return NULL;
327    }
328
329    if (getArgCount(args,keywds,&argc) != RP_OK) {
330        // trouble ensues
331        // error message was set in getArgCount()
332        return NULL;
333    }
334
335    if (argc > 3) {
336        // tested with CopyTests.testArguments_TooManyArgs()
337        PyErr_Format(PyExc_TypeError,
338            "copy() takes at most 3 arguments (%i given)",argc);
339        return NULL;
340    }
341
342    if (argc < 2) {
343        // tested with CopyTests.testArguments_NotEnoughArgs()
344        PyErr_Format(PyExc_TypeError,
345            "copy() takes at least 2 arguments (%i given)",argc);
346        return NULL;
347    }
348
349    if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|O",
350            kwlist, &topath, &frompath, &fromobj)) {
351        // tested with CopyTests.testArguments_ArgsWrongType2()
352        PyErr_Format(PyExc_TypeError,
353            "copy() takes 2 sting and 1 Rappture Library Object as arguments");
354        return NULL;
355    }
356
357    if (!RpLibraryObject_IsValid(fromobj)) {
358        // tested with CopyTests.testArguments_ArgsWrongType3()
359        PyErr_SetString(PyExc_RuntimeError,
360            "incorrectly initialized Rappture Library Object");
361        return NULL;
362    }
363
364    self->lib->copy(std::string(topath),
365        RpLibraryObject_AsLibrary(fromobj),
366        std::string(frompath));
367
368    Py_RETURN_NONE;
369}
370
371PyDoc_STRVAR(ElementProcDoc,
372"element ([path=\'\'][, as=\'object\']) -> returns string or Rappture Library Object\n\
373\n\
374Clients use this to query a particular element within the \n\
375entire data structure.  The path is a string of the form \n\
376\"structure.box(source).corner\".  This example represents \n\
377the tag <corner> within a tag <box id=\"source\"> within a \n\
378a tag <structure>, which must be found at the top level \n\
379within this document. \n\
380\n\
381By default, this method returns an object representing the \n\
382DOM node referenced by the path.  This is changed by setting \n\
383the \"as\" argument to \"id\" (for name of the tail element), \n\
384to \"type\" (for the type of the tail element), to \"component\" \n\
385(for the component name \"type(id)\"), or to \"object\" \n\
386for the default (an object representing the tail element).\n\
387");
388
389static PyObject *
390ElementProc(RpLibraryObject *self, PyObject *args, PyObject *keywds)
391{
392    char* path = (char *)"";
393    char* as = (char *)"object";
394    RpLibrary* retlib = NULL;
395    PyObject* retVal = NULL;
396    int argc = 0;
397
398    static char *kwlist[] = {
399        (char *)"path",
400        (char *)"as",
401        NULL
402    };
403
404    if (self->lib == NULL) {
405        PyErr_Format(PyExc_RuntimeError,
406            "self is uninitialized Rappture Library Object");
407        return retVal;
408    }
409
410    if (getArgCount(args,keywds,&argc) != RP_OK) {
411        // trouble ensues
412        // error message was set in getArgCount()
413        return NULL;
414    }
415
416    if (argc > 2) {
417        // tested with ElementTests.testArguments_TooManyArgs()
418        PyErr_Format(PyExc_TypeError,
419            "element() takes at most 2 arguments (%i given)", argc);
420        return retVal;
421    }
422
423    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|ss",
424                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
456    return (PyObject *)retVal;
457}
458
459
460PyDoc_STRVAR(GetProcDoc,
461"get ([path=\'\'][, decode=\'True\']) -> returns data at \'path\' as string\n\
462\n\
463Clients use this to query the value of a node.  If the path\n\
464is not specified, it returns the value associated with the\n\
465root node.  Otherwise, it returns the value for the element\n\
466specified by the path.\n\
467");
468
469static PyObject *
470GetProc(RpLibraryObject *self, PyObject *args, PyObject *keywds)
471{
472    char* path = (char *)"";
473    PyObject* decode = NULL;
474    int decodeFlag;
475    PyObject *resultPtr = NULL;
476    int argc = 0;
477
478    static char *kwlist[] = {
479        (char *)"path",
480        (char *)"decode",
481        NULL
482    };
483
484    if (self->lib == NULL) {
485        PyErr_SetString(PyExc_RuntimeError,
486            "self uninitialized Rappture Library Object");
487        return NULL;
488    }
489
490    if (getArgCount(args,keywds,&argc) != RP_OK) {
491        // trouble ensues
492        // error message was set in getArgCount()
493        return NULL;
494    }
495
496    if (argc > 2) {
497        // tested with GetTests.testArguments_TooManyArgs()
498        PyErr_Format(PyExc_TypeError,
499            "get() takes at most 2 arguments (%i given)",argc);
500        return NULL;
501    }
502
503    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sO",
504            kwlist, &path, &decode)) {
505        // tested with GetTests.testArguments_ArgsWrongType2()
506        PyErr_Format(PyExc_TypeError,"get ([path=\'\'][, decode=\'True\'])");
507        return NULL;
508    }
509    if (PyObjectToBoolean(decode,"yes", "decode", &decodeFlag) != RP_OK) {
510        // tested with GetTests.testArgumentsDecodeError()
511        return NULL;
512    }
513    if (decodeFlag) {
514        std::string s;
515
516        s = self->lib->get(std::string(path));
517        resultPtr = PyString_FromStringAndSize(s.c_str(), s.size());
518    } else {
519        Rappture::Buffer out;
520
521        out = self->lib->getData(std::string(path));
522        resultPtr = PyString_FromStringAndSize(out.bytes(), out.size());
523    }
524    return (PyObject *)resultPtr;
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 = (char *)"";
635
636    PyObject *valueObjPtr, *compressObjPtr, *appendObjPtr, *strObjPtr;
637    char *id = NULL;
638    int appendFlag, compressFlag;
639    char *type = (char *)"string";
640    int argc = 0;
641
642    static char *kwlist[] = {
643        (char *)"path",
644        (char *)"value",
645        (char *)"id",
646        (char *)"append",
647        (char *)"type",
648        (char *)"compress",
649        NULL
650    };
651    appendFlag = compressFlag = FALSE;
652    strObjPtr = appendObjPtr = valueObjPtr = compressObjPtr = NULL;
653    if (self->lib == NULL) {
654        PyErr_Format(PyExc_RuntimeError,
655            "self uninitialized Rappture Library Object");
656        return NULL;
657    }
658
659    if (getArgCount(args,keywds,&argc) != RP_OK) {
660        return NULL;
661    }
662    if (argc > 6) {
663        PyErr_Format(PyExc_TypeError,
664            "put() takes at most 6 arguments (%i given)",argc);
665        return NULL;
666    }
667    if (argc < 2) {
668        PyErr_Format(PyExc_TypeError,
669            "put() takes at least 2 arguments (%i given)",argc);
670        return NULL;
671    }
672    if (!PyArg_ParseTupleAndKeywords(args, keywds, "sO|sOsO", kwlist, &path,
673        &valueObjPtr, &id, &appendObjPtr, &type, &compressObjPtr)) {
674        return NULL;
675    }
676
677    if (valueObjPtr == NULL) {
678        PyErr_Format(PyExc_ValueError, "put()'s \'value\' arg is required");
679        return NULL;
680    }
681
682    if (PyObjectToBoolean(appendObjPtr, "no"," append", &appendFlag) != RP_OK){
683        return NULL;
684    }
685    if (PyObjectToBoolean(compressObjPtr, "no", "compress", &compressFlag)
686        != RP_OK) {
687        return NULL;
688    }
689
690    strObjPtr = PyObject_Str(valueObjPtr);
691    if (RpLibraryObject_IsValid(valueObjPtr)) {
692        self->lib->put( std::string(path),
693                RpLibraryObject_AsLibrary(valueObjPtr), "", appendFlag);
694    } else if (strObjPtr != NULL) {
695        char *string;
696        Py_ssize_t length;
697
698        if (PyString_AsStringAndSize(strObjPtr, &string, &length) == -1) {
699            return NULL;
700        }
701        if ((type == NULL) || ((*type=='s') && (strcmp("string", type) == 0))){
702            if (compressFlag == 0) {
703                self->lib->put( std::string(path),
704                                std::string(string), "", appendFlag);
705            } else {
706                self->lib->putData( std::string(path), string, length,
707                        appendFlag);
708            }
709        } else if ((*type == 'f') && (strcmp("file",type) == 0)) {
710            self->lib->putFile( std::string(path),
711                                std::string(PyString_AsString(strObjPtr)),
712                                compressFlag, appendFlag);
713        } else {
714            PyErr_Format(PyExc_ValueError,
715                "\'type\' arg must be \'string\' or \'file\'");
716            return NULL;
717        }
718    } else {
719        PyErr_Format(PyExc_TypeError,
720            "put()'s \'value\' arg must be a string or Rappture Library Object");
721        return NULL;
722    }
723    Py_RETURN_NONE;
724}
725
726PyDoc_STRVAR(XmlProcDoc,
727"xml () -> returns xml string\n\
728\n\
729Clients use this to query the XML representation for this\n\
730object.\n\
731");
732
733static PyObject*
734XmlProc(RpLibraryObject *self)
735{
736    if (self->lib == NULL) {
737        PyErr_Format(PyExc_RuntimeError,
738            "self uninitialized Rappture Library Object");
739    }
740    return PyString_FromString(self->lib->xml().c_str());
741}
742
743PyDoc_STRVAR(ResultProcDoc,
744"result ([status=0]) -> None, send results back to graphical user interface\n\
745\n\
746Use this function to report the result of a Rappture simulation.\n\
747Pass in the optional exit status. Default is 0\n\
748");
749
750static PyObject*
751ResultProc(RpLibraryObject *self, PyObject *args, PyObject *keywds)
752{
753    int argc = 0;
754    int status = 0;
755
756    static char *kwlist[] = {
757        (char *)"status",
758        NULL
759    };
760
761    if (self->lib == NULL) {
762        PyErr_Format(PyExc_RuntimeError,
763            "self uninitialized Rappture Library Object");
764        return NULL;
765    }
766
767    if (getArgCount(args,keywds,&argc) != RP_OK) {
768        // trouble ensues
769        // error message was set in getArgCount()
770        return NULL;
771    }
772
773    if (argc > 2) {
774        PyErr_Format(PyExc_TypeError,
775            "result() takes at most 1 argument (%i given)",argc);
776        return NULL;
777    }
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
785    self->lib->put("tool.version.rappture.language","python");
786    self->lib->result(status);
787
788    Py_RETURN_NONE;
789}
790
791static PyMethodDef RpLibraryObject_methods[] = {
792
793    {"copy", (PyCFunction)CopyProc, METH_VARARGS|METH_KEYWORDS, CopyProcDoc},
794
795#ifdef notdef
796    {"children", (PyCFunction)ChildrenProc, METH_VARARGS|METH_KEYWORDS,
797        ChildrenProcDoc},
798#endif
799
800    {"element", (PyCFunction)ElementProc, METH_VARARGS|METH_KEYWORDS,
801        ElementProcDoc},
802
803    {"get", (PyCFunction)GetProc, METH_VARARGS|METH_KEYWORDS,
804        GetProcDoc},
805
806#ifdef notdef
807    {"parent", (PyCFunction)ParentProc, METH_VARARGS|METH_KEYWORDS,
808                ParentProcDoc},
809#endif
810
811    {"put", (PyCFunction)PutProc, METH_VARARGS|METH_KEYWORDS, PutProcDoc},
812
813#ifdef notdef
814    {"remove", (PyCFunction)RemoveProc, METH_VARARGS|METH_KEYWORDS,
815        RemoveProcDoc},
816#endif
817
818    {"xml", (PyCFunction)XmlProc, METH_NOARGS, XmlProcDoc},
819
820    {"result", (PyCFunction)ResultProc, METH_VARARGS|METH_KEYWORDS,
821        ResultProcDoc},
822
823    {NULL,        NULL}        /* sentinel */
824};
825
826static PyTypeObject RpLibraryObjectType = {
827    /* The ob_type field must be initialized in the module init function
828     * to be portable to Windows without using C++. */
829    PyObject_HEAD_INIT(NULL)
830    0,                                    /*ob_size*/
831    "Rappture.library",                   /*tp_name*/
832    sizeof(RpLibraryObject),              /*tp_basicsize*/
833    0,                                    /*tp_itemsize*/
834    /* methods */
835    (destructor)FreeProc,               /*tp_dealloc*/
836    0,                                    /*tp_print*/
837    0,                                    /*tp_getattr*/
838    0,                                    /*tp_setattr*/
839    0,                                    /*tp_compare*/
840    0,                                    /*tp_repr*/
841    0,                                    /*tp_as_number*/
842    0,                                    /*tp_as_sequence*/
843    0,                                    /*tp_as_mapping*/
844    0,                                    /*tp_hash*/
845    0,                                    /*tp_call*/
846    0,                                    /*tp_str*/
847    0,                                    /*tp_getattro*/
848    0,                                    /*tp_setattro*/
849    0,                                    /*tp_as_buffer*/
850    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /*tp_flags*/
851    "Rappture.library Object",            /*tp_doc*/
852    0,                                    /*tp_traverse*/
853    0,                                    /*tp_clear*/
854    0,                                    /*tp_richcompare*/
855    0,                                    /*tp_weaklistoffset*/
856    0,                                    /*tp_iter*/
857    0,                                    /*tp_iternext*/
858    RpLibraryObject_methods,              /* tp_methods */
859    0,                                    /*tp_members*/
860    0,                                    /*tp_getset*/
861    0,                                    /*tp_base*/
862    0,                                    /*tp_dict*/
863    0,                                    /*tp_descr_get*/
864    0,                                    /*tp_descr_set*/
865    0,                                    /*tp_dictoffset*/
866    (initproc)InitProc,                 /*tp_init*/
867    0,                                    /*tp_alloc*/
868    NewProc,                            /*tp_new*/
869    0,                                    /*tp_new*/
870};
871
872/*
873 * used to create a RpLibrary object from a PyObject
874 */
875static RpLibrary *
876RpLibraryObject_AsLibrary(PyObject *lib)
877{
878    RpLibrary *retval = NULL;
879
880    if (lib != NULL) {
881        if (RpLibraryObject_IsValid(lib)) {
882            retval = ((RpLibraryObject *)lib)->lib;
883        }
884    }
885    return retval;
886}
887
888/*
889 * used to create a PyObject from a RpLibrary object
890 */
891PyObject *
892RpLibraryObject_FromLibrary(RpLibrary *lib)
893{
894    RpLibraryObject *self = NULL;
895
896    if (lib != NULL) {
897        self = PyObject_New(RpLibraryObject, &RpLibraryObjectType);
898        if (self != NULL) {
899            self->lib = lib;
900        } else {
901            // raise error
902            PyErr_SetString(PyExc_RuntimeError,
903                "trouble creating new RpLibraryObject");
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.