1
$\begingroup$

Need a function to check the data path is valid of driver variable target

enter image description here

import bpy

# add cube in object mode
bpy.ops.mesh.primitive_cube_add(size=1, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
cube = bpy.context.object
md = cube.modifiers.new(type="BOOLEAN", name="boo")

fc = md.driver_add("double_threshold")
dr = fc.driver
vs = dr.variables
v = vs.new()
tar = v.targets[0]
tar.id = cube

# end add cube

def is_path_valid(tar):
    tar_id = tar.id
    path = tar.data_path
    if path == "":
        return False
    else:
        # Other casees
        # for example:
        # 'modifiers["hello"].solver' --> return False
        # 'modifiers["boo"].solver'   --> return True
        ...

# test
tar.data_path = f'modifiers["hello"].solver'
if is_path_valid(tar):
    print("not red")
else:
    print("red")

# if result is "red", then success

# test 2
tar.data_path = f'modifiers["boo"].solver'
if is_path_valid(tar):
    print("not red")
else:
    print("red")

# if result is "not red", then success
$\endgroup$
6
  • $\begingroup$ blender.stackexchange.com/a/167129/86891 ? $\endgroup$
    – Gorgious
    Commented May 4, 2022 at 19:38
  • $\begingroup$ I checked dr.is_valid is True when variable Path == "", it is not success. $\endgroup$
    – X Y
    Commented May 4, 2022 at 19:44
  • 1
    $\begingroup$ why don't you directly test the path and see if it returns something ? like try : eval(path) except (AttributeError, KeyError): return False else: return True $\endgroup$
    – Gorgious
    Commented May 4, 2022 at 19:49
  • $\begingroup$ That's a good idea $\endgroup$
    – X Y
    Commented May 4, 2022 at 20:25
  • $\begingroup$ @XY Please take this as constructive advice. Blender code should conform to Python's PEP 8 Style Guide. You use extra white space before equal signs (=) in a way that is explicitly called out as wrong in the style guide. It makes your code harder to read for people who are used to conforming code. Please follow the style guide. $\endgroup$ Commented May 5, 2022 at 0:10

2 Answers 2

1
$\begingroup$

By Gorgious's idea, use eval to test the path, any answers can success are welcome.

def is_path_valid(tar):
    try:
        tar_id = tar.id
        eval(f'tar_id.{tar.data_path}')
        return True
    except:
        return False

# test
tar.data_path = f'modifiers["hello"].solver'
if is_path_valid(tar):
    print("not red")
else:
    print("red")

# >>>> red

# test 2
tar.data_path = f'modifiers["boo"].solver'
if is_path_valid(tar):
    print("not red")
else:
    print("red")

# >>>> not red
$\endgroup$
1
$\begingroup$

I think you're confusing yourself by trying to insert a function that returns true or false. Python already makes this stuff easy, You don't have to do "if tar.data_path == '' or vice versa.

In some languages, there are terms like "Truthy" or "Falsy" meaning things that evaluate to True or False if you ask the interpreter what it thinks.

Things like a string, float or int greater or less than 0, or a list or dict with a len > 0, that all evaluate to True.

Things like the number zero, empty strings, dicts, sets, lists or evaluate to False.

bool_list = ['', 1, 0, ["foo"], {}]

for b in bool_list:
    print(bool(b))

>>> False
    True
    False
    True
    False

So with your code you could just go:

if tar.data_path:
# Insert the stuff that you want it to do if the path is valid.
else:
# stuff that you want it to do if the path is invalid.

Works in Blender:

enter image description here

Edit - Additional info Regarding use of the 'getattr' operator

Think of getattr(cube, 'data_path') as as another way of writing cube.data_path. It's only meant to get existing attributes from an object, by passing the string name and the object to the operator.

Usually you only use getattr inside of another function where you don't know what the attribute will be necessarily at runtime.

class Obj:
    def __init__(self, a, b):
     self.a = a
     self.b = b

def get_object_attr_bad(obj, attr):
    print(obj.attr)

# create a new instance of the object
obj1 = Obj(10, 20)

# This won't work because inside this scope the 
# attribute "a" doesn't exist yet.
get_object_attr_bad(obj1, a)

---------------------------------------------------------------------------
>>> NameError                                 
Traceback (most recent call last)
      8 
      9 obj1 = Obj(10, 20)
---> 10 get_object_attr_bad(obj1, a)

NameError: name 'a' is not defined

def get_attr_obj_good(obj, attr):
    # pass the attribute as a string and let 
    # getattr handle it
    print(getattr(obj, attr))

get_attr_obj_good(obj1, 'a')
# works like a charm
>>> 10

A good way to debug issues like this and make sure the object you're working with is to occasionally use the dir() operator or __dict__ attribute , to quickly take a look at what attributes an object has.

# Using the previous example

import pprint

## pprint is a built-in module that let's you 
# print nested dictionaries and lists in a more readable way

pprint.ppprint(dir(obj1))

>>> ['__class__', # all the built in attributes that come with 
 '__delattr__', # Objects in python

...              # omitted for brevity

 '__weakref__',
 'a',            # our custom attributes
 'b']

# or we can use the more succinct __dict__ attribute. It doesn't 
# always work if cause sometimes the object doesn't have the __dict__ 
# method defined.

print(obj.__dict__)
>>> {'a': 10, 'b': 20}
$\endgroup$
4
  • $\begingroup$ if you see the example on line 25, it is not work in your suggestion. $\endgroup$
    – X Y
    Commented May 4, 2022 at 20:33
  • $\begingroup$ I edited the post to make sure it works, It works for me in the blender script editor? Are you sure you're asking a question about the right issue? $\endgroup$
    – Jakemoyo
    Commented May 4, 2022 at 20:43
  • $\begingroup$ It should print "doesn't work" , because getattr(cube, "..") does not exist. $\endgroup$
    – X Y
    Commented May 4, 2022 at 20:47
  • $\begingroup$ I added more info to my answer. $\endgroup$
    – Jakemoyo
    Commented May 5, 2022 at 10:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .