diff --git a/swh/graphql/resolvers/person.py b/swh/graphql/resolvers/person.py --- a/swh/graphql/resolvers/person.py +++ b/swh/graphql/resolvers/person.py @@ -2,3 +2,73 @@ # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information + +from typing import List + +from .base_connection import BaseList +from .base_node import BaseNode +from .release import BaseReleaseNode +from .revision import BaseRevisionNode + + +class Person(BaseNode): + pass + + +def get_person_list(person) -> List[Person]: + return [person] if person else [] + + +class RevisionAuthorList(BaseList): + """ + List of revision authors + """ + + obj: BaseRevisionNode + + _node_class = Person + + def _get_results(self) -> List[Person]: + """ + Author is a single object in the current data model, + return it as a list to support future evolutions + + No backend fetching required as the data exists in + the parent object (revision) + """ + + return get_person_list(self.obj.author) + + +class RevisionCommitterList(BaseList): + obj: BaseRevisionNode + + _node_class = Person + + def _get_results(self) -> List[Person]: + """ + Committer is a single object in the current data model, + return it as a list to support future evolutions + + No backend fetching required as the data exists in + the parent object (revision) + """ + + return get_person_list(self.obj.committer) + + +class ReleaseAuthorList(BaseList): + obj: BaseReleaseNode + + _node_class = Person + + def _get_results(self) -> List[Person]: + """ + Author is a single object in the current data model, + return it as a list to support future evolutions + + No backend fetching required as the data exists in + the parent object (release) + """ + + return get_person_list(self.obj.author) diff --git a/swh/graphql/resolvers/resolver_factory.py b/swh/graphql/resolvers/resolver_factory.py --- a/swh/graphql/resolvers/resolver_factory.py +++ b/swh/graphql/resolvers/resolver_factory.py @@ -13,6 +13,7 @@ from .directory import DirectoryNode, RevisionDirectoryNode, TargetDirectoryNode from .directory_entry import DirectoryEntryConnection, DirectoryEntryNode from .origin import OriginConnection, OriginNode, TargetOriginNode +from .person import ReleaseAuthorList, RevisionAuthorList, RevisionCommitterList from .release import ReleaseNode, TargetReleaseNode from .revision import ( LogRevisionConnection, @@ -105,6 +106,9 @@ class SimpleListFactory: mapping: ClassVar[Dict[str, Type[BaseList]]] = { "resolve-swhid": ResolveSwhidList, + "revision-author": RevisionAuthorList, + "revision-committer": RevisionCommitterList, + "release-author": ReleaseAuthorList, } @classmethod diff --git a/swh/graphql/resolvers/resolvers.py b/swh/graphql/resolvers/resolvers.py --- a/swh/graphql/resolvers/resolvers.py +++ b/swh/graphql/resolvers/resolvers.py @@ -286,6 +286,27 @@ return SimpleListFactory.create("resolve-swhid", obj, info, **kw) +@revision.field("author") +def revision_author_resolver( + obj: None, info: GraphQLResolveInfo, **kw +) -> rs.revision.RevisionNode: + return SimpleListFactory.create("revision-author", obj, info, **kw) + + +@revision.field("committer") +def revision_committer_resolver( + obj: None, info: GraphQLResolveInfo, **kw +) -> rs.revision.RevisionNode: + return SimpleListFactory.create("revision-committer", obj, info, **kw) + + +@release.field("author") +def release_author_resolver( + obj: rs.release.BaseReleaseNode, info: GraphQLResolveInfo, **kw +) -> rs.revision.RevisionNode: + return SimpleListFactory.create("release-author", obj, info, **kw) + + # Other resolvers diff --git a/swh/graphql/schema/schema.graphql b/swh/graphql/schema/schema.graphql --- a/swh/graphql/schema/schema.graphql +++ b/swh/graphql/schema/schema.graphql @@ -605,14 +605,14 @@ message: BinaryString """ - Revision author + Revision authors """ - author: Person + author: [Person] """ - Revision committer + Revision committers """ - committer: Person + committer: [Person] """ Commit date @@ -708,7 +708,7 @@ """ Release author """ - author: Person + author: [Person] """ Release date diff --git a/swh/graphql/tests/functional/test_release_node.py b/swh/graphql/tests/functional/test_release_node.py --- a/swh/graphql/tests/functional/test_release_node.py +++ b/swh/graphql/tests/functional/test_release_node.py @@ -63,13 +63,15 @@ "base64": base64.b64encode(release.name).decode("ascii"), }, "message": {"text": release.message.decode()}, - "author": { - "email": {"text": release.author.email.decode()}, - "name": {"text": release.author.name.decode()}, - "fullname": {"text": release.author.fullname.decode()}, - } + "author": [ + { + "email": {"text": release.author.email.decode()}, + "name": {"text": release.author.name.decode()}, + "fullname": {"text": release.author.fullname.decode()}, + } + ] if release.author - else None, + else [], "date": { "date": release.date.to_datetime().isoformat(), "offset": { diff --git a/swh/graphql/tests/functional/test_revision.py b/swh/graphql/tests/functional/test_revision.py --- a/swh/graphql/tests/functional/test_revision.py +++ b/swh/graphql/tests/functional/test_revision.py @@ -74,16 +74,20 @@ assert data["revision"] == { "swhid": str(revision.swhid()), "message": {"text": revision.message.decode()}, - "author": { - "fullname": {"text": revision.author.fullname.decode()}, - "name": {"text": revision.author.name.decode()}, - "email": {"text": revision.author.email.decode()}, - }, - "committer": { - "fullname": {"text": revision.committer.fullname.decode()}, - "name": {"text": revision.committer.name.decode()}, - "email": {"text": revision.committer.email.decode()}, - }, + "author": [ + { + "fullname": {"text": revision.author.fullname.decode()}, + "name": {"text": revision.author.name.decode()}, + "email": {"text": revision.author.email.decode()}, + } + ], + "committer": [ + { + "fullname": {"text": revision.committer.fullname.decode()}, + "name": {"text": revision.committer.name.decode()}, + "email": {"text": revision.committer.email.decode()}, + } + ], "date": { "date": revision.date.to_datetime().isoformat(), "offset": {