renamed bpy.sys to bpy.utils, since it used to be a attempt to replace pythons sys...
[blender.git] / source / blender / python / intern / bpy_interface.c
index 559ed5377571b9b7ebb8568bdb55d92584752d89..b465a494a4d88013d9b7e641420e1998bc8c5186 100644 (file)
@@ -1,26 +1,54 @@
-
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney,
+ * Chris Keith, Chris Want, Ken Hughes, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 
-#ifndef WIN32
-#include <dirent.h>
-#else
-#include "BLI_winstuff.h"
+
+/* grr, python redefines */
+#ifdef _POSIX_C_SOURCE
+#undef _POSIX_C_SOURCE
 #endif
 
 #include <Python.h>
 #include "compile.h"           /* for the PyCodeObject */
 #include "eval.h"              /* for PyEval_EvalCode */
 
-#include "bpy_compat.h"
-
 #include "bpy_rna.h"
 #include "bpy_operator.h"
 #include "bpy_ui.h"
 #include "bpy_util.h"
 
+#ifndef WIN32
+#include <dirent.h>
+#else
+#include "BLI_winstuff.h"
+#endif
+
 #include "DNA_anim_types.h"
 #include "DNA_space_types.h"
 #include "DNA_text_types.h"
 #include "MEM_guardedalloc.h"
 
 #include "BLI_util.h"
+#include "BLI_storage.h"
+#include "BLI_fileops.h"
 #include "BLI_string.h"
 
 #include "BKE_context.h"
 #include "BKE_fcurve.h"
 #include "BKE_text.h"
+#include "BKE_context.h"
 
 #include "BPY_extern.h"
 
 #include "../generic/bpy_internal_import.h" // our own imports
+/* external util modules */
+
+#include "../generic/Mathutils.h"
+#include "../generic/Geometry.h"
+#include "../generic/BGL.h"
+
+
+/* for internal use, when starting and ending python scripts */
+
+/* incase a python script triggers another python call, stop bpy_context_clear from invalidating */
+static int py_call_level= 0;
+
+
+// only for tests
+#define TIME_PY_RUN
+
+#ifdef TIME_PY_RUN
+#include "PIL_time.h"
+static int             bpy_timer_count = 0;
+static double  bpy_timer; /* time since python starts */
+static double  bpy_timer_run; /* time for each python script run */
+static double  bpy_timer_run_tot; /* accumulate python runs */
+#endif
+
+void bpy_context_set(bContext *C, PyGILState_STATE *gilstate)
+{
+       py_call_level++;
 
+       if(gilstate)
+               *gilstate = PyGILState_Ensure();
+
+       if(py_call_level==1) {
+
+               BPY_update_modules(); /* can give really bad results if this isnt here */
+
+               if(C) { // XXX - should always be true.
+                       BPy_SetContext(C);
+                       bpy_import_main_set(CTX_data_main(C));
+               }
+               else {
+                       fprintf(stderr, "ERROR: Python context called with a NULL Context. this should not happen!\n");
+               }
+
+#ifdef TIME_PY_RUN
+               if(bpy_timer_count==0) {
+                       /* record time from the beginning */
+                       bpy_timer= PIL_check_seconds_timer();
+                       bpy_timer_run = bpy_timer_run_tot = 0.0;
+               }
+               bpy_timer_run= PIL_check_seconds_timer();
+
+
+               bpy_timer_count++;
+#endif
+       }
+}
+
+void bpy_context_clear(bContext *C, PyGILState_STATE *gilstate)
+{
+       py_call_level--;
+
+       if(gilstate)
+               PyGILState_Release(*gilstate);
+
+       if(py_call_level < 0) {
+               fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n");
+       }
+       else if(py_call_level==0) {
+               // XXX - Calling classes currently wont store the context :\, cant set NULL because of this. but this is very flakey still.
+               //BPy_SetContext(NULL);
+               //bpy_import_main_set(NULL);
+
+#ifdef TIME_PY_RUN
+               bpy_timer_run_tot += PIL_check_seconds_timer() - bpy_timer_run;
+               bpy_timer_count++;
+#endif
+
+       }
+}
+
+static void bpy_import_test(char *modname)
+{
+       PyObject *mod= PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
+       if(mod) {
+               Py_DECREF(mod);
+       }
+       else {
+               PyErr_Print();
+               PyErr_Clear();
+       }       
+}
 
 void BPY_free_compiled_text( struct Text *text )
 {
@@ -60,26 +181,46 @@ static void bpy_init_modules( void )
        /* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
        PyModule_AddObject( mod, "types", BPY_rna_types() );
        PyModule_AddObject( mod, "props", BPY_rna_props() );
-       PyModule_AddObject( mod, "ops", BPY_operator_module() );
-       PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
+       PyModule_AddObject( mod, "__ops__", BPY_operator_module() ); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
+       PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
        
        /* add the module so we can import it */
        PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
        Py_DECREF(mod);
-}
 
-#if (PY_VERSION_HEX < 0x02050000)
-PyObject *PyImport_ImportModuleLevel(char *name, void *a, void *b, void *c, int d)
-{
-       return PyImport_ImportModule(name);
+       /* add our own modules dir */
+       {
+               char *modpath= BLI_gethome_folder("scripts/modules", BLI_GETHOME_ALL);
+               
+               if(modpath) {
+                       PyObject *sys_path= PySys_GetObject("path"); /* borrow */
+                       PyObject *py_modpath= PyUnicode_FromString(modpath);
+                       PyList_Insert(sys_path, 0, py_modpath); /* add first */
+                       Py_DECREF(py_modpath);
+               }
+               
+               bpy_import_test("bpy_ops"); /* adds its self to bpy.ops */
+               bpy_import_test("bpy_utils"); /* adds its self to bpy.sys */
+               bpy_import_test("bpy_ext"); /* extensions to our existing types */
+       }
+       
+       /* stand alone utility modules not related to blender directly */
+       Geometry_Init();
+       Mathutils_Init();
+       BGL_Init();
 }
-#endif
 
 void BPY_update_modules( void )
 {
+#if 0 // slow, this runs all the time poll, draw etc 100's of time a sec.
        PyObject *mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
        PyModule_AddObject( mod, "data", BPY_rna_module() );
-       PyModule_AddObject( mod, "types", BPY_rna_types() );
+       PyModule_AddObject( mod, "types", BPY_rna_types() ); // atm this does not need updating
+#endif
+
+       /* refreshes the main struct */
+       BPY_update_rna_module();
+
 }
 
 /*****************************************************************************
@@ -94,9 +235,6 @@ static PyObject *CreateGlobalDictionary( bContext *C )
        PyDict_SetItemString( dict, "__name__", item );
        Py_DECREF(item);
        
-       // XXX - evil, need to access context
-       BPy_SetContext(C);
-       
        // XXX - put somewhere more logical
        {
                PyMethodDef *ml;
@@ -105,6 +243,9 @@ static PyObject *CreateGlobalDictionary( bContext *C )
                        {"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
                        {"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
                        {"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
+                       {"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, ""},
+                       {"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, ""},
+                       {"CollectionProperty", (PyCFunction)BPy_CollectionProperty, METH_VARARGS|METH_KEYWORDS, ""},
                        {NULL, NULL, 0, NULL}
                };
                
@@ -121,13 +262,51 @@ static PyObject *CreateGlobalDictionary( bContext *C )
        return dict;
 }
 
+/* must be called before Py_Initialize */
+void BPY_start_python_path(void)
+{
+       char *py_path_bundle= BLI_gethome_folder("python", BLI_GETHOME_ALL);
+
+       if(py_path_bundle==NULL)
+               return;
+
+       /* set the environment path */
+       printf("found bundled python: %s\n", py_path_bundle);
+
+#if 0
+       BLI_setenv("PYTHONHOME", py_path_bundle);
+       BLI_setenv("PYTHONPATH", py_path_bundle);
+#endif
+
+       {
+               static wchar_t py_path_bundle_wchar[FILE_MAXDIR];
+
+               mbstowcs(py_path_bundle_wchar, py_path_bundle, FILE_MAXDIR);
+               Py_SetPythonHome(py_path_bundle_wchar);
+       }
+}
+
+
 void BPY_start_python( int argc, char **argv )
 {
        PyThreadState *py_tstate = NULL;
        
+       BPY_start_python_path(); /* allow to use our own included python */
+
        Py_Initialize(  );
        
-       //PySys_SetArgv( argc_copy, argv_copy );
+       // PySys_SetArgv( argc, argv); // broken in py3, not a huge deal
+       /* sigh, why do python guys not have a char** version anymore? :( */
+       {
+               int i;
+               PyObject *py_argv= PyList_New(argc);
+
+               for (i=0; i<argc; i++)
+                       PyList_SET_ITEM(py_argv, i, PyUnicode_FromString(argv[i]));
+
+               PySys_SetObject("argv", py_argv);
+               Py_DECREF(py_argv);
+       }
        
        /* Initialize thread support (also acquires lock) */
        PyEval_InitThreads();
@@ -143,40 +322,64 @@ void BPY_start_python( int argc, char **argv )
                PyObject *d = PyEval_GetBuiltins(  );
                PyDict_SetItemString(d, "reload",               item=PyCFunction_New(bpy_reload_meth, NULL));   Py_DECREF(item);
                PyDict_SetItemString(d, "__import__",   item=PyCFunction_New(bpy_import_meth, NULL));   Py_DECREF(item);
+               
+               /* a bit nasty but this prevents help() and input() from locking blender
+                * Ideally we could have some way for the console to replace sys.stdin but
+                * python would lock blender while waiting for a return value, not easy :| */
+               PySys_SetObject("stdin", Py_None);
        }
        
+       pyrna_alloc_types();
+
        py_tstate = PyGILState_GetThisThreadState();
        PyEval_ReleaseThread(py_tstate);
 }
 
 void BPY_end_python( void )
 {
+       // fprintf(stderr, "Ending Python!\n");
+
        PyGILState_Ensure(); /* finalizing, no need to grab the state */
        
        // free other python data.
-       //BPY_rna_free_types();
+       pyrna_free_types();
+
+       /* clear all python data from structs */
        
        Py_Finalize(  );
        
-       return;
+#ifdef TIME_PY_RUN
+       // measure time since py started
+       bpy_timer = PIL_check_seconds_timer() - bpy_timer;
+
+       printf("*bpy stats* - ");
+       printf("tot exec: %d,  ", bpy_timer_count);
+       printf("tot run: %.4fsec,  ", bpy_timer_run_tot);
+       if(bpy_timer_count>0)
+               printf("average run: %.6fsec,  ", (bpy_timer_run_tot/bpy_timer_count));
+
+       if(bpy_timer>0.0)
+               printf("tot usage %.4f%%", (bpy_timer_run_tot/bpy_timer)*100.0);
+
+       printf("\n");
+
+       // fprintf(stderr, "Ending Python Done!\n");
+
+#endif
+
 }
 
 /* Can run a file or text block */
 int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struct ReportList *reports)
 {
-       PyObject *py_dict, *py_result;
+       PyObject *py_dict, *py_result= NULL;
        PyGILState_STATE gilstate;
        
        if (fn==NULL && text==NULL) {
                return 0;
        }
        
-       //BPY_start_python();
-       
-       gilstate = PyGILState_Ensure();
-
-       BPY_update_modules(); /* can give really bad results if this isnt here */
-       bpy_import_main_set(CTX_data_main(C));
+       bpy_context_set(C, &gilstate);
        
        py_dict = CreateGlobalDictionary(C);
 
@@ -191,19 +394,31 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
                        MEM_freeN( buf );
 
                        if( PyErr_Occurred(  ) ) {
-                               BPy_errors_to_report(reports);
                                BPY_free_compiled_text( text );
-                               PyGILState_Release(gilstate);
-                               return 0;
                        }
                }
-               py_result =  PyEval_EvalCode( text->compiled, py_dict, py_dict );
+               if(text->compiled)
+                       py_result =  PyEval_EvalCode( text->compiled, py_dict, py_dict );
                
        } else {
-               char pystring[512];
-               /* TODO - look into a better way to run a file */
-               sprintf(pystring, "exec(open(r'%s').read())", fn);      
-               py_result = PyRun_String( pystring, Py_file_input, py_dict, py_dict );                  
+#if 0
+               char *pystring;
+               pystring= malloc(strlen(fn) + 32);
+               pystring[0]= '\0';
+               sprintf(pystring, "exec(open(r'%s').read())", fn);
+               py_result = PyRun_String( pystring, Py_file_input, py_dict, py_dict );
+               free(pystring);
+#else
+               FILE *fp= fopen(fn, "r");               
+               if(fp) {
+                       py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
+                       fclose(fp);
+               }
+               else {
+                       PyErr_Format(PyExc_SystemError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno));
+                       py_result= NULL;
+               }
+#endif
        }
        
        if (!py_result) {
@@ -213,10 +428,9 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
        }
        
        Py_DECREF(py_dict);
-       PyGILState_Release(gilstate);
-       bpy_import_main_set(NULL);
        
-       //BPY_end_python();
+       bpy_context_clear(C, &gilstate);
+
        return py_result ? 1:0;
 }
 
@@ -272,9 +486,9 @@ static int bpy_run_script_init(bContext *C, SpaceScript * sc)
        return 1;
 }
 
-int BPY_run_script_space_draw(struct bContext *C, SpaceScript * sc)
+int BPY_run_script_space_draw(const struct bContext *C, SpaceScript * sc)
 {
-       if (bpy_run_script_init(C, sc)) {
+       if (bpy_run_script_init( (bContext *)C, sc)) {
                PyGILState_STATE gilstate = PyGILState_Ensure();
                PyObject *result = PyObject_CallObject( sc->script->py_draw, NULL );
                
@@ -362,6 +576,26 @@ int BPY_run_python_script_space(const char *modulename, const char *func)
 #include "PIL_time.h"
 #endif
 
+/* for use by BPY_run_ui_scripts only */
+static int bpy_import_module(char *modname, int reload)
+{
+       PyObject *mod= PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
+       if (mod) {
+               if (reload) {
+                       PyObject *mod_orig= mod;
+                       mod= PyImport_ReloadModule(mod);
+                       Py_DECREF(mod_orig);
+               }
+       }
+
+       if(mod) {
+               Py_DECREF(mod); /* could be NULL from reloading */
+               return 0;
+       } else {
+               return -1;
+       }
+}
+
 /* XXX this is temporary, need a proper script registration system for 2.5 */
 void BPY_run_ui_scripts(bContext *C, int reload)
 {
@@ -373,81 +607,84 @@ void BPY_run_ui_scripts(bContext *C, int reload)
        char *file_extension;
        char *dirname;
        char path[FILE_MAX];
-       char *dirs[] = {"io", "ui", NULL};
-       int a, filelen; /* filename length */
+       char *dirs[] = {"scripts/ui", "scripts/io", NULL};
+       int path_flags[] = {BLI_GETHOME_LOCAL|BLI_GETHOME_SYSTEM, BLI_GETHOME_USER}; /* SYSTEM / NON-SYSTEM */
+       int a, err, flag_iter;
        
        PyGILState_STATE gilstate;
-       PyObject *mod;
-       PyObject *sys_path_orig;
-       PyObject *sys_path_new;
+       PyObject *sys_path;
 
-       gilstate = PyGILState_Ensure();
-       
-       // XXX - evil, need to access context
-       BPy_SetContext(C);
-       bpy_import_main_set(CTX_data_main(C));
+       bpy_context_set(C, &gilstate);
 
-       for(a=0; dirs[a]; a++) {
-               dirname= BLI_gethome_folder(dirs[a]);
+       sys_path= PySys_GetObject("path"); /* borrow */
+       PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */
 
-               if(!dirname)
-                       continue;
+       /* Scan system scripts first, then local/user */
+       for(flag_iter=0; flag_iter < sizeof(path_flags)/sizeof(int); flag_iter++) {
+               
+               for(a=0; dirs[a]; a++) {
+                       dirname= BLI_gethome_folder(dirs[a], path_flags[flag_iter]);
 
-               dir = opendir(dirname);
+                       if(!dirname)
+                               continue;
 
-               if(!dir)
-                       continue;
+                       dir = opendir(dirname);
 
-               /* backup sys.path */
-               sys_path_orig= PySys_GetObject("path");
-               Py_INCREF(sys_path_orig); /* dont free it */
-               
-               sys_path_new= PyList_New(1);
-               PyList_SET_ITEM(sys_path_new, 0, PyUnicode_FromString(dirname));
-               PySys_SetObject("path", sys_path_new);
-               Py_DECREF(sys_path_new);
-                       
-               while((de = readdir(dir)) != NULL) {
-                       /* We could stat the file but easier just to let python
-                        * import it and complain if theres a problem */
+                       if(!dir)
+                               continue;
                        
-                       file_extension = strstr(de->d_name, ".py");
-                       
-                       if(file_extension && *(file_extension + 3) == '\0') {
-                               filelen = strlen(de->d_name);
-                               BLI_strncpy(path, de->d_name, filelen-2); /* cut off the .py on copy */
+                       /* set the first dir in the sys.path for fast importing of modules */
+                       PyList_SetItem(sys_path, 0, PyUnicode_FromString(dirname)); /* steals the ref */
                                
-                               mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
-                               if (mod) {
-                                       if (reload) {
-                                               PyObject *mod_orig= mod;
-                                               mod= PyImport_ReloadModule(mod);
-                                               Py_DECREF(mod_orig);
+                       while((de = readdir(dir)) != NULL) {
+                               /* We could stat the file but easier just to let python
+                                * import it and complain if theres a problem */
+                               err = 0;
+
+                               if (de->d_name[0] == '.') {
+                                       /* do nothing, probably .svn */
+                               }
+                               else if ((file_extension = strstr(de->d_name, ".py"))) {
+                                       /* normal py files? */
+                                       if(file_extension && file_extension[3] == '\0') {
+                                               de->d_name[(file_extension - de->d_name)] = '\0';
+                                               err= bpy_import_module(de->d_name, reload);
                                        }
                                }
-                               
-                               if(mod) {
-                                       Py_DECREF(mod); /* could be NULL from reloading */
-                               } else {
-                                       BPy_errors_to_report(NULL); // TODO - reports
-                                       fprintf(stderr, "unable to import \"%s\"  %s/%s\n", path, dirname, de->d_name);
+#ifndef __linux__
+                               else if( BLI_join_dirfile(path, dirname, de->d_name), S_ISDIR(BLI_exist(path))) {
+#else
+                               else if(de->d_type==DT_DIR) {
+                                       BLI_join_dirfile(path, dirname, de->d_name);
+#endif
+                                       /* support packages */
+                                       BLI_join_dirfile(path, path, "__init__.py");
+
+                                       if(BLI_exists(path)) {
+                                               err= bpy_import_module(de->d_name, reload);
+                                       }
                                }
 
+                               if(err==-1) {
+                                       BPy_errors_to_report(NULL);
+                                       fprintf(stderr, "unable to import %s/%s\n", dirname, de->d_name);
+                               }
                        }
-               }
-
-               closedir(dir);
 
-               PySys_SetObject("path", sys_path_orig);
-               Py_DECREF(sys_path_orig);
+                       closedir(dir);
+               }
        }
        
-       bpy_import_main_set(NULL);
+       PyList_SetSlice(sys_path, 0, 1, NULL); /* remove the first item */
+
+       bpy_context_clear(C, &gilstate);
        
-       PyGILState_Release(gilstate);
 #ifdef TIME_REGISTRATION
        printf("script time %f\n", (PIL_check_seconds_timer()-time));
 #endif
+
+       /* reset the timer so as not to take loading into the stats */
+       bpy_timer_count = 0;
 }
 
 /* ****************************************** */
@@ -645,3 +882,132 @@ float BPY_pydriver_eval (ChannelDriver *driver)
 
        return result;
 }
+
+int BPY_button_eval(bContext *C, char *expr, double *value)
+{
+       PyGILState_STATE gilstate;
+       PyObject *dict, *mod, *retval;
+       int error_ret = 0;
+       
+       if (!value || !expr || expr[0]=='\0') return -1;
+       
+       bpy_context_set(C, &gilstate);
+       
+       dict= CreateGlobalDictionary(C);
+       
+       /* import some modules: builtins,math*/
+       PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
+
+       mod = PyImport_ImportModule("math");
+       if (mod) {
+               PyDict_Merge(dict, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
+               
+               /* Only keep for backwards compat! - just import all math into root, they are standard */
+               PyDict_SetItemString(dict, "math", mod);
+               PyDict_SetItemString(dict, "m", mod);
+               Py_DECREF(mod);
+       } 
+       
+       retval = PyRun_String(expr, Py_eval_input, dict, dict);
+       
+       if (retval == NULL) {
+               error_ret= -1;
+       }
+       else {
+               double val;
+
+               if(PyTuple_Check(retval)) {
+                       /* Users my have typed in 10km, 2m
+                        * add up all values */
+                       int i;
+                       val= 0.0;
+
+                       for(i=0; i<PyTuple_GET_SIZE(retval); i++) {
+                               val+= PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i));
+                       }
+               }
+               else {
+                       val = PyFloat_AsDouble(retval);
+               }
+               Py_DECREF(retval);
+               
+               if(val==-1 && PyErr_Occurred()) {
+                       error_ret= -1;
+               }
+               else {
+                       *value= val;
+               }
+       }
+       
+       if(error_ret) {
+               BPy_errors_to_report(CTX_wm_reports(C));
+       }
+       
+       Py_DECREF(dict);
+       bpy_context_clear(C, &gilstate);
+       
+       return error_ret;
+}
+
+
+
+int bpy_context_get(bContext *C, const char *member, bContextDataResult *result)
+{
+       PyObject *pyctx= (PyObject *)CTX_py_dict_get(C);
+       PyObject *item= PyDict_GetItemString(pyctx, member);
+       PointerRNA *ptr= NULL;
+       int done= 0;
+
+       if(item==NULL) {
+               /* pass */
+       }
+       else if(item==Py_None) {
+               /* pass */
+       }
+       else if(BPy_StructRNA_Check(item)) {
+               ptr= &(((BPy_StructRNA *)item)->ptr);
+
+               //result->ptr= ((BPy_StructRNA *)item)->ptr;
+               CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
+               done= 1;
+       }
+       else if (PySequence_Check(item)) {
+               PyObject *seq_fast= PySequence_Fast(item, "bpy_context_get sequence conversion");
+               if (seq_fast==NULL) {
+                       PyErr_Print();
+                       PyErr_Clear();
+               }
+               else {
+                       int len= PySequence_Fast_GET_SIZE(seq_fast);
+                       int i;
+                       for(i = 0; i < len; i++) {
+                               PyObject *list_item= PySequence_Fast_GET_ITEM(seq_fast, i);
+
+                               if(BPy_StructRNA_Check(list_item)) {
+                                       /*
+                                       CollectionPointerLink *link= MEM_callocN(sizeof(CollectionPointerLink), "bpy_context_get");
+                                       link->ptr= ((BPy_StructRNA *)item)->ptr;
+                                       BLI_addtail(&result->list, link);
+                                       */
+                                       ptr= &(((BPy_StructRNA *)list_item)->ptr);
+                                       CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data);
+                               }
+                               else {
+                                       printf("List item not a valid type\n");
+                               }
+
+                       }
+                       Py_DECREF(seq_fast);
+
+                       done= 1;
+               }
+       }
+
+       if(done==0) {
+               if (item)       printf("Context '%s' not found\n", member);
+               else            printf("Context '%s' not a valid type\n", member);
+       }
+
+       return done;
+}
+