From 8aafbf8b8c84b3267cec6df2aa9545870e249211 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Fri, 17 Aug 2018 17:57:27 -0400 Subject: [PATCH] Switch the registry data model types to our own class constructor This allows us to hide the DB ID from external-to-the-package users of the types and will allow us to add model-level caching as well --- data/registry_model/datatypes.py | 38 ++++++++++++++----- data/registry_model/registry_pre_oci_model.py | 12 +++--- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/data/registry_model/datatypes.py b/data/registry_model/datatypes.py index 4cf2a0015..8a65f4ec8 100644 --- a/data/registry_model/datatypes.py +++ b/data/registry_model/datatypes.py @@ -1,33 +1,51 @@ -from collections import namedtuple +def datatype(name, static_fields): + """ Defines a base class for a datatype that will represent a row from the database, + in an abstracted form. + """ + class DataType(object): + __name__ = name -class RepositoryReference(object): + def __init__(self, *args, **kwargs): + self._db_id = kwargs.pop('db_id', None) + self._fields = kwargs + + for name in static_fields: + assert name in self._fields, 'Missing field %s' % name + + def __getattr__(self, name): + if name in static_fields: + return self._fields[name] + + return None + + return DataType + + +class RepositoryReference(datatype('Repository', [])): """ RepositoryReference is a reference to a repository, passed to registry interface methods. """ - def __init__(self, repo_id): - self.repo_id = repo_id - @classmethod def for_repo_obj(cls, repo_obj): if repo_obj is None: return None - return RepositoryReference(repo_obj.id) + return RepositoryReference(db_id=repo_obj.id) -class Tag(namedtuple('Tag', ['id', 'name'])): +class Tag(datatype('Tag', ['name'])): """ Tag represents a tag in a repository, which points to a manifest or image. """ @classmethod def for_repository_tag(cls, repository_tag): if repository_tag is None: return None - return Tag(id=repository_tag.id, name=repository_tag.name) + return Tag(db_id=repository_tag.id, name=repository_tag.name) -class Manifest(namedtuple('Manifest', ['id', 'digest'])): +class Manifest(datatype('Manifest', ['digest'])): """ Manifest represents a manifest in a repository. """ @classmethod def for_tag_manifest(cls, tag_manifest): if tag_manifest is None: return None - return Manifest(id=tag_manifest.id, digest=tag_manifest.digest) + return Manifest(db_id=tag_manifest.id, digest=tag_manifest.digest) diff --git a/data/registry_model/registry_pre_oci_model.py b/data/registry_model/registry_pre_oci_model.py index 69443ec71..0249955cb 100644 --- a/data/registry_model/registry_pre_oci_model.py +++ b/data/registry_model/registry_pre_oci_model.py @@ -1,3 +1,5 @@ +# pylint: disable=protected-access + from data import database from data import model from data.registry_model.interface import RegistryDataInterface @@ -14,14 +16,14 @@ class PreOCIModel(RegistryDataInterface): """ Finds an alive tag in the repository matching one of the given tag names and returns it or None if none. """ - found_tag = model.tag.find_matching_tag(repository_ref.repo_id, tag_names) + found_tag = model.tag.find_matching_tag(repository_ref._db_id, tag_names) return Tag.for_repository_tag(found_tag) def get_most_recent_tag(self, repository_ref): """ Returns the most recently pushed alive tag in the repository, if any. If none, returns None. """ - found_tag = model.tag.get_most_recent_tag(repository_ref.repo_id) + found_tag = model.tag.get_most_recent_tag(repository_ref._db_id) return Tag.for_repository_tag(found_tag) def lookup_repository(self, namespace_name, repo_name, kind_filter=None): @@ -33,7 +35,7 @@ class PreOCIModel(RegistryDataInterface): def get_manifest_for_tag(self, tag): """ Returns the manifest associated with the given tag. """ try: - tag_manifest = database.TagManifest.get(tag_id=tag.id) + tag_manifest = database.TagManifest.get(tag_id=tag._db_id) except database.TagManifest.DoesNotExist: return @@ -42,7 +44,7 @@ class PreOCIModel(RegistryDataInterface): def lookup_manifest_by_digest(self, repository_ref, manifest_digest, allow_dead=False): """ Looks up the manifest with the given digest under the given repository and returns it or None if none. """ - repo = model.repository.lookup_repository(repository_ref.repo_id) + repo = model.repository.lookup_repository(repository_ref._db_id) if repo is None: return None @@ -54,7 +56,7 @@ class PreOCIModel(RegistryDataInterface): def create_manifest_label(self, manifest, key, value, source_type_name, media_type_name=None): """ Creates a label on the manifest with the given key and value. """ try: - tag_manifest = database.TagManifest.get(id=manifest.id) + tag_manifest = database.TagManifest.get(id=manifest._db_id) except database.TagManifest.DoesNotExist: return