Hey @andrea.botti ,
Looks like this commit was made from an earlier version of our connector. Just so you know, retrieving categories and category elements from a commit sent from a newer version of our connector will be different.
The problem here is with the logic introduced when retrieving parameter objects, getting values from those objects etc. I wrote those back in the day as an exercise to understand how specklepy works.
As @teocomi mentioned, problem is not all walls have those properties. For example, both Basic walls and Curtain walls are under Walls category but their properties will be different. Basic walls won’t have the properties of a curtain wall (e.g. Adjust for a Mullion size). So we need to future-proof the logic to get and check those parameters.
First problem with the code is how it gets parameters from the selected category. It gets the first item from the selected category, gets all its parameters and shows that as an input. Instead it should loop through all walls and get all parameters, store them in a set and show that as an input to the user.
First, I created a separate function to get API names of parameters. Take a look:
# get all parameter API names
def get_api_parameters_from_category(commit_data, selected_category):
# get all elements from selected category
selected_category_elements = commit_data[selected_category]
# create an empty set to store api parameters
selected_category_parameters = set()
# loop through selected category elements
for element in selected_category_elements:
# get all their parameters and add them to the set
selected_category_parameters.update(element.parameters.get_dynamic_member_names())
# return api parameters as a sorted list
return sorted(selected_category_parameters)
Feel free to add this to the functions section.
Then I modified the get_parameter_names()
function:
# get all user facing names of all parameters
def get_parameter_names(commit_data, selected_category):
# get all elements belonging to the selected category
selected_category_elements = commit_data[selected_category]
# get their API parameters using the function we previously created.
api_parameters = get_api_parameters_from_category(commit_data, selected_category)
# create an empty set to store parameter names.
selected_category_parameter_names = set()
# loop through every element in selected category
for element in selected_category_elements:
# do a nested loop for every API parameter
for param in api_parameters:
# create an empty list to store parameter names for every element
param_names = []
# 📌 Check if parameter name exists in the parameters list of the object: THIS IS IMPORTANT.
# You can turn a Speckle object into a dictionary using `__dict__` method.
if param in element.parameters.__dict__:
# After this check we are sure that this object has this parameter. So we can get its name from the objects.
param_names.append(element.parameters[param].name)
# append parameter names to the empty list
selected_category_parameter_names.update(param_names)
# again, return parameter names as a sorted list.
return sorted(selected_category_parameter_names)
How to check if an object has the parameter value?
I also modified the get_parameter_by_name() method so it doesn’t crash if an element doesn’t have that parameter. Here is the code:
#get parameter value by parameter name
def get_parameter_by_name(element, parameter_name, dict):
for parameter in parameters:
# 📌 Check if parameter exists in the object
if parameter in element["parameters"].__dict__:
# Now we are sure the element has the parameter we are trying to get. Let's get it's name.
key = element.parameters[parameter].name
# check if the parameter name is equal to the parameter we are looking for
if key == parameter_name:
# if so, add it to the dict.
dict[key] = element["parameters"][parameter]["value"]
return dict
Here is the full code I modified. I did not get any errors. Let me know if you get any errors:
chatSpeckle.py (5.2 KB)