Skip to content

Commit

Permalink
style: Re-style Repository.py
Browse files Browse the repository at this point in the history
  • Loading branch information
youngyojun committed Aug 28, 2023
1 parent a108155 commit b870603
Showing 1 changed file with 76 additions and 39 deletions.
115 changes: 76 additions & 39 deletions src/polytope/github/repository/Repository.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
from dataclasses import asdict
from typing import Optional, Tuple, Type
from typing_extensions import assert_type

import re
import requests
Expand All @@ -16,19 +17,18 @@
from .Response import GithubRepositoryResponse


# alphanumeric or hyphen, starts & ends with alphanumeric
# Alphanumeric or hyphen, starts & ends with alphanumeric
GITHUB_USERNAME_REGEX = r"^[a-zA-Z\d](?:[a-zA-Z\d]|-(?=[a-zA-Z\d])){0,37}[a-zA-Z\d]$"
# alphanumeric, hyphen, underscore. starts & ends with alphanumeric.
# Alphanumeric, hyphen, underscore. starts & ends with alphanumeric.
GITHUB_REPONAME_REGEX = r"^[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?$"


class GithubRepository:
"""! Controller of Github Repository.
"""Control a GitHub Repository.
@param owner Github Username of Repository Owner.
@param name Name of the repository.
@param token Personal Access Token.
@param session type of session.
Attributes:
owner (str): Github Username of Repository Owner.
config (GithubRepositoryConfig): Repository configurations.
"""

def __init__(
Expand All @@ -38,12 +38,20 @@ def __init__(
token: Token,
session_cls: Type[Session] = RequestsSession,
) -> None:
"""Initialize the instance.
Args:
owner (str): Github Username of Repository Owner.
name (str): Name of the repository.
token (Token): Personal Access Token.
session_cls: Type of session.
"""
assert 0 < len(owner)
assert is_valid_github_user_name(owner)
assert 0 < len(name)
assert is_valid_github_repository_name(name)

self._requester = Requester(
self._requester: Requester = Requester(
token=token,
base_url="https://api.github.com",
headers={
Expand All @@ -59,26 +67,28 @@ def __init__(

@property
def create_url(self) -> str:
"""! URL for repository creation."""
"""URL for repository creation."""
return "/repos/Studio-Polytope/Polytope-repository-template/generate"

def create(
self, description: str = "", private: bool = True
) -> GithubRepositoryResponse:
"""! Create a repository using our template repository.
"""Create a repository using our template repository.
Template repository [(click)](https://github.com/Studio-Polytope/Polytope-repository-template).
See the template repository at
https://github.com/Studio-Polytope/Polytope-repository-template
@param description: short repository description.
@param private: true if repository needs to be kept private.
Args:
description (str, optional): Short repository description.
private (bool): `True` if repository needs to be kept private. (Default is `True`.)
"""
api_url = self.create_url
api_url: str = self.create_url
data = {
"owner": self.owner,
"name": self.config.name,
"description": description,
"private": private,
"include_all_branches": False, # constantly kept false to protect template
"include_all_branches": False, # Constantly kept false to protect template
}

result = self._requester.request(
Expand All @@ -102,15 +112,23 @@ def create_without_template_url(self) -> str:
def create_without_template(
self, config: Optional[GithubRepositoryConfig] = None
) -> GithubRepositoryResponse:
"""! Create a github repository. Not a first option to consider.
"""Create a github repository.
Not a first option to consider.
Wraps [REST API for Github Repository](https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#create-a-repository-for-the-authenticated-user)
@param config: overrides default configuration for repository. Cannot modify name here.
Wrap REST API for Github Repository. See details at
https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#create-a-repository-for-the-authenticated-user
Args:
config (optional): Override default configuration for repository. Cannot modify name here.
"""
if config is None:
config = self.config

valid_config, validation_msg = config.validate()
assert_type(valid_config, bool)
assert_type(validation_msg, str)

if not valid_config:
return GithubRepositoryResponse(
status_code=None,
Expand Down Expand Up @@ -151,14 +169,14 @@ def create_without_template(

@property
def get_url(self) -> str:
"""! URL to get repository info."""
"""URL to get repository info."""
return f"/repos/{self.owner}/{self.config.name}"

def get(self) -> GithubRepositoryResponse:
"""! Get a repository named {owner}/{repo}."""
"""Get a repository named {owner}/{repo}."""
result = self._requester.request(verb=RequestVerb.GET, api_url=self.get_url)

# @todo define content to read
# TODO(TAMREF): Define content to read

if result.status_code == 200:
return GithubRepositoryResponse(
Expand All @@ -172,19 +190,22 @@ def get(self) -> GithubRepositoryResponse:

@property
def update_url(self) -> str:
"""! URL for update."""
"""URL for update."""
return f"/repos/{self.owner}/{self.config.name}"

def update(
self, config: Optional[GithubRepositoryConfig] = None
) -> GithubRepositoryResponse:
"""
Update repository by config.
"""Update repository by `config`.
@param config: GithubRepositoryConfig class. Includes name.
Args:
config: GithubRepositoryConfig class. Includes name.
"""

has_polytope_config_file, reason = self.fetch_polytope_config_file()
assert_type(has_polytope_config_file, bool)
assert_type(reason, str)

if not has_polytope_config_file:
return GithubRepositoryResponse(
status_code=None,
Expand All @@ -197,6 +218,9 @@ def update(
config = self.config

valid_config, validation_result = config.validate()
assert_type(valid_config, bool)
assert_type(validation_result, str)

if not valid_config:
return GithubRepositoryResponse(
status_code=None,
Expand All @@ -211,7 +235,7 @@ def update(
verb=RequestVerb.PATCH, api_url=self.update_url, data=json.dumps(data)
)

# succeeded to update.
# Succeeded to update.
if result.status_code == 200:
# Update local config only if update is succeeded.
self.config = config
Expand All @@ -226,12 +250,15 @@ def update(

@property
def delete_url(self) -> str:
"""! URL for delete."""
"""URL for delete."""
return f"/repos/{self.owner}/{self.config.name}"

def delete(self) -> GithubRepositoryResponse:
"""! Delete the repository."""
"""Delete the repository."""
has_polytope_config_file, reason = self.fetch_polytope_config_file()
assert_type(has_polytope_config_file, bool)
assert_type(reason, str)

if not has_polytope_config_file:
return GithubRepositoryResponse(
status_code=None,
Expand All @@ -244,7 +271,7 @@ def delete(self) -> GithubRepositoryResponse:
verb=RequestVerb.DELETE, api_url=self.delete_url
)

# succeeded to update.
# Succeeded to update.
if result.status_code == 204:
return GithubRepositoryResponse(
status_code=result.status_code,
Expand All @@ -257,17 +284,22 @@ def delete(self) -> GithubRepositoryResponse:

@property
def fetch_contents_url(self) -> str:
"""! URL to fetch contents."""
"""URL to fetch contents."""
return f"/repos/{self.owner}/{self.config.name}/contents"

# fetch Polytope config file (polytope.yaml)
# Fetch Polytope config file (polytope.yaml)
def fetch_polytope_config_file(
self, ignore_cache: bool = False
) -> Tuple[bool, str]:
"""
Fetch Polytope config file (currently polytope.yaml).
"""Fetch Polytope config file (currently `polytope.yaml`).
Args:
ignore_cache: If set to `False`, use cached value instead of sending requests.
@param ignore_cache: If set to False, use cached value instead of sending requests.
Returns:
tuple: A tuple containing:
* (bool): Existence of Polytope config file.
* (str): Reason message.
"""

# believe cached result
Expand Down Expand Up @@ -306,7 +338,7 @@ def is_valid_github_user_name(name: str) -> bool:
def fetch_message_and_errors(
result: requests.Response,
) -> Tuple[str, str] | Tuple[None, None]:
"""! post-processor of erroneous request.Response."""
"""Post-processor of erroneous request.Response."""
if not result.content:
return None, None

Expand All @@ -325,15 +357,20 @@ def fetch_message_and_errors(
def parse_polytope_config_file(
resp_content: str | bytes | bytearray | None,
) -> Tuple[bool, str]:
"""! Parse http response content from Github root directory.
"""Parse http response content from Github root directory.
Args:
resp_content: Content of http response.
@param resp_content: content of http response.
@return (if there is a Polytope config file, error msg while finding configs)
Returns:
tuple: A tuple containing:
* (bool): Whether if there is a Polytope config file.
* (str): Error message while finding configs.
"""
if not resp_content:
return False, "empty response content"

# @todo error handling while json unmarshal
# TODO(TAMREF): Error handling while json unmarshal
contents = json.loads(resp_content)

if not isinstance(contents, list):
Expand Down

0 comments on commit b870603

Please sign in to comment.