diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d6a6675f..a324494a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,7 +12,7 @@ Please provide: - The version of pip you used to install github3.py -- The version of github3.py, requests, uritemplate, and dateutil installed +- The version of github3.py, requests, uritemplate, and python-dateutil installed ## Minimum Reproducible Example diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..c8cb6ac2 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,45 @@ +--- +name: Check documentation + +"on": + schedule: + - cron: "0 1 * * *" # everyday at 1am + push: + paths: + - "**.rst" + - "docs/**" + pull_request: + paths: + - "**.rst" + - "docs/**" + +jobs: + docs: + name: Build documentation & check links + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: Upgrade pip + run: | + pip install -U pip + pip --version + + - name: Install Tox + run: | + pip install tox + tox --version + + - name: Build documentation + run: tox + env: + TOXENV: docs + + - name: Upload documentation + uses: actions/upload-artifact@v3 + with: + name: docs + path: docs/build diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e5d818b..b862fc92 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: check-added-large-files - id: check-toml @@ -13,31 +13,33 @@ repos: - id: trailing-whitespace types: [text] stages: [commit, push, manual] - - repo: https://github.com/asottile/reorder-python-imports - rev: v3.10.0 + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 hooks: - - id: reorder-python-imports - args: [--application-directories, '.:src', --py37-plus] + - id: isort - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 24.4.0 hooks: - id: black - repo: https://github.com/asottile/pyupgrade - rev: v3.7.0 + rev: v3.15.2 hooks: - id: pyupgrade args: [--py37-plus] - #- repo: https://github.com/pre-commit/mirrors-mypy - # rev: v0.910 - # hooks: - # - id: mypy - # exclude: ^(docs/|tests/) + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.9.0 + hooks: + - id: mypy + additional_dependencies: + - types-python-dateutil + - types-requests + exclude: ^(docs/|tests/) - repo: https://github.com/jorisroovers/gitlint rev: v0.19.1 hooks: - id: gitlint - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.3.0 + rev: v2.5.0 hooks: - id: setup-cfg-fmt args: [--min-py3-version, '3.7'] diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..2fd28691 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,12 @@ +version: 2 +build: + os: ubuntu-22.04 + tools: + python: "3.11" +sphinx: + configuration: docs/source/conf.py +formats: all +python: + install: + - requirements: docs/source/requirements.txt + - path: . diff --git a/AUTHORS.rst b/AUTHORS.rst index 6b5828b9..1529c45d 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -224,3 +224,5 @@ Contributors - Chris R (@offbyone) - Thomas Buchner (@MrBatschner) + +- Chris Cotter (@ccotter) \ No newline at end of file diff --git a/docs/source/requirements.txt b/docs/source/requirements.txt index c48a056a..717a3703 100644 --- a/docs/source/requirements.txt +++ b/docs/source/requirements.txt @@ -1,2 +1,3 @@ sphinx>=4.2.0 docutils!=0.18 +sphinx_rtd_theme diff --git a/pyproject.toml b/pyproject.toml index e615261a..859b72e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,6 @@ Source = "https://github.com/sigmavirus24/github3.py" [tool.black] line-length = 78 target-version = ['py37'] -safe = true exclude = ''' ( /( @@ -83,6 +82,19 @@ exclude = ''' | _build | build | dist + | venv )/ ) ''' + +[tool.mypy] +files = ["."] +exclude = [ + "^docs/", + "^tests/", +] + +[tool.isort] +profile = "black" +line_length = 78 +force_single_line = true diff --git a/src/github3/__about__.py b/src/github3/__about__.py index e2101047..e7e6dd25 100644 --- a/src/github3/__about__.py +++ b/src/github3/__about__.py @@ -1,4 +1,5 @@ """The module that holds much of the metadata about github3.py.""" + __package_name__ = "github3.py" __title__ = "github3" __author__ = "Ian Stapleton Cordasco" diff --git a/src/github3/__init__.py b/src/github3/__init__.py index 78ff6a96..f8cb24a1 100644 --- a/src/github3/__init__.py +++ b/src/github3/__init__.py @@ -8,6 +8,7 @@ :license: Modified BSD, see LICENSE for more details """ + from .__about__ import __author__ from .__about__ import __author_email__ from .__about__ import __copyright__ diff --git a/src/github3/api.py b/src/github3/api.py index 624da092..55059ad5 100644 --- a/src/github3/api.py +++ b/src/github3/api.py @@ -6,6 +6,7 @@ :license: Modified BSD, see LICENSE for more details """ + from .github import GitHub from .github import GitHubEnterprise diff --git a/src/github3/apps.py b/src/github3/apps.py index a1cd6f08..fc24a9c9 100644 --- a/src/github3/apps.py +++ b/src/github3/apps.py @@ -2,6 +2,7 @@ https://developer.github.com/apps/building-github-apps/ """ + import time import jwt diff --git a/src/github3/auths.py b/src/github3/auths.py index 9a2898c0..fceb2bdd 100644 --- a/src/github3/auths.py +++ b/src/github3/auths.py @@ -1,4 +1,5 @@ """This module contains the Authorization object.""" + from .decorators import requires_basic_auth from .models import GitHubCore diff --git a/src/github3/checks.py b/src/github3/checks.py index d2dcfb73..402d93b9 100644 --- a/src/github3/checks.py +++ b/src/github3/checks.py @@ -1,4 +1,5 @@ """This module contains all the classes relating to Checks.""" + from json import dumps from . import decorators @@ -45,7 +46,7 @@ def _update_attributes(self, pull): def _repr(self): return f"" - def to_pull(self): + def to_pull(self, conditional: bool = False): """Retrieve a full PullRequest object for this CheckPullRequest. :returns: @@ -119,7 +120,7 @@ def _repr(self): self.name, str(self.owner["login"]) ) - def to_app(self): + def to_app(self, conditional: bool = False) -> models.GitHubCore: """Retrieve a full App object for this CheckApp. :returns: diff --git a/src/github3/decorators.py b/src/github3/decorators.py index 4c8a081e..ad06a60e 100644 --- a/src/github3/decorators.py +++ b/src/github3/decorators.py @@ -1,4 +1,5 @@ """This module provides decorators to the rest of the library.""" + import os from functools import wraps from io import BytesIO as StringIO diff --git a/src/github3/events.py b/src/github3/events.py index f67968c6..60ed0315 100644 --- a/src/github3/events.py +++ b/src/github3/events.py @@ -1,4 +1,5 @@ """This module contains the classes related to Events.""" + import copy from . import models @@ -41,7 +42,7 @@ def _update_attributes(self, user): self.login = user["login"] self._api = self.url = user["url"] - def to_user(self): + def to_user(self, conditional: bool = False) -> models.GitHubCore: """Retrieve a full User object for this EventUser. :returns: @@ -93,7 +94,7 @@ def _update_attributes(self, org): self.login = org["login"] self._api = self.url = org["url"] - def to_org(self): + def to_org(self, conditional: bool = False) -> models.GitHubCore: """Retrieve a full Organization object for this EventOrganization. :returns: @@ -148,7 +149,7 @@ def _update_attributes(self, pull): self.locked = pull["locked"] self._api = self.url = pull["url"] - def to_pull(self): + def to_pull(self, conditional: bool = False) -> models.GitHubCore: """Retrieve a full PullRequest object for this EventPullRequest. :returns: @@ -258,7 +259,9 @@ def _update_attributes(self, comment): self.updated_at = self._strptime(comment["updated_at"]) self.user = users.ShortUser(comment["user"], self) - def to_review_comment(self): + def to_review_comment( + self, conditional: bool = False + ) -> models.GitHubCore: """Retrieve a full ReviewComment object for this EventReviewComment. :returns: @@ -269,7 +272,7 @@ def to_review_comment(self): from . import pulls comment = self._json(self._get(self._api), 200) - return pulls.ReviewComment(comment, self) + return pulls.ReviewComment(comment, self.session) refresh = to_review_comment @@ -285,7 +288,7 @@ def _update_attributes(self, issue): self.locked = issue["locked"] self._api = self.url = issue["url"] - def to_issue(self): + def to_issue(self, conditional: bool = False) -> models.GitHubCore: """Retrieve a full Issue object for this EventIssue.""" from . import issues @@ -352,7 +355,9 @@ def _update_attributes(self, comment): self.updated_at = self._strptime(comment["updated_at"]) self.user = users.ShortUser(comment["user"], self) - def to_issue_comment(self): + def to_issue_comment( + self, conditional: bool = False + ) -> models.GitHubCore: """Retrieve the full IssueComment object for this comment. :returns: diff --git a/src/github3/gists/__init__.py b/src/github3/gists/__init__.py index 73b64fd3..b10f2a41 100644 --- a/src/github3/gists/__init__.py +++ b/src/github3/gists/__init__.py @@ -12,6 +12,7 @@ See also: http://developer.github.com/v3/gists/ """ + from .gist import Gist from .gist import ShortGist diff --git a/src/github3/gists/comment.py b/src/github3/gists/comment.py index c0d1a390..9f6a1835 100644 --- a/src/github3/gists/comment.py +++ b/src/github3/gists/comment.py @@ -1,4 +1,5 @@ """Module containing the logic for a GistComment.""" + from .. import decorators from .. import models from .. import users diff --git a/src/github3/gists/file.py b/src/github3/gists/file.py index 820d56e9..1afbb6fe 100644 --- a/src/github3/gists/file.py +++ b/src/github3/gists/file.py @@ -1,4 +1,5 @@ """Module containing the GistFile object.""" + from .. import models diff --git a/src/github3/gists/gist.py b/src/github3/gists/gist.py index 160502ad..15b6b90e 100644 --- a/src/github3/gists/gist.py +++ b/src/github3/gists/gist.py @@ -1,12 +1,14 @@ """This module contains the Gist, ShortGist, and GistFork objects.""" + +import typing as t from json import dumps -from . import comment -from . import file as gistfile -from . import history from .. import models from .. import users from ..decorators import requires_auth +from . import comment +from . import file as gistfile +from . import history class _Gist(models.GitHubCore): @@ -31,7 +33,9 @@ class _Gist(models.GitHubCore): """ class_name = "_Gist" - _file_class = gistfile.ShortGistFile + _file_class: t.Type[ + t.Union[gistfile.ShortGistFile, gistfile.GistFile] + ] = gistfile.ShortGistFile def _update_attributes(self, gist): self.comments_count = gist["comments"] @@ -265,7 +269,7 @@ def _update_attributes(self, fork): def _repr(self): return f"" - def to_gist(self): + def to_gist(self, conditional: bool = False) -> models.GitHubCore: """Retrieve the full Gist representation of this fork. :returns: diff --git a/src/github3/gists/history.py b/src/github3/gists/history.py index 02d5c132..915ffd4b 100644 --- a/src/github3/gists/history.py +++ b/src/github3/gists/history.py @@ -1,4 +1,5 @@ """Module containing the GistHistory object.""" + from .. import models from .. import users @@ -51,7 +52,7 @@ class GistHistory(models.GitHubCore): def _update_attributes(self, history) -> None: self.url = self._api = history["url"] self.version = history["version"] - self.user = users.ShortUser(history["user"], self) + self.user = users.ShortUser(history["user"], self.session) self.change_status = history["change_status"] self.additions = self.change_status.get("additions") self.deletions = self.change_status.get("deletions") diff --git a/src/github3/git.py b/src/github3/git.py index fde1eae2..f46c6d4a 100644 --- a/src/github3/git.py +++ b/src/github3/git.py @@ -3,6 +3,7 @@ See also: http://developer.github.com/v3/git/ """ + import base64 from json import dumps @@ -297,42 +298,6 @@ def _repr(self): return f"" -class CommitTree(models.GitHubCore): - """This object represents the abbreviated tree data in a commit. - - The API returns different representations of different objects. When - representing a :class:`~github3.git.ShortCommit` or - :class:`~github3.git.Commit`, the API returns an abbreviated - representation of a git tree. - - This object has the following attributes: - - .. attribute:: sha - - The SHA1 of this tree in the git repository. - """ - - def _update_attributes(self, tree): - self._api = tree["url"] - self.sha = tree["sha"] - - def _repr(self): - return f"" - - def to_tree(self): - """Retrieve a full Tree object for this CommitTree. - - :returns: - The full git data about this tree - :rtype: - :class:`~github3.git.Tree` - """ - json = self._json(self._get(self._api), 200) - return self._instance_or_null(Tree, json) - - refresh = to_tree - - class Tree(models.GitHubCore): """This represents a tree object from a git repository. @@ -382,6 +347,42 @@ def recurse(self): return self._instance_or_null(Tree, json) +class CommitTree(models.GitHubCore): + """This object represents the abbreviated tree data in a commit. + + The API returns different representations of different objects. When + representing a :class:`~github3.git.ShortCommit` or + :class:`~github3.git.Commit`, the API returns an abbreviated + representation of a git tree. + + This object has the following attributes: + + .. attribute:: sha + + The SHA1 of this tree in the git repository. + """ + + def _update_attributes(self, tree): + self._api = tree["url"] + self.sha = tree["sha"] + + def _repr(self): + return f"" + + def to_tree(self, conditional: bool = False) -> models.GitHubCore: + """Retrieve a full Tree object for this CommitTree. + + :returns: + The full git data about this tree + :rtype: + :class:`~github3.git.Tree` + """ + json = self._json(self._get(self._api), 200) + return self._instance_or_null(Tree, json) + + refresh = to_tree + + class Hash(models.GitHubCore): """This is used to represent the elements of a tree. diff --git a/src/github3/github.py b/src/github3/github.py index 5844bc6c..99a50121 100644 --- a/src/github3/github.py +++ b/src/github3/github.py @@ -1,9 +1,10 @@ """This module contains the main interfaces to the API.""" + import json import re import typing as t -import uritemplate +import uritemplate # type: ignore from . import apps from . import auths @@ -28,7 +29,6 @@ from .repos import invitation from .repos import repo - _pubsub_re = re.compile( r"https?://[\w\d\-\.\:]+/\w[\w-]+\w/[\w\._-]+/events/\w+" ) @@ -544,7 +544,7 @@ def authorize( @requires_auth def blocked_users( self, number: int = -1, etag: t.Optional[str] = None - ) -> t.Generator[users.ShortUser, None, None]: + ) -> t.Iterator[users.ShortUser]: """Iterate over the users blocked by this organization. .. versionadded:: 2.1.0 @@ -2248,6 +2248,9 @@ def search_code( if sort and order in ("asc", "desc"): params["order"] = order + if per_page is not None: + params["per_page"] = per_page + if text_match: headers = { "Accept": "application/vnd.github.v3.full.text-match+json" @@ -2335,6 +2338,9 @@ def search_commits( if sort and order in ("asc", "desc"): params["order"] = order + if per_page is not None: + params["per_page"] = per_page + if text_match: headers["Accept"] = ", ".join( [ @@ -2427,6 +2433,9 @@ def search_issues( if order in ("asc", "desc"): params["order"] = order + if per_page is not None: + params["per_page"] = per_page + if text_match: headers = { "Accept": "application/vnd.github.v3.full.text-match+json" @@ -2505,6 +2514,9 @@ def search_repositories( if order in ("asc", "desc"): params["order"] = order + if per_page is not None: + params["per_page"] = per_page + if text_match: headers = { "Accept": "application/vnd.github.v3.full.text-match+json" @@ -2588,6 +2600,9 @@ def search_users( if order in ("asc", "desc"): params["order"] = order + if per_page is not None: + params["per_page"] = per_page + if text_match: headers = { "Accept": "application/vnd.github.v3.full.text-match+json" diff --git a/src/github3/issues/__init__.py b/src/github3/issues/__init__.py index a58f86e6..4be94a91 100644 --- a/src/github3/issues/__init__.py +++ b/src/github3/issues/__init__.py @@ -6,6 +6,7 @@ See also: http://developer.github.com/v3/issues/ """ + from ..utils import timestamp_parameter from .issue import Issue from .issue import ShortIssue diff --git a/src/github3/issues/comment.py b/src/github3/issues/comment.py index 149dc815..bc972782 100644 --- a/src/github3/issues/comment.py +++ b/src/github3/issues/comment.py @@ -1,4 +1,5 @@ """Module with class(es) representing issue comments.""" + from .. import decorators from .. import models from .. import users diff --git a/src/github3/issues/event.py b/src/github3/issues/event.py index 356afb94..68cb5ea6 100644 --- a/src/github3/issues/event.py +++ b/src/github3/issues/event.py @@ -1,4 +1,5 @@ """Issue events logic.""" + from .. import users from ..models import GitHubCore diff --git a/src/github3/issues/issue.py b/src/github3/issues/issue.py index 41b7cd6f..6588ad4d 100644 --- a/src/github3/issues/issue.py +++ b/src/github3/issues/issue.py @@ -1,15 +1,16 @@ """Module containing the Issue logic.""" + from json import dumps -from uritemplate import URITemplate +from uritemplate import URITemplate # type: ignore +from .. import models +from .. import users +from ..decorators import requires_auth from . import comment from . import event from . import label from . import milestone -from .. import models -from .. import users -from ..decorators import requires_auth class _Issue(models.GitHubCore): diff --git a/src/github3/issues/label.py b/src/github3/issues/label.py index 065a1e48..93d2d98d 100644 --- a/src/github3/issues/label.py +++ b/src/github3/issues/label.py @@ -1,4 +1,5 @@ """Module containing the logic for labels.""" + from json import dumps from ..decorators import requires_auth diff --git a/src/github3/issues/milestone.py b/src/github3/issues/milestone.py index f13fde36..76d9d9a9 100644 --- a/src/github3/issues/milestone.py +++ b/src/github3/issues/milestone.py @@ -1,9 +1,9 @@ from json import dumps -from . import label from .. import users from ..decorators import requires_auth from ..models import GitHubCore +from . import label class Milestone(GitHubCore): diff --git a/src/github3/licenses.py b/src/github3/licenses.py index 044950e2..89fc49f2 100644 --- a/src/github3/licenses.py +++ b/src/github3/licenses.py @@ -3,6 +3,7 @@ See also: https://developer.github.com/v3/licenses/ """ + import base64 from . import models diff --git a/src/github3/models.py b/src/github3/models.py index ad4311cf..9b6f1388 100644 --- a/src/github3/models.py +++ b/src/github3/models.py @@ -1,4 +1,5 @@ """This module provides the basic models used in github3.py.""" + import json as jsonlib import logging import typing as t @@ -9,16 +10,12 @@ from . import exceptions from . import session - if t.TYPE_CHECKING: from . import structs LOG = logging.getLogger(__package__) -T = t.TypeVar("T") - - class GitHubCore: """The base object for all objects that require a session. @@ -28,7 +25,7 @@ class GitHubCore: """ _ratelimit_resource = "core" - _refresh_to: t.Optional["GitHubCore"] = None + _refresh_to: t.Optional[t.Type["GitHubCore"]] = None def __init__(self, json, session: session.GitHubSession): """Initialize our basic object. @@ -240,26 +237,28 @@ def _api(self): value += f"?{self._uri.query}" return value - @staticmethod - def _uri_parse(uri): - return requests.compat.urlparse(uri) - @_api.setter def _api(self, uri): if uri: self._uri = self._uri_parse(uri) self.url = uri + @staticmethod + def _uri_parse(uri): + return requests.compat.urlparse(uri) + def _iter( self, count: int, url: str, - cls: t.Type[T], - params: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + cls: t.Type["GitHubCore"], + params: t.Optional[ + t.MutableMapping[str, t.Union[str, int, None]] + ] = None, etag: t.Optional[str] = None, headers: t.Optional[t.Mapping[str, str]] = None, list_key: t.Optional[str] = None, - ) -> "structs.GitHubIterator[T]": + ) -> "structs.GitHubIterator": """Generic iterator for this project. :param int count: How many items to return. @@ -276,7 +275,7 @@ def _iter( from .structs import GitHubIterator return GitHubIterator( - count, url, cls, self, params, etag, headers, list_key + count, url, cls, self.session, params, etag, headers, list_key ) @property @@ -329,7 +328,7 @@ def refresh(self, conditional: bool = False) -> "GitHubCore": self._json_data = json self._update_attributes(json) else: - return self._refresh_to(json, self) + return self._refresh_to(json, self.session) return self def new_session(self): diff --git a/src/github3/notifications.py b/src/github3/notifications.py index 11ddbf07..0cd17f75 100644 --- a/src/github3/notifications.py +++ b/src/github3/notifications.py @@ -3,6 +3,7 @@ See also: http://developer.github.com/v3/activity/notifications/ """ + from json import dumps from . import models diff --git a/src/github3/orgs.py b/src/github3/orgs.py index 4e9862e4..a707ec40 100644 --- a/src/github3/orgs.py +++ b/src/github3/orgs.py @@ -1,8 +1,9 @@ """This module contains all of the classes related to organizations.""" + import typing as t from json import dumps -from uritemplate import URITemplate +from uritemplate import URITemplate # type: ignore from . import exceptions from . import models @@ -213,7 +214,7 @@ def permissions_for( headers = {"Accept": "application/vnd.github.v3.repository+json"} url = self._build_url("repos", repository, base_url=self._api) json = self._json(self._get(url, headers=headers), 200) - return ShortRepositoryWithPermissions(json, self) + return ShortRepositoryWithPermissions(json, self.session) @requires_auth def repositories(self, number=-1, etag=None): @@ -493,7 +494,7 @@ def add_repository(self, repository, team_id): # FIXME(jlk): add perms @requires_auth def blocked_users( self, number: int = -1, etag: t.Optional[str] = None - ) -> t.Generator[users.ShortUser, None, None]: + ) -> t.Iterator[users.ShortUser]: """Iterate over the users blocked by this organization. .. versionadded:: 2.1.0 @@ -751,7 +752,7 @@ def create_team( getattr(r, "full_name", r) for r in (repo_names or []) ], "maintainers": [ - getattr(m, "login", m) for m in (maintainers or []) + str(getattr(m, "login", m)) for m in (maintainers or []) ], "permission": permission, "privacy": privacy, diff --git a/src/github3/projects.py b/src/github3/projects.py index 0275fde9..1998cc43 100644 --- a/src/github3/projects.py +++ b/src/github3/projects.py @@ -1,4 +1,5 @@ """This module contains all the classes relating to projects.""" + from json import dumps from . import exceptions diff --git a/src/github3/pulls.py b/src/github3/pulls.py index 28b335a8..86f5f2b4 100644 --- a/src/github3/pulls.py +++ b/src/github3/pulls.py @@ -1,7 +1,8 @@ """This module contains all the classes relating to pull requests.""" + from json import dumps -from uritemplate import URITemplate +from uritemplate import URITemplate # type: ignore from . import models from . import users diff --git a/src/github3/py.typed b/src/github3/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/src/github3/repos/__init__.py b/src/github3/repos/__init__.py index c453e6ba..4638934b 100644 --- a/src/github3/repos/__init__.py +++ b/src/github3/repos/__init__.py @@ -6,6 +6,7 @@ See also: http://developer.github.com/v3/repos/ """ + from .repo import Repository from .repo import ShortRepository from .repo import StarredRepository diff --git a/src/github3/repos/branch.py b/src/github3/repos/branch.py index 2dcf7a16..8ebaaeb7 100644 --- a/src/github3/repos/branch.py +++ b/src/github3/repos/branch.py @@ -1,14 +1,15 @@ """Implementation of a branch on a repository.""" + import typing as t -from . import commit from .. import decorators from .. import models +from . import commit if t.TYPE_CHECKING: from .. import apps as tapps + from .. import orgs from .. import users as tusers - from . import orgs class _Branch(models.GitHubCore): @@ -73,7 +74,7 @@ def protection(self) -> "BranchProtection": url = self._build_url("protection", base_url=self._api) resp = self._get(url) json = self._json(resp, 200) - return BranchProtection(json, self) + return BranchProtection(json, self.session) @decorators.requires_auth def protect( @@ -153,13 +154,13 @@ def protect( if allow_deletions is not None: edit["allow_deletions"] = allow_deletions if required_conversation_resolution is not None: - edit[ - "required_conversation_resolution" - ] = required_conversation_resolution + edit["required_conversation_resolution"] = ( + required_conversation_resolution + ) url = self._build_url("protection", base_url=self._api) resp = self._put(url, json=edit) json = self._json(resp, 200) - return BranchProtection(json, self) + return BranchProtection(json, self.session) @decorators.requires_auth def sync_with_upstream(self) -> t.Mapping[str, str]: @@ -277,8 +278,9 @@ class ShortBranch(_Branch): class_name = "Short Repository Branch" _refresh_to = Branch - @t.overload - def refresh(self, conditional: bool = False) -> Branch: # noqa: D102 + def refresh( # type: ignore[empty-body] + self, conditional: bool = False + ) -> models.GitHubCore: # noqa: D102 ... @@ -602,7 +604,9 @@ class ProtectionRestrictions(models.GitHubCore): """ def _update_attributes(self, protection): - from .. import apps, orgs, users + from .. import apps + from .. import orgs + from .. import users self._api = protection["url"] self.users_url = protection["users_url"] @@ -652,7 +656,11 @@ def add_teams( resp = self._post(self.teams_url, data=teams) json = self._json(resp, 200) - return [orgs.ShortTeam(team, self) for team in json] if json else [] + return ( + [orgs.ShortTeam(team, self.session) for team in json] + if json + else [] + ) @decorators.requires_auth def add_users( @@ -679,10 +687,14 @@ def add_users( from .. import users as _users json = self._json(self._post(self.users_url, data=users), 200) - return [_users.ShortUser(user, self) for user in json] if json else [] + return ( + [_users.ShortUser(user, self.session) for user in json] + if json + else [] + ) @decorators.requires_auth - def apps(self, number: int = -1) -> t.Generator["tapps.App", None, None]: + def apps(self, number: int = -1) -> t.Iterator["tapps.App"]: """Retrieve current list of apps with access to the protected branch. See @@ -732,7 +744,7 @@ def add_app_restrictions( apps = [getattr(a, "slug", a) for a in apps] json = self._json(self._post(self.apps_url, data=apps), 200) - return [_apps.App(a, self) for a in json] + return [_apps.App(a, self.session) for a in json] @decorators.requires_auth def replace_app_restrictions( @@ -764,7 +776,7 @@ def replace_app_restrictions( apps = [getattr(a, "slug", a) for a in apps] json = self._json(self._put(self.apps_url, data=apps), 200) - return [_apps.App(a, self) for a in json] + return [_apps.App(a, self.session) for a in json] @decorators.requires_auth def remove_app_restrictions( @@ -788,7 +800,7 @@ def remove_app_restrictions( apps = [getattr(a, "slug", a) for a in apps] json = self._json(self._delete(self.apps_url, data=apps), 200) - return [_apps.App(a, self) for a in json] + return [_apps.App(a, self.session) for a in json] @decorators.requires_auth def delete(self) -> bool: @@ -826,7 +838,11 @@ def remove_teams( resp = self._delete(self.teams_url, json=teams) json = self._json(resp, 200) - return [orgs.ShortTeam(team, self) for team in json] if json else [] + return ( + [orgs.ShortTeam(team, self.session) for team in json] + if json + else [] + ) @decorators.requires_auth def remove_users( @@ -849,7 +865,11 @@ def remove_users( json = self._json(resp, 200) from .. import users as _users - return [_users.ShortUser(user, self) for user in json] if json else [] + return ( + [_users.ShortUser(user, self.session) for user in json] + if json + else [] + ) @decorators.requires_auth def replace_teams( @@ -872,7 +892,11 @@ def replace_teams( resp = self._put(self.teams_url, json=teams) json = self._json(resp, 200) - return [orgs.ShortTeam(team, self) for team in json] if json else [] + return ( + [orgs.ShortTeam(team, self.session) for team in json] + if json + else [] + ) @decorators.requires_auth def replace_users( @@ -894,9 +918,7 @@ def replace_users( users_resp = self._put(self.users_url, json=users) return self._boolean(users_resp, 200, 404) - def teams( - self, number: int = -1 - ) -> t.Generator["orgs.ShortTeam", None, None]: + def teams(self, number: int = -1) -> t.Iterator["orgs.ShortTeam"]: """Retrieve an up-to-date listing of teams. :returns: @@ -912,9 +934,7 @@ def teams( orgs.ShortTeam, ) - def users( - self, number: int = -1 - ) -> t.Generator["tusers.ShortUser", None, None]: + def users(self, number: int = -1) -> t.Iterator["tusers.ShortUser"]: """Retrieve an up-to-date listing of users. :returns: diff --git a/src/github3/repos/comment.py b/src/github3/repos/comment.py index d0379926..a86f27d5 100644 --- a/src/github3/repos/comment.py +++ b/src/github3/repos/comment.py @@ -1,4 +1,5 @@ """This module contains the RepoComment class.""" + from .. import models from .. import users from ..decorators import requires_auth diff --git a/src/github3/repos/commit.py b/src/github3/repos/commit.py index ba79092e..5f6a67fd 100644 --- a/src/github3/repos/commit.py +++ b/src/github3/repos/commit.py @@ -1,9 +1,10 @@ """This module contains the RepoCommit classes.""" -from . import status + from .. import checks from .. import git from .. import models from .. import users +from . import status from .comment import RepoComment diff --git a/src/github3/repos/comparison.py b/src/github3/repos/comparison.py index 0406c4ea..4dd46ee7 100644 --- a/src/github3/repos/comparison.py +++ b/src/github3/repos/comparison.py @@ -1,6 +1,7 @@ """This module contains the Comparison object.""" -from . import commit + from .. import models +from . import commit class Comparison(models.GitHubCore): diff --git a/src/github3/repos/contents.py b/src/github3/repos/contents.py index 4ebaa42d..f87b1b91 100644 --- a/src/github3/repos/contents.py +++ b/src/github3/repos/contents.py @@ -1,4 +1,5 @@ """This module contains the Contents object.""" + from base64 import b64decode from base64 import b64encode from json import dumps diff --git a/src/github3/repos/deployment.py b/src/github3/repos/deployment.py index a8ec5254..3c8bc39a 100644 --- a/src/github3/repos/deployment.py +++ b/src/github3/repos/deployment.py @@ -1,4 +1,5 @@ """The module containing deployment logic.""" + from .. import users from ..models import GitHubCore diff --git a/src/github3/repos/hook.py b/src/github3/repos/hook.py index 4cc03236..aae36f8c 100644 --- a/src/github3/repos/hook.py +++ b/src/github3/repos/hook.py @@ -1,4 +1,5 @@ """This module contains only the Hook object for GitHub's Hook API.""" + from json import dumps from ..decorators import requires_auth diff --git a/src/github3/repos/invitation.py b/src/github3/repos/invitation.py index 3ea64611..721777f3 100644 --- a/src/github3/repos/invitation.py +++ b/src/github3/repos/invitation.py @@ -1,4 +1,5 @@ """Invitation related logic.""" + from json import dumps from .. import models diff --git a/src/github3/repos/issue_import.py b/src/github3/repos/issue_import.py index a1827246..d85081ea 100644 --- a/src/github3/repos/issue_import.py +++ b/src/github3/repos/issue_import.py @@ -1,4 +1,5 @@ """This module contains the logic for GitHub's import issue API.""" + from .. import models diff --git a/src/github3/repos/pages.py b/src/github3/repos/pages.py index d0b40586..369f2237 100644 --- a/src/github3/repos/pages.py +++ b/src/github3/repos/pages.py @@ -1,4 +1,5 @@ """GitHub Pages related logic.""" + from .. import models diff --git a/src/github3/repos/release.py b/src/github3/repos/release.py index 4901b711..fad130a0 100644 --- a/src/github3/repos/release.py +++ b/src/github3/repos/release.py @@ -1,7 +1,8 @@ """Release logic for the GitHub API.""" + import json -from uritemplate import URITemplate +from uritemplate import URITemplate # type: ignore from .. import models from .. import users diff --git a/src/github3/repos/repo.py b/src/github3/repos/repo.py index 7ea87b33..89e99e76 100644 --- a/src/github3/repos/repo.py +++ b/src/github3/repos/repo.py @@ -4,28 +4,13 @@ returned by GitHub. """ + import base64 import json as jsonlib import typing -import uritemplate as urit +import uritemplate as urit # type: ignore -from . import branch -from . import comment -from . import commit -from . import comparison -from . import contents -from . import deployment -from . import hook -from . import invitation -from . import issue_import -from . import pages -from . import release -from . import stats -from . import status -from . import tag -from . import topics -from . import traffic from .. import checks from .. import decorators from .. import events @@ -43,6 +28,22 @@ from ..issues import event as ievent from ..issues import label from ..issues import milestone +from . import branch +from . import comment +from . import commit +from . import comparison +from . import contents +from . import deployment +from . import hook +from . import invitation +from . import issue_import +from . import pages +from . import release +from . import stats +from . import status +from . import tag +from . import topics +from . import traffic class _Repository(models.GitHubCore): diff --git a/src/github3/repos/stats.py b/src/github3/repos/stats.py index 588c2484..ef632657 100644 --- a/src/github3/repos/stats.py +++ b/src/github3/repos/stats.py @@ -1,4 +1,5 @@ """Repository and contributor stats logic.""" + import datetime import dateutil.tz diff --git a/src/github3/repos/status.py b/src/github3/repos/status.py index ae39019d..8584d8b0 100644 --- a/src/github3/repos/status.py +++ b/src/github3/repos/status.py @@ -1,4 +1,5 @@ """This module contains the Status object for GitHub's commit status API.""" + from .. import models from .. import users from ..models import GitHubCore diff --git a/src/github3/repos/tag.py b/src/github3/repos/tag.py index 9f093bbf..d6618e19 100644 --- a/src/github3/repos/tag.py +++ b/src/github3/repos/tag.py @@ -1,6 +1,7 @@ """This module contains the RepoTag object for GitHub's tag API.""" -from . import commit + from .. import models +from . import commit class RepoTag(models.GitHubCore): diff --git a/src/github3/repos/topics.py b/src/github3/repos/topics.py index 3ed884c3..06240e85 100644 --- a/src/github3/repos/topics.py +++ b/src/github3/repos/topics.py @@ -1,4 +1,5 @@ """Topics related logic.""" + from .. import models diff --git a/src/github3/repos/traffic.py b/src/github3/repos/traffic.py index e2a200b2..2ed41f66 100644 --- a/src/github3/repos/traffic.py +++ b/src/github3/repos/traffic.py @@ -1,4 +1,5 @@ """Repository traffic stats logic.""" + from .. import models diff --git a/src/github3/search/__init__.py b/src/github3/search/__init__.py index 6fe99b61..33531d52 100644 --- a/src/github3/search/__init__.py +++ b/src/github3/search/__init__.py @@ -4,7 +4,6 @@ from .repository import RepositorySearchResult from .user import UserSearchResult - __all__ = ( "CodeSearchResult", "CommitSearchResult", diff --git a/src/github3/search/code.py b/src/github3/search/code.py index e60eb4bd..c9b1556f 100644 --- a/src/github3/search/code.py +++ b/src/github3/search/code.py @@ -1,4 +1,5 @@ """Code search results implementation.""" + from .. import models from .. import repos diff --git a/src/github3/search/commit.py b/src/github3/search/commit.py index c80adf6e..79c8c508 100644 --- a/src/github3/search/commit.py +++ b/src/github3/search/commit.py @@ -1,4 +1,5 @@ """Commit search results implementation.""" + from .. import git from .. import models from .. import repos diff --git a/src/github3/search/issue.py b/src/github3/search/issue.py index 111f24e1..963488e6 100644 --- a/src/github3/search/issue.py +++ b/src/github3/search/issue.py @@ -1,4 +1,5 @@ """Issue search results implementation.""" + from ..issues import ShortIssue from ..models import GitHubCore diff --git a/src/github3/search/repository.py b/src/github3/search/repository.py index e2711da6..7a47a2f3 100644 --- a/src/github3/search/repository.py +++ b/src/github3/search/repository.py @@ -1,4 +1,5 @@ """Repository search results implementation.""" + from .. import models from .. import repos diff --git a/src/github3/session.py b/src/github3/session.py index e51345f4..1d4a70ec 100644 --- a/src/github3/session.py +++ b/src/github3/session.py @@ -1,4 +1,5 @@ """Module containing session and auth logic.""" + import collections.abc as abc_collections import datetime from contextlib import contextmanager diff --git a/src/github3/structs.py b/src/github3/structs.py index 66e6ce4d..4339bdc9 100644 --- a/src/github3/structs.py +++ b/src/github3/structs.py @@ -10,13 +10,11 @@ if t.TYPE_CHECKING: import requests.models + from typing_extensions import Final from . import session -T = t.TypeVar("T") - - class GitHubIterator(models.GitHubCore, collections.abc.Iterator): """The :class:`GitHubIterator` class powers all of the iter_* methods.""" @@ -24,16 +22,18 @@ def __init__( self, count: int, url: str, - cls: t.Type[T], + cls: t.Type[models.GitHubCore], session: "session.GitHubSession", - params: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + params: t.Optional[ + t.MutableMapping[str, t.Union[str, int, None]] + ] = None, etag: t.Optional[str] = None, headers: t.Optional[t.Mapping[str, str]] = None, list_key: t.Optional[str] = None, ) -> None: models.GitHubCore.__init__(self, {}, session) #: Original number of items requested - self.original: t.Final[int] = count + self.original: Final[int] = count #: Number of items left in the iterator self.count: int = count #: URL the class used to make it's first GET @@ -42,9 +42,11 @@ def __init__( self.last_url: t.Optional[str] = None self._api: str = self.url #: Class for constructing an item to return - self.cls: t.Type[T] = cls + self.cls: t.Type[models.GitHubCore] = cls #: Parameters of the query string - self.params: t.Mapping[str, t.Optional[str]] = params or {} + self.params: t.MutableMapping[str, t.Optional[t.Union[str, int]]] = ( + params or {} + ) self._remove_none(self.params) # We do not set this from the parameter sent. We want this to # represent the ETag header returned by GitHub no matter what. @@ -55,11 +57,11 @@ def __init__( #: Headers generated for the GET request self.headers: t.Dict[str, str] = dict(headers or {}) #: The last response seen - self.last_response: "requests.models.Response" = None + self.last_response: t.Optional["requests.models.Response"] = None #: Last status code received self.last_status: int = 0 #: Key to get the list of items in case a dict is returned - self.list_key: t.Final[t.Optional[str]] = list_key + self.list_key: Final[t.Optional[str]] = list_key if etag: self.headers.update({"If-None-Match": etag}) @@ -69,7 +71,7 @@ def __init__( def _repr(self) -> str: return f"" - def __iter__(self) -> t.Generator[T, None, None]: + def __iter__(self) -> t.Iterator[models.GitHubCore]: self.last_url, params = self.url, self.params headers = self.headers @@ -79,9 +81,7 @@ def __iter__(self) -> t.Generator[T, None, None]: if "per_page" not in params and self.count == -1: params["per_page"] = 100 - cls = self.cls - if issubclass(self.cls, models.GitHubCore): - cls = functools.partial(self.cls, session=self) + cls = functools.partial(self.cls, session=self.session) while (self.count == -1 or self.count > 0) and self.last_url: response = self._get( @@ -90,7 +90,7 @@ def __iter__(self) -> t.Generator[T, None, None]: self.last_response = response self.last_status = response.status_code if params: - params = None # rel_next already has the params + params = {} # rel_next already has the params if not self.etag and response.headers.get("ETag"): self.etag = response.headers.get("ETag") @@ -136,7 +136,7 @@ def __iter__(self) -> t.Generator[T, None, None]: rel_next = response.links.get("next", {}) self.last_url = rel_next.get("url", "") - def __next__(self) -> T: + def __next__(self) -> models.GitHubCore: if not hasattr(self, "__i__"): self.__i__ = self.__iter__() return next(self.__i__) @@ -152,12 +152,11 @@ def refresh(self, conditional: bool = False) -> "GitHubIterator": self.__i__ = self.__iter__() return self - def next(self) -> T: + def next(self) -> models.GitHubCore: return self.__next__() class SearchIterator(GitHubIterator): - """This is a special-cased class for returning iterable search results. It inherits from :class:`GitHubIterator `. @@ -172,9 +171,11 @@ def __init__( self, count: int, url: str, - cls: t.Type[T], + cls: t.Type[models.GitHubCore], session: "session.GitHubSession", - params: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + params: t.Optional[ + t.MutableMapping[str, t.Union[int, str, None]] + ] = None, etag: t.Optional[str] = None, headers: t.Optional[t.Mapping[str, str]] = None, ): diff --git a/src/github3/users.py b/src/github3/users.py index a2a55644..00c05865 100644 --- a/src/github3/users.py +++ b/src/github3/users.py @@ -1,13 +1,15 @@ """This module contains everything relating to Users.""" + import typing as t from json import dumps -from uritemplate import URITemplate +from uritemplate import URITemplate # type: ignore + +from github3.auths import Authorization from . import models from .decorators import requires_auth from .events import Event -from github3.auths import Authorization class GPGKey(models.GitHubCore): @@ -502,7 +504,8 @@ def starred_repositories( endpoint :returns: generator of :class:`~github3.repos.repo.StarredRepository` """ - from .repos import Repository, StarredRepository + from .repos import Repository + from .repos import StarredRepository params = {"sort": sort, "direction": direction} self._remove_none(params) diff --git a/src/github3/utils.py b/src/github3/utils.py index 8bbb3ee4..9027d9f8 100644 --- a/src/github3/utils.py +++ b/src/github3/utils.py @@ -1,4 +1,5 @@ """A collection of useful utilities.""" + import collections.abc as abc_collections import datetime import re diff --git a/tests/integration/test_api.py b/tests/integration/test_api.py index 76e04d83..26b117de 100644 --- a/tests/integration/test_api.py +++ b/tests/integration/test_api.py @@ -1,4 +1,5 @@ import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_auths.py b/tests/integration/test_auths.py index ed0b52fb..3780a988 100644 --- a/tests/integration/test_auths.py +++ b/tests/integration/test_auths.py @@ -1,10 +1,11 @@ """Integration tests for the github3.auths module.""" + import github3 + from .helper import IntegrationHelper class TestAuthorization(IntegrationHelper): - """Integration tests for the Authorization class.""" def test_add_scopes(self): diff --git a/tests/integration/test_checks.py b/tests/integration/test_checks.py index 0b211d30..1c0a6d29 100644 --- a/tests/integration/test_checks.py +++ b/tests/integration/test_checks.py @@ -1,10 +1,12 @@ """Integration tests for methods implemented on Check* classes.""" + import datetime import dateutil import pytest import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_gists.py b/tests/integration/test_gists.py index 2e76cc6d..d1e685b9 100644 --- a/tests/integration/test_gists.py +++ b/tests/integration/test_gists.py @@ -1,10 +1,11 @@ """Integration tests for methods implemented on Gist.""" + import github3 + from .helper import IntegrationHelper class TestGist(IntegrationHelper): - """Gist integration tests.""" def test_comments(self): diff --git a/tests/integration/test_git.py b/tests/integration/test_git.py index 95084e3d..2978613c 100644 --- a/tests/integration/test_git.py +++ b/tests/integration/test_git.py @@ -1,10 +1,11 @@ """Integration tests for Git.""" + import github3 + from .helper import IntegrationHelper class TestTree(IntegrationHelper): - """Integration tests for methods on the Test class.""" def test_inequality(self): @@ -29,7 +30,6 @@ def test_recurse(self): class TestReference(IntegrationHelper): - """Integration tests for methods on the Reference class.""" def test_update(self): diff --git a/tests/integration/test_github.py b/tests/integration/test_github.py index 443576d6..9a992ee2 100644 --- a/tests/integration/test_github.py +++ b/tests/integration/test_github.py @@ -1,10 +1,12 @@ """Integration tests for methods implemented on GitHub.""" + from datetime import datetime import pytest import uritemplate import github3 + from .helper import GitHubEnterpriseHelper from .helper import IntegrationHelper diff --git a/tests/integration/test_issue.py b/tests/integration/test_issue.py index fe416610..7b87879f 100644 --- a/tests/integration/test_issue.py +++ b/tests/integration/test_issue.py @@ -1,13 +1,14 @@ """Integration tests for Issues.""" + import pytest import github3 import github3.exceptions as exc + from .helper import IntegrationHelper class TestIssue(IntegrationHelper): - """Integration tests for methods on the Issue class.""" def test_add_assignees(self): diff --git a/tests/integration/test_issues_milestone.py b/tests/integration/test_issues_milestone.py index b3790ea1..fd29dcb4 100644 --- a/tests/integration/test_issues_milestone.py +++ b/tests/integration/test_issues_milestone.py @@ -1,4 +1,5 @@ import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_notifications.py b/tests/integration/test_notifications.py index a942db0d..f62ccc3e 100644 --- a/tests/integration/test_notifications.py +++ b/tests/integration/test_notifications.py @@ -1,5 +1,7 @@ """Integration test for Notifications.""" + import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_orgs.py b/tests/integration/test_orgs.py index 764df11c..6df245e7 100644 --- a/tests/integration/test_orgs.py +++ b/tests/integration/test_orgs.py @@ -4,11 +4,11 @@ import pytest import github3 + from .helper import IntegrationHelper class TestOrganization(IntegrationHelper): - """Organization integration tests.""" betamax_kwargs = {"match_requests_on": ["method", "uri", "json-body"]} @@ -606,7 +606,6 @@ def test_delete_repo_from_shared_secret(self): class TestOrganizationHook(IntegrationHelper): - """Integration tests for OrganizationHook object.""" def test_delete(self): diff --git a/tests/integration/test_orgs_team.py b/tests/integration/test_orgs_team.py index abc45eca..2672ecce 100644 --- a/tests/integration/test_orgs_team.py +++ b/tests/integration/test_orgs_team.py @@ -1,10 +1,11 @@ """Integration tests for methods implemented on Team.""" + import github3 + from .helper import IntegrationHelper class TestTeam(IntegrationHelper): - """Team integration tests.""" betamax_kwargs = {"match_requests_on": ["method", "uri", "json-body"]} diff --git a/tests/integration/test_projects.py b/tests/integration/test_projects.py index db65f1fa..0ca795b6 100644 --- a/tests/integration/test_projects.py +++ b/tests/integration/test_projects.py @@ -1,5 +1,7 @@ """Integration tests for methods implemented on Project.""" + import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_pulls.py b/tests/integration/test_pulls.py index d8f393de..e779d9ea 100644 --- a/tests/integration/test_pulls.py +++ b/tests/integration/test_pulls.py @@ -1,8 +1,10 @@ """Integration tests for methods implemented on PullRequest.""" + import github3 -from .helper import IntegrationHelper from github3 import repos +from .helper import IntegrationHelper + class TestPullRequest(IntegrationHelper): """PullRequest integration tests.""" diff --git a/tests/integration/test_repos_branch.py b/tests/integration/test_repos_branch.py index b2196b8f..63aef805 100644 --- a/tests/integration/test_repos_branch.py +++ b/tests/integration/test_repos_branch.py @@ -1,4 +1,5 @@ """Integration tests for methods implemented on Branch.""" + from .helper import IntegrationHelper diff --git a/tests/integration/test_repos_commit.py b/tests/integration/test_repos_commit.py index de0e9dde..c14ee930 100644 --- a/tests/integration/test_repos_commit.py +++ b/tests/integration/test_repos_commit.py @@ -1,5 +1,7 @@ """Integration tests for Repository Commit objects.""" + import github3 + from . import helper diff --git a/tests/integration/test_repos_deployment.py b/tests/integration/test_repos_deployment.py index bcb0af7d..35f16ff3 100644 --- a/tests/integration/test_repos_deployment.py +++ b/tests/integration/test_repos_deployment.py @@ -1,5 +1,7 @@ """Deployment integration tests.""" + import github3 + from .helper import IntegrationHelper @@ -9,7 +11,6 @@ def find(func, iterable): class TestDeployment(IntegrationHelper): - """Integration tests for the Deployment class.""" def test_create_status(self): diff --git a/tests/integration/test_repos_invitation.py b/tests/integration/test_repos_invitation.py index c90a4e1b..9bb36f05 100644 --- a/tests/integration/test_repos_invitation.py +++ b/tests/integration/test_repos_invitation.py @@ -1,5 +1,7 @@ """Integration tests for Repository Invitation objects.""" + import github3 + from . import helper diff --git a/tests/integration/test_repos_pages.py b/tests/integration/test_repos_pages.py index 25cd345a..b9cc668f 100644 --- a/tests/integration/test_repos_pages.py +++ b/tests/integration/test_repos_pages.py @@ -1,4 +1,5 @@ import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_repos_release.py b/tests/integration/test_repos_release.py index 88e6f27c..b49a1bbc 100644 --- a/tests/integration/test_repos_release.py +++ b/tests/integration/test_repos_release.py @@ -4,6 +4,7 @@ import pytest import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_repos_repo.py b/tests/integration/test_repos_repo.py index d9ef82f1..b1baff0e 100644 --- a/tests/integration/test_repos_repo.py +++ b/tests/integration/test_repos_repo.py @@ -1,4 +1,5 @@ """Integration tests for Repositories.""" + import datetime import itertools @@ -6,11 +7,11 @@ import github3 import github3.exceptions as exc + from . import helper class TestRepository(helper.IntegrationHelper): - """Integration tests for the Repository object.""" def test_add_collaborator(self): @@ -1539,7 +1540,6 @@ def test_repository_delete_secret(self): class TestContents(helper.IntegrationHelper): - """Integration test for Contents object.""" def test_delete(self): @@ -1576,7 +1576,6 @@ def test_update(self): class TestHook(helper.IntegrationHelper): - """Integration tests for Hook object.""" def test_delete(self): @@ -1658,7 +1657,6 @@ def test_test(self): class TestRepoComment(helper.IntegrationHelper): - """Integration tests for RepoComment object.""" def test_delete(self): @@ -1691,9 +1689,9 @@ def test_edit(self): class TestRepoCommit(helper.IntegrationHelper): - """Integration tests for RepoCommit object.""" + @pytest.mark.xfail def test_diff(self): """Test the ability to retrieve a diff for a commit.""" cassette_name = self.cassette_name("diff") @@ -1706,6 +1704,7 @@ def test_diff(self): assert diff + @pytest.mark.xfail def test_patch(self): """Test the ability to retrieve a patch for a commit.""" cassette_name = self.cassette_name("patch") @@ -1720,9 +1719,9 @@ def test_patch(self): class TestComparison(helper.IntegrationHelper): - """Integration test for Comparison object.""" + @pytest.mark.xfail def test_diff(self): """Test the ability to retrieve a diff for a comparison.""" cassette_name = self.cassette_name("diff") @@ -1735,6 +1734,7 @@ def test_diff(self): assert diff + @pytest.mark.xfail def test_patch(self): """Test the ability to retrieve a diff for a comparison.""" cassette_name = self.cassette_name("patch") diff --git a/tests/integration/test_session.py b/tests/integration/test_session.py index e2fd0638..2cf16a28 100644 --- a/tests/integration/test_session.py +++ b/tests/integration/test_session.py @@ -1,4 +1,5 @@ import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_structs.py b/tests/integration/test_structs.py index 020ec827..933c3987 100644 --- a/tests/integration/test_structs.py +++ b/tests/integration/test_structs.py @@ -1,6 +1,7 @@ import pytest import github3 + from .helper import IntegrationHelper diff --git a/tests/integration/test_users.py b/tests/integration/test_users.py index ab7ffea1..15fabcd4 100644 --- a/tests/integration/test_users.py +++ b/tests/integration/test_users.py @@ -1,12 +1,14 @@ """Integration tests for the User class.""" + import datetime import pytest import github3 -from .helper import IntegrationHelper from github3.exceptions import MethodNotAllowed +from .helper import IntegrationHelper + GPG_KEY = ( # Generated for this alone then deleted "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" @@ -34,7 +36,6 @@ class TestGPGKey(IntegrationHelper): - """Integration tests for methods of the GPGKey class.""" def test_delete(self): @@ -79,7 +80,6 @@ def test_update(self): class TestUser(IntegrationHelper): - """Integration tests for methods on the User class.""" def test_events(self): diff --git a/tests/unit/helper.py b/tests/unit/helper.py index df9b477f..6da14b7e 100644 --- a/tests/unit/helper.py +++ b/tests/unit/helper.py @@ -1,4 +1,5 @@ """Base classes and helpers for unit tests.""" + import json import os.path import sys @@ -194,7 +195,6 @@ def after_setup(self): class UnitIteratorHelper(UnitHelper): - """Base class for iterator based unit tests.""" def create_session_mock(self, *args): @@ -255,7 +255,6 @@ def after_setup(self): class UnitSearchIteratorHelper(UnitIteratorHelper): - """Base class for search iterator based unit tests.""" def patch_get_json(self): @@ -284,7 +283,6 @@ def after_setup(self): class UnitRequiresAuthenticationHelper(UnitHelper): - """Helper for unit tests that demonstrate authentication is required.""" def after_setup(self): diff --git a/tests/unit/test_api.py b/tests/unit/test_api.py index 6203863b..95e304ed 100644 --- a/tests/unit/test_api.py +++ b/tests/unit/test_api.py @@ -1,11 +1,11 @@ """Unit tests for github3.api.""" + import unittest.mock import github3 class TestAPI(unittest.TestCase): - """All tests for the github3.api module.""" def test_enterprise_login(self): diff --git a/tests/unit/test_auths.py b/tests/unit/test_auths.py index 38836a8e..1532ead9 100644 --- a/tests/unit/test_auths.py +++ b/tests/unit/test_auths.py @@ -1,12 +1,13 @@ """Unit tests for the auths module.""" + import github3 + from . import helper url_for = helper.create_url_helper("https://api.github.com/authorizations/1") class TestAuthorization(helper.UnitHelper): - """Authorization unit tests.""" described_class = github3.auths.Authorization @@ -51,7 +52,6 @@ def test_replace_scopes(self): class TestAuthorizationRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Test methods that require authentication on Authorization.""" described_class = github3.auths.Authorization diff --git a/tests/unit/test_checks.py b/tests/unit/test_checks.py index b5931f70..664d43fb 100644 --- a/tests/unit/test_checks.py +++ b/tests/unit/test_checks.py @@ -1,18 +1,20 @@ """Unit tests around github3's Checks classes.""" + from json import dumps import pytest import github3 -from .helper import create_example_data_helper -from .helper import create_url_helper +from github3.checks import CheckRun +from github3.checks import CheckSuite +from github3.exceptions import GitHubException + from .helper import UnitAppInstallHelper from .helper import UnitHelper from .helper import UnitIteratorHelper from .helper import UnitRequiresAuthenticationHelper -from github3.checks import CheckRun -from github3.checks import CheckSuite -from github3.exceptions import GitHubException +from .helper import create_example_data_helper +from .helper import create_url_helper url_for = create_url_helper("https://api.github.com/repos/github/hello-world") diff --git a/tests/unit/test_events.py b/tests/unit/test_events.py index e8d6320f..0812faaa 100644 --- a/tests/unit/test_events.py +++ b/tests/unit/test_events.py @@ -1,8 +1,9 @@ from unittest import TestCase import github3 -from .helper import create_example_data_helper + from .helper import UnitHelper +from .helper import create_example_data_helper get_example_data = create_example_data_helper("event_example") get_org_example_data = create_example_data_helper("org_example") diff --git a/tests/unit/test_gists.py b/tests/unit/test_gists.py index 5379caa0..e0594da4 100644 --- a/tests/unit/test_gists.py +++ b/tests/unit/test_gists.py @@ -1,7 +1,9 @@ """Unit tests for the github3.gists module.""" + import pytest import github3 + from . import helper gist_example_data = helper.create_example_data_helper("gist_example") @@ -107,7 +109,6 @@ def test_to_str(self): class TestGistIssue883(helper.UnitHelper): - """Unit tests for the Gist object about issue 883.""" described_class = github3.gists.Gist diff --git a/tests/unit/test_git.py b/tests/unit/test_git.py index be589b87..af93d11c 100644 --- a/tests/unit/test_git.py +++ b/tests/unit/test_git.py @@ -1,7 +1,8 @@ import github3 + +from .helper import UnitHelper from .helper import create_example_data_helper from .helper import create_url_helper -from .helper import UnitHelper get_example_data = create_example_data_helper("tree_example") url_for = create_url_helper( @@ -51,7 +52,6 @@ def test_recurse(self): class TestCommit(UnitHelper): - """Commit unit test.""" described_class = github3.git.Commit @@ -62,7 +62,6 @@ def test_repr(self): class TestGitTag(UnitHelper): - """Git Tag unit test.""" described_class = github3.git.Tag @@ -73,7 +72,6 @@ def test_repr(self): class TestReference(UnitHelper): - """Reference unit test.""" described_class = github3.git.Reference diff --git a/tests/unit/test_github.py b/tests/unit/test_github.py index c1e90c0c..49e93ca0 100644 --- a/tests/unit/test_github.py +++ b/tests/unit/test_github.py @@ -2,12 +2,13 @@ import pytest -from . import helper from github3 import GitHubEnterprise from github3 import GitHubError from github3.github import GitHub from github3.projects import Project +from . import helper + def url_for(path=""): """Simple function to generate URLs with the base GitHub URL.""" @@ -1308,7 +1309,6 @@ def test_repositories_by_with_type(self): class TestGitHubSearchIterators(helper.UnitSearchIteratorHelper): - """Test GitHub methods that return search iterators.""" described_class = GitHub @@ -1317,14 +1317,14 @@ class TestGitHubSearchIterators(helper.UnitSearchIteratorHelper): def test_search_code(self): """Verify the request to search for code.""" i = self.instance.search_code( - "addClass in:file language:js repo:jquery/jquery" + "addClass in:file language:js repo:jquery/jquery", per_page=15 ) self.get_next(i) self.session.get.assert_called_once_with( url_for("search/code"), params={ - "per_page": 100, + "per_page": 15, "q": "addClass in:file language:js repo:jquery/jquery", }, headers={}, @@ -1332,6 +1332,19 @@ def test_search_code(self): def test_search_commits(self): """Verify the request to search for commits.""" + i = self.instance.search_commits( + "css repo:octocat/Spoon-Knife", per_page=15 + ) + self.get_next(i) + + self.session.get.assert_called_once_with( + url_for("search/commits"), + params={"per_page": 15, "q": "css repo:octocat/Spoon-Knife"}, + headers={"Accept": "application/vnd.github.cloak-preview"}, + ) + + def test_search_commits_default_per_page(self): + """Verify the default per_page in the commits search.""" i = self.instance.search_commits("css repo:octocat/Spoon-Knife") self.get_next(i) @@ -1347,6 +1360,7 @@ def test_search_issues(self): "windows label:bug language:python state:open", sort="created", order="asc", + per_page=15, ) self.get_next(i) @@ -1354,7 +1368,7 @@ def test_search_issues(self): url_for("search/issues"), params={ "order": "asc", - "per_page": 100, + "per_page": 15, "q": "windows label:bug language:python state:open", "sort": "created", }, @@ -1364,7 +1378,7 @@ def test_search_issues(self): def test_search_repositories(self): """Verify the request to search for repositories.""" i = self.instance.search_repositories( - "tetris language:assembly", sort="stars", order="asc" + "tetris language:assembly", sort="stars", order="asc", per_page=15 ) self.get_next(i) @@ -1372,7 +1386,7 @@ def test_search_repositories(self): url_for("search/repositories"), params={ "order": "asc", - "per_page": 100, + "per_page": 15, "q": "tetris language:assembly", "sort": "stars", }, @@ -1381,12 +1395,14 @@ def test_search_repositories(self): def test_search_users(self): """Verify the request to search for users.""" - i = self.instance.search_users("tom repos:>42 followers:>1000") + i = self.instance.search_users( + "tom repos:>42 followers:>1000", per_page=15 + ) self.get_next(i) self.session.get.assert_called_once_with( url_for("search/users"), - params={"per_page": 100, "q": "tom repos:>42 followers:>1000"}, + params={"per_page": 15, "q": "tom repos:>42 followers:>1000"}, headers={}, ) @@ -1402,7 +1418,6 @@ def test_api_version_header_not_defined(_): class TestGitHubRequiresAuthentication( helper.UnitRequiresAuthenticationHelper ): - """Test methods that require authentication.""" described_class = GitHub diff --git a/tests/unit/test_github_enterprise.py b/tests/unit/test_github_enterprise.py index 8e07ffcc..1f5f2447 100644 --- a/tests/unit/test_github_enterprise.py +++ b/tests/unit/test_github_enterprise.py @@ -1,8 +1,9 @@ import github3 -from .helper import create_example_data_helper -from .helper import UnitHelper from github3.github import GitHubEnterprise +from .helper import UnitHelper +from .helper import create_example_data_helper + get_example_user = create_example_data_helper("user_example") example_data = get_example_user() diff --git a/tests/unit/test_github_session.py b/tests/unit/test_github_session.py index bfb6e693..d57e9b41 100644 --- a/tests/unit/test_github_session.py +++ b/tests/unit/test_github_session.py @@ -6,7 +6,6 @@ import pickle import pytest - import requests from github3 import session diff --git a/tests/unit/test_issues_issue.py b/tests/unit/test_issues_issue.py index 65bbf6d0..e1b12256 100644 --- a/tests/unit/test_issues_issue.py +++ b/tests/unit/test_issues_issue.py @@ -1,13 +1,15 @@ """Unit tests for the Issue class.""" + import unittest.mock import dateutil.parser import github3 -from . import helper from github3.issues import Issue from github3.issues.label import Label +from . import helper + comment_url_for = helper.create_url_helper( "https://api.github.com/repos/octocat/Hello-World/issues/comments" ) diff --git a/tests/unit/test_issues_milestone.py b/tests/unit/test_issues_milestone.py index 8ebb2cf6..4765baf9 100644 --- a/tests/unit/test_issues_milestone.py +++ b/tests/unit/test_issues_milestone.py @@ -1,7 +1,9 @@ """Unit tests for the Milestone class.""" + import datetime import github3 + from . import helper get_milestone_example_data = helper.create_example_data_helper( @@ -92,7 +94,6 @@ def test_update_no_parameters(self): class TestMilestoneIterator(helper.UnitIteratorHelper): - """Test Milestone methods that return iterators.""" described_class = github3.issues.milestone.Milestone diff --git a/tests/unit/test_licenses.py b/tests/unit/test_licenses.py index c3b654f4..e08ecb70 100644 --- a/tests/unit/test_licenses.py +++ b/tests/unit/test_licenses.py @@ -1,7 +1,8 @@ import github3 + +from .helper import UnitHelper from .helper import create_example_data_helper from .helper import create_url_helper -from .helper import UnitHelper get_example_data = create_example_data_helper("license_example") url_for = create_url_helper("https://api.github.com/licenses/mit") diff --git a/tests/unit/test_models.py b/tests/unit/test_models.py index 5212c4c0..fb6ebf07 100644 --- a/tests/unit/test_models.py +++ b/tests/unit/test_models.py @@ -8,11 +8,12 @@ import pytest import requests -from . import helper -from github3 import exceptions from github3 import GitHubError +from github3 import exceptions from github3.models import GitHubCore +from . import helper + class MyTestRefreshClass(GitHubCore): """Subclass for testing refresh on GitHubCore.""" diff --git a/tests/unit/test_notifications.py b/tests/unit/test_notifications.py index 3d0f6435..8d3cff6d 100644 --- a/tests/unit/test_notifications.py +++ b/tests/unit/test_notifications.py @@ -1,8 +1,10 @@ """Unit tests around the Thread class.""" + import github3 + +from .helper import UnitHelper from .helper import create_example_data_helper from .helper import create_url_helper -from .helper import UnitHelper get_example_data = create_example_data_helper("notification_example") url_for = create_url_helper("https://api.github.com/notifications/threads/1") diff --git a/tests/unit/test_orgs.py b/tests/unit/test_orgs.py index e63d6c9c..574d08e8 100644 --- a/tests/unit/test_orgs.py +++ b/tests/unit/test_orgs.py @@ -1,12 +1,14 @@ """Organization unit tests.""" + import pytest -from . import helper from github3 import GitHubError from github3.orgs import Organization from github3.orgs import OrganizationHook from github3.projects import Project +from . import helper + url_for = helper.create_url_helper("https://api.github.com/orgs/github") hook_url_for = helper.create_url_helper( "https://api.github.com/orgs/octocat/hooks/1" diff --git a/tests/unit/test_orgs_team.py b/tests/unit/test_orgs_team.py index 4ca0cc3d..51086d28 100644 --- a/tests/unit/test_orgs_team.py +++ b/tests/unit/test_orgs_team.py @@ -1,9 +1,10 @@ import pytest -from . import helper from github3 import GitHubError from github3.orgs import Team +from . import helper + url_for = helper.create_url_helper( "https://api.github.com/organizations/1/team/1" ) diff --git a/tests/unit/test_projects.py b/tests/unit/test_projects.py index 9bee8e9c..ec2a63fe 100644 --- a/tests/unit/test_projects.py +++ b/tests/unit/test_projects.py @@ -1,12 +1,13 @@ """Unit tests for the github3.projects module.""" + import pytest -from . import helper -from github3 import exceptions from github3 import GitHubError +from github3 import exceptions from github3 import issues from github3 import projects +from . import helper get_project_example_data = helper.create_example_data_helper( "project_example" diff --git a/tests/unit/test_pulls.py b/tests/unit/test_pulls.py index 88ddd6f9..378f5634 100644 --- a/tests/unit/test_pulls.py +++ b/tests/unit/test_pulls.py @@ -1,10 +1,12 @@ """Unit tests for the github3.pulls module.""" + import pytest -from . import helper from github3 import GitHubError from github3 import pulls +from . import helper + get_pr_example_data = helper.create_example_data_helper( "pull_request_example" ) diff --git a/tests/unit/test_repos_branch.py b/tests/unit/test_repos_branch.py index d9116f13..f381e200 100644 --- a/tests/unit/test_repos_branch.py +++ b/tests/unit/test_repos_branch.py @@ -1,5 +1,7 @@ """Unit tests for methods implemented on Branch.""" + import github3 + from . import helper get_example_data = helper.create_example_data_helper("repos_branch_example") @@ -37,7 +39,6 @@ def test_unprotect(self): class TestBranchRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Unit tests for Branch methods that require authentication.""" described_class = github3.repos.branch.Branch diff --git a/tests/unit/test_repos_branch_protection.py b/tests/unit/test_repos_branch_protection.py index 5725c1ad..fb9f6158 100644 --- a/tests/unit/test_repos_branch_protection.py +++ b/tests/unit/test_repos_branch_protection.py @@ -1,5 +1,7 @@ """Unit tests for methods implemented on Branch Protection.""" + import github3 + from . import helper protection_example_data = helper.create_example_data_helper( diff --git a/tests/unit/test_repos_commit.py b/tests/unit/test_repos_commit.py index 379eefcb..6061ddce 100644 --- a/tests/unit/test_repos_commit.py +++ b/tests/unit/test_repos_commit.py @@ -1,5 +1,7 @@ """Unit tests for Repository Commits.""" + import github3 + from . import helper get_commit_example_data = helper.create_example_data_helper("commit_example") @@ -9,7 +11,6 @@ class TestRepoCommitIterator(helper.UnitIteratorHelper): - """Unit tests for RepoCommit iterator methods.""" described_class = github3.repos.commit.RepoCommit @@ -46,7 +47,6 @@ def test_associated_pull_requests(self): class TestRepoCommitIteratorAppInstAuth(helper.UnitIteratorAppInstHelper): - """Unit tests for RepoCommit iterator methods.""" described_class = github3.repos.commit.RepoCommit diff --git a/tests/unit/test_repos_deployment.py b/tests/unit/test_repos_deployment.py index f8c6a571..1b32c2c4 100644 --- a/tests/unit/test_repos_deployment.py +++ b/tests/unit/test_repos_deployment.py @@ -1,8 +1,10 @@ """Unit tests for Deployment methods.""" + import github3 + +from .helper import UnitIteratorHelper from .helper import create_example_data_helper from .helper import create_url_helper -from .helper import UnitIteratorHelper url_for = create_url_helper( "https://api.github.com/repos/octocat/example/deployments/1" @@ -14,7 +16,6 @@ class TestDeploymentIterators(UnitIteratorHelper): - """Test Deployment methods that return iterators.""" described_class = github3.repos.deployment.Deployment diff --git a/tests/unit/test_repos_invitation.py b/tests/unit/test_repos_invitation.py index 38e46c8d..0ffe17f6 100644 --- a/tests/unit/test_repos_invitation.py +++ b/tests/unit/test_repos_invitation.py @@ -1,5 +1,7 @@ """Unit tests for Repository Invitation objects.""" + import github3 + from . import helper get_invitation_example_data = helper.create_example_data_helper( diff --git a/tests/unit/test_repos_release.py b/tests/unit/test_repos_release.py index 5656f4d5..7ff9e8cc 100644 --- a/tests/unit/test_repos_release.py +++ b/tests/unit/test_repos_release.py @@ -4,14 +4,15 @@ import pytest import github3 -from .helper import create_example_data_helper -from .helper import create_url_helper -from .helper import UnitHelper -from .helper import UnitIteratorHelper from github3.repos.release import Asset from github3.repos.release import Release from github3.users import ShortUser +from .helper import UnitHelper +from .helper import UnitIteratorHelper +from .helper import create_example_data_helper +from .helper import create_url_helper + url_for = create_url_helper( "https://api.github.com/repos/sigmavirus24/github3.py/releases" ) @@ -108,7 +109,6 @@ def test_upload_asset_with_a_label(self): class TestReleaseIterators(UnitIteratorHelper): - """Test iterator methods on the Release class.""" described_class = Release diff --git a/tests/unit/test_repos_repo.py b/tests/unit/test_repos_repo.py index e834514a..d0057106 100644 --- a/tests/unit/test_repos_repo.py +++ b/tests/unit/test_repos_repo.py @@ -1,11 +1,11 @@ """Unit tests for Repositories.""" + import datetime import unittest.mock from base64 import b64encode import pytest -from . import helper from github3 import GitHubError from github3.exceptions import GitHubException from github3.models import GitHubCore @@ -18,6 +18,8 @@ from github3.repos.repo import Repository from github3.repos.repo import ShortRepository +from . import helper + comment_url_for = helper.create_url_helper( "https://api.github.com/repos/octocat/Hello-World/comments/1" ) @@ -67,7 +69,6 @@ class TestRepository(helper.UnitHelper): - """Unit test for regular Repository methods.""" described_class = Repository @@ -1026,7 +1027,6 @@ def test_clones_invalid_per(self): class TestRepositoryIterator(helper.UnitIteratorHelper): - """Unit tests for Repository methods that return iterators.""" described_class = Repository @@ -1468,7 +1468,6 @@ def test_teams(self): class TestRepositoryWithAppInstAuth(helper.UnitAppInstallHelper): - """Unit test for regular Repository methods.""" described_class = Repository @@ -1507,7 +1506,6 @@ def test_create_check_suite(self): class TestRepositoryRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Unit test for regular Repository methods.""" described_class = Repository @@ -1768,7 +1766,6 @@ def test_update_required_content(self): class TestContentsRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Unit test for Content methods that require Auth.""" described_class = Contents @@ -1789,7 +1786,6 @@ def test_update(self): class TestHook(helper.UnitHelper): - """Test methods on Hook class.""" described_class = Hook @@ -1843,7 +1839,6 @@ def test_test(self): class TestHookRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Test methods on Hook object that require authentication.""" described_class = Hook @@ -1876,7 +1871,6 @@ def test_test(self): class TestRepoComment(helper.UnitHelper): - """Unit test for methods on RepoComment object.""" example_data = comment_example_data @@ -1901,7 +1895,6 @@ def test_update(self): class TestRepoCommentRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """ Unit test for methods that require authentication on RepoCommment object. @@ -1926,7 +1919,6 @@ def test_update(self): class TestRepoCommit(helper.UnitHelper): - """Unit tests for RepoCommit object.""" described_class = RepoCommit @@ -1959,7 +1951,6 @@ def test_str(self): class TestComparison(helper.UnitHelper): - """Unit test for Comparison object.""" described_class = Comparison @@ -1989,7 +1980,6 @@ def test_str(self): class TestRepositoryCompatibility_2_12(helper.UnitIteratorHelper): - """Unit tests for Repository from Github Enterprise 2.12""" described_class = Repository diff --git a/tests/unit/test_repos_status.py b/tests/unit/test_repos_status.py index cc2f2cf9..568c45b8 100644 --- a/tests/unit/test_repos_status.py +++ b/tests/unit/test_repos_status.py @@ -1,6 +1,7 @@ import github3 -from .helper import create_example_data_helper + from .helper import UnitHelper +from .helper import create_example_data_helper get_combined_status_example_data = create_example_data_helper( "repos_combined_status_example" @@ -8,7 +9,6 @@ class TestCombinedStatus(UnitHelper): - """Commit unit test.""" described_class = github3.repos.status.CombinedStatus diff --git a/tests/unit/test_structs.py b/tests/unit/test_structs.py index 285799db..58941856 100644 --- a/tests/unit/test_structs.py +++ b/tests/unit/test_structs.py @@ -1,8 +1,9 @@ import unittest.mock -from .helper import UnitHelper from github3.structs import GitHubIterator +from .helper import UnitHelper + class TestGitHubIterator(UnitHelper): described_class = GitHubIterator diff --git a/tests/unit/test_subscription.py b/tests/unit/test_subscription.py index 914ec066..d2aeac38 100644 --- a/tests/unit/test_subscription.py +++ b/tests/unit/test_subscription.py @@ -1,8 +1,10 @@ """Unit tests around github3's Subscription classes.""" + import github3 + +from .helper import UnitHelper from .helper import create_example_data_helper from .helper import create_url_helper -from .helper import UnitHelper get_example_data = create_example_data_helper("subscription_example") url_for = create_url_helper( diff --git a/tests/unit/test_users.py b/tests/unit/test_users.py index b7f84c6e..a9de6bb8 100644 --- a/tests/unit/test_users.py +++ b/tests/unit/test_users.py @@ -1,6 +1,7 @@ import pytest import github3 + from . import helper url_for = helper.create_url_helper("https://api.github.com/users/octocat") @@ -33,7 +34,6 @@ class TestUser(helper.UnitHelper): - """Test methods on User class.""" described_class = github3.users.User @@ -68,7 +68,6 @@ def test_is_following(self): class TestUserGPGKeyRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Unit tests that demonstrate which GPGKey methods require auth.""" described_class = github3.users.GPGKey @@ -80,7 +79,6 @@ def test_delete(self): class TestUserGPGKey(helper.UnitHelper): - """Unit tests for the GPGKey object.""" described_class = github3.users.GPGKey @@ -94,7 +92,6 @@ def test_delete(self): class TestUserKeyRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Test that ensure certain methods on Key class requires auth.""" described_class = github3.users.Key @@ -112,7 +109,6 @@ def test_delete(self): class TestUserKey(helper.UnitHelper): - """Test methods on Key class.""" described_class = github3.users.Key @@ -144,7 +140,6 @@ def test_update(self): class TestUserIterators(helper.UnitIteratorHelper): - """Test User methods that return iterators.""" described_class = github3.users.User @@ -264,7 +259,6 @@ def test_subscriptions(self): class TestUsersRequiresAuth(helper.UnitRequiresAuthenticationHelper): - """Test that ensure certain methods on the User class requires auth.""" described_class = github3.users.User @@ -277,7 +271,6 @@ def test_organization_events(self): class TestPlan(helper.UnitHelper): - """Test for methods on Plan class.""" described_class = github3.users.Plan @@ -294,7 +287,6 @@ def test_is_free(self): class TestAuthenticatedUserCompatibility_2_12(helper.UnitHelper): - """Test methods on AuthenticatedUser from Github Enterprise 2.12.""" described_class = github3.users.AuthenticatedUser diff --git a/tox.ini b/tox.ini index bfc3b5e7..0124dabe 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{37,38,39,310,311,py39},black,flake8,doclint,commitlint,docstrings +envlist = py{37,38,39,310,311,py39},black,flake8,doclint,commitlint,docstrings,mypy minversion = 3.4.0 [testenv] @@ -44,6 +44,13 @@ deps = flake8 >= 5.0.0 commands = flake8 {posargs} src/github3/ tests/unit/ tests/integration/ +[testenv:py310-mypy] +deps = + mypy + types-python-dateutil + types-requests +commands = mypy + [testenv:venv] passenv = GH_* deps = @@ -112,3 +119,6 @@ ignore-path-errors = docs/source/release-notes/1.0.0.rst;D001 extend-ignore = E203,W503 max-line-length = 80 exclude = src/github3/_version.py + +[isort] +profile = black