diff --git a/pontos/github/api/__init__.py b/pontos/github/api/__init__.py index ee4e677ed..f70933779 100644 --- a/pontos/github/api/__init__.py +++ b/pontos/github/api/__init__.py @@ -17,6 +17,7 @@ ) from .labels import GitHubAsyncRESTLabels from .organizations import GitHubAsyncRESTOrganizations +from .packages import GitHubAsyncRESTPackages from .pull_requests import GitHubAsyncRESTPullRequests from .release import GitHubAsyncRESTReleases from .repositories import GitHubAsyncRESTRepositories @@ -39,6 +40,7 @@ "GitHubAsyncRESTDependabot", "GitHubAsyncRESTLabels", "GitHubAsyncRESTOrganizations", + "GitHubAsyncRESTPackages", "GitHubAsyncRESTPullRequests", "GitHubAsyncRESTReleases", "GitHubAsyncRESTRepositories", diff --git a/pontos/github/api/api.py b/pontos/github/api/api.py index 11dbc6694..b6e9ecbc0 100644 --- a/pontos/github/api/api.py +++ b/pontos/github/api/api.py @@ -22,6 +22,7 @@ ) from pontos.github.api.labels import GitHubAsyncRESTLabels from pontos.github.api.organizations import GitHubAsyncRESTOrganizations +from pontos.github.api.packages import GitHubAsyncRESTPackages from pontos.github.api.pull_requests import GitHubAsyncRESTPullRequests from pontos.github.api.release import GitHubAsyncRESTReleases from pontos.github.api.repositories import GitHubAsyncRESTRepositories @@ -120,6 +121,13 @@ def labels(self) -> GitHubAsyncRESTLabels: """ return GitHubAsyncRESTLabels(self._client) + @property + def packages(self) -> GitHubAsyncRESTPackages: + """ + Packages related API + """ + return GitHubAsyncRESTPackages(self._client) + @property @deprecated( since="23.3.4", diff --git a/pontos/github/api/foo.json b/pontos/github/api/foo.json new file mode 100644 index 000000000..63eb46dfd --- /dev/null +++ b/pontos/github/api/foo.json @@ -0,0 +1,54 @@ +{ + 'id': 4917607, + 'name': 'asset-management-backend', + 'package_type': 'container', + 'owner': { + 'login': 'greenbone', + 'id': 31986857, + 'node_id': 'MDEyOk9yZ2FuaXphdGlvbjMxOTg2ODU3', + 'avatar_url': 'https: //avatars.githubusercontent.com/u/31986857?v=4', + 'gravatar_id': '', + 'url': 'https://api.github.com/users/greenbone', + 'html_url': 'https://github.com/greenbone', + 'followers_url': 'https://api.github.com/users/greenbone/followers', + 'following_url': 'https://api.github.com/users/greenbone/following{/other_user}', + 'gists_url': 'https://api.github.com/users/greenbone/gists{/gist_id}', + 'starred_url': 'https://api.github.com/users/greenbone/starred{/owner}{/repo}', + 'subscriptions_url': 'https://api.github.com/users/greenbone/subscriptions', 'organizations_url': 'https://api.github.com/users/greenbone/orgs', 'repos_url': 'https://api.github.com/users/greenbone/repos', 'events_url': 'https://api.github.com/users/greenbone/events{/privacy}', 'received_events_url': 'https://api.github.com/users/greenbone/received_events', 'type': 'Organization', 'site_admin': False + }, + 'version_count': 7686, + 'visibility': 'public', + 'url': 'https://api.github.com/orgs/greenbone/packages/container/asset-management-backend', + 'created_at': '2023-03-16T14:39:23Z', + 'updated_at': '2024-05-06T07:46:34Z', + 'repository': { + 'id': 498688333, + 'node_id': 'R_kgDOHblhTQ', + 'name': 'asset-management-backend', + 'full_name': 'greenbone/asset-management-backend', + 'private': True, + 'owner': {'login': 'greenbone', 'id': 31986857, 'node_id': 'MDEyOk9yZ2FuaXphdGlvbjMxOTg2ODU3', 'avatar_url': 'https://avatars.githubusercontent.com/u/31986857?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/greenbone', 'html_url': 'https://github.com/greenbone', 'followers_url': 'https://api.github.com/users/greenbone/followers', 'following_url': 'https://api.github.com/users/greenbone/following{/other_user}', 'gists_url': 'https://api.github.com/users/greenbone/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/greenbone/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/greenbone/subscriptions', 'organizations_url': 'https://api.github.com/users/greenbone/orgs', 'repos_url': 'https://api.github.com/users/greenbone/repos', 'events_url': 'https://api.github.com/users/greenbone/events{/privacy}', 'received_events_url': 'https://api.github.com/users/greenbone/received_events', 'type': 'Organization', 'site_admin': False + }, + 'html_url': 'https://github.com/greenbone/asset-management-backend', + 'description': 'Backend for the asset-management-frontend that provides REST endpoints with the main functionality of the Opensight Asset product.', + 'fork': False, + 'url': 'https://api.github.com/repos/greenbone/asset-management-backend', + 'forks_url': 'https://api.github.com/repos/greenbone/asset-management-backend/forks', + 'keys_url': 'https://api.github.com/repos/greenbone/asset-management-backend/keys{/key_id}', + 'collaborators_url': 'https://api.github.com/repos/greenbone/asset-management-backend/collaborators{/collaborator}', + 'teams_url': 'https://api.github.com/repos/greenbone/asset-management-backend/teams', + 'hooks_url': 'https://api.github.com/repos/greenbone/asset-management-backend/hooks', + 'issue_events_url': 'https://api.github.com/repos/greenbone/asset-management-backend/issues/events{/number}', + 'events_url': 'https://api.github.com/repos/greenbone/asset-management-backend/events', + 'assignees_url': 'https://api.github.com/repos/greenbone/asset-management-backend/assignees{/user}', + 'branches_url': 'https://api.github.com/repos/greenbone/asset-management-backend/branches{/branch}', + 'tags_url': 'https://api.github.com/repos/greenbone/asset-management-backend/tags', 'blobs_url': 'https://api.github.com/repos/greenbone/asset-management-backend/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/greenbone/asset-management-backend/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/greenbone/asset-management-backend/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/greenbone/asset-management-backend/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/greenbone/asset-management-backend/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/greenbone/asset-management-backend/languages', 'stargazers_url': 'https://api.github.com/repos/greenbone/asset-management-backend/stargazers', 'contributors_url': 'https://api.github.com/repos/greenbone/asset-management-backend/contributors', + 'subscribers_url': 'https://api.github.com/repos/greenbone/asset-management-backend/subscribers', 'subscription_url': 'https://api.github.com/repos/greenbone/asset-management-backend/subscription', 'commits_url': 'https://api.github.com/repos/greenbone/asset-management-backend/commits{/sha}', + 'git_commits_url': 'https://api.github.com/repos/greenbone/asset-management-backend/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/greenbone/asset-management-backend/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/greenbone/asset-management-backend/issues/comments{/number}', + 'contents_url': 'https://api.github.com/repos/greenbone/asset-management-backend/contents/{+path}', 'compare_url': 'https://api.github.com/repos/greenbone/asset-management-backend/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/greenbone/asset-management-backend/merges', 'archive_url': 'https://api.github.com/repos/greenbone/asset-management-backend/{archive_format}{/ref}', + 'downloads_url': 'https://api.github.com/repos/greenbone/asset-management-backend/downloads', 'issues_url': 'https://api.github.com/repos/greenbone/asset-management-backend/issues{/number}', 'pulls_url': 'https://api.github.com/repos/greenbone/asset-management-backend/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/greenbone/asset-management-backend/milestones{/number}', + 'notifications_url': 'https://api.github.com/repos/greenbone/asset-management-backend/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/greenbone/asset-management-backend/labels{/name}', 'releases_url': 'https://api.github.com/repos/greenbone/asset-management-backend/releases{/id}', + 'deployments_url': 'https://api.github.com/repos/greenbone/asset-management-backend/deployments' + }, + 'html_url': 'https://github.com/orgs/greenbone/packages/container/package/asset-management-backend' +} \ No newline at end of file diff --git a/pontos/github/api/packages.py b/pontos/github/api/packages.py new file mode 100644 index 000000000..b13c27fee --- /dev/null +++ b/pontos/github/api/packages.py @@ -0,0 +1,364 @@ +# SPDX-FileCopyrightText: 2024 Greenbone AG +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +from typing import AsyncIterator + +from pontos.github.api.client import GitHubAsyncREST +from pontos.github.api.errors import GitHubApiError +from pontos.github.models.packages import Package, PackageType, PackageVersion + + +class GitHubAsyncRESTPackages(GitHubAsyncREST): + async def exists( + self, organization: str, package_type: PackageType, package_name: str + ) -> bool: + """ + Check if a package exists + + Args: + package: GitHub package (owner/name) to use + + Returns: + True if the package exists + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + exists = api.packages.exists("foo") + """ + api = f"/orgs/{organization}/packages/{package_type}/{package_name}" + response = await self._client.get(api) + return response.is_success + + async def package( + self, organization: str, package_type: PackageType, package_name: str + ) -> Package: + """ + Get information about a package + + https://docs.github.com/en/rest/reference/packages#get-a-package-for-an-organization + + Args: + organization: GitHub organization to use + package_type: Type of the package to get + package_name: Name of the package to get + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Returns: + Package information + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + package = api.packages.package( + organization="foo", + package_type="container", + package_name="bar", + ): + + print(package.name) + + """ + api = f"/orgs/{organization}/packages/{package_type}/{package_name}" + response = await self._client.get(api) + response.raise_for_status() + return Package.from_dict(response.json()) + + async def packages( + self, organization: str, package_type: str + ) -> AsyncIterator[Package]: + """ + Get information about organization packages + + https://docs.github.com/en/rest/reference/packages#list-packages-for-an-organization + + Args: + organization: GitHub organization to use + package_type: Type of the packages to list + + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Returns: + An async iterator yielding packages information + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + async for package in api.packages.packages( + organization="foo", + package_type="container", + ): + print(package) + """ + api = f"/orgs/{organization}/packages/{package_type}" + params = {"per_page": "100"} + async for response in self._client.get_all(api, params=params): + response.raise_for_status() + + for package in response.json(): + yield Package.from_dict(package) + + async def package_version( + self, + organization: str, + package_type: PackageType, + package_name: str, + version: int, + ) -> PackageVersion: + """ + Get information about a package version + + https://docs.github.com/en/rest/reference/packages#get-a-package-version-for-an-organization + + Args: + organization: GitHub organization to use + package_type: Type of the package to get + package_name: Name of the package to get + version: Version of the package to get + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Returns: + Package version information + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + package = api.packages.package_version( + organization="foo", + package_type="container", + package_name="bar", + version=1, + ): + + print(package.version) + """ + api = f"/orgs/{organization}/packages/{package_type}/{package_name}/versions/{version}" + response = await self._client.get(api) + if not response.is_success: + raise GitHubApiError(response) + return PackageVersion.from_dict(response.json()) + + async def package_versions( + self, organization: str, package_type: PackageType, package_name: str + ) -> AsyncIterator[PackageVersion]: + """ + Get information about package versions + + + https://docs.github.com/en/rest/reference/packages#list-package-versions-for-an-organization + + + Args: + organization: GitHub organization to use + package_type: Type of the package to get + package_name: Name of the package to get + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Returns: + An async iterator yielding package versions + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + async for package in api.packages.package_versions( + organization="foo", + package_type="container", + package_name="bar", + ): + print(package) + """ + api = f"/orgs/{organization}/packages/{package_type}/{package_name}/versions" + async for response in self._client.get_all(api): + response.raise_for_status() + versions = response.json() + if versions: + for version in versions: + yield PackageVersion.from_dict(version) + + async def package_version_tags( + self, + organization: str, + package_type: PackageType, + package_name: str, + version: int, + ) -> list[str]: + """ + Get information about package version tags + + Uses https://docs.github.com/en/rest/reference/packages#get-a-package-version-for-an-organization + and only returns the tags + + Args: + organization: GitHub organization to use + package_type: Type of the package to get + package_name: Name of the package to get + version: Version of the package to get + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Returns: + List of tags for the package version + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + tags = api.packages.package_version_tags( + organization="foo", + package_type="container", + package_name="bar", + version=1, + ) + + print(tags) + """ + api = f"/orgs/{organization}/packages/{package_type}/{package_name}/versions/{version}" + response = await self._client.get(api) + if not response.is_success: + raise GitHubApiError(response) + resp = response.json() + return resp["metadata"]["container"]["tags"] + + async def delete_package( + self, organization: str, package_type: PackageType, package_name: str + ) -> None: + """ + Delete a package + + https://docs.github.com/en/rest/reference/packages#delete-a-package-for-an-organization + + Args: + organization: GitHub organization to use + package_type: Type of the package to delete + package_name: Name of the package to delete + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + api.packages.delete_package( + organization="foo", + package_type="container", + package_name="bar", + ) + """ + api = f"/orgs/{organization}/packages/{package_type}/{package_name}" + response = await self._client.delete(api) + if not response.is_success: + raise GitHubApiError(response) + + async def delete_package_version( + self, + organization: str, + package_type: PackageType, + package_name: str, + version: int, + ) -> None: + """ + Delete a package version + + https://docs.github.com/en/rest/reference/packages#delete-a-package-version-for-an-organization + + Args: + organization: GitHub organization to use + package_type: Type of the package to delete + package_name: Name of the package to delete + version: Version of the package to delete + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + api.packages.delete_package_version( + organization="foo", + package_type="container", + package_name="bar", + version=1, + ) + """ + + api = f"/orgs/{organization}/packages/{package_type}/{package_name}/versions/{version}" + response = await self._client.delete(api) + if not response.is_success: + raise GitHubApiError(response) + + async def delete_package_with_tag( + self, + organization: str, + package_type: PackageType, + package_name: str, + tag: str, + ) -> None: + """ + Delete a package with a specific tag + + Args: + organization: GitHub organization to use + package_type: Type of the package to delete + package_name: Name of the package to delete + tag: Tag of the package to delete + + Raises: + `httpx.HTTPStatusError`: If there was an error in the request + + Example: + .. code-block:: python + + from pontos.github.api import GitHubAsyncRESTApi + + async with GitHubAsyncRESTApi(token) as api: + api.packages.delete_package_with_tag( + organization="foo", + package_type="container", + package_name="bar", + tag="latest", + ) + """ + async for package_version in self.package_versions( + organization, package_type, package_name + ): + if tag in await self.package_version_tags( + organization, package_type, package_name, package_version.id + ): + api = f"/orgs/{organization}/packages/{package_type}/{package_name}/versions/{package_version.id}" + response = await self._client.delete(api) + if not response.is_success: + raise GitHubApiError(response) diff --git a/pontos/github/models/__init__.py b/pontos/github/models/__init__.py index f2b5327b9..8fad89ad6 100644 --- a/pontos/github/models/__init__.py +++ b/pontos/github/models/__init__.py @@ -9,6 +9,7 @@ from pontos.github.models.base import * from pontos.github.models.branch import * from pontos.github.models.organization import * +from pontos.github.models.packages import * from pontos.github.models.pull_request import * from pontos.github.models.release import * from pontos.github.models.search import * diff --git a/pontos/github/models/packages.py b/pontos/github/models/packages.py new file mode 100644 index 000000000..c632981a2 --- /dev/null +++ b/pontos/github/models/packages.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2024 Greenbone AG +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +from dataclasses import dataclass, field + +from pontos.github.models.base import GitHubModel, User +from pontos.github.models.organization import Repository +from pontos.models import StrEnum + +__all__ = [ + "PackageType", + "PackageVisibility", + "Package", + "Container", + "PackageVersionMetadata", + "PackageVersion", +] + + +class PackageType(StrEnum): + CONTAINER = "container" + DOCKER = "docker" + MAVEN = "maven" + NPM = "npm" + NUGET = "nuget" + RUBYGEMS = "rubygems" + + +class PackageVisibility(StrEnum): + PUBLIC = "public" + PRIVATE = "private" + + +@dataclass +class Package(GitHubModel): + id: int + name: str + package_type: PackageType + owner: User + version_count: int + visibility: PackageVisibility + url: str + created_at: str + updated_at: str + repository: Repository + html_url: str + + +@dataclass +class Container(GitHubModel): + tags: list[str] = field(default_factory=list) + + +@dataclass +class PackageVersionMetadata(GitHubModel): + package_type: PackageType + container: Container + + +@dataclass +class PackageVersion(GitHubModel): + id: int + name: str + url: str + package_html_url: str + created_at: str + updated_at: str + html_url: str + metadata: PackageVersionMetadata diff --git a/pontos/github/scripts/delete-package-with-tag.py b/pontos/github/scripts/delete-package-with-tag.py new file mode 100644 index 000000000..348d05fae --- /dev/null +++ b/pontos/github/scripts/delete-package-with-tag.py @@ -0,0 +1,50 @@ +""" +This script delete a package from a repository, if it contains the specified tag. +""" + +from argparse import ArgumentParser, Namespace + +from pontos.github.api import GitHubAsyncRESTApi +from pontos.github.models.packages import PackageType + + +def package_type(value: str) -> PackageType: + if isinstance(value, PackageType): + return value + return PackageType(value.lower()) + + +def add_script_arguments(parser: ArgumentParser) -> None: + parser.add_argument("organization", help="organization name") + parser.add_argument("package", help="package name") + parser.add_argument( + "--package-type", + type=package_type, + help="package type", + default=PackageType.CONTAINER, + ) + parser.add_argument("tag", help="The tag to be deleted.") + + +async def github_script(api: GitHubAsyncRESTApi, args: Namespace) -> int: + if not await api.packages.exists( + organization=args.organization, + package_name=args.package, + package_type=args.package_type, + ): + print( + f"Package {args.package} does not exist in organization {args.organization}" + ) + return 1 + print(f"Found package {args.package} in organization {args.organization}") + + await api.packages.delete_package_with_tag( + organization=args.organization, + package_name=args.package, + package_type=args.package_type, + tag=args.tag, + ) + print( + f"Deleted tag {args.tag} from package {args.package} in organization {args.organization}" + ) + return 0 diff --git a/pontos/github/scripts/find-package-tag.py b/pontos/github/scripts/find-package-tag.py new file mode 100644 index 000000000..104b5c2e0 --- /dev/null +++ b/pontos/github/scripts/find-package-tag.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2022-2023 Greenbone AG +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +""" +This script checks wether a package has a specific tag +""" + +from argparse import ArgumentParser, Namespace + +from pontos.github.api import GitHubAsyncRESTApi +from pontos.github.models.packages import PackageType + + +def package_type(value: str) -> PackageType: + if isinstance(value, PackageType): + return value + return PackageType(value.lower()) + + +def add_script_arguments(parser: ArgumentParser) -> None: + parser.add_argument("organization", help="organization name") + parser.add_argument("package", help="package name") + parser.add_argument("tag", help="tag to check") + parser.add_argument( + "--package-type", + type=package_type, + help="package type", + default=PackageType.CONTAINER, + ) + + +async def github_script(api: GitHubAsyncRESTApi, args: Namespace) -> int: + if not await api.packages.exists( + organization=args.organization, + package_name=args.package, + package_type=args.package_type, + ): + print( + f"Package {args.package} does not exist in organization {args.organization}" + ) + return 1 + print(f"Found package {args.package} in organization {args.organization}") + + async for package in api.packages.package_versions( + organization=args.organization, + package_name=args.package, + package_type=args.package_type, + ): + print(f"Checking package {args.package} with id {package.id}") + if package.metadata.container.tags: + if args.tag in package.metadata.container.tags: + print( + f"Package {args.package} with id {package.id} has tag {args.tag}" + ) + tags = await api.packages.package_version_tags( + args.organization, + args.package_type, + args.package, + package.id, + ) + print(f"Tags: {tags}") + + await api.packages.delete_package_version( + args.organization, + args.package_type, + args.package, + package.id, + ) + return 0 + + print(f"Package {args.package} does not have tag {args.tag}") + return 0 diff --git a/tests/github/api/test_organizations.py b/tests/github/api/test_organizations.py index 61b264c3e..1b1f230b3 100644 --- a/tests/github/api/test_organizations.py +++ b/tests/github/api/test_organizations.py @@ -5,6 +5,7 @@ # pylint: disable=too-many-lines, redefined-builtin, line-too-long +from copy import deepcopy from pathlib import Path from unittest.mock import MagicMock @@ -23,6 +24,126 @@ here = Path(__file__).parent +REPOSITORY_DICT = { + "id": 1, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": False, + }, + "private": False, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": False, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": None, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "is_template": False, + "topics": ["octocat", "atom", "electron", "api"], + "has_issues": True, + "has_projects": True, + "has_wiki": True, + "has_pages": False, + "has_downloads": True, + "has_discussions": False, + "archived": False, + "disabled": False, + "visibility": "public", + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": {"admin": False, "push": False, "pull": True}, + "forks": 1, + "open_issues": 0, + "watchers": 1, +} + +MEMBER_DICT = { + "id": 1, + "login": "octocat", + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": False, +} + class GitHubAsyncRESTOrganizationsTestCase(GitHubAsyncRESTTestCase): api_cls = GitHubAsyncRESTOrganizations @@ -45,305 +166,13 @@ async def test_not_exists(self): async def test_get_repositories(self): response1 = create_response() - response1.json.return_value = [ - { - "id": 1, - "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", - "name": "Hello-World", - "full_name": "octocat/Hello-World", - "owner": { - "login": "octocat", - "id": 1, - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - "private": False, - "html_url": "https://github.com/octocat/Hello-World", - "description": "This your first repo!", - "fork": False, - "url": "https://api.github.com/repos/octocat/Hello-World", - "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", - "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", - "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", - "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", - "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", - "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", - "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", - "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", - "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", - "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", - "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", - "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", - "events_url": "https://api.github.com/repos/octocat/Hello-World/events", - "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", - "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", - "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", - "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", - "git_url": "git:github.com/octocat/Hello-World.git", - "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", - "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", - "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", - "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", - "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", - "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", - "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", - "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", - "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", - "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", - "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", - "ssh_url": "git@github.com:octocat/Hello-World.git", - "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", - "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", - "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", - "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", - "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", - "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", - "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", - "clone_url": "https://github.com/octocat/Hello-World.git", - "mirror_url": "git:git.example.com/octocat/Hello-World", - "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", - "svn_url": "https://svn.github.com/octocat/Hello-World", - "homepage": "https://github.com", - "language": None, - "forks_count": 9, - "stargazers_count": 80, - "watchers_count": 80, - "size": 108, - "default_branch": "master", - "open_issues_count": 0, - "is_template": False, - "topics": ["octocat", "atom", "electron", "api"], - "has_issues": True, - "has_projects": True, - "has_wiki": True, - "has_pages": False, - "has_downloads": True, - "has_discussions": False, - "archived": False, - "disabled": False, - "visibility": "public", - "pushed_at": "2011-01-26T19:06:43Z", - "created_at": "2011-01-26T19:01:12Z", - "updated_at": "2011-01-26T19:14:43Z", - "permissions": {"admin": False, "push": False, "pull": True}, - "forks": 1, - "open_issues": 0, - "watchers": 1, - } - ] + response1.json.return_value = [REPOSITORY_DICT] response2 = create_response() - response2.json.return_value = [ - { - "id": 2, - "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", - "name": "Hello-World", - "full_name": "octocat/Hello-World", - "owner": { - "login": "octocat", - "id": 1, - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - "private": False, - "html_url": "https://github.com/octocat/Hello-World", - "description": "This your first repo!", - "fork": False, - "url": "https://api.github.com/repos/octocat/Hello-World", - "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", - "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", - "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", - "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", - "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", - "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", - "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", - "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", - "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", - "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", - "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", - "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", - "events_url": "https://api.github.com/repos/octocat/Hello-World/events", - "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", - "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", - "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", - "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", - "git_url": "git:github.com/octocat/Hello-World.git", - "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", - "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", - "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", - "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", - "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", - "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", - "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", - "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", - "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", - "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", - "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", - "ssh_url": "git@github.com:octocat/Hello-World.git", - "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", - "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", - "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", - "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", - "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", - "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", - "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", - "clone_url": "https://github.com/octocat/Hello-World.git", - "mirror_url": "git:git.example.com/octocat/Hello-World", - "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", - "svn_url": "https://svn.github.com/octocat/Hello-World", - "homepage": "https://github.com", - "language": None, - "forks_count": 9, - "stargazers_count": 80, - "watchers_count": 80, - "size": 108, - "default_branch": "master", - "open_issues_count": 0, - "is_template": False, - "topics": ["octocat", "atom", "electron", "api"], - "has_issues": True, - "has_projects": True, - "has_wiki": True, - "has_pages": False, - "has_downloads": True, - "has_discussions": False, - "archived": False, - "disabled": False, - "visibility": "public", - "pushed_at": "2011-01-26T19:06:43Z", - "created_at": "2011-01-26T19:01:12Z", - "updated_at": "2011-01-26T19:14:43Z", - "permissions": {"admin": False, "push": False, "pull": True}, - "forks": 1, - "open_issues": 0, - "watchers": 1, - }, - { - "id": 3, - "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", - "name": "Hello-World", - "full_name": "octocat/Hello-World", - "owner": { - "login": "octocat", - "id": 1, - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - "private": False, - "html_url": "https://github.com/octocat/Hello-World", - "description": "This your first repo!", - "fork": False, - "url": "https://api.github.com/repos/octocat/Hello-World", - "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", - "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", - "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", - "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", - "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", - "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", - "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", - "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", - "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", - "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", - "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", - "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", - "events_url": "https://api.github.com/repos/octocat/Hello-World/events", - "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", - "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", - "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", - "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", - "git_url": "git:github.com/octocat/Hello-World.git", - "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", - "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", - "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", - "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", - "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", - "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", - "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", - "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", - "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", - "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", - "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", - "ssh_url": "git@github.com:octocat/Hello-World.git", - "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", - "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", - "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", - "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", - "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", - "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", - "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", - "clone_url": "https://github.com/octocat/Hello-World.git", - "mirror_url": "git:git.example.com/octocat/Hello-World", - "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", - "svn_url": "https://svn.github.com/octocat/Hello-World", - "homepage": "https://github.com", - "language": None, - "forks_count": 9, - "stargazers_count": 80, - "watchers_count": 80, - "size": 108, - "default_branch": "master", - "open_issues_count": 0, - "is_template": False, - "topics": ["octocat", "atom", "electron", "api"], - "has_issues": True, - "has_projects": True, - "has_wiki": True, - "has_pages": False, - "has_downloads": True, - "has_discussions": False, - "archived": False, - "disabled": False, - "visibility": "public", - "pushed_at": "2011-01-26T19:06:43Z", - "created_at": "2011-01-26T19:01:12Z", - "updated_at": "2011-01-26T19:14:43Z", - "permissions": {"admin": False, "push": False, "pull": True}, - "forks": 1, - "open_issues": 0, - "watchers": 1, - }, - ] + repository_dict2 = deepcopy(REPOSITORY_DICT) + repository_dict2["id"] = 2 + repository_dict3 = deepcopy(REPOSITORY_DICT) + repository_dict3["id"] = 3 + response2.json.return_value = [repository_dict2, repository_dict3] self.client.get_all.return_value = AsyncIteratorMock( [response1, response2] @@ -367,305 +196,13 @@ async def test_get_repositories(self): async def test_get_private_repositories(self): response1 = create_response() - response1.json.return_value = [ - { - "id": 1, - "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", - "name": "Hello-World", - "full_name": "octocat/Hello-World", - "owner": { - "login": "octocat", - "id": 1, - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - "private": False, - "html_url": "https://github.com/octocat/Hello-World", - "description": "This your first repo!", - "fork": False, - "url": "https://api.github.com/repos/octocat/Hello-World", - "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", - "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", - "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", - "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", - "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", - "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", - "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", - "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", - "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", - "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", - "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", - "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", - "events_url": "https://api.github.com/repos/octocat/Hello-World/events", - "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", - "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", - "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", - "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", - "git_url": "git:github.com/octocat/Hello-World.git", - "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", - "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", - "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", - "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", - "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", - "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", - "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", - "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", - "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", - "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", - "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", - "ssh_url": "git@github.com:octocat/Hello-World.git", - "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", - "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", - "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", - "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", - "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", - "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", - "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", - "clone_url": "https://github.com/octocat/Hello-World.git", - "mirror_url": "git:git.example.com/octocat/Hello-World", - "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", - "svn_url": "https://svn.github.com/octocat/Hello-World", - "homepage": "https://github.com", - "language": None, - "forks_count": 9, - "stargazers_count": 80, - "watchers_count": 80, - "size": 108, - "default_branch": "master", - "open_issues_count": 0, - "is_template": False, - "topics": ["octocat", "atom", "electron", "api"], - "has_issues": True, - "has_projects": True, - "has_wiki": True, - "has_pages": False, - "has_downloads": True, - "has_discussions": False, - "archived": False, - "disabled": False, - "visibility": "public", - "pushed_at": "2011-01-26T19:06:43Z", - "created_at": "2011-01-26T19:01:12Z", - "updated_at": "2011-01-26T19:14:43Z", - "permissions": {"admin": False, "push": False, "pull": True}, - "forks": 1, - "open_issues": 0, - "watchers": 1, - } - ] + response1.json.return_value = [REPOSITORY_DICT] response2 = create_response() - response2.json.return_value = [ - { - "id": 2, - "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", - "name": "Hello-World", - "full_name": "octocat/Hello-World", - "owner": { - "login": "octocat", - "id": 1, - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - "private": False, - "html_url": "https://github.com/octocat/Hello-World", - "description": "This your first repo!", - "fork": False, - "url": "https://api.github.com/repos/octocat/Hello-World", - "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", - "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", - "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", - "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", - "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", - "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", - "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", - "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", - "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", - "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", - "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", - "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", - "events_url": "https://api.github.com/repos/octocat/Hello-World/events", - "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", - "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", - "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", - "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", - "git_url": "git:github.com/octocat/Hello-World.git", - "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", - "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", - "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", - "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", - "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", - "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", - "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", - "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", - "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", - "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", - "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", - "ssh_url": "git@github.com:octocat/Hello-World.git", - "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", - "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", - "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", - "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", - "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", - "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", - "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", - "clone_url": "https://github.com/octocat/Hello-World.git", - "mirror_url": "git:git.example.com/octocat/Hello-World", - "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", - "svn_url": "https://svn.github.com/octocat/Hello-World", - "homepage": "https://github.com", - "language": None, - "forks_count": 9, - "stargazers_count": 80, - "watchers_count": 80, - "size": 108, - "default_branch": "master", - "open_issues_count": 0, - "is_template": False, - "topics": ["octocat", "atom", "electron", "api"], - "has_issues": True, - "has_projects": True, - "has_wiki": True, - "has_pages": False, - "has_downloads": True, - "has_discussions": False, - "archived": False, - "disabled": False, - "visibility": "public", - "pushed_at": "2011-01-26T19:06:43Z", - "created_at": "2011-01-26T19:01:12Z", - "updated_at": "2011-01-26T19:14:43Z", - "permissions": {"admin": False, "push": False, "pull": True}, - "forks": 1, - "open_issues": 0, - "watchers": 1, - }, - { - "id": 3, - "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", - "name": "Hello-World", - "full_name": "octocat/Hello-World", - "owner": { - "login": "octocat", - "id": 1, - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - "private": False, - "html_url": "https://github.com/octocat/Hello-World", - "description": "This your first repo!", - "fork": False, - "url": "https://api.github.com/repos/octocat/Hello-World", - "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", - "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", - "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", - "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", - "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", - "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", - "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", - "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", - "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", - "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", - "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", - "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", - "events_url": "https://api.github.com/repos/octocat/Hello-World/events", - "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", - "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", - "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", - "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", - "git_url": "git:github.com/octocat/Hello-World.git", - "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", - "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", - "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", - "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", - "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", - "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", - "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", - "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", - "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", - "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", - "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", - "ssh_url": "git@github.com:octocat/Hello-World.git", - "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", - "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", - "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", - "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", - "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", - "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", - "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", - "clone_url": "https://github.com/octocat/Hello-World.git", - "mirror_url": "git:git.example.com/octocat/Hello-World", - "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", - "svn_url": "https://svn.github.com/octocat/Hello-World", - "homepage": "https://github.com", - "language": None, - "forks_count": 9, - "stargazers_count": 80, - "watchers_count": 80, - "size": 108, - "default_branch": "master", - "open_issues_count": 0, - "is_template": False, - "topics": ["octocat", "atom", "electron", "api"], - "has_issues": True, - "has_projects": True, - "has_wiki": True, - "has_pages": False, - "has_downloads": True, - "has_discussions": False, - "archived": False, - "disabled": False, - "visibility": "public", - "pushed_at": "2011-01-26T19:06:43Z", - "created_at": "2011-01-26T19:01:12Z", - "updated_at": "2011-01-26T19:14:43Z", - "permissions": {"admin": False, "push": False, "pull": True}, - "forks": 1, - "open_issues": 0, - "watchers": 1, - }, - ] + repository_dict2 = deepcopy(REPOSITORY_DICT) + repository_dict2["id"] = 2 + repository_dict3 = deepcopy(REPOSITORY_DICT) + repository_dict3["id"] = 3 + response2.json.return_value = [repository_dict2, repository_dict3] self.client.get_all.return_value = AsyncIteratorMock( [response1, response2] @@ -693,71 +230,13 @@ async def test_get_private_repositories(self): async def test_members(self): response1 = create_response() - response1.json.return_value = [ - { - "id": 1, - "login": "octocat", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - } - ] + response1.json.return_value = [MEMBER_DICT] response2 = create_response() - response2.json.return_value = [ - { - "id": 2, - "login": "octocat2", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - { - "id": 3, - "login": "octocat3", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - ] + member_dict2 = deepcopy(MEMBER_DICT) + member_dict2["id"] = 2 + member_dict3 = deepcopy(MEMBER_DICT) + member_dict3["id"] = 3 + response2.json.return_value = [member_dict2, member_dict3] self.client.get_all.return_value = AsyncIteratorMock( [response1, response2] @@ -781,71 +260,13 @@ async def test_members(self): async def test_members_admins(self): response1 = create_response() - response1.json.return_value = [ - { - "id": 1, - "login": "octocat", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - } - ] + response1.json.return_value = [MEMBER_DICT] response2 = create_response() - response2.json.return_value = [ - { - "id": 2, - "login": "octocat2", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - { - "id": 3, - "login": "octocat3", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - ] + member_dict2 = deepcopy(MEMBER_DICT) + member_dict2["id"] = 2 + member_dict3 = deepcopy(MEMBER_DICT) + member_dict3["id"] = 3 + response2.json.return_value = [member_dict2, member_dict3] self.client.get_all.return_value = AsyncIteratorMock( [response1, response2] @@ -869,71 +290,13 @@ async def test_members_admins(self): async def test_members_filter(self): response1 = create_response() - response1.json.return_value = [ - { - "id": 1, - "login": "octocat", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - } - ] + response1.json.return_value = [MEMBER_DICT] response2 = create_response() - response2.json.return_value = [ - { - "id": 2, - "login": "octocat2", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - { - "id": 3, - "login": "octocat3", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - ] + member_dict2 = deepcopy(MEMBER_DICT) + member_dict2["id"] = 2 + member_dict3 = deepcopy(MEMBER_DICT) + member_dict3["id"] = 3 + response2.json.return_value = [member_dict2, member_dict3] self.client.get_all.return_value = AsyncIteratorMock( [response1, response2] @@ -1048,71 +411,13 @@ async def test_remove_member_failure(self): async def test_outside_collaborators(self): response1 = create_response() - response1.json.return_value = [ - { - "id": 1, - "login": "octocat", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - } - ] + response1.json.return_value = [MEMBER_DICT] response2 = create_response() - response2.json.return_value = [ - { - "id": 2, - "login": "octocat2", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - { - "id": 3, - "login": "octocat3", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - ] + member_dict2 = deepcopy(MEMBER_DICT) + member_dict2["id"] = 2 + member_dict3 = deepcopy(MEMBER_DICT) + member_dict3["id"] = 3 + response2.json.return_value = [member_dict2, member_dict3] self.client.get_all.return_value = AsyncIteratorMock( [response1, response2] @@ -1136,71 +441,13 @@ async def test_outside_collaborators(self): async def test_outside_collaborators_filter(self): response1 = create_response() - response1.json.return_value = [ - { - "id": 1, - "login": "octocat", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - } - ] + response1.json.return_value = [MEMBER_DICT] response2 = create_response() - response2.json.return_value = [ - { - "id": 2, - "login": "octocat2", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - { - "id": 3, - "login": "octocat3", - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": False, - }, - ] + member_dict2 = deepcopy(MEMBER_DICT) + member_dict2["id"] = 2 + member_dict3 = deepcopy(MEMBER_DICT) + member_dict3["id"] = 3 + response2.json.return_value = [member_dict2, member_dict3] self.client.get_all.return_value = AsyncIteratorMock( [response1, response2] diff --git a/tests/github/api/test_packages.py b/tests/github/api/test_packages.py new file mode 100644 index 000000000..bf24fe465 --- /dev/null +++ b/tests/github/api/test_packages.py @@ -0,0 +1,273 @@ +# SPDX-FileCopyrightText: 2024 Greenbone AG +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +from pontos.github.api.packages import GitHubAsyncRESTPackages +from pontos.github.models.packages import ( + Package, + PackageType, + PackageVersion, + PackageVisibility, +) +from pontos.testing import AsyncIteratorMock +from tests import aiter, anext +from tests.github.api import GitHubAsyncRESTTestCase, create_response + +from .test_organizations import MEMBER_DICT, REPOSITORY_DICT + +PACKAGE_VERSION = { + "id": 1, + "name": "v1.0.0", + "url": "https://api.github.com/orgs/foo/packages/container/bar/versions/1", + "package_html_url": "https://github.com/orgs/foo/packages/container/bar/versions", + "created_at": "2022-01-01T00:00:00Z", + "updated_at": "2022-01-01T00:00:00Z", + "html_url": "https://github.com/orgs/foo/packages/container/bar/1", + "metadata": { + "package_type": "container", + "container": {"tags": ["latest"]}, + }, +} + + +class GitHubAsyncRESTPackagesTestCase(GitHubAsyncRESTTestCase): + api_cls = GitHubAsyncRESTPackages + + async def test_exists(self): + response = create_response(is_success=True) + self.client.get.return_value = response + + self.assertTrue( + await self.api.exists( + organization="foo", + package_type=PackageType.CONTAINER, + package_name="bar", + ) + ) + + self.client.get.assert_awaited_once_with( + "/orgs/foo/packages/container/bar" + ) + + async def test_package(self): + response = create_response() + response.json.return_value = { + "id": 1, + "name": "bar", + "package_type": "container", + "owner": MEMBER_DICT, + "version_count": 1, + "visibility": "public", + "url": "https://api.github.com/orgs/foo/packages/container/bar", + "tags": ["foo", "bar", "baz"], + "created_at": "2022-01-01T00:00:00Z", + "updated_at": "2022-01-01T00:00:00Z", + "repository": REPOSITORY_DICT, + "html_url": "https://github.com/orgs/foo/packages/container/repo/bar", + } + + self.client.get.return_value = response + + package = await self.api.package("foo", PackageType.CONTAINER, "bar") + + self.client.get.assert_awaited_once_with( + "/orgs/foo/packages/container/bar" + ) + + self.assertIsInstance(package, Package) + self.assertEqual(package.owner.login, "octocat") + self.assertEqual(package.name, "bar") + self.assertEqual(package.version_count, 1) + self.assertEqual(package.visibility, PackageVisibility.PUBLIC) + self.assertEqual( + package.url, + "https://api.github.com/orgs/foo/packages/container/bar", + ) + self.assertEqual(package.tags, ["foo", "bar", "baz"]) + self.assertEqual(package.created_at, "2022-01-01T00:00:00Z") + self.assertEqual(package.updated_at, "2022-01-01T00:00:00Z") + self.assertEqual( + package.html_url, + "https://github.com/orgs/foo/packages/container/repo/bar", + ) + + async def test_packages(self): + response = create_response() + response.json.return_value = [ + { + "id": 1, + "name": "bar", + "package_type": "container", + "owner": MEMBER_DICT, + "version_count": 1, + "visibility": "public", + "url": "https://api.github.com/orgs/foo/packages/container/bar", + "tags": ["foo", "bar", "baz"], + "created_at": "2022-01-01T00:00:00Z", + "updated_at": "2022-01-01T00:00:00Z", + "repository": REPOSITORY_DICT, + "html_url": "https://github.com/orgs/foo/packages/container/repo/bar", + } + ] + + self.client.get_all.return_value = AsyncIteratorMock([response]) + + async_it = aiter( + self.api.packages("foo", package_type=PackageType.CONTAINER) + ) + package = await anext(async_it) + self.assertEqual(package.id, 1) + + with self.assertRaises(StopAsyncIteration): + await anext(async_it) + + self.client.get_all.assert_called_once_with( + "/orgs/foo/packages/container", + params={"per_page": "100"}, + ) + + async def test_package_version(self): + response = create_response() + response.json.return_value = PACKAGE_VERSION + + self.client.get.return_value = response + + package_version: PackageVersion = await self.api.package_version( + "foo", PackageType.CONTAINER, "bar", 1 + ) + + self.client.get.assert_awaited_once_with( + "/orgs/foo/packages/container/bar/versions/1" + ) + + self.assertEqual(package_version.id, 1) + self.assertEqual(package_version.name, "v1.0.0") + self.assertEqual( + package_version.url, + "https://api.github.com/orgs/foo/packages/container/bar/versions/1", + ) + self.assertEqual( + package_version.package_html_url, + "https://github.com/orgs/foo/packages/container/bar/versions", + ) + self.assertEqual(package_version.created_at, "2022-01-01T00:00:00Z") + self.assertEqual(package_version.updated_at, "2022-01-01T00:00:00Z") + self.assertEqual( + package_version.html_url, + "https://github.com/orgs/foo/packages/container/bar/1", + ) + self.assertEqual( + package_version.metadata.package_type, PackageType.CONTAINER + ) + self.assertEqual(package_version.metadata.container.tags, ["latest"]) + + async def test_package_version_tags(self): + response = create_response() + response.json.return_value = { + "metadata": {"container": {"tags": ["latest", "stable"]}} + } + + self.client.get.return_value = response + + tags = await self.api.package_version_tags( + organization="foo", + package_type=PackageType.CONTAINER, + package_name="bar", + version=1, + ) + + self.client.get.assert_awaited_once_with( + "/orgs/foo/packages/container/bar/versions/1" + ) + + self.assertEqual(tags, ["latest", "stable"]) + + async def test_delete_package(self): + response = create_response(is_success=True) + self.client.delete.return_value = response + + await self.api.delete_package( + organization="foo", + package_type=PackageType.CONTAINER, + package_name="bar", + ) + + self.client.delete.assert_awaited_once_with( + "/orgs/foo/packages/container/bar" + ) + + async def test_delete_package_version(self): + response = create_response(is_success=True) + self.client.delete.return_value = response + + await self.api.delete_package_version( + organization="foo", + package_type=PackageType.CONTAINER, + package_name="bar", + version=1, + ) + + self.client.delete.assert_awaited_once_with( + "/orgs/foo/packages/container/bar/versions/1" + ) + + async def test_package_versions(self): + response1 = create_response() + response1.json.return_value = [PACKAGE_VERSION] + response2 = create_response() + package_version2 = PACKAGE_VERSION.copy() + package_version2["id"] = 2 + response2.json.return_value = [package_version2] + + self.client.get_all.return_value = AsyncIteratorMock( + [response1, response2] + ) + + async_it = aiter( + self.api.package_versions("foo", PackageType.CONTAINER, "bar") + ) + package_version = await anext(async_it) + self.assertEqual(package_version.id, 1) + package_version = await anext(async_it) + self.assertEqual(package_version.id, 2) + + with self.assertRaises(StopAsyncIteration): + await anext(async_it) + + self.client.get_all.assert_called_once_with( + "/orgs/foo/packages/container/bar/versions" + ) + + async def test_delete_package_with_tag(self): + response = create_response(is_success=True) + self.client.delete.return_value = response + + package_version_response = create_response() + package_version_response.json.return_value = [PACKAGE_VERSION] + self.client.get_all.return_value = AsyncIteratorMock( + [package_version_response] + ) + + tags_response = create_response() + tags_response.json.return_value = { + "metadata": {"container": {"tags": ["latest", "stable"]}} + } + self.client.get.return_value = tags_response + + await self.api.delete_package_with_tag( + organization="foo", + package_type=PackageType.CONTAINER, + package_name="bar", + tag="latest", + ) + + self.client.get_all.assert_called_once_with( + "/orgs/foo/packages/container/bar/versions" + ) + self.client.get.assert_awaited_once_with( + "/orgs/foo/packages/container/bar/versions/1" + ) + self.client.delete.assert_awaited_once_with( + "/orgs/foo/packages/container/bar/versions/1" + )