From cf27a896faf6e5fee7eeea9e70fbee1a9447572f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 Feb 2008 13:42:15 +0000 Subject: Python Bugfix, Setting the user preference for python scripts didnt add the bpymodules subdirectory to sys.path (python module search path). Also problems with entering and exiting- the old path was used until next restart. --- source/blender/python/BPY_extern.h | 1 + source/blender/python/BPY_interface.c | 99 ++++++++++++++++++++++++----------- source/blender/src/header_script.c | 1 + source/blender/src/headerbuttons.c | 1 + source/blender/src/space.c | 6 +-- 5 files changed, 74 insertions(+), 34 deletions(-) diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 28c4c2f55ff..8b4760fe25d 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -85,6 +85,7 @@ extern "C" { void BPY_post_start_python( void ); void init_syspath( int first_time ); void syspath_append( char *dir ); + void BPY_rebuild_syspath( void ); int BPY_Err_getLinenumber( void ); const char *BPY_Err_getFilename( void ); diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index acede12244f..02b65c3077d 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -95,6 +95,7 @@ /* for pydrivers (ipo drivers defined by one-line Python expressions) */ PyObject *bpy_pydriver_Dict = NULL; +PyObject *bpy_orig_syspath_List = NULL; /* * set up a weakref list for Armatures @@ -255,6 +256,11 @@ void BPY_end_python( void ) Py_DECREF( bpy_pydriver_Dict ); bpy_pydriver_Dict = NULL; } + + if( bpy_orig_syspath_List ) { + Py_DECREF( bpy_orig_syspath_List ); + bpy_orig_syspath_List = NULL; + } /* Freeing all scripts here prevents problems with the order in which * Python is finalized and G.main is freed in exit_usiblender() */ @@ -293,13 +299,14 @@ void syspath_append( char *dirname ) /* cant get the sys module */ ok = 0; } - - if (ok && PyList_Append( path, dir ) != 0) - ok = 0; /* append failed */ - - if( (ok==0) || PyErr_Occurred( ) ) - Py_FatalError( "could import or build sys.path, can't continue" ); - + + if (PySequence_Contains(path, dir)==0) { /* Only add if we need to */ + if (ok && PyList_Append( path, dir ) != 0) + ok = 0; /* append failed */ + + if( (ok==0) || PyErr_Occurred( ) ) + Py_FatalError( "could import or build sys.path, can't continue" ); + } Py_XDECREF( mod_sys ); } @@ -311,7 +318,8 @@ void init_syspath( int first_time ) char execdir[FILE_MAXDIR]; /*defines from DNA_space_types.h */ int n; - + + path = Py_BuildValue( "s", bprogname ); mod = PyImport_ImportModule( "Blender.sys" ); @@ -333,9 +341,10 @@ void init_syspath( int first_time ) execdir[n] = '\0'; syspath_append( execdir ); /* append to module search path */ - } else + } else { printf( "Warning: could not determine argv[0] path\n" ); - + } + /* attempt to import 'site' module as a check for valid python install found. @@ -366,28 +375,48 @@ void init_syspath( int first_time ) if( mod ) { d = PyModule_GetDict( mod ); /* borrowed ref */ - EXPP_dict_set_item_str( d, "executable", - Py_BuildValue( "s", bprogname ) ); + EXPP_dict_set_item_str( d, "executable", Py_BuildValue( "s", bprogname ) ); + + if (first_time) { + /* backup the original sys.path to rebuild later */ + PyObject *syspath = PyDict_GetItemString( d, "path" ); /* borrowed ref */ + if (bpy_orig_syspath_List) { /* This should never happen but just incase, be nice */ + Py_DECREF(bpy_orig_syspath_List); + } + bpy_orig_syspath_List = PyList_GetSlice(syspath, 0, PyList_Size(syspath)); + } + Py_DECREF( mod ); } else{ printf("import of sys module failed\n"); } } -/**************************************************************************** -* Description: This function finishes Python initialization in Blender. -Because U.pythondir (user defined dir for scripts) isn't -initialized when BPY_start_Python needs to be executed, we -postpone adding U.pythondir to sys.path and also BPyMenus -(mechanism to register scripts in Blender menus) for when -that dir info is available. -****************************************************************************/ -void BPY_post_start_python( void ) +void BPY_rebuild_syspath( void ) { + PyObject *mod, *dict, *syspath; char dirpath[FILE_MAX]; char *sdir = NULL; - + + mod = PyImport_ImportModule( "sys" ); + if (!mod) { + printf("error: could not import python sys module. some modules may not import."); + return; + } + + if (!bpy_orig_syspath_List) { /* should never happen */ + printf("error refershing python path"); + Py_DECREF(mod); + return; + } + + dict = PyModule_GetDict( mod ); /* borrowed ref */ + + /* Reset sys.path */ + syspath = PyDict_GetItemString( dict, "path" ); /* borrowed ref */ + PyList_SetSlice(syspath, 0, PyList_Size(syspath), bpy_orig_syspath_List); + if(U.pythondir[0] != '\0' ) { char modpath[FILE_MAX]; int upyslen = strlen(U.pythondir); @@ -396,10 +425,7 @@ void BPY_post_start_python( void ) * (for eventual implementations of c library's stat function that might * not like it) */ if (upyslen > 2) { /* avoids doing anything if dir == '//' */ - char ending = U.pythondir[upyslen - 1]; - - if (ending == '/' || ending == '\\') - U.pythondir[upyslen - 1] = '\0'; + BLI_add_slash(U.pythondir); } BLI_strncpy(dirpath, U.pythondir, FILE_MAX); @@ -409,19 +435,30 @@ void BPY_post_start_python( void ) BLI_make_file_string("/", modpath, dirpath, "bpymodules"); if (BLI_exists(modpath)) syspath_append(modpath); } - + sdir = bpy_gethome(1); if (sdir) { - syspath_append(sdir); - BLI_make_file_string("/", dirpath, sdir, "bpymodules"); if (BLI_exists(dirpath)) syspath_append(dirpath); } + + Py_DECREF(mod); +} - BPyMenu_Init( 0 ); /* get dynamic menus (registered scripts) data */ +/**************************************************************************** +* Description: This function finishes Python initialization in Blender. - return; +Because U.pythondir (user defined dir for scripts) isn't +initialized when BPY_start_Python needs to be executed, we +postpone adding U.pythondir to sys.path and also BPyMenus +(mechanism to register scripts in Blender menus) for when +that dir info is available. +****************************************************************************/ +void BPY_post_start_python( void ) +{ + BPY_rebuild_syspath(); + BPyMenu_Init( 0 ); /* get dynamic menus (registered scripts) data */ } /**************************************************************************** diff --git a/source/blender/src/header_script.c b/source/blender/src/header_script.c index 98f18c4e2ac..de76a30ecdd 100644 --- a/source/blender/src/header_script.c +++ b/source/blender/src/header_script.c @@ -117,6 +117,7 @@ static void do_script_scriptsmenu(void *arg, int event) switch(event) { case 0: /* update menus */ BPyMenu_RemoveAllEntries(); + BPY_rebuild_syspath(); if (BPyMenu_Init(1) == -1) error("Invalid scripts dir: check console"); break; } diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index d6e0b054a8b..e3c594f4ea3 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -1496,6 +1496,7 @@ void do_global_buttons(unsigned short event) case B_PYMENUEVAL: /* is button from space.c *info* */ waitcursor( 1 ); /* can take some time */ BPyMenu_RemoveAllEntries(); /* free old data */ + BPY_rebuild_syspath(); if (BPyMenu_Init(1) == -1) { /* re-eval scripts registration in menus */ waitcursor( 0 ); error("Invalid scripts dir: check console"); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index a586d1e0e36..382b72967bc 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -4214,12 +4214,12 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefBut(block, TEX, 0, "Python: ", + uiDefBut(block, TEX, B_PYMENUEVAL, "Python Scripts: ", (xpos+edgsp+lpref+midsp),y1,(lpref-2*smfileselbut),buth, - U.pythondir, 1.0, 63.0, 0, 0, "The default directory to search for Python scripts"); + U.pythondir, 1.0, 63.0, 0, 0, "The default directory to search for Python scripts (resets python module search path: sys.path)"); uiDefIconBut(block, BUT, B_PYMENUEVAL, ICON_SCRIPT, (xpos+edgsp+(2*lpref)+midsp-2*smfileselbut),y1,smfileselbut,buth, - 0, 0, 0, 0, 0, "Re-evaluate scripts registration in menus"); + 0, 0, 0, 0, 0, "Re-evaluate scripts registration in menus (resets python module search path: sys.path)"); uiDefIconBut(block, BUT, B_PYTHONDIRFILESEL, ICON_FILESEL, (xpos+edgsp+(2*lpref)+midsp-smfileselbut),y1,smfileselbut,buth, 0, 0, 0, 0, 0, "Select the default Python script location"); -- cgit v1.2.3