fix [#30623] user-defined render presets bug
authorCampbell Barton <ideasman42@gmail.com>
Wed, 21 Mar 2012 22:29:49 +0000 (22:29 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 21 Mar 2012 22:29:49 +0000 (22:29 +0000)
this report exposed multiple bugs in blender when using a non utf8 compatible home directory.

- bpy.utils.script_paths() would crash when homedir wasn't utf8 (reported bug)
- PyC_DefaultNameSpace() - would raise an error when running when __file__ was non utf8.
- preset filepath property was not set to accept non utf8.
- bpy.paths.display_name would raise an error on non utf8 paths, (used for preset draw)

release/scripts/modules/bpy/path.py
release/scripts/startup/bl_operators/presets.py
source/blender/bmesh/bmesh.h
source/blender/editors/space_script/script_edit.c
source/blender/python/generic/py_capi_utils.c
source/blender/python/intern/bpy.c

index 9a90797bf2894f393ad550ab17dd68591dde8048..7b54af944ada9bc05027a74c84f70dbb1c1bae56 100644 (file)
@@ -118,6 +118,14 @@ def clean_name(name, replace="_"):
     return name
 
 
+def _clean_utf8(name):
+    name = _os.path.splitext(basename(name))[0]
+    if type(name) == bytes:
+        return name.decode("utf8", "replace")
+    else:
+        return name.encode("utf8", "replace").decode("utf8")
+
+
 def display_name(name):
     """
     Creates a display string from name to be used menus and the user interface.
@@ -126,17 +134,18 @@ def display_name(name):
     filenames and module names.
     """
 
-    name_base = _os.path.splitext(name)[0]
+    name = _os.path.splitext(name)[0]
 
     # string replacements
-    name_base = name_base.replace("_colon_", ":")
+    name = name.replace("_colon_", ":")
 
-    name_base = name_base.replace("_", " ")
+    name = name.replace("_", " ")
 
-    if name_base.islower():
-        return name_base.lower().title()
-    else:
-        return name_base
+    if name.islower():
+        name = name.lower().title()
+
+    name = _clean_utf8(name)
+    return name
 
 
 def display_name_from_filepath(name):
@@ -144,11 +153,10 @@ def display_name_from_filepath(name):
     Returns the path stripped of directory and extension,
     ensured to be utf8 compatible.
     """
+
     name = _os.path.splitext(basename(name))[0]
-    if type(name) == bytes:
-        return name.decode("utf8", "replace")
-    else:
-        return name.encode("utf8", "replace").decode("utf8")
+    name = _clean_utf8(name)
+    return name
 
 
 def resolve_ncase(path):
index 1a17cd9f000bf7fcdf277964e8e6ae632f913a7c..abd940e06f96ef2d24992043c06b18874aa89936 100644 (file)
@@ -20,7 +20,7 @@
 
 import bpy
 from bpy.types import Menu, Operator
-
+from bpy.props import StringProperty, BoolProperty
 
 class AddPresetBase():
     '''Base preset class, only for subclassing
@@ -31,13 +31,13 @@ class AddPresetBase():
     # bl_label = "Add a Python Preset"
     bl_options = {'REGISTER'}  # only because invoke_props_popup requires.
 
-    name = bpy.props.StringProperty(
+    name = StringProperty(
             name="Name",
             description="Name of the preset, used to make the path name",
             maxlen=64,
             options={'SKIP_SAVE'},
             )
-    remove_active = bpy.props.BoolProperty(
+    remove_active = BoolProperty(
             default=False,
             options={'HIDDEN', 'SKIP_SAVE'},
             )
@@ -166,12 +166,10 @@ class ExecutePreset(Operator):
     bl_idname = "script.execute_preset"
     bl_label = "Execute a Python Preset"
 
-    filepath = bpy.props.StringProperty(
-            name="Path",
-            description="Path of the Python file to execute",
-            maxlen=512,
+    filepath = StringProperty(
+            subtype='FILE_PATH',
             )
-    menu_idname = bpy.props.StringProperty(
+    menu_idname = StringProperty(
             name="Menu ID Name",
             description="ID name of the menu this was called from",
             )
@@ -456,7 +454,7 @@ class AddPresetOperator(AddPresetBase, Operator):
     bl_label = "Operator Preset"
     preset_menu = "WM_MT_operator_presets"
 
-    operator = bpy.props.StringProperty(
+    operator = StringProperty(
             name="Operator",
             maxlen=64,
             options={'HIDDEN'},
index 59b96cafca02a752a33eb9ae5ceb3e20d4bfab38..2e568a15117ecd342904f83b426d39a02cbc43cb 100644 (file)
@@ -222,7 +222,6 @@ extern "C" {
 #include "intern/bmesh_polygon.h"
 #include "intern/bmesh_queries.h"
 #include "intern/bmesh_walkers.h"
-#include "intern/bmesh_walkers.h"
 
 #include "intern/bmesh_inline.c"
 #include "intern/bmesh_operator_api_inline.c"
index 7702e952e246a296d2038375291b4b69118a95e7..c752b86c1e80fbd5d469cd244dc7a24dec9d8bdd 100644 (file)
@@ -80,7 +80,7 @@ void SCRIPT_OT_python_file_run(wmOperatorType *ot)
        ot->exec= run_pyfile_exec;
        ot->poll= ED_operator_areaactive;
 
-       RNA_def_string_file_path(ot->srna, "filepath", "", 512, "Path", "");
+       RNA_def_string_file_path(ot->srna, "filepath", "", FILE_MAX, "Path", "");
 }
 
 
index fdb5f6291155c391b8b0b1c4d1fa18ec16a6c11a..c670f728cb9488632b936b505986d149e4e0feb1 100644 (file)
@@ -437,8 +437,10 @@ PyObject *PyC_DefaultNameSpace(const char *filename)
        PyDict_SetItemString(interp->modules, "__main__", mod_main);
        Py_DECREF(mod_main); /* sys.modules owns now */
        PyModule_AddStringConstant(mod_main, "__name__", "__main__");
-       if (filename)
-               PyModule_AddStringConstant(mod_main, "__file__", filename); /* __file__ only for nice UI'ness */
+       if (filename) {
+               /* __file__ mainly for nice UI'ness */
+               PyModule_AddObject(mod_main, "__file__", PyUnicode_DecodeFSDefault(filename));
+       }
        PyModule_AddObject(mod_main, "__builtins__", interp->builtins);
        Py_INCREF(interp->builtins); /* AddObject steals a reference */
        return PyModule_GetDict(mod_main);
index 0f5ca13586c360e55bb8c44fada606bcd0086263..71cfa50743dc908e5d8992bbbe2f7a25a132d36b 100644 (file)
@@ -71,12 +71,17 @@ PyDoc_STRVAR(bpy_script_paths_doc,
 static PyObject *bpy_script_paths(PyObject *UNUSED(self))
 {
        PyObject *ret = PyTuple_New(2);
+       PyObject *item;
        char *path;
 
        path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL);
-       PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(path?path:""));
+       item = PyUnicode_DecodeFSDefault(path ? path : "");
+       BLI_assert(item != NULL);
+       PyTuple_SET_ITEM(ret, 0, item);
        path = BLI_get_folder(BLENDER_USER_SCRIPTS, NULL);
-       PyTuple_SET_ITEM(ret, 1, PyUnicode_FromString(path?path:""));
+       item = PyUnicode_DecodeFSDefault(path ? path : "");
+       BLI_assert(item != NULL);
+       PyTuple_SET_ITEM(ret, 1, item);
 
        return ret;
 }
@@ -200,7 +205,7 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj
 
        path = BLI_get_folder_version(folder_id, (major * 100) + minor, FALSE);
 
-       return PyUnicode_DecodeFSDefault(path);
+       return PyUnicode_DecodeFSDefault(path ? path : "");
 }
 
 static PyMethodDef meth_bpy_script_paths =