diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 0d9a7809a00..d9229c2e761 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -27,7 +27,7 @@ import bpy as _bpy import os as _os import sys as _sys -from _bpy import blend_paths +from _bpy import blend_paths, user_resource from _bpy import script_paths as _bpy_script_paths diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py index d15dc8934ca..f601b255510 100644 --- a/release/scripts/ui/space_userpref.py +++ b/release/scripts/ui/space_userpref.py @@ -1096,7 +1096,24 @@ class WM_OT_addon_install(bpy.types.Operator): import zipfile pyfile = self.filepath - path_addons = bpy.utils.script_paths("addons")[-1] + # dont use bpy.utils.script_paths("addons") because we may not be able to write to it. + path_addons = bpy.utils.user_resource('SCRIPTS', 'addons') + + # should never happen. + if not path_addons: + self.report({'WARNING'}, "Failed to get addons path\n") + return {'CANCELLED'} + + # create path if not existing. + if not os.path.exists(path_addons): + try: + os.makedirs(path_addons) + except: + self.report({'WARNING'}, "Failed to create %r\n" % path_addons) + + traceback.print_exc() + return {'CANCELLED'} + contents = set(os.listdir(path_addons)) #check to see if the file is in compressed format (.zip) @@ -1115,7 +1132,7 @@ class WM_OT_addon_install(bpy.types.Operator): path_dest = os.path.join(path_addons, os.path.basename(pyfile)) if os.path.exists(path_dest): - self.report({'WARNING'}, "File already installed to '%s'\n" % path_dest) + self.report({'WARNING'}, "File already installed to %r\n" % path_dest) return {'CANCELLED'} #if not compressed file just copy into the addon path @@ -1148,11 +1165,6 @@ class WM_OT_addon_install(bpy.types.Operator): return {'FINISHED'} def invoke(self, context, event): - paths = bpy.utils.script_paths("addons") - if not paths: - self.report({'ERROR'}, "No 'addons' path could be found in " + str(bpy.utils.script_paths())) - return {'CANCELLED'} - wm = context.window_manager wm.add_fileselect(self) return {'RUNNING_MODAL'} diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index f01e1a25d8a..b9a4468fe57 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -44,6 +44,7 @@ char *BLI_getDefaultDocumentFolder(void); char *BLI_get_folder(int folder_id, char *subfolder); char *BLI_get_folder_create(int folder_id, char *subfolder); +char *BLI_get_user_folder_notest(int folder_id, char *subfolder); /* folder_id */ diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index d388586bf66..fd69b7233de 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -477,7 +477,7 @@ int BLI_parent_dir(char *path) static char *parent_dir="../"; #endif char tmp[FILE_MAXDIR+FILE_MAXFILE+4]; - BLI_strncpy(tmp, path, sizeof(tmp)); + BLI_strncpy(tmp, path, sizeof(tmp)-4); BLI_add_slash(tmp); strcat(tmp, parent_dir); BLI_cleanup_dir(NULL, tmp); @@ -839,8 +839,6 @@ static int get_path_local(char *targetpath, char *folder_name, char *subfolder_n char bprogdir[FILE_MAX]; char relfolder[FILE_MAX]; char cwd[FILE_MAX]; - char *s; - int i; #ifdef PATH_DEBUG2 printf("get_path_local...\n"); @@ -853,9 +851,7 @@ static int get_path_local(char *targetpath, char *folder_name, char *subfolder_n } /* use argv[0] (bprogname) to get the path to the executable */ - s = BLI_last_slash(bprogname); - i = s - bprogname + 1; - BLI_strncpy(bprogdir, bprogname, i); + BLI_split_dirfile(bprogname, bprogdir, NULL); /* try EXECUTABLE_DIR/folder_name */ if(test_path(targetpath, bprogdir, "", relfolder)) @@ -1024,7 +1020,7 @@ char *BLI_get_folder(int folder_id, char *subfolder) return path; } -static char *BLI_get_user_folder_notest(int folder_id, char *subfolder) +char *BLI_get_user_folder_notest(int folder_id, char *subfolder) { static char path[FILE_MAX] = ""; @@ -1038,6 +1034,9 @@ static char *BLI_get_user_folder_notest(int folder_id, char *subfolder) case BLENDER_USER_AUTOSAVE: get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE"); break; + case BLENDER_USER_SCRIPTS: + get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS"); + break; } if ('\0' == path[0]) { return NULL; @@ -1050,7 +1049,7 @@ char *BLI_get_folder_create(int folder_id, char *subfolder) char *path; /* only for user folders */ - if (!ELEM3(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_AUTOSAVE)) + if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE)) return NULL; path = BLI_get_folder(folder_id, subfolder); @@ -1205,8 +1204,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, /* Get the file name, chop everything past the last slash (ie. the filename) */ strcpy(string, relabase); - lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\'); - + lslash= BLI_last_slash(string); if(lslash) *(lslash+1)= 0; dir+=2; /* Skip over the relative reference */ diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index 11f8ff49ffe..394c388394a 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -281,8 +281,8 @@ static PyObject *blender_reload( PyObject * self, PyObject * module ) return newmodule; } -PyMethodDef bpy_import_meth[] = { {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"} }; -PyMethodDef bpy_reload_meth[] = { {"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"} }; +PyMethodDef bpy_import_meth = {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"}; +PyMethodDef bpy_reload_meth = {"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"}; /* Clear user modules. diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h index 09e1fa629d3..f191ab22651 100644 --- a/source/blender/python/generic/bpy_internal_import.h +++ b/source/blender/python/generic/bpy_internal_import.h @@ -53,8 +53,8 @@ PyObject* bpy_text_reimport( PyObject *module, int *found ); void bpy_text_filename_get(char *fn, struct Text *text); -extern PyMethodDef bpy_import_meth[]; -extern PyMethodDef bpy_reload_meth[]; +extern PyMethodDef bpy_import_meth; +extern PyMethodDef bpy_reload_meth; /* The game engine has its own Main struct, if this is set search this rather then G.main */ struct Main *bpy_import_main_get(void); diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 12a5221f76e..69b5faceca0 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -112,8 +112,52 @@ static PyObject *bpy_blend_paths(PyObject * self, PyObject *args, PyObject *kw) return list; } -static PyMethodDef meth_bpy_script_paths[] = {{ "script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc}}; -static PyMethodDef meth_bpy_blend_paths[] = {{ "blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS|METH_KEYWORDS, bpy_blend_paths_doc}}; + +static char bpy_user_resource_doc[] = +".. function:: user_resource(type, subdir)\n" +"\n" +" Returns a list of paths to external files referenced by the loaded .blend file.\n" +"\n" +" :arg type: Resource type in ['DATAFILES', 'CONFIG', 'SCRIPTS', 'AUTOSAVE'].\n" +" :type type: string\n" +" :arg subdir: Optional subdirectory.\n" +" :type subdir: string\n" +" :return: a path.\n" +" :rtype: string\n"; +static PyObject *bpy_user_resource(PyObject * self, PyObject *args, PyObject *kw) +{ + char *type; + char *subdir= NULL; + int folder_id; + static char *kwlist[] = {"type", "subdir", NULL}; + + char *path; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s:user_resource", kwlist, &type, &subdir)) + return NULL; + + /* stupid string compare */ + if (!strcmp(type, "DATAFILES")) folder_id= BLENDER_USER_DATAFILES; + else if(!strcmp(type, "CONFIG")) folder_id= BLENDER_USER_CONFIG; + else if(!strcmp(type, "SCRIPTS")) folder_id= BLENDER_USER_SCRIPTS; + else if(!strcmp(type, "AUTOSAVE")) folder_id= BLENDER_USER_AUTOSAVE; + else { + PyErr_SetString(PyExc_ValueError, "invalid resource argument"); + return NULL; + } + + /* same logic as BLI_get_folder_create(), but best leave it up to the script author to create */ + path= BLI_get_folder(folder_id, subdir); + + if (!path) + path = BLI_get_user_folder_notest(folder_id, subdir); + + return PyUnicode_FromString(path ? path : ""); +} + +static PyMethodDef meth_bpy_script_paths = {"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc}; +static PyMethodDef meth_bpy_blend_paths = {"blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS|METH_KEYWORDS, bpy_blend_paths_doc}; +static PyMethodDef meth_bpy_user_resource = {"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS|METH_KEYWORDS, bpy_user_resource_doc}; static void bpy_import_test(char *modname) { @@ -186,8 +230,9 @@ void BPy_init_modules( void ) PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module); /* utility func's that have nowhere else to go */ - PyModule_AddObject(mod, meth_bpy_script_paths->ml_name, (PyObject *)PyCFunction_New(meth_bpy_script_paths, NULL)); - PyModule_AddObject(mod, meth_bpy_blend_paths->ml_name, (PyObject *)PyCFunction_New(meth_bpy_blend_paths, NULL)); + PyModule_AddObject(mod, meth_bpy_script_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL)); + PyModule_AddObject(mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL)); + PyModule_AddObject(mod, meth_bpy_user_resource.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL)); /* add our own modules dir, this is a python package */ bpy_import_test("bpy"); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 6aaac3cd0e8..b905fb3729e 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -248,8 +248,8 @@ void BPY_start_python( int argc, char **argv ) //PyObject *m = PyImport_AddModule("__builtin__"); //PyObject *d = PyModule_GetDict(m); 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); + 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); } pyrna_alloc_types(); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 33564834bcb..67decd6292e 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -681,15 +681,20 @@ int WM_write_homefile(bContext *C, wmOperator *op) wm_window_close(C, wm, win); BLI_make_file_string("/", tstr, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); - printf("trying to save homefile at %s \n", tstr); + printf("trying to save homefile at %s ", tstr); /* force save as regular blend file */ fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN); - BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports, NULL); + if(BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports, NULL) == 0) { + printf("fail\n"); + return OPERATOR_CANCELLED; + } + printf("ok\n"); + G.save_over= 0; - + return OPERATOR_FINISHED; } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 3a754f1f466..a6b2453f0c5 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1760,8 +1760,8 @@ static void setSandbox(TPythonSecurityLevel level) */ default: /* Allow importing internal text, from bpy_internal_import.py */ - 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); + 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); break; } }