async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up GitHub from a config entry.""" hass.data.setdefault(DOMAIN, {}) client = GitHubAPI( token=entry.data[CONF_ACCESS_TOKEN], session=async_get_clientsession(hass), **{"client_name": SERVER_SOFTWARE}, ) repositories: list[str] = entry.options[CONF_REPOSITORIES] for repository in repositories: coordinator = GitHubDataUpdateCoordinator( hass=hass, client=client, repository=repository, ) await coordinator.async_config_entry_first_refresh() hass.data[DOMAIN][repository] = coordinator async_cleanup_device_registry(hass=hass, entry=entry) hass.config_entries.async_setup_platforms(entry, PLATFORMS) entry.async_on_unload(entry.add_update_listener(async_reload_entry)) return True
async def test_session_creation_with_enter(): async with GitHubAPI() as github: assert github._session assert isinstance(github._session, aiohttp.ClientSession) assert not github._session.closed assert github._session.closed
async def async_get_config_entry_diagnostics( hass: HomeAssistant, config_entry: ConfigEntry, ) -> dict[str, Any]: """Return diagnostics for a config entry.""" data = {"options": {**config_entry.options}} client = GitHubAPI( token=config_entry.data[CONF_ACCESS_TOKEN], session=async_get_clientsession(hass), **{"client_name": SERVER_SOFTWARE}, ) try: rate_limit_response = await client.rate_limit() except GitHubException as err: data["rate_limit"] = {"error": str(err)} else: data["rate_limit"] = rate_limit_response.data.as_dict repositories: dict[str, GitHubDataUpdateCoordinator] = hass.data[DOMAIN] data["repositories"] = {} for repository, coordinator in repositories.items(): data["repositories"][repository] = coordinator.data return data
async def starred_repositories(hass: HomeAssistant, access_token: str) -> list[str]: """Return a list of repositories that the user has starred.""" client = GitHubAPI(token=access_token, session=async_get_clientsession(hass)) async def _get_starred() -> list[GitHubRepositoryModel] | None: response = await client.user.starred(**{"params": {"per_page": 100}}) if not response.is_last_page: results = await asyncio.gather(*(client.user.starred( **{"params": { "per_page": 100, "page": page_number }}, ) for page_number in range(response.next_page_number, response.last_page_number + 1))) for result in results: response.data.extend(result.data) return response.data try: result = await _get_starred() except GitHubException: return DEFAULT_REPOSITORIES if not result or len(result) == 0: return DEFAULT_REPOSITORIES return sorted((repo.full_name for repo in result), key=str.casefold)
async def test_session_creation(): github = GitHubAPI() assert github._session assert isinstance(github._session, aiohttp.ClientSession) assert not github._session.closed await github.close_session() assert github._session.closed
async def github_api(client_session, mock_response): """Fixture to provide a GitHub object.""" mock_response.throw_on_file_error = True async with GitHubAPI( token=TOKEN, session=client_session, ) as github_obj: yield github_obj
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 async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up GitHub from a config entry.""" hass.data.setdefault(DOMAIN, {}) client = GitHubAPI( token=entry.data[CONF_ACCESS_TOKEN], session=async_get_clientsession(hass), **{"client_name": SERVER_SOFTWARE}, ) repositories: list[str] = entry.options[CONF_REPOSITORIES] for repository in repositories: coordinators: DataUpdateCoordinators = { "information": RepositoryInformationDataUpdateCoordinator(hass=hass, entry=entry, client=client, repository=repository), "release": RepositoryReleaseDataUpdateCoordinator(hass=hass, entry=entry, client=client, repository=repository), "issue": RepositoryIssueDataUpdateCoordinator(hass=hass, entry=entry, client=client, repository=repository), "commit": RepositoryCommitDataUpdateCoordinator(hass=hass, entry=entry, client=client, repository=repository), } await asyncio.gather(*( coordinators["information"].async_config_entry_first_refresh(), coordinators["release"].async_config_entry_first_refresh(), coordinators["issue"].async_config_entry_first_refresh(), coordinators["commit"].async_config_entry_first_refresh(), )) hass.data[DOMAIN][repository] = coordinators await async_cleanup_device_registry(hass=hass, entry=entry) hass.config_entries.async_setup_platforms(entry, PLATFORMS) entry.async_on_unload(entry.add_update_listener(async_reload_entry)) return True
def __init__(self, repository, access_token, session, server_url=None): """Set up GitHub.""" self._repository = repository self.repository_path = repository[CONF_PATH] self._github = GitHubAPI(token=access_token, session=session, **{"base_url": server_url}) self.available = False self.repository_response = None self.commit_response = None self.issues_response = None self.pulls_response = None self.releases_response = None self.views_response = None self.clones_response = None
async def async_initialize_integration( hass: HomeAssistant, *, config_entry: ConfigEntry | None = None, config: dict[str, Any] | None = None, ) -> bool: """Initialize the integration""" hass.data[DOMAIN] = hacs = HacsBase() hacs.enable_hacs() if config is not None: if DOMAIN not in config: return True if hacs.configuration.config_type == ConfigurationType.CONFIG_ENTRY: return True hacs.configuration.update_from_dict( { "config_type": ConfigurationType.YAML, **config[DOMAIN], "config": config[DOMAIN], } ) if config_entry is not None: if config_entry.source == SOURCE_IMPORT: hass.async_create_task(hass.config_entries.async_remove(config_entry.entry_id)) return False hacs.configuration.update_from_dict( { "config_entry": config_entry, "config_type": ConfigurationType.CONFIG_ENTRY, **config_entry.data, **config_entry.options, } ) integration = await async_get_integration(hass, DOMAIN) hacs.set_stage(None) hacs.log.info(STARTUP, integration.version) clientsession = async_get_clientsession(hass) hacs.integration = integration hacs.version = integration.version hacs.configuration.dev = integration.version == "0.0.0" hacs.hass = hass hacs.queue = QueueManager(hass=hass) hacs.data = HacsData(hacs=hacs) hacs.system.running = True hacs.session = clientsession 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 BaseException: # lgtm [py/catch-base-exception] pylint: disable=broad-except # If this happens, the users YAML is not valid, we assume YAML mode pass hacs.log.debug("Configuration type: %s", hacs.configuration.config_type) hacs.core.config_path = hacs.hass.config.path() if hacs.core.ha_version is None: hacs.core.ha_version = AwesomeVersion(HAVERSION) ## Legacy GitHub client hacs.github = GitHub( hacs.configuration.token, clientsession, headers={ "User-Agent": f"HACS/{hacs.version}", "Accept": ACCEPT_HEADERS["preview"], }, ) ## New GitHub client hacs.githubapi = GitHubAPI( token=hacs.configuration.token, session=clientsession, **{"client_name": f"HACS/{hacs.version}"}, ) async def async_startup(): """HACS startup tasks.""" hacs.enable_hacs() for location in ( hass.config.path("custom_components/custom_updater.py"), hass.config.path("custom_components/custom_updater/__init__.py"), ): if os.path.exists(location): hacs.log.critical( "This cannot be used with custom_updater. " "To use this you need to remove custom_updater form %s", location, ) hacs.disable_hacs(HacsDisabledReason.CONSTRAINS) return False if not version_left_higher_or_equal_then_right( hacs.core.ha_version.string, MINIMUM_HA_VERSION, ): hacs.log.critical( "You need HA version %s or newer to use this integration.", MINIMUM_HA_VERSION, ) hacs.disable_hacs(HacsDisabledReason.CONSTRAINS) return False if not await hacs.data.restore(): hacs.disable_hacs(HacsDisabledReason.RESTORE) return False can_update = await hacs.async_can_update() hacs.log.debug("Can update %s repositories", can_update) hacs.set_active_categories() async_register_websocket_commands(hass) async_register_frontend(hass, hacs) if hacs.configuration.config_type == ConfigurationType.YAML: hass.async_create_task( async_load_platform(hass, Platform.SENSOR, DOMAIN, {}, hacs.configuration.config) ) hacs.log.info("Update entities are only supported when using UI configuration") else: if hacs.configuration.experimental: hass.config_entries.async_setup_platforms( hacs.configuration.config_entry, [Platform.SENSOR, Platform.UPDATE] ) else: hass.config_entries.async_setup_platforms( hacs.configuration.config_entry, [Platform.SENSOR] ) hacs.set_stage(HacsStage.SETUP) if hacs.system.disabled: return False # Schedule startup tasks async_at_start(hass=hass, at_start_cb=hacs.startup_tasks) hacs.set_stage(HacsStage.WAITING) hacs.log.info("Setup complete, waiting for Home Assistant before startup tasks starts") return not hacs.system.disabled async def async_try_startup(_=None): """Startup wrapper for yaml config.""" try: startup_result = await async_startup() except AIOGitHubAPIException: startup_result = False if not startup_result: if ( hacs.configuration.config_type == ConfigurationType.YAML or hacs.system.disabled_reason != HacsDisabledReason.INVALID_TOKEN ): hacs.log.info("Could not setup HACS, trying again in 15 min") async_call_later(hass, 900, async_try_startup) return hacs.enable_hacs() await async_try_startup() # Mischief managed! return True
async def test_token(): assert GitHubAPI()._client._base_request_data.token is None assert GitHubAPI(token=TOKEN)._client._base_request_data.token == TOKEN with patch("os.environ", {"GITHUB_TOKEN": TOKEN}): assert GitHubAPI()._client._base_request_data.token == TOKEN
async def test_session_pass(): async with aiohttp.ClientSession() as session: github = GitHubAPI(session=session) assert github._session is session
async def async_initialize_integration( hass: HomeAssistant, *, config_entry: ConfigEntry | None = None, config: dict[str, Any] | None = None, ) -> bool: """Initialize the integration""" hass.data[DOMAIN] = hacs = HacsBase() hacs.enable_hacs() if config is not None: if DOMAIN not in config: return True if hacs.configuration.config_type == ConfigurationType.CONFIG_ENTRY: return True hacs.configuration.update_from_dict({ "config_type": ConfigurationType.YAML, **config[DOMAIN], "config": config[DOMAIN], }) if config_entry is not None: if config_entry.source == SOURCE_IMPORT: hass.async_create_task( hass.config_entries.async_remove(config_entry.entry_id)) return False hacs.configuration.update_from_dict({ "config_entry": config_entry, "config_type": ConfigurationType.CONFIG_ENTRY, **config_entry.data, **config_entry.options, }) integration = await async_get_integration(hass, DOMAIN) await hacs.async_set_stage(None) hacs.log.info(STARTUP, integration.version) clientsession = async_get_clientsession(hass) hacs.integration = integration hacs.version = integration.version hacs.configuration.dev = integration.version == "0.0.0" hacs.hass = hass hacs.queue = QueueManager(hass=hass) hacs.data = HacsData(hacs=hacs) hacs.system.running = True hacs.session = clientsession hacs.tasks = HacsTaskManager(hacs=hacs, hass=hass) hacs.validation = ValidationManager(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 BaseException: # lgtm [py/catch-base-exception] pylint: disable=broad-except # If this happens, the users YAML is not valid, we assume YAML mode pass hacs.log.debug("Configuration type: %s", hacs.configuration.config_type) hacs.core.config_path = hacs.hass.config.path() if hacs.core.ha_version is None: hacs.core.ha_version = AwesomeVersion(HAVERSION) await hacs.tasks.async_load() ## Legacy GitHub client hacs.github = GitHub( hacs.configuration.token, clientsession, headers={ "User-Agent": f"HACS/{hacs.version}", "Accept": ACCEPT_HEADERS["preview"], }, ) ## New GitHub client hacs.githubapi = GitHubAPI( token=hacs.configuration.token, session=clientsession, **{"client_name": f"HACS/{hacs.version}"}, ) async def async_startup(): """HACS startup tasks.""" hacs.enable_hacs() await hacs.async_set_stage(HacsStage.SETUP) if hacs.system.disabled: return False # Setup startup tasks if hacs.hass.state == CoreState.running: async_call_later(hacs.hass, 5, hacs.startup_tasks) else: hacs.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, hacs.startup_tasks) await hacs.async_set_stage(HacsStage.WAITING) hacs.log.info( "Setup complete, waiting for Home Assistant before startup tasks starts" ) return not hacs.system.disabled async def async_try_startup(_=None): """Startup wrapper for yaml config.""" try: startup_result = await async_startup() except AIOGitHubAPIException: startup_result = False if not startup_result: hacs.log.info("Could not setup HACS, trying again in 15 min") async_call_later(hass, 900, async_try_startup) return hacs.enable_hacs() await async_try_startup() # Mischief managed! return True