Package: pycddl
PyCDDL: Deserialize CBOR and/or do CDDL schema validationCDDLis a schema language for the CBOR serialization format.pycddlallows you to:Validate CBOR documents match a particular CDDL schema, based on the Rustcddllibrary.Optionally, decode CBOR documents.UsageValidationHere we use thecbor2library to serialize a dictionary to CBOR, and then validate it:frompycddlimportSchemaimportcbor2uint_schema=Schema("""object = {xint: uint}""")uint_schema.validate_cbor(cbor2.dumps({"xint",-2}))If validation fails, apycddl.ValidationErroris raised.Validation + deserializationYou can deserialize CBOR to Python objects usingcbor.loads().
However:cbor2uses C code by default, and the C programming language is prone to memory safety issues.
If you are reading untrusted CBOR, better to use a Rust library to decode the data.You will need to parse the CBOR twice, once for validation and once for decoding, adding performance overhead.By deserializing withpycddl, you solve the first problem, and a future version ofpycddlwill solve the second problem (seehttps://gitlab.com/tahoe-lafs/pycddl/-/issues/37).frompycddlimportSchemaimportcbor2uint_schema=Schema("""object = {xint: uint}""")deserialized=uint_schema.validate_cbor(cbor2.dumps({"xint",-2}),True)assertdeserialized=={"xint":-2}Deserializing without schema validationIf you don't care about schemas, you can just deserialize the CBOR like so:frompycddlimportSchemaACCEPT_ANYTHING=Schema("main = any")defloads(encoded_cbor_bytes):returnACCEPT_ANYTHING.validate_cbor(encoded_cbor_bytes,True)In a future release this will become a standalone, more efficient API, seehttps://gitlab.com/tahoe-lafs/pycddl/-/issues/36Reducing memory usage and safety constraintsIn order to reduce memory usage, you can pass in any Python object that implements the buffer API and stores bytes, e.g. amemoryview()or ammapobject.The passed-in object must be read-only, and the data must not change during validation!If you mutate the data while validation is happening the result can be memory corruption or otherundefined behavior.Supported CBOR types for deserializationIf you are deserializing a CBOR document into Python objects, you can deserialize:Null/None.Booleans.Floats.Integers up to 64-bit size.
Larger integers aren't supported yet.Bytes.Strings.Lists.Maps/dictionaries.Sets.Other types will be added in the future if there is user demand.Schema validation is not restricted to this list, but rather is limited by the functionality of thecddlRust crate.Release notes0.6.1Bug fixes:Allow PyPy to deserialize CBOR too.0.6.0Features:validate_cbor(serialized_cbor, True)will deserialize the CBOR document into Python objects, so you don't need to use e.g.cbor2.loads(serialized_cbor)separately.Bug fixes:Release the GIL in a much more useful way.Misc:Upgrade to newercddlcrate (0.9.4).0.5.3Upgrade to newercddlcrate (0.9.3).Add Python 3.12 support.0.5.2Upgrade to newercddlcrate (0.9.2), improving validation functionality.0.5.1Upgrade to newercddlcrate, fixing some validation bugs.0.5.0Support for ARM macOS.Dropped Python 3.7 support.0.4.1Test fixes, with no user-relevant changes.0.4.0validate_cbor()now accepts read-only buffers, not justbytes. This is useful if you want to e.g. validate a large file, since you canmmap()it.The GIL is released when parsing documents larger than 10KiB.0.3.0Fixed major bug where if the document was valid UTF-8, the library would attempt to parse it as JSON!Added support for ARM macOS.0.2.2Updated tocddl0.9.1.0.2.1Added PyPy wheels.0.2.0Schemas are now only parsed once (when theSchema()object is created), instead of every time validation happens, which should improve validation performance.Updated to a newer version ofunderlying CDDL library, which should make CDDL parsing more compliant.Added arepr()implementation toSchemafor easier debugging.0.1.11Initial release.