Closed JMante1 closed 2 years ago
I am not sure if the issue is that functional components can't be referred to more than once. The error is: <SBOLErrorCode.SBOL_ERROR_URI_NOT_UNIQUE: 17>, 'Cannot update SBOL-compliant URI. An object with URI http://examples.org/ModuleDefinition/mod2/fc1/1 is already in the Document
Yes, I believe that error indicates that you can't add the same object fc1
to more than one parent ModuleDefinition
It is interesting as the error seems to indicate a difficulty with the specific uri e.g. http://examples.org/ModuleDefinition/mod2/fc1/1 and http://examples.org/ModuleDefinition/mod1/fc1/1 would work. Is it an SBOL thing that you can't have repeated functional components?
The error message is indirectly telling you that fc1
already has a parent and that you can't assign it to more that one parent. The error message is not as clear and direct as it should be.
When you add a child object to a parent, pySBOL automatically generates the URI of the child object. Once an object is assigned a URI, pySBOL prohibits you from changing the URI. So when you attempt to add that child object to a different parent, pySBOL tries to change the URI, hence the error message.
It's not an error specific to FunctionalComponents
. It's that a child object (black diamond relationship in UML) cannot have more than one parent. This is different from a reference association(white diamond relationship) which may be what you are expecting.
Is it possible to keep a copy unlinked so I can add the sub properties only once? like a template fc?
Yes, I believe so. I think sbol-utilities may have some convenience method for handling template copies. @tcmitchell or @jakebeal would know more about that. Regardless, I think you should be able to implement something like this for your specific use case.
You could try the copy
method and see if it works for your use case. I'm not sure it will, and it's worth a try. I have modified your erroring example to use copy
:
doc = sbol2.Document()
fc1 = sbol2.FunctionalComponent("fc1")
fc2 = sbol2.FunctionalComponent("fc2")
cp1 = sbol2.ComponentDefinition("cp1")
doc.add(cp1)
fc2.definition = cp1
mod1 = sbol2.ModuleDefinition("mod1")
mod2 = sbol2.ModuleDefinition("mod2")
doc.add(mod1)
doc.add(mod2)
mod1.functionalComponents.add(fc1.copy())
mod2.functionalComponents.add(fc1.copy())
doc.write(file_path_out)
Please let us know if this works for you.
This works, thanks.
There is something slightly odd happening here.
This does not throw an error but also doesn't provide the expected output.
Whilst this throws an error: