Python: Support multiple custom script directories in Preferences #104876

Merged
Julian Eisel merged 9 commits from JulianEisel/blender:temp-multiple-script-dirs into main 2023-04-11 15:21:06 +02:00
7 changed files with 28 additions and 22 deletions
Showing only changes of commit 0631840f5d - Show all commits

View File

@ -354,8 +354,8 @@ def script_paths_pref():
"""returns the user preference script directory paths or None"""
JulianEisel marked this conversation as resolved Outdated

Should read "Returns a list of user preference script directories." or similar.

Should read `"Returns a list of user preference script directories."` or similar.
paths = []
for script_directory in _preferences.filepaths.script_directories:
if script_directory.path:
paths.append(_os.path.normpath(script_directory.path))
if script_directory.directory:
JulianEisel marked this conversation as resolved Outdated

picky assign a value and avoid accessing script_directory.directory twice.

*picky* assign a value and avoid accessing `script_directory.directory` twice.
paths.append(_os.path.normpath(script_directory.directory))
return paths

View File

@ -593,7 +593,7 @@ class PREFERENCES_OT_addon_install(Operator):
return (
('DEFAULT', "Default", ""),
None,
*[(item.name, item.name, "") for index, item in enumerate(paths.script_directories) if item.path],
*[(item.name, item.name, "") for index, item in enumerate(paths.script_directories) if item.directory],
)
target: EnumProperty(
@ -635,7 +635,7 @@ class PREFERENCES_OT_addon_install(Operator):
paths = context.preferences.filepaths
for script_directory in paths.script_directories:
if script_directory.name == self.target:
path_addons = os.path.join(script_directory.path, "addons")
path_addons = os.path.join(script_directory.directory, "addons")
break
if not path_addons:
@ -1161,14 +1161,14 @@ class PREFERENCES_OT_script_directory_new(Operator):
)
def execute(self, context):
from pathlib import Path
import os
script_directories = context.preferences.filepaths.script_directories
new_dir = script_directories.new()
# Assign path selected via file browser.
new_dir.path = self.directory
new_dir.name = Path(self.directory).name
new_dir.directory = self.directory
new_dir.name = os.path.basename(self.directory.rstrip(os.sep))
assert(context.preferences.is_dirty == True)
JulianEisel marked this conversation as resolved Outdated

newer autopep8 removes parenthesis after assert (they're not needed), so prefer not to add them.

newer autopep8 removes parenthesis after assert (they're not needed), so prefer not to add them.

View File

@ -1336,16 +1336,16 @@ class USERPREF_PT_file_paths_data(FilePathsPanel, Panel):
class USERPREF_PT_file_paths_script_directories(FilePathsPanel, Panel):
bl_label = "Script Directories"
def draw(self, context):
layout = self.layout
paths = context.preferences.filepaths
if len(paths.script_directories) == 0:
layout.operator("preferences.script_directory_add", text="Add", icon='ADD')
return
layout.use_property_split = False
layout.use_property_decorate = False
@ -1353,26 +1353,26 @@ class USERPREF_PT_file_paths_script_directories(FilePathsPanel, Panel):
split = box.split(factor=0.35)
name_col = split.column()
path_col = split.column()
row = name_col.row(align=True) # Padding
row.separator()
row.label(text="Name")
row = path_col.row(align=True) # Padding
row.separator()
row.label(text="Path")
row.operator("preferences.script_directory_add", text="", icon='ADD', emboss=False)
for i, script_directory in enumerate(paths.script_directories):
row = name_col.row()
row.alert = not script_directory.name
row.prop(script_directory, "name", text="")
row = path_col.row()
subrow = row.row()
subrow.alert = not script_directory.path
subrow.prop(script_directory, "path", text="")
subrow.alert = not script_directory.directory
subrow.prop(script_directory, "directory", text="")
row.operator("preferences.script_directory_remove", text="", icon='X', emboss=False).index = i

View File

@ -782,10 +782,10 @@ void blo_do_versions_userdef(UserDef *userdef)
}
if (!USER_VERSION_ATLEAST(306, 1)) {
if (userdef->pythondir[0]) {
if (userdef->pythondir_legacy[0]) {
NamedDirectoryPathEntry *script_path = MEM_callocN(sizeof(*script_path),
"Versioning user script path");
STRNCPY(script_path->dir_path, userdef->pythondir);
STRNCPY(script_path->dir_path, userdef->pythondir_legacy);
BLI_addhead(&userdef->script_directories, script_path);
}
}

View File

@ -700,7 +700,7 @@ typedef struct UserDef {
char render_cachedir[768];
char textudir[768];
/* Deprecated, use #UserDef.script_directories instead. */
char pythondir[768] DNA_DEPRECATED;
char pythondir_legacy[768] DNA_DEPRECATED;
char sounddir[768];
char i18ndir[768];
/** 1024 = FILE_MAX. */

View File

@ -139,6 +139,7 @@ DNA_STRUCT_RENAME_ELEM(ThemeSpace, scrubbing_background, time_scrub_background)
DNA_STRUCT_RENAME_ELEM(ThemeSpace, show_back_grad, background_type)
DNA_STRUCT_RENAME_ELEM(UVProjectModifierData, num_projectors, projectors_num)
DNA_STRUCT_RENAME_ELEM(UserDef, gp_manhattendist, gp_manhattandist)
DNA_STRUCT_RENAME_ELEM(UserDef, pythondir, pythondir_legacy)
DNA_STRUCT_RENAME_ELEM(VFont, name, filepath)
DNA_STRUCT_RENAME_ELEM(View3D, far, clip_end)
DNA_STRUCT_RENAME_ELEM(View3D, near, clip_start)

View File

@ -349,6 +349,11 @@ static void rna_userdef_script_directory_name_set(PointerRNA *ptr, const char *v
{
NamedDirectoryPathEntry *script_dir = ptr->data;
if (STREQ(value, "DEFAULT")) {
BKE_report(NULL, RPT_ERROR, "Name 'DEFAULT' is reserved for internal use and cannot be used");
return;
}
BLI_strncpy_utf8(script_dir->name, value, sizeof(script_dir->name));
BLI_uniquename(&U.script_directories,
JulianEisel marked this conversation as resolved
Review

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.
script_dir,
@ -6211,7 +6216,7 @@ static void rna_def_userdef_script_directory(BlenderRNA *brna)
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "path", PROP_STRING, PROP_DIRPATH);
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
RNA_def_property_string_sdna(prop, NULL, "dir_path");
RNA_def_property_ui_text(
prop,