Python: Support multiple custom script directories in Preferences #104876
|
@ -345,17 +345,23 @@ def script_path_pref():
|
||||||
DEPRECATED. Use `script_paths_pref` which supports multiple script paths now. Returns the
|
DEPRECATED. Use `script_paths_pref` which supports multiple script paths now. Returns the
|
||||||
first valid of these script paths for now, for compatibility.
|
first valid of these script paths for now, for compatibility.
|
||||||
"""
|
"""
|
||||||
# TODO how to handle deprecation of this?
|
from warnings import warn
|
||||||
|
warn(
|
||||||
|
"bpy.utils.script_path_pref() is deprecated use script_paths_pref() instead!",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
script_paths = script_paths_pref()
|
script_paths = script_paths_pref()
|
||||||
return script_paths[0] if len(script_paths) > 0 else ""
|
return script_paths[0] if len(script_paths) > 0 else ""
|
||||||
|
|
||||||
|
|
||||||
def script_paths_pref():
|
def script_paths_pref():
|
||||||
"""returns the user preference script directory paths or None"""
|
"""Returns a list of user preference script directories."""
|
||||||
paths = []
|
paths = []
|
||||||
for script_directory in _preferences.filepaths.script_directories:
|
for script_directory in _preferences.filepaths.script_directories:
|
||||||
if script_directory.directory:
|
directory = script_directory.directory
|
||||||
paths.append(_os.path.normpath(script_directory.directory))
|
if directory:
|
||||||
|
paths.append(_os.path.normpath(directory))
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1170,7 +1170,7 @@ class PREFERENCES_OT_script_directory_new(Operator):
|
||||||
new_dir.directory = self.directory
|
new_dir.directory = self.directory
|
||||||
new_dir.name = os.path.basename(self.directory.rstrip(os.sep))
|
new_dir.name = os.path.basename(self.directory.rstrip(os.sep))
|
||||||
|
|
||||||
assert(context.preferences.is_dirty == True)
|
assert context.preferences.is_dirty == True
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
@ -1197,7 +1197,7 @@ class PREFERENCES_OT_script_directory_remove(Operator):
|
||||||
script_directories.remove(script_directory)
|
script_directories.remove(script_directory)
|
||||||
break
|
break
|
||||||
|
|
||||||
assert(context.preferences.is_dirty == True)
|
assert context.preferences.is_dirty == True
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
|
@ -685,6 +685,7 @@ typedef struct UserDef_Experimental {
|
||||||
typedef struct NamedDirectoryPathEntry {
|
typedef struct NamedDirectoryPathEntry {
|
||||||
struct NamedDirectoryPathEntry *next, *prev;
|
struct NamedDirectoryPathEntry *next, *prev;
|
||||||
|
|
||||||
|
/** Depending on the use case of this struct, this should probably be a unique name. */
|
||||||
char name[64]; /* MAX_NAME */
|
char name[64]; /* MAX_NAME */
|
||||||
char dir_path[768]; /* FILE_MAXDIR */
|
char dir_path[768]; /* FILE_MAXDIR */
|
||||||
} NamedDirectoryPathEntry;
|
} NamedDirectoryPathEntry;
|
||||||
|
|
|
@ -348,10 +348,19 @@ static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain),
|
||||||
static void rna_userdef_script_directory_name_set(PointerRNA *ptr, const char *value)
|
static void rna_userdef_script_directory_name_set(PointerRNA *ptr, const char *value)
|
||||||
JulianEisel marked this conversation as resolved
|
|||||||
{
|
{
|
||||||
NamedDirectoryPathEntry *script_dir = ptr->data;
|
NamedDirectoryPathEntry *script_dir = ptr->data;
|
||||||
|
bool value_invalid = false;
|
||||||
|
|
||||||
|
if (!value[0]) {
|
||||||
|
value_invalid = true;
|
||||||
|
}
|
||||||
if (STREQ(value, "DEFAULT")) {
|
if (STREQ(value, "DEFAULT")) {
|
||||||
BKE_report(NULL, RPT_ERROR, "Name 'DEFAULT' is reserved for internal use and cannot be used");
|
BKE_report(
|
||||||
return;
|
NULL, RPT_WARNING, "Name 'DEFAULT' is reserved for internal use and cannot be used");
|
||||||
JulianEisel marked this conversation as resolved
Campbell Barton
commented
Rather not warn as in the rare case a user runs into this - it's not as if there is anything to "fix", besides the script author adding explicit checks for "DEFAULT" which isn't useful. Over long names will also be clipped for e.g. which doesn't warn. In general it's possible the name requested in Blender is manipulated. It can't be assumed a string literal will be used verbatim. Rather not warn as in the rare case a user runs into this - it's not as if there is anything to "fix", besides the script author adding explicit checks for "DEFAULT" which isn't useful.
Over long names will also be clipped for e.g. which doesn't warn. In general it's possible the name requested in Blender is manipulated. It can't be assumed a string literal will be used verbatim.
|
|||||||
|
value_invalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value_invalid) {
|
||||||
|
value = DATA_("Untitled");
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_strncpy_utf8(script_dir->name, value, sizeof(script_dir->name));
|
BLI_strncpy_utf8(script_dir->name, value, sizeof(script_dir->name));
|
||||||
|
|
Loading…
Reference in New Issue
If
DEFAULT
or an empty string is passed in, use a fallback name such as "Untitled" or "Path", this avoids having to account for unlikely corner cases - maybe the user has a points to a script dir calledDEFAULT
and gets an error in the operator.Disallowing empty strings is just a convention from data-block naming, which I think would be good to enforce here too since it's not expected and means the enum identifier for e.g. would be an empty string - probably it works for the most-part but could cause issues (empty strings have a special meaning for enum separators .. for e.g.). Python scripts may do truth checks on a value without realizing an empty string is a valid value... so we can avoid all this with a default name.