It was leaving an orphaned pset if 'products' was a list of all elements pset is assigned to. Then it would create a new pset for each element leaving original pset orphaned.
In IFC it's possible for a property set to be assigned to multiple elements and which may lead to confusing behaviour when you edit a pset on one element and other element seems to get edited too.
Which makes it worse is that that it is possible that some software is might be doing this unintentionally when exporting IFC (as some sort of optimization as storing 1 is more optimal than n copies of it).
So now there are some tools in Bonsai and in IfcOpenShell to handle the shared psest:
1) Indication that property is shared - https://imgur.com/a/9dd3jST (similar to how Blender indicates ID data-block users). You can click on it to "unshare" the pset - a new copy for the pset will be created and it's going to be linked only to the active object.
2) api pset.unshare_pset method that does the same. And util.element.get_elements_using_pset method that encapsulates schema differences and different approaches for occurrences/types.
3) ifcpatch recipe 'UnsharePsets' that's making all property sets in the IFC file to have just 1 element that's using them. You can limit the affected elements by providing query.
ifcpatch recipe is also available in Bonsai - https://i.imgur.com/aOCx7HI.png
Kind of experimental. The idea is that it will reassign class e.g. from IfcWindow to IfcWindowType (or vice versa) and will keep the IFC representations and property sets.
Example - https://imgur.com/a/X7MHR0s
1) For psets there was an issue - it was instantiating abstract IfcProfileProperties
2) For materials it was only able to instantiate IfcExtendedMaterialProperties though there are other pset types too in ifc2x3.
TessellateElements patch was failing because it was relying on optionality of `edges` argument. Though argument itself is currently useless and not used in the code.
It wasn't considering that IfcTaskTimeRecurring might be just created and IfcTaskTimeRecurring.Recurrence is None resulting in error below
File "\api\sequence\assign_recurrence_pattern.py", line 120, in assign_recurrence_pattern
if len(file.get_inverse(settings["parent"].Recurrence)) == 1:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\file.py", line 524, in get_inverse
inverses = [entity_instance(e, self) for e in self.wrapped_data.get_inverse(inst.wrapped_data)]
AttributeError: 'NoneType' object has no attribute 'wrapped_data'
1) It wasn't removing ownerhistory in the case if task was RelatingObject in IfcRelNests
2) Replaced handling of IfcRelNests as an inverse with direct api calls.
3) Added some basic tests.