async def test_headers(mock_response, client_session): mock_response.mock_headers = HEADERS async with GitHub(TOKEN, session=client_session) as github: await github.client.get("/") assert github.client.headers["User-Agent"] == DEFAULT_USER_AGENT async with GitHub(TOKEN, headers={"User-Agent": "test/client"}, session=client_session) as github: await github.client.get("/") assert github.client.headers["User-Agent"] == "test/client"
async def test_get_views(aresponses, repository_response, pageviews_fixtrue_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/traffic/views", "get", aresponses.Response( text=json.dumps(pageviews_fixtrue_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") views = await repository.traffic.get_views() assert views.count == 14850
async def check(): print("Information: https://hacs.xyz/docs/publish/include#check-wheels") if get_category() != "integration": print("Only integrations are checked.") return manifest = get_manifest() domain = manifest.get("domain") requirements = manifest.get("requirements") if domain is None: exit("No domain") if not requirements: print("No requirements found") return async with GitHub(TOKEN) as github: repository = await github.get_repo( "home-assistant/wheels-custom-integrations") files = await repository.get_contents("components") components = [x.attributes["name"] for x in files] if domain in components or f"{domain}.json" in components: print( f"{domain} is added to https://github.com/home-assistant/wheels-custom-integrations, NICE!" ) return exit( f"::error::{domain} is not added to https://github.com/home-assistant/wheels-custom-integrations, " + "this is needed to ensure the best possible experience for the user" )
async def check(): print("Information: https://hacs.xyz/docs/publish/include#check-brands") if get_category() != "integration": print("Only integrations are checked.") return manifest = get_manifest() domain = manifest.get("domain") if domain is None: print("No domain") exit(1) async with GitHub(TOKEN) as github: repository = await github.get_repo("home-assistant/brands") core = await repository.get_contents("core_integrations") custom = await repository.get_contents("custom_integrations") if domain not in [x.attributes["name"] for x in core + custom]: exit( f"::error::{domain} is not added to https://github.com/home-assistant/brands, " + "this is needed to ensure the best possible experience for the user" ) else: print( f"{domain} is added to https://github.com/home-assistant/brands, NICE!" )
async def test_comment_on_issue(aresponses, repository_response, issue_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/issues/1", "get", aresponses.Response( text=json.dumps(issue_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/issues/1/comments", "post", aresponses.Response( status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") issue = await repository.get_issue(1) await issue.comment("test")
async def test_get_contents_list(aresponses, repository_response, contents_list_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/contents/", "get", aresponses.Response( text=json.dumps(contents_list_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") contents = await repository.get_contents("", "main") assert len(contents) == 2
async def test_set_last_commit(aresponses, repository_response, branch_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/branches/master", "get", aresponses.Response( text=json.dumps(branch_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") assert repository.last_commit is None await repository.set_last_commit() assert repository.last_commit == "7fd1a60"
async def test_issue_comments(aresponses, repository_response, issue_response, issue_comments_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/issues/1", "get", aresponses.Response( text=json.dumps(issue_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/issues/1/comments", "get", aresponses.Response( text=json.dumps(issue_comments_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") issue = await repository.get_issue(1) comments = await issue.get_comments() first = comments[0] assert first.html_url == "https://github.com/octocat/Hello-World/issues/1347#issuecomment-1" assert first.body == "Me too" assert first.created_at == "2011-04-14T16:00:49Z" assert first.updated_at == "2011-04-14T16:00:49Z" user = first.user assert user.login == "octocat" assert user.id == 1 assert user.avatar_url == "https://github.com/images/error/octocat_happy.gif" assert user.html_url == "https://github.com/octocat" assert user.type == "User" assert not user.site_admin
async def test_create_issue(aresponses, repository_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/issues", "post", aresponses.Response( status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") data = { "title": "test", "body": "body", "state": "closed", "milestone": "v1.0", "labels": ["test"], "assignees": ["octocat"], } await repository.create_issue(**data)
async def test_get_repository(aresponses, repository_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") assert repository.description == "This your first repo!" assert repository.id == 1296269 assert repository.name == "Hello-World" assert repository.full_name == "octocat/Hello-World" assert repository.pushed_at == datetime.datetime( 2011, 1, 26, 19, 6, 43) assert not repository.archived assert repository.topics == ["octocat", "atom", "electron", "api"] assert not repository.fork assert repository.forks_count == 9 assert repository.default_branch == "master" assert repository.last_commit is None assert repository.homepage == "https://github.com" assert repository.stargazers_count == 80 assert repository.watchers_count == 80 assert repository.owner.login == "octocat"
async def check(): if get_category() != "integration": print("Only integrations are checked.") return manifest = get_manifest() domain = manifest.get("domain") if domain is None: print("No domain") exit(1) async with GitHub(TOKEN) as github: repository = await github.get_repo("home-assistant/brands") files = await repository.get_contents("custom_integrations") if domain not in [x.attributes["name"] for x in files]: print( f"{domain} is not added to https://github.com/home-assistant/brands" ) print( "This is needed to ensure the best possible experience for the user" ) exit(1) else: print( f"{domain} is added to https://github.com/home-assistant/brands, NICE!" )
async def check(): print( "Information: https://hacs.xyz/docs/publish/include#check-repository") repo = get_repo() issues = [] async with GitHub(TOKEN) as github: repository = await github.get_repo(repo) repo = repository.attributes if not repo["has_issues"]: issues.append("::error::Issues not enabled.") if not repo["description"]: issues.append( "::error::No description. (https://hacs.xyz/docs/publish/start#description)" ) if not repo["topics"]: issues.append( "::error::No topics. (https://hacs.xyz/docs/publish/start#topics)") if issues: for issue in issues: print(issue) exit(1)
async def test_get_tree(aresponses, repository_response, tree_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/git/trees/main", "get", aresponses.Response( text=json.dumps(tree_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") contents = await repository.get_tree("main") assert contents[0].full_path == "subdir/file.txt" with pytest.raises(AIOGitHubAPIException): await repository.get_tree()
async def test_post_with_json(mock_response, base_response, client_session): mock_response.mock_headers = HEADERS mock_response.mock_data = base_response async with GitHub(TOKEN, session=client_session) as github: await github.client.post("/", data={"test": "test"}, jsondata=True) assert github.client.ratelimits.remaining == "4999"
async def test_content(aresponses, repository_response, contents_file_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/contents/README.md", "get", aresponses.Response( text=json.dumps(contents_file_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") content = await repository.get_contents("README.md", "master") assert content.type == "file" assert content.encoding == "base64" assert content.name == "README.md" assert content.path == "README.md" assert content.content == "" assert ( content.download_url == "https://raw.githubusercontent.com/octokit/octokit.rb/master/README.md" )
async def test_ok_get_auth_error(mock_response, bad_auth_response, client_session): mock_response.mock_data = bad_auth_response async with GitHub(TOKEN, session=client_session) as github: with pytest.raises(AIOGitHubAPIException): await github.client.get("/")
async def test_get_contents_file(aresponses, repository_response, contents_file_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/contents/README.md", "get", aresponses.Response( text=json.dumps(contents_file_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") contents = await repository.get_contents("README.md", "master") assert contents.name == "README.md"
async def test_get_tree(aresponses, repository_response, tree_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/git/trees/master", "get", aresponses.Response( text=json.dumps(tree_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") contents = await repository.get_tree("master") assert contents[0].full_path == "subdir/file.txt" with pytest.raises(AIOGitHubAPIException): await repository.get_tree()
async def get_repository(session, token, repository_full_name): """Return a repository object or None.""" try: github = GitHub(token, session) repository = await github.get_repo(repository_full_name) return repository except (AIOGitHubAPIException, Exception) as exception: raise HacsException(exception)
async def check(): print("Information: https://hacs.xyz/docs/publish/include#check-fork") repo = get_repo() async with GitHub(TOKEN) as github: repository = await github.get_repo(repo) repo = repository.attributes if repo["fork"]: exit(1)
async def get_repository(session, token, repository_full_name, etag=None): """Return a repository object or None.""" try: github = GitHub(token, session) repository = await github.get_repo(repository_full_name, etag) return repository, github.client.last_response.etag except AIOGitHubAPINotModifiedException as exception: raise HacsNotModifiedException(exception) from exception except (ValueError, AIOGitHubAPIException, Exception) as exception: raise HacsException(exception) from exception
async def test_custom_base_url(mock_response, mock_requests, client_session): mock_response.mock_headers = HEADERS async with GitHub(TOKEN, base_url="http://example.com", session=client_session) as github: await github.client.get("/") assert github.client.ratelimits.remaining == "4999" assert mock_requests.last_request["url"] == "http://example.com/"
async def _async_common_setup(hass: HomeAssistant): """Common setup stages.""" integration = await async_get_integration(hass, DOMAIN) hacs = get_hacs() hacs.enable_hacs() await hacs.async_set_stage(None) hacs.log.info(STARTUP.format(version=integration.version)) hacs.integration = integration hacs.version = integration.version hacs.hass = hass hacs.data = HacsData() hacs.system.running = True hacs.session = async_create_clientsession(hass) hacs.tasks = HacsTaskManager(hacs=hacs, hass=hass) hacs.core.lovelace_mode = LovelaceMode.YAML try: lovelace_info = await system_health_info(hacs.hass) hacs.core.lovelace_mode = LovelaceMode( lovelace_info.get("mode", "yaml")) except Exception: # pylint: disable=broad-except # If this happens, the users YAML is not valid, we assume YAML mode pass hacs.log.debug(f"Configuration type: {hacs.configuration.config_type}") hacs.core.config_path = hacs.hass.config.path() hacs.core.ha_version = HAVERSION await hacs.tasks.async_load() # Setup session for API clients session = async_create_clientsession(hacs.hass) ## Legacy GitHub client hacs.github = GitHub( hacs.configuration.token, session, headers={ "User-Agent": f"HACS/{hacs.version}", "Accept": ACCEPT_HEADERS["preview"], }, ) ## New GitHub client hacs.githubapi = GitHubAPI( token=hacs.configuration.token, session=session, **{"client_name": f"HACS/{hacs.version}"}, ) hass.data[DOMAIN] = hacs
async def test_tree_content(aresponses, repository_response, tree_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/git/trees/main", "get", aresponses.Response( text=json.dumps(tree_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/git/trees/main", "get", aresponses.Response(status=304), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") contents = await repository.get_tree("main") assert len([x for x in contents if x.is_directory]) == 1 assert contents[0].full_path == "subdir/file.txt" assert not contents[0].is_directory assert contents[0].path == "subdir" assert contents[0].filename == "file.txt" assert ( contents[0].url == "https://api.github.com/repos/octocat/Hello-World/git/7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b" ) assert ( contents[0].download_url == "https://raw.githubusercontent.com/octocat/Hello-World/main/subdir/file.txt" ) with pytest.raises(AIOGitHubAPINotModifiedException): await repository.get_tree("main", etag=github.client.last_response.etag)
async def test_update_issue(aresponses, repository_response, issue_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/issues/1", "get", aresponses.Response( text=json.dumps(issue_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/issues/1", "post", aresponses.Response( status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") issue = await repository.get_issue(1) data = { "title": "test", "body": "body", "state": "closed", "milestone": "v1.0", "labels": ["test"], "assignees": ["octocat"], } await issue.update(**data)
async def test_get_releases(aresponses, repository_response, releases_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/releases", "get", aresponses.Response( text=json.dumps(releases_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/releases", "get", aresponses.Response( text=json.dumps(releases_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/releases", "get", aresponses.Response( text=json.dumps(releases_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") releases = await repository.get_releases() assert len(releases) == 1 releases = await repository.get_releases(prerelease=True) assert len(releases) == 2 assert releases[0].tag_name == "v1.0.0" assert not releases[0].prerelease releases = await repository.get_releases(prerelease=True, returnlimit=1) assert len(releases) == 1
async def test_get_releases(aresponses, repository_response, releases_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/releases", "get", aresponses.Response( text=json.dumps(releases_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/releases", "get", aresponses.Response( text=json.dumps(releases_response), status=200, headers=NOT_RATELIMITED, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/releases", "get", aresponses.Response( text=json.dumps(releases_response), status=200, headers=NOT_RATELIMITED, ), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") releases = await repository.get_releases() first = releases[0] assert first.tag_name == "v1.0.0" assert first.name == "v1.0.0" assert first.published_at == datetime.datetime(2013, 2, 27, 19, 35, 32) assert not first.draft assert not first.prerelease assert len(first.assets) == 1
async def test_content(aresponses, repository_response, contents_file_response): aresponses.add( "api.github.com", "/repos/octocat/Hello-World", "get", aresponses.Response( text=json.dumps(repository_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/contents/README.md", "get", aresponses.Response( text=json.dumps(contents_file_response), status=200, headers={ "X-RateLimit-Remaining": "1337", "Content-Type": "application/json", "Etag": "xyz..zyx", }, ), ) aresponses.add( "api.github.com", "/repos/octocat/Hello-World/contents/README.md", "get", aresponses.Response(status=304), ) async with GitHub(TOKEN) as github: repository = await github.get_repo("octocat/Hello-World") content = await repository.get_contents("README.md", "main") assert content.type == "file" assert content.encoding == "base64" assert content.name == "README.md" assert content.path == "README.md" assert content.content == "" assert ( content.download_url == "https://raw.githubusercontent.com/octokit/octokit.rb/main/README.md" ) with pytest.raises(AIOGitHubAPINotModifiedException): await repository.get_contents( "README.md", "main", etag=github.client.last_response.etag )
async def validate_repository(repository, category, ref=None): """Validate.""" async with aiohttp.ClientSession() as session: hacs = get_hacs() hacs.session = session hacs.configuration = Configuration() hacs.configuration.token = TOKEN hacs.github = GitHub(hacs.configuration.token, hacs.session) try: await register_repository(repository, category, ref=ref, action=True) except HacsException as exception: exit(exception) print("All good!")