Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move metadata class model de/serialization to sub-package #1279

Merged
merged 18 commits into from
Mar 10, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions tuf/api/serialization/json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""TUF role metadata JSON serialization and deserialization.
joshuagl marked this conversation as resolved.
Show resolved Hide resolved

This module provides concrete implementations to serialize and deserialize TUF
role metadata to and from the JSON wireline format for transportation, and
to serialize the 'signed' part of TUF role metadata to the OLPC Canonical JSON
format for signature generation and verification.

"""
import json

from securesystemslib.formats import encode_canonical

from tuf.api.metadata import Metadata, Signed
from tuf.api.serialization import (MetadataSerializer,
MetadataDeserializer,
SignedSerializer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: the recently adopted style guide recommends against importing individual classes or functions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know. I guess I just kept using the convention that we already used in this file, which we started before fully embracing our new style guide... and because PEP 8 says it's okay.

Copy link
Collaborator

@MVrachev MVrachev Mar 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Joshua on this one.
We don't have a linter that would automatically catch those mistakes, but it's important we correct each other.
Also, it seems logical to forbid importing of functions and classes.
This way we prevent future problems with naming and namespaces.



class JSONDeserializer(MetadataDeserializer):
"""Provides JSON-to-Metadata deserialize method. """

def deserialize(self, raw_data: bytes) -> Metadata:
"""Deserialize utf-8 encoded JSON bytes into Metadata object. """
_dict = json.loads(raw_data.decode("utf-8"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could we rename this variable, rather than using the _ trick? Maybe json_dict, json_object (as the return type of json.loads is a Python object), or loaded_json.

return Metadata.from_dict(_dict)


class JSONSerializer(MetadataSerializer):
"""A Metadata-to-JSON serialize method.

Attributes:
compact: A boolean indicating if the JSON bytes generated in
'serialize' should be compact by excluding whitespace.

"""
def __init__(self, compact: bool = False) -> None:
self.compact = compact

def serialize(self, metadata_obj: Metadata) -> bytes:
"""Serialize Metadata object into utf-8 encoded JSON bytes. """
indent = (None if self.compact else 1)
joshuagl marked this conversation as resolved.
Show resolved Hide resolved
separators=((',', ':') if self.compact else (',', ': '))
return json.dumps(metadata_obj.to_dict(),
indent=indent,
separators=separators,
sort_keys=True).encode("utf-8")


class CanonicalJSONSerializer(SignedSerializer):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it is worth clarifying, via the class name, that this is the OLPC canonical JSON?
You mention it in the header above, but as we have had several adopters surprised that our Canonical JSON isn't compatible with go-tuf's Canonical JSON, I wonder whether it is worth being very explicit?

Counter-argument, I do not like OLPCCanonicalJSONSerializer as a class name...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with both arguments. :D

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another way to avoid ambiguity would be to not call it CanonicalJSONSerializer at all, but something like DefaultSignedSerializer or so? Then people are forced to read the docstring to get more info. At any rate, I will mention OLPC in the class and function docstrings.

"""A Signed-to-Canonical JSON 'serialize' method. """

def serialize(self, signed_obj: Signed) -> bytes:
"""Serialize Signed object into utf-8 encoded Canonical JSON bytes. """
signed_dict = signed_obj.to_dict()
return encode_canonical(signed_dict).encode("utf-8")