kopia lustrzana https://github.com/Langenfeld/py-gitea
(style) reformatted with python black for easier merges
rodzic
3b8f04e31b
commit
9f6785cdee
10
README.md
10
README.md
|
@ -41,10 +41,11 @@ other_user = User.request(gitea, "OtherUserName")
|
||||||
print(other_user.username)
|
print(other_user.username)
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the fields of the User, Organization,... classes are dynamically created at runtime, and thus not visible during divelopment. Refer to the Gitea-API documentation for the fields names.
|
Note that the fields of the User, Organization,... classes are dynamically created at runtime, and thus not visible
|
||||||
|
during divelopment. Refer to the Gitea-API documentation for the fields names.
|
||||||
|
|
||||||
|
Fields that can not be altered via gitea-api, are read only. After altering a field, the `.commit` method of the
|
||||||
Fields that can not be altered via gitea-api, are read only. After altering a field, the `.commit` method of the according object must be called to synchronize the changed fields with your gitea instance.
|
according object must be called to synchronize the changed fields with your gitea instance.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
org = Organization.request(gitea, test_org)
|
org = Organization.request(gitea, test_org)
|
||||||
|
@ -54,11 +55,13 @@ org.commit()
|
||||||
```
|
```
|
||||||
|
|
||||||
An entity in gitea can be deleted by calling delete.
|
An entity in gitea can be deleted by calling delete.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
org.delete()
|
org.delete()
|
||||||
```
|
```
|
||||||
|
|
||||||
All entity objects do have methods to execute some of the requests possible though the gitea-api:
|
All entity objects do have methods to execute some of the requests possible though the gitea-api:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
org = Organization.request(gitea, ORGNAME)
|
org = Organization.request(gitea, ORGNAME)
|
||||||
teams = org.get_teams()
|
teams = org.get_teams()
|
||||||
|
@ -68,7 +71,6 @@ for team in teams:
|
||||||
print(repo.name)
|
print(repo.name)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Use ``pip install py-gitea`` to install.
|
Use ``pip install py-gitea`` to install.
|
||||||
|
|
|
@ -15,21 +15,21 @@ from .apiobject import (
|
||||||
Milestone,
|
Milestone,
|
||||||
Commit,
|
Commit,
|
||||||
Comment,
|
Comment,
|
||||||
Content
|
Content,
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'Gitea',
|
"Gitea",
|
||||||
'User',
|
"User",
|
||||||
'Organization',
|
"Organization",
|
||||||
'Team',
|
"Team",
|
||||||
'Repository',
|
"Repository",
|
||||||
'Branch',
|
"Branch",
|
||||||
'NotFoundException',
|
"NotFoundException",
|
||||||
'AlreadyExistsException',
|
"AlreadyExistsException",
|
||||||
'Issue',
|
"Issue",
|
||||||
'Milestone',
|
"Milestone",
|
||||||
'Commit',
|
"Commit",
|
||||||
'Comment',
|
"Comment",
|
||||||
'Content'
|
"Content",
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,18 +21,19 @@ class Organization(ApiObject):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Organization): return False
|
if not isinstance(other, Organization):
|
||||||
|
return False
|
||||||
return self.gitea == other.gitea and self.name == other.name
|
return self.gitea == other.gitea and self.name == other.name
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.gitea) ^ hash(self.name)
|
return hash(self.gitea) ^ hash(self.name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request(cls, gitea: 'Gitea', name: str) -> 'Organization':
|
def request(cls, gitea: "Gitea", name: str) -> "Organization":
|
||||||
return cls._request(gitea, {"name": name})
|
return cls._request(gitea, {"name": name})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_response(cls, gitea, result) -> 'Organization':
|
def parse_response(cls, gitea, result) -> "Organization":
|
||||||
api_object = super().parse_response(gitea, result)
|
api_object = super().parse_response(gitea, result)
|
||||||
# add "name" field to make this behave similar to users for gitea < 1.18
|
# add "name" field to make this behave similar to users for gitea < 1.18
|
||||||
# also necessary for repository-owner when org is repo owner
|
# also necessary for repository-owner when org is repo owner
|
||||||
|
@ -40,14 +41,18 @@ class Organization(ApiObject):
|
||||||
Organization._add_read_property("name", result["username"], api_object)
|
Organization._add_read_property("name", result["username"], api_object)
|
||||||
return api_object
|
return api_object
|
||||||
|
|
||||||
_patchable_fields = {"description", "full_name", "location", "visibility", "website"}
|
_patchable_fields = {
|
||||||
|
"description",
|
||||||
|
"full_name",
|
||||||
|
"location",
|
||||||
|
"visibility",
|
||||||
|
"website",
|
||||||
|
}
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
values = self.get_dirty_fields()
|
values = self.get_dirty_fields()
|
||||||
args = {"name": self.name}
|
args = {"name": self.name}
|
||||||
self.gitea.requests_patch(
|
self.gitea.requests_patch(Organization.API_OBJECT.format(**args), data=values)
|
||||||
Organization.API_OBJECT.format(**args), data=values
|
|
||||||
)
|
|
||||||
self.dirty_fields = {}
|
self.dirty_fields = {}
|
||||||
|
|
||||||
def create_repo(
|
def create_repo(
|
||||||
|
@ -83,7 +88,9 @@ class Organization(ApiObject):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if "id" in result:
|
if "id" in result:
|
||||||
self.gitea.logger.info("Successfully created Repository %s " % result["name"])
|
self.gitea.logger.info(
|
||||||
|
"Successfully created Repository %s " % result["name"]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.gitea.logger.error(result["message"])
|
self.gitea.logger.error(result["message"])
|
||||||
raise Exception("Repository not created... (gitea: %s)" % result["message"])
|
raise Exception("Repository not created... (gitea: %s)" % result["message"])
|
||||||
|
@ -108,7 +115,8 @@ class Organization(ApiObject):
|
||||||
)
|
)
|
||||||
teams = [Team.parse_response(self.gitea, result) for result in results]
|
teams = [Team.parse_response(self.gitea, result) for result in results]
|
||||||
# organisation seems to be missing using this request, so we add org manually
|
# organisation seems to be missing using this request, so we add org manually
|
||||||
for t in teams: setattr(t, "_organization", self)
|
for t in teams:
|
||||||
|
setattr(t, "_organization", self)
|
||||||
return teams
|
return teams
|
||||||
|
|
||||||
def get_team(self, name) -> "Team":
|
def get_team(self, name) -> "Team":
|
||||||
|
@ -167,7 +175,8 @@ class User(ApiObject):
|
||||||
self._emails = []
|
self._emails = []
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, User): return False
|
if not isinstance(other, User):
|
||||||
|
return False
|
||||||
return self.gitea == other.gitea and self.id == other.id
|
return self.gitea == other.gitea and self.id == other.id
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
|
@ -179,7 +188,7 @@ class User(ApiObject):
|
||||||
return self._emails
|
return self._emails
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request(cls, gitea: 'Gitea', name: str) -> "User":
|
def request(cls, gitea: "Gitea", name: str) -> "User":
|
||||||
api_object = cls._request(gitea, {"name": name})
|
api_object = cls._request(gitea, {"name": name})
|
||||||
return api_object
|
return api_object
|
||||||
|
|
||||||
|
@ -249,7 +258,9 @@ class User(ApiObject):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if "id" in result:
|
if "id" in result:
|
||||||
self.gitea.logger.info("Successfully created Repository %s " % result["name"])
|
self.gitea.logger.info(
|
||||||
|
"Successfully created Repository %s " % result["name"]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.gitea.logger.error(result["message"])
|
self.gitea.logger.error(result["message"])
|
||||||
raise Exception("Repository not created... (gitea: %s)" % result["message"])
|
raise Exception("Repository not created... (gitea: %s)" % result["message"])
|
||||||
|
@ -267,12 +278,12 @@ class User(ApiObject):
|
||||||
results = self.gitea.requests_get_paginated(url)
|
results = self.gitea.requests_get_paginated(url)
|
||||||
return [Organization.parse_response(self.gitea, result) for result in results]
|
return [Organization.parse_response(self.gitea, result) for result in results]
|
||||||
|
|
||||||
def get_teams(self) -> List['Team']:
|
def get_teams(self) -> List["Team"]:
|
||||||
url = f"/user/teams"
|
url = f"/user/teams"
|
||||||
results = self.gitea.requests_get_paginated(url, sudo=self)
|
results = self.gitea.requests_get_paginated(url, sudo=self)
|
||||||
return [Team.parse_response(self.gitea, result) for result in results]
|
return [Team.parse_response(self.gitea, result) for result in results]
|
||||||
|
|
||||||
def get_accessible_repos(self) -> List['Repository']:
|
def get_accessible_repos(self) -> List["Repository"]:
|
||||||
"""Get all Repositories accessible by the logged in User."""
|
"""Get all Repositories accessible by the logged in User."""
|
||||||
results = self.gitea.requests_get("/user/repos", sudo=self)
|
results = self.gitea.requests_get("/user/repos", sudo=self)
|
||||||
return [Repository.parse_response(self, result) for result in results]
|
return [Repository.parse_response(self, result) for result in results]
|
||||||
|
@ -300,7 +311,6 @@ class User(ApiObject):
|
||||||
|
|
||||||
|
|
||||||
class Branch(ReadonlyApiObject):
|
class Branch(ReadonlyApiObject):
|
||||||
|
|
||||||
def __init__(self, gitea):
|
def __init__(self, gitea):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
|
@ -318,13 +328,15 @@ class Branch(ReadonlyApiObject):
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request(cls, gitea: 'Gitea', owner: str, repo: str, ref: str):
|
def request(cls, gitea: "Gitea", owner: str, repo: str, ref: str):
|
||||||
return cls._request(gitea, {"owner": owner, "repo": repo, "ref": ref})
|
return cls._request(gitea, {"owner": owner, "repo": repo, "ref": ref})
|
||||||
|
|
||||||
|
|
||||||
class Repository(ApiObject):
|
class Repository(ApiObject):
|
||||||
API_OBJECT = """/repos/{owner}/{name}""" # <owner>, <reponame>
|
API_OBJECT = """/repos/{owner}/{name}""" # <owner>, <reponame>
|
||||||
REPO_IS_COLLABORATOR = """/repos/%s/%s/collaborators/%s""" # <owner>, <reponame>, <username>
|
REPO_IS_COLLABORATOR = (
|
||||||
|
"""/repos/%s/%s/collaborators/%s""" # <owner>, <reponame>, <username>
|
||||||
|
)
|
||||||
REPO_SEARCH = """/repos/search/%s""" # <reponame>
|
REPO_SEARCH = """/repos/search/%s""" # <reponame>
|
||||||
REPO_BRANCHES = """/repos/%s/%s/branches""" # <owner>, <reponame>
|
REPO_BRANCHES = """/repos/%s/%s/branches""" # <owner>, <reponame>
|
||||||
REPO_ISSUES = """/repos/{owner}/{repo}/issues""" # <owner, reponame>
|
REPO_ISSUES = """/repos/{owner}/{repo}/issues""" # <owner, reponame>
|
||||||
|
@ -339,7 +351,8 @@ class Repository(ApiObject):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Repository): return False
|
if not isinstance(other, Repository):
|
||||||
|
return False
|
||||||
return self.owner == other.owner and self.name == other.name
|
return self.owner == other.owner and self.name == other.name
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
|
@ -348,12 +361,13 @@ class Repository(ApiObject):
|
||||||
_fields_to_parsers = {
|
_fields_to_parsers = {
|
||||||
# dont know how to tell apart user and org as owner except form email being empty.
|
# dont know how to tell apart user and org as owner except form email being empty.
|
||||||
"owner": lambda gitea, r: Organization.parse_response(gitea, r)
|
"owner": lambda gitea, r: Organization.parse_response(gitea, r)
|
||||||
if r["email"] == "" else User.parse_response(gitea, r),
|
if r["email"] == ""
|
||||||
|
else User.parse_response(gitea, r),
|
||||||
"updated_at": lambda gitea, t: Util.convert_time(t),
|
"updated_at": lambda gitea, t: Util.convert_time(t),
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request(cls, gitea: 'Gitea', owner: str, name: str):
|
def request(cls, gitea: "Gitea", owner: str, name: str):
|
||||||
return cls._request(gitea, {"owner": owner, "name": name})
|
return cls._request(gitea, {"owner": owner, "name": name})
|
||||||
|
|
||||||
_patchable_fields = {
|
_patchable_fields = {
|
||||||
|
@ -391,7 +405,7 @@ class Repository(ApiObject):
|
||||||
self.gitea.requests_patch(self.API_OBJECT.format(**args), data=values)
|
self.gitea.requests_patch(self.API_OBJECT.format(**args), data=values)
|
||||||
self.dirty_fields = {}
|
self.dirty_fields = {}
|
||||||
|
|
||||||
def get_branches(self) -> List['Branch']:
|
def get_branches(self) -> List["Branch"]:
|
||||||
"""Get all the Branches of this Repository."""
|
"""Get all the Branches of this Repository."""
|
||||||
results = self.gitea.requests_get(
|
results = self.gitea.requests_get(
|
||||||
Repository.REPO_BRANCHES % (self.owner.username, self.name)
|
Repository.REPO_BRANCHES % (self.owner.username, self.name)
|
||||||
|
@ -431,7 +445,8 @@ class Repository(ApiObject):
|
||||||
issues = []
|
issues = []
|
||||||
data = {"state": state}
|
data = {"state": state}
|
||||||
results = self.gitea.requests_get_paginated(
|
results = self.gitea.requests_get_paginated(
|
||||||
Repository.REPO_ISSUES.format(owner=self.owner.username, repo=self.name), params=data
|
Repository.REPO_ISSUES.format(owner=self.owner.username, repo=self.name),
|
||||||
|
params=data,
|
||||||
)
|
)
|
||||||
for result in results:
|
for result in results:
|
||||||
issue = Issue.parse_response(self.gitea, result)
|
issue = Issue.parse_response(self.gitea, result)
|
||||||
|
@ -467,14 +482,20 @@ class Repository(ApiObject):
|
||||||
"title": title,
|
"title": title,
|
||||||
}
|
}
|
||||||
result = self.gitea.requests_post(
|
result = self.gitea.requests_post(
|
||||||
Repository.REPO_ISSUES.format(owner=self.owner.username, repo=self.name), data=data
|
Repository.REPO_ISSUES.format(owner=self.owner.username, repo=self.name),
|
||||||
|
data=data,
|
||||||
)
|
)
|
||||||
return Issue.parse_response(self.gitea, result)
|
return Issue.parse_response(self.gitea, result)
|
||||||
|
|
||||||
def create_milestone(self, title: str, description: str, due_date: str = None, state: str = "open") -> "Milestone":
|
def create_milestone(
|
||||||
url = Repository.REPO_MILESTONES.format(owner=self.owner.username, repo=self.name)
|
self, title: str, description: str, due_date: str = None, state: str = "open"
|
||||||
|
) -> "Milestone":
|
||||||
|
url = Repository.REPO_MILESTONES.format(
|
||||||
|
owner=self.owner.username, repo=self.name
|
||||||
|
)
|
||||||
data = {"title": title, "description": description, "state": state}
|
data = {"title": title, "description": description, "state": state}
|
||||||
if due_date: data["due_date"] = due_date
|
if due_date:
|
||||||
|
data["due_date"] = due_date
|
||||||
result = self.gitea.requests_post(url, data=data)
|
result = self.gitea.requests_post(url, data=data)
|
||||||
return Milestone.parse_response(self.gitea, result)
|
return Milestone.parse_response(self.gitea, result)
|
||||||
|
|
||||||
|
@ -528,11 +549,17 @@ class Repository(ApiObject):
|
||||||
url = f"/repos/{self.owner.username}/{self.name}/collaborators/{user_name}"
|
url = f"/repos/{self.owner.username}/{self.name}/collaborators/{user_name}"
|
||||||
self.gitea.requests_delete(url)
|
self.gitea.requests_delete(url)
|
||||||
|
|
||||||
def transfer_ownership(self, new_owner: Union["User", "Organization"], new_teams: Set["Team"] = frozenset()):
|
def transfer_ownership(
|
||||||
|
self,
|
||||||
|
new_owner: Union["User", "Organization"],
|
||||||
|
new_teams: Set["Team"] = frozenset(),
|
||||||
|
):
|
||||||
url = Repository.REPO_TRANSFER.format(owner=self.owner.username, repo=self.name)
|
url = Repository.REPO_TRANSFER.format(owner=self.owner.username, repo=self.name)
|
||||||
data = {"new_owner": new_owner.username}
|
data = {"new_owner": new_owner.username}
|
||||||
if isinstance(new_owner, Organization):
|
if isinstance(new_owner, Organization):
|
||||||
new_team_ids = [team.id for team in new_teams if team in new_owner.get_teams()]
|
new_team_ids = [
|
||||||
|
team.id for team in new_teams if team in new_owner.get_teams()
|
||||||
|
]
|
||||||
data["team_ids"] = new_team_ids
|
data["team_ids"] = new_team_ids
|
||||||
self.gitea.requests_post(url, data=data)
|
self.gitea.requests_post(url, data=data)
|
||||||
# TODO: make sure this instance is either updated or discarded
|
# TODO: make sure this instance is either updated or discarded
|
||||||
|
@ -541,17 +568,25 @@ class Repository(ApiObject):
|
||||||
"""https://try.gitea.io/api/swagger#/repository/repoGetContentsList"""
|
"""https://try.gitea.io/api/swagger#/repository/repoGetContentsList"""
|
||||||
url = f"/repos/{self.owner.username}/{self.name}/contents"
|
url = f"/repos/{self.owner.username}/{self.name}/contents"
|
||||||
data = {"ref": commit.sha} if commit else {}
|
data = {"ref": commit.sha} if commit else {}
|
||||||
result = [Content.parse_response(self.gitea, f) for f in self.gitea.requests_get(url, data)]
|
result = [
|
||||||
|
Content.parse_response(self.gitea, f)
|
||||||
|
for f in self.gitea.requests_get(url, data)
|
||||||
|
]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_file_content(self, content: "Content", commit: "Commit" = None) -> Union[str, List["Content"]]:
|
def get_file_content(
|
||||||
|
self, content: "Content", commit: "Commit" = None
|
||||||
|
) -> Union[str, List["Content"]]:
|
||||||
"""https://try.gitea.io/api/swagger#/repository/repoGetContents"""
|
"""https://try.gitea.io/api/swagger#/repository/repoGetContents"""
|
||||||
url = f"/repos/{self.owner.username}/{self.name}/contents/{content.path}"
|
url = f"/repos/{self.owner.username}/{self.name}/contents/{content.path}"
|
||||||
data = {"ref": commit.sha} if commit else {}
|
data = {"ref": commit.sha} if commit else {}
|
||||||
if content.type == Content.FILE:
|
if content.type == Content.FILE:
|
||||||
return self.gitea.requests_get(url, data)["content"]
|
return self.gitea.requests_get(url, data)["content"]
|
||||||
else:
|
else:
|
||||||
return [Content.parse_response(self.gitea, f) for f in self.gitea.requests_get(url, data)]
|
return [
|
||||||
|
Content.parse_response(self.gitea, f)
|
||||||
|
for f in self.gitea.requests_get(url, data)
|
||||||
|
]
|
||||||
|
|
||||||
def create_file(self, file_path: str, content: str, data: dict = None):
|
def create_file(self, file_path: str, content: str, data: dict = None):
|
||||||
"""https://try.gitea.io/api/swagger#/repository/repoCreateFile"""
|
"""https://try.gitea.io/api/swagger#/repository/repoCreateFile"""
|
||||||
|
@ -561,7 +596,9 @@ class Repository(ApiObject):
|
||||||
data.update({"content": content})
|
data.update({"content": content})
|
||||||
return self.gitea.requests_post(url, data)
|
return self.gitea.requests_post(url, data)
|
||||||
|
|
||||||
def change_file(self, file_path: str, file_sha: str, content: str, data: dict = None):
|
def change_file(
|
||||||
|
self, file_path: str, file_sha: str, content: str, data: dict = None
|
||||||
|
):
|
||||||
"""https://try.gitea.io/api/swagger#/repository/repoCreateFile"""
|
"""https://try.gitea.io/api/swagger#/repository/repoCreateFile"""
|
||||||
if not data:
|
if not data:
|
||||||
data = {}
|
data = {}
|
||||||
|
@ -583,7 +620,8 @@ class Milestone(ApiObject):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Milestone): return False
|
if not isinstance(other, Milestone):
|
||||||
|
return False
|
||||||
return self.gitea == other.gitea and self.id == other.id
|
return self.gitea == other.gitea and self.id == other.id
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
|
@ -612,17 +650,17 @@ class Milestone(ApiObject):
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request(cls, gitea: 'Gitea', owner: str, repo: str, number: str):
|
def request(cls, gitea: "Gitea", owner: str, repo: str, number: str):
|
||||||
return cls._request(gitea, {"owner": owner, "repo": repo, "number": number})
|
return cls._request(gitea, {"owner": owner, "repo": repo, "number": number})
|
||||||
|
|
||||||
|
|
||||||
class Comment(ApiObject):
|
class Comment(ApiObject):
|
||||||
|
|
||||||
def __init__(self, gitea):
|
def __init__(self, gitea):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Comment): return False
|
if not isinstance(other, Comment):
|
||||||
|
return False
|
||||||
return self.repo == other.repo and self.id == other.id
|
return self.repo == other.repo and self.id == other.id
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
|
@ -636,24 +674,26 @@ class Comment(ApiObject):
|
||||||
|
|
||||||
|
|
||||||
class Commit(ReadonlyApiObject):
|
class Commit(ReadonlyApiObject):
|
||||||
|
|
||||||
def __init__(self, gitea):
|
def __init__(self, gitea):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
_fields_to_parsers = {
|
_fields_to_parsers = {
|
||||||
# NOTE: api may return None for commiters that are no gitea users
|
# NOTE: api may return None for commiters that are no gitea users
|
||||||
"author": lambda gitea, u: User.parse_response(gitea, u) if u else None
|
"author": lambda gitea, u: User.parse_response(gitea, u)
|
||||||
|
if u
|
||||||
|
else None
|
||||||
}
|
}
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Commit): return False
|
if not isinstance(other, Commit):
|
||||||
|
return False
|
||||||
return self.sha == other.sha
|
return self.sha == other.sha
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.sha)
|
return hash(self.sha)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_response(cls, gitea, result) -> 'Commit':
|
def parse_response(cls, gitea, result) -> "Commit":
|
||||||
commit_cache = result["commit"]
|
commit_cache = result["commit"]
|
||||||
api_object = cls(gitea)
|
api_object = cls(gitea)
|
||||||
cls._initialize(gitea, api_object, result)
|
cls._initialize(gitea, api_object, result)
|
||||||
|
@ -675,7 +715,8 @@ class Issue(ApiObject):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Issue): return False
|
if not isinstance(other, Issue):
|
||||||
|
return False
|
||||||
return self.repo == other.repo and self.id == other.id
|
return self.repo == other.repo and self.id == other.id
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
|
@ -688,7 +729,7 @@ class Issue(ApiObject):
|
||||||
"assignees": lambda gitea, us: [User.parse_response(gitea, u) for u in us],
|
"assignees": lambda gitea, us: [User.parse_response(gitea, u) for u in us],
|
||||||
"state": lambda gitea, s: Issue.CLOSED if s == "closed" else Issue.OPENED,
|
"state": lambda gitea, s: Issue.CLOSED if s == "closed" else Issue.OPENED,
|
||||||
# Repository in this request is just a "RepositoryMeta" record, thus request whole object
|
# Repository in this request is just a "RepositoryMeta" record, thus request whole object
|
||||||
"repository": lambda gitea, r: Repository.request(gitea, r["owner"], r["name"])
|
"repository": lambda gitea, r: Repository.request(gitea, r["owner"], r["name"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
_parsers_to_fields = {
|
_parsers_to_fields = {
|
||||||
|
@ -707,13 +748,19 @@ class Issue(ApiObject):
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
values = self.get_dirty_fields()
|
values = self.get_dirty_fields()
|
||||||
args = {"owner": self.repository.owner.username, "repo": self.repository.name, "index": self.number}
|
args = {
|
||||||
|
"owner": self.repository.owner.username,
|
||||||
|
"repo": self.repository.name,
|
||||||
|
"index": self.number,
|
||||||
|
}
|
||||||
self.gitea.requests_patch(Issue.API_OBJECT.format(**args), data=values)
|
self.gitea.requests_patch(Issue.API_OBJECT.format(**args), data=values)
|
||||||
self.dirty_fields = {}
|
self.dirty_fields = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def request(cls, gitea: 'Gitea', owner: str, repo: str, number: str):
|
def request(cls, gitea: "Gitea", owner: str, repo: str, number: str):
|
||||||
api_object = cls._request(gitea, {"owner": owner, "repo": repo, "index": number})
|
api_object = cls._request(
|
||||||
|
gitea, {"owner": owner, "repo": repo, "index": number}
|
||||||
|
)
|
||||||
return api_object
|
return api_object
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -774,7 +821,8 @@ class Team(ApiObject):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Team): return False
|
if not isinstance(other, Team):
|
||||||
|
return False
|
||||||
return self.organization == other.organization and self.id == other.id
|
return self.organization == other.organization and self.id == other.id
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
|
@ -838,8 +886,11 @@ class Content(ReadonlyApiObject):
|
||||||
super().__init__(gitea)
|
super().__init__(gitea)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Team): return False
|
if not isinstance(other, Team):
|
||||||
return self.repo == self.repo and self.sha == other.sha and self.name == other.name
|
return False
|
||||||
|
return (
|
||||||
|
self.repo == self.repo and self.sha == other.sha and self.name == other.name
|
||||||
|
)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.repo) ^ hash(self.sha) ^ hash(self.name)
|
return hash(self.repo) ^ hash(self.sha) ^ hash(self.name)
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
from .exceptions import ObjectIsInvalid, MissiongEqualyImplementation, RawRequestEndpointMissing
|
from .exceptions import (
|
||||||
|
ObjectIsInvalid,
|
||||||
|
MissiongEqualyImplementation,
|
||||||
|
RawRequestEndpointMissing,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ReadonlyApiObject:
|
class ReadonlyApiObject:
|
||||||
|
|
||||||
def __init__(self, gitea):
|
def __init__(self, gitea):
|
||||||
self.gitea = gitea
|
self.gitea = gitea
|
||||||
self.deleted = False # set if .delete was called, so that an exception is risen
|
self.deleted = False # set if .delete was called, so that an exception is risen
|
||||||
|
@ -61,8 +64,7 @@ class ReadonlyApiObject:
|
||||||
def _add_read_property(cls, name, value, api_object):
|
def _add_read_property(cls, name, value, api_object):
|
||||||
if not hasattr(api_object, name):
|
if not hasattr(api_object, name):
|
||||||
setattr(api_object, "_" + name, value)
|
setattr(api_object, "_" + name, value)
|
||||||
prop = property(
|
prop = property((lambda n: lambda self: self._get_var(n))(name))
|
||||||
(lambda n: lambda self: self._get_var(n))(name))
|
|
||||||
setattr(cls, name, prop)
|
setattr(cls, name, prop)
|
||||||
else:
|
else:
|
||||||
raise AttributeError(f"Attribute {name} already exists on api object.")
|
raise AttributeError(f"Attribute {name} already exists on api object.")
|
||||||
|
@ -107,7 +109,8 @@ class ApiObject(ReadonlyApiObject):
|
||||||
setattr(api_object, "_" + name, value)
|
setattr(api_object, "_" + name, value)
|
||||||
prop = property(
|
prop = property(
|
||||||
(lambda n: lambda self: self._get_var(n))(name),
|
(lambda n: lambda self: self._get_var(n))(name),
|
||||||
(lambda n: lambda self, v: self.__set_var(n, v))(name))
|
(lambda n: lambda self, v: self.__set_var(n, v))(name),
|
||||||
|
)
|
||||||
setattr(cls, name, prop)
|
setattr(cls, name, prop)
|
||||||
|
|
||||||
def __set_var(self, name, i):
|
def __set_var(self, name, i):
|
||||||
|
|
|
@ -17,6 +17,7 @@ class ConflictException(Exception):
|
||||||
class RawRequestEndpointMissing(Exception):
|
class RawRequestEndpointMissing(Exception):
|
||||||
"""This ApiObject can only be obtained through other api objects and does not have
|
"""This ApiObject can only be obtained through other api objects and does not have
|
||||||
diret .request method."""
|
diret .request method."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,4 +26,5 @@ class MissiongEqualyImplementation(Exception):
|
||||||
Each Object obtained from the gitea api must be able to check itself for equality in relation to its
|
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.
|
fields obtained from gitea. Risen if an api object is lacking the proper implementation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -12,6 +12,7 @@ from .exceptions import NotFoundException, ConflictException, AlreadyExistsExcep
|
||||||
|
|
||||||
class Gitea:
|
class Gitea:
|
||||||
"""Object to establish a session with Gitea."""
|
"""Object to establish a session with Gitea."""
|
||||||
|
|
||||||
ADMIN_CREATE_USER = """/admin/users"""
|
ADMIN_CREATE_USER = """/admin/users"""
|
||||||
GET_USERS_ADMIN = """/admin/users"""
|
GET_USERS_ADMIN = """/admin/users"""
|
||||||
ADMIN_REPO_CREATE = """/admin/users/%s/repos""" # <ownername>
|
ADMIN_REPO_CREATE = """/admin/users/%s/repos""" # <ownername>
|
||||||
|
@ -21,12 +22,7 @@ class Gitea:
|
||||||
CREATE_TEAM = """/orgs/%s/teams""" # <orgname>
|
CREATE_TEAM = """/orgs/%s/teams""" # <orgname>
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self, gitea_url: str, token_text=None, auth=None, verify=True, log_level="INFO"
|
||||||
gitea_url: str,
|
|
||||||
token_text=None,
|
|
||||||
auth=None,
|
|
||||||
verify=True,
|
|
||||||
log_level="INFO"
|
|
||||||
):
|
):
|
||||||
"""Initializing Gitea-instance
|
"""Initializing Gitea-instance
|
||||||
|
|
||||||
|
@ -60,7 +56,6 @@ class Gitea:
|
||||||
if not verify:
|
if not verify:
|
||||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||||
|
|
||||||
|
|
||||||
def __get_url(self, endpoint):
|
def __get_url(self, endpoint):
|
||||||
url = self.url + "/api/v1" + endpoint
|
url = self.url + "/api/v1" + endpoint
|
||||||
self.logger.debug("Url: %s" % url)
|
self.logger.debug("Url: %s" % url)
|
||||||
|
@ -78,19 +73,25 @@ class Gitea:
|
||||||
combined_params.update(params)
|
combined_params.update(params)
|
||||||
if sudo:
|
if sudo:
|
||||||
combined_params["sudo"] = sudo.username
|
combined_params["sudo"] = sudo.username
|
||||||
request = self.requests.get(self.__get_url(endpoint), headers=self.headers, params=combined_params)
|
request = self.requests.get(
|
||||||
|
self.__get_url(endpoint), headers=self.headers, params=combined_params
|
||||||
|
)
|
||||||
if request.status_code not in [200, 201]:
|
if request.status_code not in [200, 201]:
|
||||||
message = f"Received status code: {request.status_code} ({request.url})"
|
message = f"Received status code: {request.status_code} ({request.url})"
|
||||||
if request.status_code in [404]:
|
if request.status_code in [404]:
|
||||||
raise NotFoundException(message)
|
raise NotFoundException(message)
|
||||||
if request.status_code in [403]:
|
if request.status_code in [403]:
|
||||||
raise Exception(f"Unauthorized: {request.url} - Check your permissions and try again! ({message})")
|
raise Exception(
|
||||||
|
f"Unauthorized: {request.url} - Check your permissions and try again! ({message})"
|
||||||
|
)
|
||||||
if request.status_code in [409]:
|
if request.status_code in [409]:
|
||||||
raise ConflictException(message)
|
raise ConflictException(message)
|
||||||
raise Exception(message)
|
raise Exception(message)
|
||||||
return self.parse_result(request)
|
return self.parse_result(request)
|
||||||
|
|
||||||
def requests_get_paginated(self, endpoint: str, params=frozendict(), sudo=None, page_key: str = "page"):
|
def requests_get_paginated(
|
||||||
|
self, endpoint: str, params=frozendict(), sudo=None, page_key: str = "page"
|
||||||
|
):
|
||||||
page = 1
|
page = 1
|
||||||
combined_params = {}
|
combined_params = {}
|
||||||
combined_params.update(params)
|
combined_params.update(params)
|
||||||
|
@ -106,7 +107,9 @@ class Gitea:
|
||||||
def requests_put(self, endpoint: str, data: dict = None):
|
def requests_put(self, endpoint: str, data: dict = None):
|
||||||
if not data:
|
if not data:
|
||||||
data = {}
|
data = {}
|
||||||
request = self.requests.put(self.__get_url(endpoint), headers=self.headers, data=json.dumps(data))
|
request = self.requests.put(
|
||||||
|
self.__get_url(endpoint), headers=self.headers, data=json.dumps(data)
|
||||||
|
)
|
||||||
if request.status_code not in [200, 204]:
|
if request.status_code not in [200, 204]:
|
||||||
message = f"Received status code: {request.status_code} ({request.url}) {request.text}"
|
message = f"Received status code: {request.status_code} ({request.url}) {request.text}"
|
||||||
self.logger.error(message)
|
self.logger.error(message)
|
||||||
|
@ -120,21 +123,34 @@ class Gitea:
|
||||||
raise Exception(message)
|
raise Exception(message)
|
||||||
|
|
||||||
def requests_post(self, endpoint: str, data: dict):
|
def requests_post(self, endpoint: str, data: dict):
|
||||||
request = self.requests.post(self.__get_url(endpoint), headers=self.headers, data=json.dumps(data))
|
request = self.requests.post(
|
||||||
|
self.__get_url(endpoint), headers=self.headers, data=json.dumps(data)
|
||||||
|
)
|
||||||
if request.status_code not in [200, 201, 202]:
|
if request.status_code not in [200, 201, 202]:
|
||||||
if ("already exists" in request.text or "e-mail already in use" in request.text):
|
if (
|
||||||
|
"already exists" in request.text
|
||||||
|
or "e-mail already in use" in request.text
|
||||||
|
):
|
||||||
self.logger.warning(request.text)
|
self.logger.warning(request.text)
|
||||||
raise AlreadyExistsException()
|
raise AlreadyExistsException()
|
||||||
self.logger.error(f"Received status code: {request.status_code} ({request.url})")
|
self.logger.error(
|
||||||
|
f"Received status code: {request.status_code} ({request.url})"
|
||||||
|
)
|
||||||
self.logger.error(f"With info: {data} ({self.headers})")
|
self.logger.error(f"With info: {data} ({self.headers})")
|
||||||
self.logger.error(f"Answer: {request.text}")
|
self.logger.error(f"Answer: {request.text}")
|
||||||
raise Exception(f"Received status code: {request.status_code} ({request.url}), {request.text}")
|
raise Exception(
|
||||||
|
f"Received status code: {request.status_code} ({request.url}), {request.text}"
|
||||||
|
)
|
||||||
return self.parse_result(request)
|
return self.parse_result(request)
|
||||||
|
|
||||||
def requests_patch(self, endpoint: str, data: dict):
|
def requests_patch(self, endpoint: str, data: dict):
|
||||||
request = self.requests.patch(self.__get_url(endpoint), headers=self.headers, data=json.dumps(data))
|
request = self.requests.patch(
|
||||||
|
self.__get_url(endpoint), headers=self.headers, data=json.dumps(data)
|
||||||
|
)
|
||||||
if request.status_code not in [200, 201]:
|
if request.status_code not in [200, 201]:
|
||||||
error_message = f"Received status code: {request.status_code} ({request.url}) {data}"
|
error_message = (
|
||||||
|
f"Received status code: {request.status_code} ({request.url}) {data}"
|
||||||
|
)
|
||||||
self.logger.error(error_message)
|
self.logger.error(error_message)
|
||||||
raise Exception(error_message)
|
raise Exception(error_message)
|
||||||
return self.parse_result(request)
|
return self.parse_result(request)
|
||||||
|
|
34
setup.py
34
setup.py
|
@ -1,35 +1,31 @@
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
with open('README.md') as readme_file:
|
with open("README.md") as readme_file:
|
||||||
README = readme_file.read()
|
README = readme_file.read()
|
||||||
|
|
||||||
setup_args = dict(
|
setup_args = dict(
|
||||||
name='py-gitea',
|
name="py-gitea",
|
||||||
version='0.2.6',
|
version="0.2.6",
|
||||||
description='A python wrapper for the Gitea API',
|
description="A python wrapper for the Gitea API",
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
long_description=README,
|
long_description=README,
|
||||||
license='MIT',
|
license="MIT",
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
author='Vincent Langenfeld ',
|
author="Vincent Langenfeld ",
|
||||||
author_email='langenfv@tf.uni-freiburg.de',
|
author_email="langenfv@tf.uni-freiburg.de",
|
||||||
keywords=['Gitea','api','wrapper'],
|
keywords=["Gitea", "api", "wrapper"],
|
||||||
url='https://github.com/Langenfeld/py-gitea',
|
url="https://github.com/Langenfeld/py-gitea",
|
||||||
download_url='https://pypi.org/project/py-gitea/'
|
download_url="https://pypi.org/project/py-gitea/",
|
||||||
)
|
)
|
||||||
|
|
||||||
install_requires = [
|
install_requires = [
|
||||||
'requests',
|
"requests",
|
||||||
'frozendict',
|
"frozendict",
|
||||||
]
|
]
|
||||||
|
|
||||||
extras_require = {
|
extras_require = {"test": ["pytest"]}
|
||||||
'test': ['pytest']
|
|
||||||
}
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
setup(
|
setup(
|
||||||
**setup_args,
|
**setup_args, install_requires=install_requires, extras_require=extras_require
|
||||||
install_requires=install_requires,
|
|
||||||
extras_require=extras_require
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import pytest
|
||||||
|
|
||||||
from gitea import Gitea
|
from gitea import Gitea
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def instance(scope="module"):
|
def instance(scope="module"):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -6,6 +6,7 @@ import uuid
|
||||||
from gitea import Gitea, User, Organization, Team, Repository, Issue, Milestone
|
from gitea import Gitea, User, Organization, Team, Repository, Issue, Milestone
|
||||||
from gitea import NotFoundException, AlreadyExistsException
|
from gitea import NotFoundException, AlreadyExistsException
|
||||||
|
|
||||||
|
|
||||||
# put a ".token" file into your directory containg only the token for gitea
|
# put a ".token" file into your directory containg only the token for gitea
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def instance(scope="module"):
|
def instance(scope="module"):
|
||||||
|
@ -22,10 +23,13 @@ def instance(scope="module"):
|
||||||
- Token at .token \
|
- Token at .token \
|
||||||
?"
|
?"
|
||||||
|
|
||||||
|
|
||||||
# make up some fresh names for the tests run
|
# make up some fresh names for the tests run
|
||||||
test_org = "org_" + uuid.uuid4().hex[:8]
|
test_org = "org_" + uuid.uuid4().hex[:8]
|
||||||
test_user = "user_" + uuid.uuid4().hex[:8]
|
test_user = "user_" + uuid.uuid4().hex[:8]
|
||||||
test_team = "team_" + uuid.uuid4().hex[:8] # team names seem to have a rather low max lenght
|
test_team = (
|
||||||
|
"team_" + uuid.uuid4().hex[:8]
|
||||||
|
) # team names seem to have a rather low max lenght
|
||||||
test_repo = "repo_" + uuid.uuid4().hex[:8]
|
test_repo = "repo_" + uuid.uuid4().hex[:8]
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,6 +69,7 @@ def test_create_user(instance):
|
||||||
assert type(user.id) is int
|
assert type(user.id) is int
|
||||||
assert user.is_admin is False
|
assert user.is_admin is False
|
||||||
|
|
||||||
|
|
||||||
def test_change_user(instance):
|
def test_change_user(instance):
|
||||||
user = instance.get_user_by_name(test_user)
|
user = instance.get_user_by_name(test_user)
|
||||||
location = "a house"
|
location = "a house"
|
||||||
|
@ -72,7 +77,7 @@ def test_change_user(instance):
|
||||||
new_fullname = "Other Test Full Name"
|
new_fullname = "Other Test Full Name"
|
||||||
user.full_name = new_fullname
|
user.full_name = new_fullname
|
||||||
user.commit(user.username, 0)
|
user.commit(user.username, 0)
|
||||||
del(user)
|
del user
|
||||||
user = instance.get_user_by_name(test_user)
|
user = instance.get_user_by_name(test_user)
|
||||||
assert user.full_name == new_fullname
|
assert user.full_name == new_fullname
|
||||||
assert user.location == location
|
assert user.location == location
|
||||||
|
@ -153,6 +158,7 @@ def test_list_branches(instance):
|
||||||
master = [b for b in branches if b.name == "master"]
|
master = [b for b in branches if b.name == "master"]
|
||||||
assert len(master) > 0
|
assert len(master) > 0
|
||||||
|
|
||||||
|
|
||||||
def test_list_files_and_content(instance):
|
def test_list_files_and_content(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = org.get_repository(test_repo)
|
repo = org.get_repository(test_repo)
|
||||||
|
@ -165,13 +171,13 @@ def test_list_files_and_content(instance):
|
||||||
assert len(readme_content) > 0
|
assert len(readme_content) > 0
|
||||||
assert "descr" in str(base64.b64decode(readme_content))
|
assert "descr" in str(base64.b64decode(readme_content))
|
||||||
|
|
||||||
|
|
||||||
def test_create_file(instance):
|
def test_create_file(instance):
|
||||||
TESTFILE_CONENTE = "TestStringFileContent"
|
TESTFILE_CONENTE = "TestStringFileContent"
|
||||||
TESTFILE_CONENTE_B64 = base64.b64encode(bytes(TESTFILE_CONENTE, 'utf-8'))
|
TESTFILE_CONENTE_B64 = base64.b64encode(bytes(TESTFILE_CONENTE, "utf-8"))
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = org.get_repository(test_repo)
|
repo = org.get_repository(test_repo)
|
||||||
repo.create_file("testfile.md",
|
repo.create_file("testfile.md", content=TESTFILE_CONENTE_B64.decode("ascii"))
|
||||||
content = TESTFILE_CONENTE_B64.decode("ascii"))
|
|
||||||
# test if putting was successful
|
# test if putting was successful
|
||||||
content = repo.get_git_content()
|
content = repo.get_git_content()
|
||||||
readmes = [c for c in content if c.name == "testfile.md"]
|
readmes = [c for c in content if c.name == "testfile.md"]
|
||||||
|
@ -180,17 +186,19 @@ def test_create_file(instance):
|
||||||
assert len(readme_content) > 0
|
assert len(readme_content) > 0
|
||||||
assert TESTFILE_CONENTE in str(base64.b64decode(readme_content))
|
assert TESTFILE_CONENTE in str(base64.b64decode(readme_content))
|
||||||
|
|
||||||
|
|
||||||
def test_change_file(instance):
|
def test_change_file(instance):
|
||||||
TESTFILE_CONENTE = "TestStringFileContent with changed content now"
|
TESTFILE_CONENTE = "TestStringFileContent with changed content now"
|
||||||
TESTFILE_CONENTE_B64 = base64.b64encode(bytes(TESTFILE_CONENTE, 'utf-8'))
|
TESTFILE_CONENTE_B64 = base64.b64encode(bytes(TESTFILE_CONENTE, "utf-8"))
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = org.get_repository(test_repo)
|
repo = org.get_repository(test_repo)
|
||||||
# figure out the sha of the file to change
|
# figure out the sha of the file to change
|
||||||
content = repo.get_git_content()
|
content = repo.get_git_content()
|
||||||
readmes = [c for c in content if c.name == "testfile.md"]
|
readmes = [c for c in content if c.name == "testfile.md"]
|
||||||
# change
|
# change
|
||||||
repo.change_file("testfile.md", readmes[0].sha,
|
repo.change_file(
|
||||||
content = TESTFILE_CONENTE_B64.decode("ascii"))
|
"testfile.md", readmes[0].sha, content=TESTFILE_CONENTE_B64.decode("ascii")
|
||||||
|
)
|
||||||
# test if putting was successful
|
# test if putting was successful
|
||||||
content = repo.get_git_content()
|
content = repo.get_git_content()
|
||||||
readmes = [c for c in content if c.name == "testfile.md"]
|
readmes = [c for c in content if c.name == "testfile.md"]
|
||||||
|
@ -199,6 +207,7 @@ def test_change_file(instance):
|
||||||
assert len(readme_content) > 0
|
assert len(readme_content) > 0
|
||||||
assert TESTFILE_CONENTE in str(base64.b64decode(readme_content))
|
assert TESTFILE_CONENTE in str(base64.b64decode(readme_content))
|
||||||
|
|
||||||
|
|
||||||
def test_create_branch(instance):
|
def test_create_branch(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = org.get_repository(test_repo)
|
repo = org.get_repository(test_repo)
|
||||||
|
@ -207,6 +216,7 @@ def test_create_branch(instance):
|
||||||
assert len(master) > 0
|
assert len(master) > 0
|
||||||
repo.add_branch(master[0], "test_branch")
|
repo.add_branch(master[0], "test_branch")
|
||||||
|
|
||||||
|
|
||||||
def test_create_team(instance):
|
def test_create_team(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
team = instance.create_team(org, test_team, "descr")
|
team = instance.create_team(org, test_team, "descr")
|
||||||
|
@ -214,6 +224,7 @@ def test_create_team(instance):
|
||||||
assert team.description == "descr"
|
assert team.description == "descr"
|
||||||
assert team.organization == org
|
assert team.organization == org
|
||||||
|
|
||||||
|
|
||||||
def test_patch_team(instance):
|
def test_patch_team(instance):
|
||||||
fields = {
|
fields = {
|
||||||
"can_create_org_repo": True,
|
"can_create_org_repo": True,
|
||||||
|
@ -238,13 +249,17 @@ def test_request_team(instance):
|
||||||
team2 = Team.request(instance, team.id)
|
team2 = Team.request(instance, team.id)
|
||||||
assert team.name == team2.name
|
assert team.name == team2.name
|
||||||
|
|
||||||
|
|
||||||
def test_create_milestone(instance):
|
def test_create_milestone(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = org.get_repository(test_repo)
|
repo = org.get_repository(test_repo)
|
||||||
ms = repo.create_milestone("I love this Milestone", "Find an otter to adopt this milestone")
|
ms = repo.create_milestone(
|
||||||
|
"I love this Milestone", "Find an otter to adopt this milestone"
|
||||||
|
)
|
||||||
assert isinstance(ms, Milestone)
|
assert isinstance(ms, Milestone)
|
||||||
assert ms.title == "I love this Milestone"
|
assert ms.title == "I love this Milestone"
|
||||||
|
|
||||||
|
|
||||||
def test_user_teams(instance):
|
def test_user_teams(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
team = org.get_team(test_team)
|
team = org.get_team(test_team)
|
||||||
|
@ -253,11 +268,13 @@ def test_user_teams(instance):
|
||||||
teams = user.get_teams()
|
teams = user.get_teams()
|
||||||
assert team in teams
|
assert team in teams
|
||||||
|
|
||||||
|
|
||||||
def test_get_accessible_repositories(instance):
|
def test_get_accessible_repositories(instance):
|
||||||
user = instance.get_user_by_name(test_user)
|
user = instance.get_user_by_name(test_user)
|
||||||
repos = user.get_accessible_repos()
|
repos = user.get_accessible_repos()
|
||||||
assert len(repos) > 0
|
assert len(repos) > 0
|
||||||
|
|
||||||
|
|
||||||
def test_create_issue(instance):
|
def test_create_issue(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = Repository.request(instance, org.username, test_repo)
|
repo = Repository.request(instance, org.username, test_repo)
|
||||||
|
@ -266,6 +283,7 @@ def test_create_issue(instance):
|
||||||
assert issue.title == "TestIssue"
|
assert issue.title == "TestIssue"
|
||||||
assert issue.body == "Body text with this issue"
|
assert issue.body == "Body text with this issue"
|
||||||
|
|
||||||
|
|
||||||
def test_hashing(instance):
|
def test_hashing(instance):
|
||||||
# just call the hash function of each object to see if something bad happens
|
# just call the hash function of each object to see if something bad happens
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
|
@ -284,7 +302,9 @@ def test_change_issue(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = org.get_repositories()[0]
|
repo = org.get_repositories()[0]
|
||||||
ms_title = "othermilestone"
|
ms_title = "othermilestone"
|
||||||
issue = Issue.create_issue(instance, repo, "IssueTestissue with Testinput", "asdf2332")
|
issue = Issue.create_issue(
|
||||||
|
instance, repo, "IssueTestissue with Testinput", "asdf2332"
|
||||||
|
)
|
||||||
new_body = "some new description with some more of that char stuff :)"
|
new_body = "some new description with some more of that char stuff :)"
|
||||||
issue.body = new_body
|
issue.body = new_body
|
||||||
issue.commit()
|
issue.commit()
|
||||||
|
@ -300,8 +320,17 @@ def test_change_issue(instance):
|
||||||
assert issue3.milestone is not None
|
assert issue3.milestone is not None
|
||||||
assert issue3.milestone.description == "this is only a teststone2"
|
assert issue3.milestone.description == "this is only a teststone2"
|
||||||
issues = repo.get_issues()
|
issues = repo.get_issues()
|
||||||
assert len([issue for issue in issues
|
assert (
|
||||||
if issue.milestone is not None and issue.milestone.title == ms_title]) > 0
|
len(
|
||||||
|
[
|
||||||
|
issue
|
||||||
|
for issue in issues
|
||||||
|
if issue.milestone is not None and issue.milestone.title == ms_title
|
||||||
|
]
|
||||||
|
)
|
||||||
|
> 0
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_team_get_org(instance):
|
def test_team_get_org(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
|
@ -309,6 +338,7 @@ def test_team_get_org(instance):
|
||||||
teams = user.get_teams()
|
teams = user.get_teams()
|
||||||
assert org.username == teams[0].organization.name
|
assert org.username == teams[0].organization.name
|
||||||
|
|
||||||
|
|
||||||
def test_delete_repo_userowned(instance):
|
def test_delete_repo_userowned(instance):
|
||||||
user = User.request(instance, test_user)
|
user = User.request(instance, test_user)
|
||||||
repo = Repository.request(instance, user.username, test_repo)
|
repo = Repository.request(instance, user.username, test_repo)
|
||||||
|
@ -316,6 +346,7 @@ def test_delete_repo_userowned(instance):
|
||||||
with pytest.raises(NotFoundException) as e:
|
with pytest.raises(NotFoundException) as e:
|
||||||
Repository.request(instance, test_user, test_repo)
|
Repository.request(instance, test_user, test_repo)
|
||||||
|
|
||||||
|
|
||||||
def test_secundary_email(instance):
|
def test_secundary_email(instance):
|
||||||
SECONDARYMAIL = "secondarytest@test.org" # set up with real email
|
SECONDARYMAIL = "secondarytest@test.org" # set up with real email
|
||||||
sec_user = instance.get_user_by_email(SECONDARYMAIL)
|
sec_user = instance.get_user_by_email(SECONDARYMAIL)
|
||||||
|
@ -334,7 +365,9 @@ def test_delete_repo_orgowned(instance):
|
||||||
def test_change_repo_ownership_org(instance):
|
def test_change_repo_ownership_org(instance):
|
||||||
old_org = Organization.request(instance, test_org)
|
old_org = Organization.request(instance, test_org)
|
||||||
user = User.request(instance, test_user)
|
user = User.request(instance, test_user)
|
||||||
new_org = instance.create_org(user,test_org+"_repomove", "Org for testing moving repositories")
|
new_org = instance.create_org(
|
||||||
|
user, test_org + "_repomove", "Org for testing moving repositories"
|
||||||
|
)
|
||||||
new_team = instance.create_team(new_org, test_team + "_repomove", "descr")
|
new_team = instance.create_team(new_org, test_team + "_repomove", "descr")
|
||||||
repo_name = test_repo + "_repomove"
|
repo_name = test_repo + "_repomove"
|
||||||
repo = instance.create_repo(old_org, repo_name, "descr")
|
repo = instance.create_repo(old_org, repo_name, "descr")
|
||||||
|
@ -342,6 +375,7 @@ def test_change_repo_ownership_org(instance):
|
||||||
assert repo_name not in [repo.name for repo in old_org.get_repositories()]
|
assert repo_name not in [repo.name for repo in old_org.get_repositories()]
|
||||||
assert repo_name in [repo.name for repo in new_org.get_repositories()]
|
assert repo_name in [repo.name for repo in new_org.get_repositories()]
|
||||||
|
|
||||||
|
|
||||||
def test_change_repo_ownership_user(instance):
|
def test_change_repo_ownership_user(instance):
|
||||||
old_org = Organization.request(instance, test_org)
|
old_org = Organization.request(instance, test_org)
|
||||||
user = User.request(instance, test_user)
|
user = User.request(instance, test_user)
|
||||||
|
@ -363,6 +397,7 @@ def test_delete_team(instance):
|
||||||
with pytest.raises(NotFoundException) as e:
|
with pytest.raises(NotFoundException) as e:
|
||||||
team = org.get_team(test_team)
|
team = org.get_team(test_team)
|
||||||
|
|
||||||
|
|
||||||
def test_delete_teams(instance):
|
def test_delete_teams(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repos = org.get_repositories()
|
repos = org.get_repositories()
|
||||||
|
@ -371,6 +406,7 @@ def test_delete_teams(instance):
|
||||||
repos = org.get_repositories()
|
repos = org.get_repositories()
|
||||||
assert len(repos) == 0
|
assert len(repos) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_delete_org(instance):
|
def test_delete_org(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
org.delete()
|
org.delete()
|
||||||
|
|
|
@ -4,6 +4,7 @@ import uuid
|
||||||
from gitea import Gitea, User, Organization, Team, Repository, Issue
|
from gitea import Gitea, User, Organization, Team, Repository, Issue
|
||||||
from gitea import NotFoundException, AlreadyExistsException
|
from gitea import NotFoundException, AlreadyExistsException
|
||||||
|
|
||||||
|
|
||||||
# put a ".token" file into your directory containg only the token for gitea
|
# put a ".token" file into your directory containg only the token for gitea
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def instance(scope="module"):
|
def instance(scope="module"):
|
||||||
|
@ -20,15 +21,20 @@ def instance(scope="module"):
|
||||||
- Token at .token \
|
- Token at .token \
|
||||||
?"
|
?"
|
||||||
|
|
||||||
|
|
||||||
# make up some fresh names for the tests run
|
# make up some fresh names for the tests run
|
||||||
test_org = "org_" + uuid.uuid4().hex[:8]
|
test_org = "org_" + uuid.uuid4().hex[:8]
|
||||||
test_user = "user_" + uuid.uuid4().hex[:8]
|
test_user = "user_" + uuid.uuid4().hex[:8]
|
||||||
test_team = "team_" + uuid.uuid4().hex[:8] # team names seem to have a rather low max lenght
|
test_team = (
|
||||||
|
"team_" + uuid.uuid4().hex[:8]
|
||||||
|
) # team names seem to have a rather low max lenght
|
||||||
test_repo = "repo_" + uuid.uuid4().hex[:8]
|
test_repo = "repo_" + uuid.uuid4().hex[:8]
|
||||||
|
|
||||||
|
|
||||||
def test_list_repos(instance):
|
def test_list_repos(instance):
|
||||||
user = instance.create_user(test_user, test_user + "@example.org", "abcdefg1.23AB", send_notify=False)
|
user = instance.create_user(
|
||||||
|
test_user, test_user + "@example.org", "abcdefg1.23AB", send_notify=False
|
||||||
|
)
|
||||||
org = instance.create_org(user, test_org, "some Description for longtests")
|
org = instance.create_org(user, test_org, "some Description for longtests")
|
||||||
repos = org.get_repositories()
|
repos = org.get_repositories()
|
||||||
assert len(repos) == 0
|
assert len(repos) == 0
|
||||||
|
@ -41,8 +47,15 @@ def test_list_repos(instance):
|
||||||
|
|
||||||
def test_list_issue(instance):
|
def test_list_issue(instance):
|
||||||
org = Organization.request(instance, test_org)
|
org = Organization.request(instance, test_org)
|
||||||
repo = instance.create_repo(org, test_repo, "Testing a huge number of Issues and how they are listed")
|
repo = instance.create_repo(
|
||||||
|
org, test_repo, "Testing a huge number of Issues and how they are listed"
|
||||||
|
)
|
||||||
for x in range(0, 100):
|
for x in range(0, 100):
|
||||||
Issue.create_issue(instance, repo, "TestIssue" + str(x), "We will be too many to be listed on one page")
|
Issue.create_issue(
|
||||||
|
instance,
|
||||||
|
repo,
|
||||||
|
"TestIssue" + str(x),
|
||||||
|
"We will be too many to be listed on one page",
|
||||||
|
)
|
||||||
issues = repo.get_issues()
|
issues = repo.get_issues()
|
||||||
assert len(issues) > 98
|
assert len(issues) > 98
|
||||||
|
|
Ładowanie…
Reference in New Issue