python-tuf/tuf/api/serialization/__init__.py

59 lines
1.8 KiB
Python
Raw Permalink Normal View History

# Copyright New York University and the TUF contributors
# SPDX-License-Identifier: MIT OR Apache-2.0
"""``tuf.api.serialization`` module provides abstract base classes and concrete
implementations to serialize and deserialize TUF metadata.
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
Any custom de/serialization implementations should inherit from the abstract
base classes defined in this module. The implementations can use the
``to_dict()``/``from_dict()`` implementations available in the Metadata
API objects.
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
- Metadata de/serializers are used to convert to and from wireline formats.
- Signed serializers are used to canonicalize data for cryptographic signatures
generation and verification.
"""
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
import abc
from typing import TYPE_CHECKING
from tuf.api.exceptions import RepositoryError
if TYPE_CHECKING:
from tuf.api.metadata import Metadata, Signed
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
class SerializationError(RepositoryError):
"""Error during serialization."""
class DeserializationError(RepositoryError):
"""Error during deserialization."""
class MetadataDeserializer(metaclass=abc.ABCMeta):
"""Abstract base class for deserialization of Metadata objects."""
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
@abc.abstractmethod
def deserialize(self, raw_data: bytes) -> "Metadata":
"""Deserialize bytes to Metadata object."""
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
raise NotImplementedError
class MetadataSerializer(metaclass=abc.ABCMeta):
"""Abstract base class for serialization of Metadata objects."""
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
@abc.abstractmethod
def serialize(self, metadata_obj: "Metadata") -> bytes:
"""Serialize Metadata object to bytes."""
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
raise NotImplementedError
class SignedSerializer(metaclass=abc.ABCMeta):
"""Abstract base class for serialization of Signed objects."""
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
@abc.abstractmethod
def serialize(self, signed_obj: "Signed") -> bytes:
"""Serialize Signed object to bytes."""
Add metadata serialization sub-package Add sub-package with 3 abstract base classes to: - serialize Metadata objects to bytes (transport) - deserialize Metadata objects from bytes (transport) - serialize Signed objects to bytes (signatures) pylint notes: - configure tox to use api/pylintrc - configure api/pylintrc to allow classes without public methods (default was 2) Design considerations --------------------- - Why not implement de/serialization on metadata classes? -> See ADR0006. - Why use separate classes for serialization and deserialization? -> Some users might only need either one, e.g. client only needs Deserializer. Maybe there are use cases where different implementations are used to serialize and deserialize. - Why use separate classes for Metadata- and Signed-Serialization? -> They require different concrete types, i.e. Metadata and Signed as parameters, and using these specific types seems to make the interface stronger. - Why are de/serialize methods not class/staticmethods? -> In reality we only use classes to namespace and define a type annotated interface, thus it would be enough to make the methods classmethods. However, to keep the de/serialize interface minimal, we move any custom format configuration to the constructor. (See e.g. "compact" for JSONSerializer in subsequent commit). Naming considerations --------------------- - Why de/serialize? -> Implies byte stream as input or output to the function, which is what our interface needs. - Why not marshaling? -> Synonym for serialize but implies transport, would be okay. - Why not encoding? -> Too abstract and too many connotations (character, a/v). - Why not parse? -> Too abstract and no good opposite terms (unparse, write, dump?) Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-02-08 16:15:27 +00:00
raise NotImplementedError