Skip to content

Instantly share code, notes, and snippets.

@hesido
Created November 21, 2023 07:49
Show Gist options
  • Save hesido/eef189fe1f6e111c704ac5f927f985f8 to your computer and use it in GitHub Desktop.
Save hesido/eef189fe1f6e111c704ac5f927f985f8 to your computer and use it in GitHub Desktop.
Blender Python Function To Evaluate User Input Property Paths without Eval
def evaluate_path(path, alternative_root = None):
#alternative_root can be used to define a default parent root object if user is not expected to enter full path
#Note: full paths start with "bpy."
if(path is None or path == ""):
return (None, None, None)
#Regular expression pattern to match segments of the path
pattern = r'(.+?)\.|(?:\["(.+?)"\])|([^"\[\]]+)'
segments = re.findall(pattern, path)
parent_obj = None
enumerate_from = 0
# If full path, start with bpy
if segments[0][0] == "bpy":
current_obj = bpy
enumerate_from = 1
else:
current_obj = alternative_root
if(current_obj is None):
return (None, None, None)
for segment in segments[enumerate_from:]:
prop_name = segment[0] or segment[1] or segment[2]
# Check if the property exists
if hasattr(current_obj, prop_name):
parent_obj = current_obj
current_obj = getattr(current_obj, prop_name)
else:
if isinstance(current_obj, list):
# Check if the property is an indexed attribute in a list
index = int(prop_name) # Extract the index
if 0 <= index < len(current_obj):
parent_obj = current_obj
current_obj = current_obj[index]
else:
return (None, None, None) # Index out of range
elif prop_name in current_obj:
parent_obj = current_obj
current_obj = current_obj[prop_name]
else:
return (None, None, None) # Key not found
#return (target object of path, parent of target object, property name string of the target object)
return (current_obj, parent_obj, prop_name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment