If I understand correctly, when receiving an object with the Python SDK, information on which (Base type) properties of that object are detached is lost. It would be nice to get that information for further processing.
Let me know if you I am missing something or need to provide more details on this.
You most definitely receive back any properties (detached or non-detached), although I just went through the docs and we don’t have any mention of this behaviour specifically in the Python side. So maybe we should expand those docs!
I’m sure @izzylys would be able to give you more details about why this works the way it does, but here’s the gist of it:
Any you can access any property of a Base object just as you would access a dictionary
# Assuming you're receiving the object like so
received_base = operations.receive(obj_id=hash, remote_transport=transport)
# This allows you to get only the property names that were dynamically added
members = received_base.get_dynamic_member_names()
# And this will get all the property names of that base object (either class members or dynamic)
all_members = received_base.get_member_names()
# Access a specific property value
my_prop = received_base["my_property_name"]
# Access detached properties with an preceding @
my_prop = received_base["@my_detached_prop_name"]
Note that when you get the member names, detached properties will already contain the necessary preceding @.
Thanks for the quick response. So I’m aware you get back both detached and non-detached properties. However, how to know whether a properties is/was detached or not?
When defining a class inheriting from Base, the set of detached properties are stored in the _detachable attribute. However, when receiving an object from a Speckle server in Python, that attribute is always an empty set.
oh! sorry I misunderstood your question! I spoke to Izzy and it seems the behaviour is “by-design”, meaning the _detachable prop shouldn’t get populated on receive.
Just to clarify, could you give us more details of what you’re trying to achieve, and how is knowing if a prop is detached important to you?
All detached properties will always start with an @, so you could directly rely on that to know if a property is detached or not. Or would that not be sufficient?
to further clarify, the _detachable prop is defined on the class definition and is specific to that model (docs). you can modify it on a specific python class instance, but it is not populated by the deserialisation. it is just a way to flag predefined attributes of the class as detachable without using the @ syntax (since you can’t use the @ to prepend an attribute in a class definition). it serves the same purpose as the [Detachable] flag in the .NET sdk.
if you are receiving a speckle type and you have a class for it in python, it will instantiate that class on deserialisation and your _detachable prop will be there since the object is an instance of your defined class (or any of the included specklepy classes).
if you are receiving a speckle type that you don’t have as a class in python, then of course you won’t have anything in the _detachable field since what you are getting is a regular Base object.
for any base object, you can use get_dynamic_member_names (docs) to get all the dynamic members (not defined on the class) which will include all the detached ones. if you want just the detached ones, then as Alan said you just look for the prepending @
So just as a bit of background: I’m creating a class which mimics a certain XML schema (gbXML). The XML schema uses references, so I want to use detached attributes in line with that, to later easily convert to a valid XML file.
I could indeed first import the class, and then receive the Speckle object. But that will give errors when the class definition changes.
Using the fact that detached property names start with an @ could work. However, I don’t yet see how (see screenshot below, in which the class definition was defined first). Probably I’m missing something again?
here it looks like you have already defined a class and flagged construction as detachable. this means you are not looking at a vanilla Base object in speckle_object["Campus"]["Surface"][0] so the field will indeed be called constructionnot@construction. as stated previously, the _detachable field is for flagging attributes that you want to detach without using the @ syntax
could you explain what you’re trying to do a bit more? maybe with a simple example of where your issue comes up? I’m afraid I don’t really understand the problem. it looks like you already have your class definition with the flagged detached attribute and it’s serialising and deserialising correctly.
also, why would your class definition change / cause errors? if you know what your classes should look like, then creating them and importing them seems like the cleanest solution. even if they change, you will be importing the updated class and since the objects are flexible I’m not sure what errors would be happening on serialisation / deserialisation? the possible errors I see are on the user end if fields are null and you’re trying to access them. however if it is the case that fields could be null, then I think you should be checking if the attribute has a value before trying to step into it.