Skip to content

Commit

Permalink
libs: Add aio.api.github (#149)
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Northey <ryan@synca.io>
  • Loading branch information
phlax authored Jan 3, 2022
1 parent 5ced85d commit e6e2f7a
Show file tree
Hide file tree
Showing 34 changed files with 2,544 additions and 0 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ pypi: https://pypi.org/project/abstracts
---


#### [aio.api.github](aio.api.github)

version: 0.0.1

pypi: https://pypi.org/project/aio.api.github

##### requirements:

- [abstracts](https://pypi.org/project/abstracts)
- [aio.functional](https://pypi.org/project/aio.functional)
- [gidgethub](https://pypi.org/project/gidgethub)
- [packaging](https://pypi.org/project/packaging)

---


#### [aio.functional](aio.functional)

version: 0.0.10.dev0
Expand Down
2 changes: 2 additions & 0 deletions aio.api.github/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

pytooling_package("aio.api.github")
5 changes: 5 additions & 0 deletions aio.api.github/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

aio.api.github
==============

Wrapper around gidgethub
1 change: 1 addition & 0 deletions aio.api.github/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.1
26 changes: 26 additions & 0 deletions aio.api.github/aio/api/github/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

pytooling_library(
"aio.api.github",
dependencies=[
"//deps:abstracts",
"//deps:aio.functional",
"//deps:gidgethub",
"//deps:packaging",
],
sources=[
"abstract/__init__.py",
"abstract/api.py",
"abstract/base.py",
"abstract/commit.py",
"abstract/issues.py",
"abstract/iterator.py",
"abstract/label.py",
"abstract/release.py",
"abstract/repo.py",
"abstract/tag.py",
"__init__.py",
"api.py",
"exceptions.py",
"utils.py",
],
)
49 changes: 49 additions & 0 deletions aio.api.github/aio/api/github/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""aio.api.github."""

from . import abstract
from . import exceptions
from . import utils
from .api import (
GithubAPI,
GithubCommit,
GithubIssue,
GithubIssues,
GithubIterator,
GithubLabel,
GithubRelease,
GithubRepo,
GithubTag)
from .abstract import (
AGithubAPI,
AGithubCommit,
AGithubIssue,
AGithubIssues,
AGithubIterator,
AGithubLabel,
AGithubRelease,
AGithubRepo,
AGithubTag)


__all__ = (
"abstract",
"AGithubAPI",
"AGithubCommit",
"AGithubIssue",
"AGithubIssues",
"AGithubIterator",
"AGithubLabel",
"AGithubRelease",
"AGithubRepo",
"AGithubTag",
"exceptions",
"GithubAPI",
"GithubCommit",
"GithubLabel",
"GithubIssue",
"GithubIssues",
"GithubIterator",
"GithubRelease",
"GithubRepo",
"GithubTag",
"utils")
21 changes: 21 additions & 0 deletions aio.api.github/aio/api/github/abstract/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

from .api import AGithubAPI
from .commit import AGithubCommit
from .issues import AGithubIssue, AGithubIssues
from .iterator import AGithubIterator
from .label import AGithubLabel
from .release import AGithubRelease
from .repo import AGithubRepo
from .tag import AGithubTag


__all__ = (
"AGithubAPI",
"AGithubCommit",
"AGithubIssue",
"AGithubIssues",
"AGithubIterator",
"AGithubLabel",
"AGithubRelease",
"AGithubRepo",
"AGithubTag")
126 changes: 126 additions & 0 deletions aio.api.github/aio/api/github/abstract/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@

import abc
from functools import cached_property
from typing import Any, Type

import gidgethub
import gidgethub.abc
import gidgethub.aiohttp

import abstracts

from .commit import AGithubCommit
from .issues import AGithubIssue, AGithubIssues
from .iterator import AGithubIterator
from .label import AGithubLabel
from .release import AGithubRelease
from .repo import AGithubRepo
from .tag import AGithubTag


class AGithubAPI(metaclass=abstracts.Abstraction):
"""Github API wrapper.
Can be used to access the gidgethub API directly.
Can also be used to work with repos by calling `self["repo/name"]`.
"""

def __init__(self, *args, **kwargs) -> None:
self.args = args
self.kwargs = kwargs

def __getitem__(self, k) -> AGithubRepo:
"""Return a `GithubRepository` for `k`"""
# TODO: make this work with user and organization
# and validate `k`
return self.repo_class(self, k)

@cached_property
def api(self) -> gidgethub.abc.GitHubAPI:
"""Gidgethub API."""
return self.api_class(*self.args, **self.kwargs)

@property
@abc.abstractmethod
def api_class(self) -> Type[gidgethub.abc.GitHubAPI]:
"""API class."""
return gidgethub.aiohttp.GitHubAPI

@property # type:ignore
@abstracts.interfacemethod
def commit_class(self) -> Type[AGithubCommit]:
"""Github commit class."""
raise NotImplementedError

@property # type:ignore
@abstracts.interfacemethod
def label_class(self) -> Type[AGithubLabel]:
"""Github label class."""
raise NotImplementedError

@property # type:ignore
@abstracts.interfacemethod
def issue_class(self) -> Type[AGithubIssue]:
"""Github issue class."""
raise NotImplementedError

@property # type:ignore
@abstracts.interfacemethod
def issues_class(self) -> Type[AGithubIssues]:
"""Github issues class."""
raise NotImplementedError

@property # type:ignore
@abstracts.interfacemethod
def iterator_class(self) -> Type[AGithubIterator]:
"""Github iterator class.
Provides both an async iterator and a `total_count` async prop.
"""
raise NotImplementedError

@property # type:ignore
@abstracts.interfacemethod
def release_class(self) -> Type[AGithubRelease]:
"""Github release class."""
raise NotImplementedError

@property # type:ignore
@abstracts.interfacemethod
def repo_class(self) -> Type[AGithubRepo]:
"""Github repo class."""
raise NotImplementedError

@property # type:ignore
@abstracts.interfacemethod
def tag_class(self) -> Type[AGithubTag]:
"""Github tag class."""
raise NotImplementedError

async def getitem(self, *args, **kwargs) -> Any:
"""Call the `gidgethub.getitem` api."""
# print("GETITEM", args, kwargs)
return await self.api.getitem(*args, **kwargs)

def getiter(self, *args, **kwargs) -> AGithubIterator:
"""Return a `GithubIterator` wrapping `gidgethub.getiter`."""
# print("GETITER", args, kwargs)
return self.iterator_class(self.api, *args, **kwargs)

async def patch(self, *args, **kwargs):
"""Call the `gidgethub.patch` api."""
# print("PATCH", args, kwargs)
return await self.api.patch(*args, **kwargs)

async def post(self, *args, **kwargs):
"""Call the `gidgethub.post` api."""
# print("POST", args, kwargs)
return await self.api.post(*args, **kwargs)

def repo_from_url(self, url):
"""Return the corresponding `GithubRepo` for an api url."""
repo_url = f"{self.api.base_url}/repos/"
if not url.startswith(repo_url):
return None
return self["/".join(url[len(repo_url):].split("/")[:2])]
48 changes: 48 additions & 0 deletions aio.api.github/aio/api/github/abstract/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

from typing import Any, Callable, Dict

from aio.api.github import abstract


UNSET = object()


class GithubEntity:
"""Base Github entity class."""

def __init__(self, github: "abstract.AGithubAPI", data: Dict) -> None:
self._github = github
self.data = data

@property
def github(self) -> "abstract.AGithubAPI":
"""Github API."""
return self._github

@property
def __data__(self) -> Dict[str, Callable]:
"""Dictionary of callables to mangle corresponding `self.data` keys."""
return {}

def __getattr__(self, k: str, default: Any = UNSET) -> Any:
"""Return the item from `self.data`, after mangling if required."""
try:
v = self.data[k]
except KeyError:
if default is not UNSET:
return default
return self.__getattribute__(k)
return self.__data__.get(k, lambda x: x)(v)


class GithubRepoEntity(GithubEntity):
"""Base Github repo entity class."""

def __init__(self, repo: "abstract.AGithubRepo", data: Dict) -> None:
self.repo = repo
self.data = data

@property
def github(self) -> "abstract.AGithubAPI":
"""Github API."""
return self.repo.github
21 changes: 21 additions & 0 deletions aio.api.github/aio/api/github/abstract/commit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

from datetime import datetime
from functools import cached_property

import abstracts

from aio.api.github import utils
from .base import GithubRepoEntity


class AGithubCommit(GithubRepoEntity, metaclass=abstracts.Abstraction):
"""A Github commit."""

def __str__(self):
return f"<{self.__class__.__name__} {self.repo.name}#{self.sha}>"

@cached_property
def timestamp(self) -> datetime:
"""Datetime of the commit."""
return utils.dt_from_js_isoformat(
self.data["commit"]["committer"]["date"])
Loading

0 comments on commit e6e2f7a

Please sign in to comment.