Get all objects.ids in a version

Hey Guys,

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:

so i’m getting the version object:

project_id_R    = "6a87e55c77"
version_id_R    = "7a943d3e3e"
versionObject=client.version.get(version_id_R,project_id_R).referencedObject

Then im getting the attributes

server_transport = ServerTransport(project_id_R, client)
data = operations.receive(versionObject, remote_transport=server_transport)
serializable_attributes=data.get_serializable_attributes()
serializer = BaseObjectSerializer()
obj_dict = serializer.traverse_base(data)

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.

could this be a bug?

Hi,

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. :slight_smile:

3 Likes