Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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)
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 7
0
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
Esempio n. 8
0
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
Esempio n. 9
0
    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
Esempio n. 11
0
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
Esempio n. 12
0
async def test_session_pass():
    async with aiohttp.ClientSession() as session:
        github = GitHubAPI(session=session)
        assert github._session is session
Esempio n. 13
0
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