I’m trying to get al the objects which are in a specific version with specklepy. I can only find a way to retrieve one object at a time. Is there a way to get a list of object id’s of a specific version with specklepy so that i can get all the information?
The script im using now is like below (which is for one element).
def getObjectData(client,project_id,model_id,object_id):
project = client.project.get(project_id)
models = client.model.get_models(project_id).items
model = next((m for m in models if m.id == model_id), None)
server_transport = ServerTransport(project_id, client)
data = operations.receive(object_id, remote_transport=server_transport)
serializable_attributes=data.get_serializable_attributes()
serializer = BaseObjectSerializer()
hash, obj_dict = serializer.traverse_base(data)
return data, hash, obj_dict
I’m not a python expert, but you will get all ids in the root version’s object’s closure table. You can flatten that dictionary → the keys are what you’re looking for.
So:
get the root commit object by its id
look at its closure table dictionary and get its keys
profit!
You can also simply use the rest api endpoint for objects to get “everything”, eg.
To help you better, please do provide some wider context around what you’re trying to do - there might be implications that we’re not aware of.
Also, note: from the script that you’re using, if you pass in the as object_id the root version’s object, data will have the full tree - ie, all the object data from that model version.
Thanks for your response! Im trying to make a custom connector for revit with Dyanomo and this part is meant to get the object information of all the objects in a certain version. Im not sure if i’m understanding your input correctly though:
What i get is a tuple with in there a dictionary at index 1. When looking into that dictionary i find a key named ‘elements’. In there i get 8 elements (while there should be 2) with no corrsponding id’s but two of them have corresponding speckle_types.
for item in obj_dict[1]["elements"]:
for x in item["elements"]:
print(x['speckle_type'])
print(x['id'])
Note: the applicationId does match the elements but the id does not.
As @dimitrie suggested, the base object should be flattened to get the object IDs as a list. Here is an updated version of your first function with the flattening logic.
def GetObjectsList(client, project_id, model_id):
model = client.model.get_with_versions(model_id, project_id).versions
root_object_id = model.items[0].referencedObject
server_transport = ServerTransport(project_id, client)
data = operations.receive(
root_object_id, remote_transport=server_transport)
object_list = []
objects_to_process = [data]
while objects_to_process:
current = objects_to_process.pop()
object_list.append(current.id)
elements = getattr(current, "elements",
getattr(current, "@elements", None))
if elements:
objects_to_process.extend(elements)
return object_list
Now this should return a list with the object IDs. We will consider to add this function to our SDK, so everyone can directly access it.
For further questions, it would be nice if you could share your model with us -if you don’t mind- so we can work on the same model.