refactoring equals for api objects

adding access to repository files (non-gitea objects in general) requires a more granular comparison of api objects than the old hope that there is an id approach
pull/10/head
Langenfeld 2021-11-11 10:18:23 +01:00
rodzic a0d1b6f80a
commit 53410b79e7
5 zmienionych plików z 78 dodań i 43 usunięć

Wyświetl plik

@ -1,24 +1,22 @@
from .exceptions import ObjectIsInvalid
from .exceptions import ObjectIsInvalid, MissiongEqualyImplementation
class BasicGiteaApiObject:
GET_API_OBJECT = "FORMAT/STINING/{argument}"
PATCH_API_OBJECT = "FORMAT/STINING/{argument}"
def __init__(self, gitea, id):
self.__id = id
def __init__(self, gitea):
self.gitea = gitea
self.deleted = False # set if .delete was called, so that an exception is risen
self.dirty_fields = set()
def __eq__(self, other):
return other.id == self.id if isinstance(other, type(self)) else False
def __str__(self):
return "GiteaAPIObject (%s) id: %s" % (type(self), self.id)
return "GiteaAPIObject (%s):" % (type(self))
def __eq__(self, other):
"""Compare only fields that are part of the gitea-data"""
raise MissiongEqualyImplementation()
def __hash__(self):
return self.id
fields_to_parsers = {}
@ -30,12 +28,8 @@ class BasicGiteaApiObject:
@classmethod
def parse_response(cls, gitea, result) -> "BasicGiteaApiObject":
if "id" in result:
id = int(result["id"])
else:
id = hash(result.items)
# gitea.logger.debug("Found api object of type %s (id: %s)" % (type(cls), id))
api_object = cls(gitea, id=id)
api_object = cls(gitea)
cls._initialize(gitea, api_object, result)
return api_object
@ -56,7 +50,7 @@ class BasicGiteaApiObject:
cls._add_property(name, value, api_object)
else:
cls._add_readonly_property(name,value,api_object)
# add all patchable fields to be watched if changed
# add all patchable fields missing in the request to be writable
for name in cls.patchable_fields:
if not hasattr(api_object,name):
cls._add_property(name, None, api_object)

Wyświetl plik

@ -12,3 +12,10 @@ class ObjectIsInvalid(Exception):
class ConflictException(Exception):
pass
class MissiongEqualyImplementation(Exception):
"""
Each Object obtained from the gitea api must be able to check itself for equality in relation to its
fields obtained from gitea. Risen if an api object is lacking the proper implementation.
"""
pass

Wyświetl plik

@ -24,8 +24,12 @@ class Organization(GiteaApiObject):
ORG_DELETE = """/orgs/%s""" # <org>
ORG_HEATMAP = """/users/%s/heatmap""" # <username>
def __init__(self, gitea, id: int):
super(Organization, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Organization, self).__init__(gitea)
def __eq__(self, other):
if not isinstance(other, Organization): return False
return self.gitea == other.gitea and self.name == other.name
@classmethod
def request(cls, gitea, name):
@ -118,10 +122,14 @@ class User(GiteaApiObject):
ADMIN_EDIT_USER = """/admin/users/{username}""" # <username>
USER_HEATMAP = """/users/%s/heatmap""" # <username>
def __init__(self, gitea, id: int):
super(User, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(User, self).__init__(gitea)
self._emails = []
def __eq__(self, other):
if not isinstance(other, User): return False
return self.gitea == other.gitea and self.id == other.id
@property
def emails(self):
self.__request_emails()
@ -212,8 +220,12 @@ class User(GiteaApiObject):
class Branch(GiteaApiObject):
GET_API_OBJECT = """/repos/%s/%s/branches/%s""" # <owner>, <repo>, <ref>
def __init__(self, gitea, id: int):
super(Branch, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Branch, self).__init__(gitea)
def __eq__(self, other):
if not isinstance(other, Branch): return False
return self.gitea == other.gitea and self.repo == other.repo and self.name == other.name
fields_to_parsers = {
"commit": lambda gitea, c: Commit.parse_response(gitea, c)
@ -239,8 +251,12 @@ class Repository(GiteaApiObject):
REPO_TRANSFER = "/repos/{owner}/{repo}/transfer"
REPO_CONTENTS = "/repos/{owner}/{repo}/contents"
def __init__(self, gitea, id: int):
super(Repository, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Repository, self).__init__(gitea)
def __eq__(self, other):
if not isinstance(other, Repository): return False
return self.gitea == other.gitea and self.owner == other.owner and self.name == other.name
fields_to_parsers = {
# dont know how to tell apart user and org as owner except form email being empty.
@ -430,11 +446,15 @@ class Repository(GiteaApiObject):
class Milestone(GiteaApiObject):
GET_API_OBJECT = (
"""/repos/{owner}/{repo}/milestones/{number}""" # <owner, repo, id>
"""/repos/{owner}/{repo}/milestones/{number}""" # <owner, repo>
)
def __init__(self, gitea, id: int):
super(Milestone, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Milestone, self).__init__(gitea)
def __eq__(self, other):
if not isinstance(other, Milestone): return False
return self.gitea == other.gitea and self.repo == other.repo and self.id == other.id
fields_to_parsers = {
"closed_at": lambda gitea, t: Util.convert_time(t),
@ -466,8 +486,12 @@ class Milestone(GiteaApiObject):
class Comment(BasicGiteaApiObject):
PATCH_API_OBJECT = "/repos/{owner}/{repo}/issues/comments/{id}"
def __init__(self, gitea, id: int):
super(Comment, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Comment, self).__init__(gitea)
def __eq__(self, other):
if not isinstance(other, Comment): return False
return self.gitea == other.gitea and self.repo == other.repo and self.id == other.id
fields_to_parsers = {
"user": lambda gitea, r: User.parse_response(gitea, r),
@ -479,14 +503,18 @@ class Comment(BasicGiteaApiObject):
class Commit(GiteaApiObject):
def __init__(self, gitea, id: int):
super(Commit, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Commit, self).__init__(gitea)
fields_to_parsers = {
# NOTE: do not try to parse gitea-users from git-committers/authors, as
# they are not necessarily users of gitea as well
}
def __eq__(self, other):
if not isinstance(other, Commit): return False
return self.gitea == other.gitea and self.repo == other.repo and self.ref == other.ref
@classmethod
def request(cls, gitea, owner, repo):
api_object = cls._request(gitea, {"owner": owner, "repo": repo})
@ -494,9 +522,7 @@ class Commit(GiteaApiObject):
@classmethod
def parse_response(cls, gitea, result):
id = result["id"] #``sha`` is now called ``id``
# gitea.logger.debug("Found api object of type %s (id: %s)" % (type(cls), id))
api_object = cls(gitea, id=id)
api_object = cls(gitea)
cls._initialize(gitea, api_object, result)
return api_object
@ -510,8 +536,12 @@ class Issue(GiteaApiObject):
OPENED = "open"
CLOSED = "closed"
def __init__(self, gitea, id: int):
super(Issue, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Issue, self).__init__(gitea)
def __eq__(self, other):
if not isinstance(other, Issue): return False
return self.gitea == other.gitea and self.repo == other.repo and self.id == other.id
fields_to_parsers = {
"milestone": lambda gitea, m: Milestone.parse_response(gitea, m),
@ -593,8 +623,12 @@ class Team(GiteaApiObject):
GET_MEMBERS = """/teams/%s/members""" # <id>
GET_REPOS = """/teams/%s/repos""" # <id>
def __init__(self, gitea, id: int):
super(Team, self).__init__(gitea, id=id)
def __init__(self, gitea):
super(Team, self).__init__(gitea)
def __eq__(self, other):
if not isinstance(other, Team): return False
return self.gitea == other.gitea and self.organization == other.organization and self.id == other.id
fields_to_parsers = {
"organization": lambda gitea, o: Organization.parse_response(gitea, o)

Wyświetl plik

@ -2,17 +2,17 @@ from .basicGiteaApiObject import BasicGiteaApiObject
class GiteaApiObject(BasicGiteaApiObject):
GET_API_OBJECT = "FORMAT/STINING/{argument}"
PATCH_API_OBJECT = "FORMAT/STINING/{argument}"
GET_API_OBJECT = "FORMAT/STRING/{argument}"
PATCH_API_OBJECT = "FORMAT/STRING/{argument}"
def __init__(self, gitea, id):
super(GiteaApiObject, self).__init__(gitea, id)
def __init__(self, gitea):
super(GiteaApiObject, self).__init__(gitea)
@classmethod
def request(cls, gitea, id):
"""Use for giving a nice e.g. 'request(gita, orgname, repo, ticket)'.
All args are put into an args tuple for passing around"""
return cls._request(gitea, {"id": id})
return cls._request(gitea)
@classmethod
def _request(cls, gitea, args):

Wyświetl plik

@ -79,7 +79,7 @@ def test_change_user(instance):
def test_create_org(instance):
user = instance.get_user()
org = instance.create_org(user, test_org, "some-desc", "loc")
assert org.get_members() == [user]
assert org.get_members()[0] == user
assert org.description == "some-desc"
assert org.username == test_org
assert org.location == "loc"