-
Notifications
You must be signed in to change notification settings - Fork 5
Description
py-serializable version: 2.0.0
python version: 3.13.3
os: linux
What is the problem?
I try to implement the missing identity element of componentEvidenceType into cyclonedx-python-lib. Since version 1.6 of the schema the identity has maxOccurs="unbounded" that means something like this is possible in 1.6:
<evidence>
<identity>
<field>purl</field>
</identity>
<identity>
<field>name</field>
</identity>
</evidence>I am developing now a helper with a custom xml_normalize function. The problem I have now is that only:
- None
- a single Element
- a string which is used as value
are supported:
serializable/py_serializable/__init__.py
Lines 508 to 515 in bb035d2
| v_ser = prop_info.custom_type.xml_normalize( | |
| v, view=view_, element_name=new_key, xmlns=xmlns, prop_info=prop_info, ctx=self.__class__) | |
| if v_ser is None: | |
| pass # skip the element | |
| elif isinstance(v_ser, Element): | |
| this_e.append(v_ser) | |
| else: | |
| SubElement(this_e, new_key).text = _xs_string_mod_apply(str(v_ser), |
How to improve this?
It would be great to support also List[Element]. Maybe something like that:
elif isinstance(ver_ser, List):
for element in ver_ser:
this_e.append(element)With this simple approach something like this is possible:
988 @classmethod
989 def xml_normalize(
990 cls, o: SortedSet[Identity], *,
991 element_name: str,
992 view: Optional[type['ViewType']],
993 xmlns: Optional[str],
994 **__: Any
~ 995 ) -> Optional[list[Element]]:
~ 996 if view is not None:
+ 997 schema_version: BaseSchemaVersion = cast(BaseSchemaVersion, view())
+ 998 if schema_version.schema_version_enum < SchemaVersion.V1_6 and len(o) > 1:
+ 999 raise SerializationOfUnexpectedValueException(
+ 1000 "The schema version 1.5 only supports a single identity object"
+ 1001 )
+ 1002 else:
+ 1003 return [
E 1004 identity.as_xml(
+ 1005 view_=view,
+ 1006 as_string=False,
+ 1007 element_name=element_name,
+ 1008 xmlns=xmlns,
+ 1009 )
+ 1010 for identity in o
+ 1011 ]
+ 1012 return None >>> from cyclonedx.schema.schema import SchemaVersion1Dot4, SchemaVersion1Dot5, SchemaVersion1Dot6
>>> from cyclonedx.model.component import ComponentEvidence, Identity, IdentityField
>>> foo = ComponentEvidence(identity=Identity(field=IdentityField.PURL))
>>> foo.as_xml(view_=SchemaVersion1Dot6)
'<componentEvidence><identity><field>purl</field></identity></componentEvidence>'
>>> foo.as_xml(view_=SchemaVersion1Dot5)
'<componentEvidence><identity><field>purl</field></identity></componentEvidence>'
>>> bar = ComponentEvidence(identity=[Identity(field=IdentityField.PURL), Identity(field=IdentityField.NAME)])
>>> bar.as_xml(view_=SchemaVersion1Dot6)
'<componentEvidence><identity><field>name</field></identity><identity><field>purl</field></identity></componentEvidence>'
>>> bar.as_xml(view_=SchemaVersion1Dot5)
Traceback (most recent call last):
File "<python-input-7>", line 1, in <module>
bar.as_xml(view_=SchemaVersion1Dot5)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jloehel/projects/github.com/jloehel/cyclonedx-python-lib/.venv/lib64/python3.13/site-packages/py_serializable/__init__.py", line 508, in as_xml
v_ser = prop_info.custom_type.xml_normalize(
v, view=view_, element_name=new_key, xmlns=xmlns, prop_info=prop_info, ctx=self.__class__)
File "/home/jloehel/projects/github.com/jloehel/cyclonedx-python-lib/cyclonedx/model/component.py", line 999, in xml_normalize
raise SerializationOfUnexpectedValueException(
"The schema version 1.5 only supports a single identity object"
)
cyclonedx.exception.serialization.SerializationOfUnexpectedValueException: The schema version 1.5 only supports a single identity objectedit: Maybe it's better to consider the helper for prop_info.is_array because
@serializable.xml_array(serializable.XmlArraySerializationType.FLAT, child_name='identity')is doing the right thing. I just wanna raise an exception in a special case.