PageRenderTime 118ms CodeModel.GetById 77ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pyglue/PyUtil.cpp

http://github.com/imageworks/OpenColorIO
C++ | 771 lines | 572 code | 125 blank | 74 comment | 91 complexity | a448647036a65418edb518203cd57850 MD5 | raw file
  1/*
  2Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
  3All Rights Reserved.
  4
  5Redistribution and use in source and binary forms, with or without
  6modification, are permitted provided that the following conditions are
  7met:
  8* Redistributions of source code must retain the above copyright
  9  notice, this list of conditions and the following disclaimer.
 10* Redistributions in binary form must reproduce the above copyright
 11  notice, this list of conditions and the following disclaimer in the
 12  documentation and/or other materials provided with the distribution.
 13* Neither the name of Sony Pictures Imageworks nor the names of its
 14  contributors may be used to endorse or promote products derived from
 15  this software without specific prior written permission.
 16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 17"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 18LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 19A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 20OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 21SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 22LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 26OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27*/
 28
 29#include <Python.h>
 30#include <sstream>
 31#include <OpenColorIO/OpenColorIO.h>
 32
 33#include "PyUtil.h"
 34
 35OCIO_NAMESPACE_ENTER
 36{
 37    
 38    ///////////////////////////////////////////////////////////////////////////
 39    
 40    // http://docs.python.org/c-api/object.html#PyObject_IsTrue
 41    int ConvertPyObjectToBool(PyObject *object, void *valuePtr)
 42    {
 43        bool *boolPtr = static_cast<bool*>(valuePtr);
 44        int status = PyObject_IsTrue(object);
 45        
 46        if (status == -1 || PyErr_Occurred())
 47        {
 48            if (!PyErr_Occurred())
 49            {
 50                PyErr_SetString(PyExc_ValueError, "could not convert object to bool.");
 51            }
 52            
 53            return 0;
 54        }
 55
 56        *boolPtr = (status == 1) ? true : false;
 57
 58        return 1;
 59    }
 60    
 61    int ConvertPyObjectToAllocation(PyObject *object, void *valuePtr)
 62    {
 63        Allocation* allocPtr = static_cast<Allocation*>(valuePtr);
 64        
 65        if(!PyString_Check(object))
 66        {
 67            PyErr_SetString(PyExc_ValueError, "Object is not a string.");
 68            return 0;
 69        }
 70        
 71        *allocPtr = AllocationFromString(PyString_AsString( object ));
 72        
 73        return 1;
 74    }
 75    
 76    
 77    
 78    int ConvertPyObjectToInterpolation(PyObject *object, void *valuePtr)
 79    {
 80        Interpolation* interpPtr = static_cast<Interpolation*>(valuePtr);
 81        
 82        if(!PyString_Check(object))
 83        {
 84            PyErr_SetString(PyExc_ValueError, "Object is not a string.");
 85            return 0;
 86        }
 87        
 88        *interpPtr = InterpolationFromString(PyString_AsString( object ));
 89        
 90        return 1;
 91    }
 92    
 93    int ConvertPyObjectToTransformDirection(PyObject *object, void *valuePtr)
 94    {
 95        TransformDirection* dirPtr = static_cast<TransformDirection*>(valuePtr);
 96        
 97        if(!PyString_Check(object))
 98        {
 99            PyErr_SetString(PyExc_ValueError, "Object is not a string.");
100            return 0;
101        }
102        
103        *dirPtr = TransformDirectionFromString(PyString_AsString( object ));
104        
105        return 1;
106    }
107    
108    
109    int ConvertPyObjectToColorSpaceDirection(PyObject *object, void *valuePtr)
110    {
111        ColorSpaceDirection* dirPtr = static_cast<ColorSpaceDirection*>(valuePtr);
112        
113        if(!PyString_Check(object))
114        {
115            PyErr_SetString(PyExc_ValueError, "Object is not a string.");
116            return 0;
117        }
118        
119        *dirPtr = ColorSpaceDirectionFromString(PyString_AsString( object ));
120        
121        return 1;
122    }
123    
124    
125    int ConvertPyObjectToGpuLanguage(PyObject *object, void *valuePtr)
126    {
127        GpuLanguage* gpuLanguagePtr = static_cast<GpuLanguage*>(valuePtr);
128        
129        if(!PyString_Check(object))
130        {
131            PyErr_SetString(PyExc_ValueError, "Object is not a string.");
132            return 0;
133        }
134        
135        *gpuLanguagePtr = GpuLanguageFromString(PyString_AsString( object ));
136        
137        return 1;
138    }
139    
140    int ConvertPyObjectToEnvironmentMode(PyObject *object, void *valuePtr)
141    {
142        EnvironmentMode* environmentmodePtr = static_cast<EnvironmentMode*>(valuePtr);
143        
144        if(!PyString_Check(object))
145        {
146            PyErr_SetString(PyExc_ValueError, "Object is not a string.");
147            return 0;
148        }
149        
150        *environmentmodePtr = EnvironmentModeFromString(PyString_AsString( object ));
151        
152        return 1;
153    }
154    
155    ///////////////////////////////////////////////////////////////////////////
156    
157    bool GetIntFromPyObject(PyObject* object, int* val)
158    {
159        if(!val || !object) return false;
160        
161        if( PyInt_Check( object ) )
162        {
163            *val = static_cast<int>( PyInt_AS_LONG( object ) );
164            return true;
165        }
166        
167        if( PyFloat_Check( object ) )
168        {
169            *val = static_cast<int>( PyFloat_AS_DOUBLE( object ) );
170            return true;
171        }
172        
173        PyObject* intObject = PyNumber_Int(object);
174        if(intObject)
175        {
176            *val = static_cast<int>( PyInt_AS_LONG( intObject ) );
177            Py_DECREF(intObject);
178            return true;
179        }
180        
181        PyErr_Clear();
182        return false;
183    }
184    
185    bool GetFloatFromPyObject(PyObject* object, float* val)
186    {
187        if(!val || !object) return false;
188        
189        if( PyFloat_Check( object ) )
190        {
191            *val = static_cast<float>( PyFloat_AS_DOUBLE( object ) );
192            return true;
193        }
194        
195        if( PyInt_Check( object ) )
196        {
197            *val = static_cast<float>( PyInt_AS_LONG( object ) );
198            return true;
199        }
200        
201        PyObject* floatObject = PyNumber_Float(object);
202        if(floatObject)
203        {
204            *val = static_cast<float>( PyFloat_AS_DOUBLE( floatObject ) );
205            Py_DECREF(floatObject);
206            return true;
207        }
208        
209        PyErr_Clear();
210        return false;
211    }
212    
213    bool GetDoubleFromPyObject(PyObject* object, double* val)
214    {
215        if(!val || !object) return false;
216        
217        if( PyFloat_Check( object ) )
218        {
219            *val = PyFloat_AS_DOUBLE( object );
220            return true;
221        }
222        
223        if( PyInt_Check( object ) )
224        {
225            *val = static_cast<double>( PyInt_AS_LONG( object ) );
226            return true;
227        }
228        
229        PyObject* floatObject = PyNumber_Float(object);
230        if(floatObject)
231        {
232            *val = PyFloat_AS_DOUBLE( floatObject );
233            Py_DECREF(floatObject);
234            return true;
235        }
236        
237        PyErr_Clear();
238        return false;
239    }
240    
241    bool GetStringFromPyObject(PyObject* object, std::string* val)
242    {
243        if(!val || !object) return false;
244        
245        if( PyString_Check( object ) )
246        {
247            *val = std::string(PyString_AS_STRING(object));
248            return true;
249        }
250        
251        PyObject* strObject = PyObject_Str(object);
252        if(strObject)
253        {
254            *val = std::string(PyString_AS_STRING(strObject));
255            Py_DECREF(strObject);
256            return true;
257        }
258        
259        PyErr_Clear();
260        return false;
261    }
262    
263    
264    
265    ///////////////////////////////////////////////////////////////////////////
266    
267    PyObject* CreatePyListFromIntVector(const std::vector<int> &data)
268    {
269        PyObject* returnlist = PyList_New( data.size() );
270        if(!returnlist) return 0;
271        
272        for(unsigned int i =0; i<data.size(); ++i)
273        {
274            PyList_SET_ITEM(returnlist, i, PyInt_FromLong(data[i]));
275        }
276        
277        return returnlist;
278    }
279    
280    PyObject* CreatePyListFromFloatVector(const std::vector<float> &data)
281    {
282        PyObject* returnlist = PyList_New( data.size() );
283        if(!returnlist) return 0;
284        
285        for(unsigned int i =0; i<data.size(); ++i)
286        {
287            PyList_SET_ITEM(returnlist, i, PyFloat_FromDouble(data[i]));
288        }
289        
290        return returnlist;
291    }
292    
293    PyObject* CreatePyListFromDoubleVector(const std::vector<double> &data)
294    {
295        PyObject* returnlist = PyList_New( data.size() );
296        if(!returnlist) return 0;
297        
298        for(unsigned int i =0; i<data.size(); ++i)
299        {
300            PyList_SET_ITEM(returnlist, i, PyFloat_FromDouble(data[i]));
301        }
302        
303        return returnlist;
304    }
305    
306    PyObject* CreatePyListFromStringVector(const std::vector<std::string> &data)
307    {
308        PyObject* returnlist = PyList_New( data.size() );
309        if(!returnlist) return 0;
310        
311        for(unsigned int i =0; i<data.size(); ++i)
312        {
313            PyObject *str =  PyString_FromString(data[i].c_str());
314            if (str == NULL)
315            {
316                Py_DECREF(returnlist);
317                return NULL;
318            }
319            PyList_SET_ITEM(returnlist, i, str);
320        }
321        
322        return returnlist;
323    }
324    
325    PyObject* CreatePyListFromTransformVector(const std::vector<ConstTransformRcPtr> &data)
326    {
327        PyObject* returnlist = PyList_New( data.size() );
328        if(!returnlist) return 0;
329        
330        for(unsigned int i =0; i<data.size(); ++i)
331        {
332            PyList_SET_ITEM(returnlist, i, BuildConstPyTransform(data[i]));
333        }
334        
335        return returnlist;
336    }
337    
338    PyObject* CreatePyDictFromStringMap(const std::map<std::string, std::string> &data)
339    {
340        PyObject* returndict = PyDict_New();
341        if(!returndict) return 0;
342        
343        std::map<std::string, std::string>::const_iterator iter;
344        for(iter = data.begin(); iter != data.end(); ++iter)
345        {
346            int ret = PyDict_SetItem(returndict,
347                PyString_FromString(iter->first.c_str()),
348                PyString_FromString(iter->second.c_str()));
349            if(ret)
350            {
351                Py_DECREF(returndict);
352                return NULL;
353            }
354        }
355        
356        return returndict;
357    }
358    
359    namespace
360    {
361        // These are safer than PySequence_Fast, as we can
362        // Confirm that no exceptions will be set in the python runtime.
363        
364        inline bool PyListOrTuple_Check(PyObject* pyobj)
365        {
366            return (PyTuple_Check(pyobj) || PyList_Check(pyobj));
367        }
368        
369        inline int PyListOrTuple_GET_SIZE(PyObject* pyobj)
370        {
371            if(PyList_Check(pyobj))
372            {
373                return static_cast<int>(PyList_GET_SIZE(pyobj));
374            }
375            else if(PyTuple_Check(pyobj))
376            {
377                return static_cast<int>(PyTuple_GET_SIZE(pyobj));
378            }
379            return -1;
380        }
381        
382        // Return a boworrowed reference
383        inline PyObject* PyListOrTuple_GET_ITEM(PyObject* pyobj, int index)
384        {
385            if(PyList_Check(pyobj))
386            {
387                return PyList_GET_ITEM(pyobj, index);
388            }
389            else if(PyTuple_Check(pyobj))
390            {
391                return PyTuple_GET_ITEM(pyobj, index);
392            }
393            return 0;
394        }
395    }
396    
397    ///////////////////////////////////////////////////////////////////////////
398    
399    /*
400        A note on why PyErr_Clear is needed in multiple locations...
401        
402        Even though it's not immediately apparent, almost every function
403        in the Abstract Objects Layer,
404        http://www.python.org/doc/2.5/api/abstract.html
405        can set a global excpetion under certain circumstances.
406        
407        For example, calling the equivalent of int( obj ) will set
408        an exception if the object cannot be casted (such as None),
409        or if it's a custom type that implements the number protocol
410        but throws an exception during the cast.
411        
412        During iteration, even an object that implements the sequence
413        protocol can raise an exception if the iteration fails.
414        
415        As we want to guarantee that an exception *never* remains on
416        the stack after an internal failure, the simplest way to
417        guarantee this is to always call PyErr_Clear() before
418        returing the failure condition.
419    */
420    
421    bool FillIntVectorFromPySequence(PyObject* datalist, std::vector<int> &data)
422    {
423        data.clear();
424        
425        // First, try list or tuple iteration (for speed).
426        if(PyListOrTuple_Check(datalist))
427        {
428            int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
429            data.reserve(sequenceSize);
430            
431            for(int i=0; i < sequenceSize; i++)
432            {
433                PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
434                
435                int val;
436                if (!GetIntFromPyObject(item, &val))
437                {
438                    data.clear();
439                    return false;
440                }
441                data.push_back(val);
442            }
443            
444            return true;
445        }
446        // As a fallback, try general iteration.
447        else
448        {
449            PyObject *item;
450            PyObject *iter = PyObject_GetIter(datalist);
451            if (iter == NULL)
452            {
453                PyErr_Clear();
454                return false;
455            }
456            while((item = PyIter_Next(iter)) != NULL)
457            {
458                int val;
459                if (!GetIntFromPyObject(item, &val))
460                {
461                    Py_DECREF(item);
462                    Py_DECREF(iter);
463                    
464                    data.clear();
465                    return false;
466                }
467                data.push_back(val);
468                Py_DECREF(item);
469            }
470            
471            Py_DECREF(iter);
472            if (PyErr_Occurred())
473            {
474                PyErr_Clear();
475                data.clear();
476                return false;
477            }
478            return true;
479        }
480    }
481    
482    bool FillFloatVectorFromPySequence(PyObject* datalist, std::vector<float> &data)
483    {
484        data.clear();
485        
486        if(PyListOrTuple_Check(datalist))
487        {
488            int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
489            data.reserve(sequenceSize);
490            
491            for(int i=0; i < sequenceSize; i++)
492            {
493                PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
494                
495                float val;
496                if (!GetFloatFromPyObject(item, &val))
497                {
498                    data.clear();
499                    return false;
500                }
501                data.push_back(val);
502            }
503            return true;
504        }
505        else
506        {
507            PyObject *item;
508            PyObject *iter = PyObject_GetIter(datalist);
509            if (iter == NULL)
510            {
511                PyErr_Clear();
512                return false;
513            }
514            while((item = PyIter_Next(iter)) != NULL)
515            {
516                float val;
517                if (!GetFloatFromPyObject(item, &val))
518                {
519                    Py_DECREF(item);
520                    Py_DECREF(iter);
521                    
522                    data.clear();
523                    return false;
524                }
525                data.push_back(val);
526                Py_DECREF(item);
527            }
528            Py_DECREF(iter);
529            if (PyErr_Occurred())
530            {
531                PyErr_Clear();
532                data.clear();
533                return false;
534            }
535            return true;
536        }
537    }
538    
539    bool FillDoubleVectorFromPySequence(PyObject* datalist, std::vector<double> &data)
540    {
541        data.clear();
542        
543        if(PyListOrTuple_Check(datalist))
544        {
545            int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
546            data.reserve(sequenceSize);
547            
548            for(int i=0; i < sequenceSize; i++)
549            {
550                PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
551                double val;
552                if (!GetDoubleFromPyObject(item, &val))
553                {
554                    data.clear();
555                    return false;
556                }
557                data.push_back( val );
558            }
559            return true;
560        }
561        else
562        {
563            PyObject *item;
564            PyObject *iter = PyObject_GetIter(datalist);
565            if (iter == NULL)
566            {
567                PyErr_Clear();
568                return false;
569            }
570            while((item = PyIter_Next(iter)) != NULL)
571            {
572                double val;
573                if (!GetDoubleFromPyObject(item, &val))
574                {
575                    Py_DECREF(item);
576                    Py_DECREF(iter);
577                    
578                    data.clear();
579                    return false;
580                }
581                data.push_back(val);
582                Py_DECREF(item);
583            }
584            
585            Py_DECREF(iter);
586            if (PyErr_Occurred())
587            {
588                PyErr_Clear();
589                data.clear();
590                return false;
591            }
592            return true;
593        }
594    }
595    
596    
597    bool FillStringVectorFromPySequence(PyObject* datalist, std::vector<std::string> &data)
598    {
599        data.clear();
600        
601        if(PyListOrTuple_Check(datalist))
602        {
603            int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
604            data.reserve(sequenceSize);
605            
606            for(int i=0; i < sequenceSize; i++)
607            {
608                PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
609                std::string val;
610                if (!GetStringFromPyObject(item, &val))
611                {
612                    data.clear();
613                    return false;
614                }
615                data.push_back( val );
616            }
617            return true;
618        }
619        else
620        {
621            PyObject *item;
622            PyObject *iter = PyObject_GetIter(datalist);
623            if (iter == NULL)
624            {
625                PyErr_Clear();
626                return false;
627            }
628            while((item = PyIter_Next(iter)) != NULL)
629            {
630                std::string val;
631                if (!GetStringFromPyObject(item, &val))
632                {
633                    Py_DECREF(item);
634                    Py_DECREF(iter);
635                    
636                    data.clear();
637                    return false;
638                }
639                data.push_back(val);
640                Py_DECREF(item);
641            }
642            
643            Py_DECREF(iter);
644            if (PyErr_Occurred())
645            {
646                PyErr_Clear();
647                data.clear();
648                return false;
649            }
650            return true;
651        }
652    }
653    
654    
655    
656    bool FillTransformVectorFromPySequence(PyObject* datalist, std::vector<ConstTransformRcPtr> &data)
657    {
658        data.clear();
659        
660        if(PyListOrTuple_Check(datalist))
661        {
662            int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
663            data.reserve(sequenceSize);
664            
665            for(int i=0; i < sequenceSize; i++)
666            {
667                PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
668                ConstTransformRcPtr val;
669                try
670                {
671                    val = GetConstTransform(item, true);
672                }
673                catch(...)
674                {
675                    data.clear();
676                    return false;
677                }
678                
679                data.push_back( val );
680            }
681            return true;
682        }
683        else
684        {
685            PyObject *item;
686            PyObject *iter = PyObject_GetIter(datalist);
687            if (iter == NULL)
688            {
689                PyErr_Clear();
690                return false;
691            }
692            while((item = PyIter_Next(iter)) != NULL)
693            {
694                ConstTransformRcPtr val;
695                try
696                {
697                    val = GetConstTransform(item, true);
698                }
699                catch(...)
700                {
701                    Py_DECREF(item);
702                    Py_DECREF(iter);
703                    
704                    data.clear();
705                    return false;
706                }
707                
708                data.push_back(val);
709                Py_DECREF(item);
710            }
711            
712            Py_DECREF(iter);
713            if (PyErr_Occurred())
714            {
715                PyErr_Clear();
716                data.clear();
717                return false;
718            }
719            
720            return true;
721        }
722    }
723    
724    ///////////////////////////////////////////////////////////////////////////
725    
726    
727    
728    
729    ///////////////////////////////////////////////////////////////////////////
730    
731    /* See the header for the justification for this function.
732    
733    The trick to making this technique work is that we know
734    we've been called from within a catch block, so there
735    is an exception on the stack.  We can re-throw this
736    exception, using the throw statement.  By doing this
737    inside a try...catch block, it's possible to use the
738    standard catch mechanism to categorize whatever exception
739    was actually caught by the caller.
740    */
741    
742    void Python_Handle_Exception()
743    {
744        try
745        {
746            // Re-throw whatever exception is already on the stack.
747            // This will fail horribly if no exception is already
748            // on the stack, so this function must only be called
749            // from inside an exception handler catch block!
750            throw;
751        }
752        catch (ExceptionMissingFile & e)
753        {
754            PyErr_SetString(GetExceptionMissingFilePyType(), e.what());
755        }
756        catch (Exception & e)
757        {
758            PyErr_SetString(GetExceptionPyType(), e.what());
759        }
760        catch (std::exception& e)
761        {
762            PyErr_SetString(PyExc_RuntimeError, e.what());
763        }
764        catch (...)
765        {
766            PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception caught.");
767        }
768    }
769    
770}
771OCIO_NAMESPACE_EXIT