From 2d5b74a92af9db72cf428f05f0e9260c2cd898ef Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Mon, 19 Jun 2023 13:07:34 -0700 Subject: [PATCH 1/7] Don't mark certain labels as stale. --- .github/workflows/stale.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d72417b1..6191610b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -24,7 +24,8 @@ jobs: days-before-stale: 30 days-before-close: 3 exempt-draft-pr: true - exempt-issue-labels: "pinned,security" + exempt-issue-labels: + "pinned,security,help wanted,pending,good first issue" exempt-pr-labels: "pinned,security,dependencies" operations-per-run: 1000 - name: Print outputs From 9a9a8c438b8b5b609023808318e76d8f79177313 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jul 2023 06:55:58 +0000 Subject: [PATCH 2/7] Bump actions/setup-python from 4.6.1 to 4.7.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.6.1 to 4.7.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4.6.1...v4.7.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3b23e6ff..4717e803 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: - name: Check out the repository uses: actions/checkout@v3.5.2 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Install requirements @@ -61,7 +61,7 @@ jobs: - name: Check out code from GitHub uses: "actions/checkout@v3.5.2" - name: Setup Python ${{ env.DEFAULT_PYTHON }} - uses: "actions/setup-python@v4.6.1" + uses: "actions/setup-python@v4.7.0" with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Install requirements From e2a04fac37b51ba0d664a185d5a10588ed70a536 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 06:35:28 +0000 Subject: [PATCH 3/7] Bump crazy-max/ghaction-github-labeler from 4.1.0 to 4.2.0 Bumps [crazy-max/ghaction-github-labeler](https://github.com/crazy-max/ghaction-github-labeler) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/crazy-max/ghaction-github-labeler/releases) - [Commits](https://github.com/crazy-max/ghaction-github-labeler/compare/v4.1.0...v4.2.0) --- updated-dependencies: - dependency-name: crazy-max/ghaction-github-labeler dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index ce35187c..b82d6ac9 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -16,6 +16,6 @@ jobs: uses: actions/checkout@v3.5.2 - name: Run Labeler - uses: crazy-max/ghaction-github-labeler@v4.1.0 + uses: crazy-max/ghaction-github-labeler@v4.2.0 with: skip-delete: true From 03d357e21a1dcae59ed575de556f467e729216ed Mon Sep 17 00:00:00 2001 From: jannesblobel <72493222+jannesblobel@users.noreply.github.com> Date: Tue, 19 Sep 2023 17:51:51 +0200 Subject: [PATCH 4/7] fix: inlang settings --- inlang.config.js | 28 ---------------------------- project.inlang.json | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 28 deletions(-) delete mode 100644 inlang.config.js create mode 100644 project.inlang.json diff --git a/inlang.config.js b/inlang.config.js deleted file mode 100644 index 4c16b62b..00000000 --- a/inlang.config.js +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-check - -/** - * @type { import("@inlang/core/config").DefineConfig } - */ -export async function defineConfig(env) { - const plugin = await env.$import( - "https://cdn.jsdelivr.net/gh/samuelstroschein/inlang-plugin-json@1/dist/index.js" - ); - - const { standardLintRules } = await env.$import( - "https://cdn.jsdelivr.net/gh/inlang/standard-lint-rules@1/dist/index.js" - ); - - const pluginConfig = { - pathPattern: "./custom_components/frigate/translations/{language}.json", - }; - - return { - referenceLanguage: "en", - languages: await plugin.getLanguages({ ...env, pluginConfig }), - readResources: (args) => plugin.readResources({ ...args, ...env, pluginConfig }), - writeResources: (args) => plugin.writeResources({ ...args, ...env, pluginConfig }), - lint: { - rules: [standardLintRules()], - }, - }; -} diff --git a/project.inlang.json b/project.inlang.json new file mode 100644 index 00000000..ab59fea2 --- /dev/null +++ b/project.inlang.json @@ -0,0 +1,14 @@ +{ + "$schema":"https://inlang.com/schema/project-settings", + "sourceLanguageTag": "en", + "languageTags": ["de","en","pt_br","pt-BR"], + "modules": [ + "https://cdn.jsdelivr.net/npm/@inlang/plugin-json@4/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@1/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@1/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@1/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@1/dist/index.js" + ], "plugin.inlang.json": { + "pathPattern": "./custom_components/frigate/translations/{languageTag}.json" + } +} From 94128447ea52da7ab41fb4460c6243dc419c2818 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 02:05:18 +0000 Subject: [PATCH 5/7] Bump actions/checkout from 3.5.2 to 4.1.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 4.1.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.2...v4.1.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yaml | 8 ++++---- .github/workflows/labeler.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4717e803..22bb8820 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -19,7 +19,7 @@ jobs: name: Pre-commit steps: - name: Check out the repository - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4.1.1 - name: Set up Python ${{ env.DEFAULT_PYTHON }} uses: actions/setup-python@v4.7.0 with: @@ -37,7 +37,7 @@ jobs: name: HACS steps: - name: Check out the repository - uses: "actions/checkout@v3.5.2" + uses: "actions/checkout@v4.1.1" - name: HACS validation uses: "hacs/action@22.5.0" @@ -49,7 +49,7 @@ jobs: name: Hassfest steps: - name: Check out the repository - uses: "actions/checkout@v3.5.2" + uses: "actions/checkout@v4.1.1" - name: Hassfest validation uses: "home-assistant/actions/hassfest@master" @@ -59,7 +59,7 @@ jobs: name: Run tests steps: - name: Check out code from GitHub - uses: "actions/checkout@v3.5.2" + uses: "actions/checkout@v4.1.1" - name: Setup Python ${{ env.DEFAULT_PYTHON }} uses: "actions/setup-python@v4.7.0" with: diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index b82d6ac9..8950f617 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repository - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4.1.1 - name: Run Labeler uses: crazy-max/ghaction-github-labeler@v4.2.0 From e20d92e025e4fa0f9654de882aadfa7d9b24d59b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 02:05:31 +0000 Subject: [PATCH 6/7] Bump release-drafter/release-drafter from 5.23.0 to 5.25.0 Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.23.0 to 5.25.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5.23.0...v5.25.0) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index b4bcef41..ed66e55a 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -13,6 +13,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Run release-drafter - uses: release-drafter/release-drafter@v5.23.0 + uses: release-drafter/release-drafter@v5.25.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From ff245638d737c05e2849ae757629a1015549270a Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Tue, 17 Oct 2023 19:54:43 -0700 Subject: [PATCH 7/7] Upgrade pylint/pylint-test and address variety of pylint issues. --- custom_components/frigate/__init__.py | 13 +++-- custom_components/frigate/camera.py | 2 +- custom_components/frigate/config_flow.py | 2 +- custom_components/frigate/const.py | 4 +- custom_components/frigate/diagnostics.py | 8 +-- custom_components/frigate/media_source.py | 59 +++++++++-------------- custom_components/frigate/update.py | 2 +- pyproject.toml | 7 ++- requirements_dev.txt | 2 +- 9 files changed, 43 insertions(+), 56 deletions(-) diff --git a/custom_components/frigate/__init__.py b/custom_components/frigate/__init__.py index 88011612..585658e3 100644 --- a/custom_components/frigate/__init__.py +++ b/custom_components/frigate/__init__.py @@ -6,10 +6,11 @@ """ from __future__ import annotations +from collections.abc import Callable from datetime import timedelta import logging import re -from typing import Any, Callable, Final +from typing import Any, Final from awesomeversion import AwesomeVersion @@ -70,8 +71,7 @@ def get_frigate_device_identifier( """Get a device identifier.""" if camera_name: return (DOMAIN, f"{entry.entry_id}:{slugify(camera_name)}") - else: - return (DOMAIN, entry.entry_id) + return (DOMAIN, entry.entry_id) def get_frigate_entity_unique_id( @@ -155,10 +155,9 @@ async def async_setup(hass: HomeAssistant, config: Config) -> bool: """Set up this integration using YAML is not supported.""" integration = await async_get_integration(hass, DOMAIN) _LOGGER.info( - STARTUP_MESSAGE.format( - title=NAME, - integration_version=integration.version, - ) + STARTUP_MESSAGE, + NAME, + integration.version, ) hass.data.setdefault(DOMAIN, {}) diff --git a/custom_components/frigate/camera.py b/custom_components/frigate/camera.py index ef05a6e0..f82fa5d1 100644 --- a/custom_components/frigate/camera.py +++ b/custom_components/frigate/camera.py @@ -451,7 +451,7 @@ async def async_camera_image( return self._last_image @property - def state(self) -> str: + def state(self) -> str: # pylint: disable=overridden-final-method """Return the camera state.""" if self._last_image is None: return STATE_IDLE diff --git a/custom_components/frigate/config_flow.py b/custom_components/frigate/config_flow.py index e26c3a7f..761654a1 100644 --- a/custom_components/frigate/config_flow.py +++ b/custom_components/frigate/config_flow.py @@ -83,7 +83,7 @@ def _show_config_form( self, user_input: dict[str, Any] | None = None, errors: dict[str, Any] | None = None, - ) -> dict[str, Any]: # pylint: disable=unused-argument + ) -> dict[str, Any]: """Show the configuration form.""" if user_input is None: user_input = {} diff --git a/custom_components/frigate/const.py b/custom_components/frigate/const.py index 568793d9..f6bcb51c 100644 --- a/custom_components/frigate/const.py +++ b/custom_components/frigate/const.py @@ -50,8 +50,8 @@ STARTUP_MESSAGE = """ ------------------------------------------------------------------- -{title} -Integration Version: {integration_version} +%s +Integration Version: %s This is a custom integration! If you have any issues with this you need to open an issue here: https://github.com/blakeblackshear/frigate-hass-integration/issues diff --git a/custom_components/frigate/diagnostics.py b/custom_components/frigate/diagnostics.py index 8d6d315a..1aea4768 100644 --- a/custom_components/frigate/diagnostics.py +++ b/custom_components/frigate/diagnostics.py @@ -1,6 +1,8 @@ """Diagnostics support for Frigate.""" -from typing import Any, Dict +from __future__ import annotations + +from typing import Any from homeassistant.components.diagnostics import async_redact_data from homeassistant.config_entries import ConfigEntry @@ -11,7 +13,7 @@ REDACT_CONFIG = {CONF_PASSWORD, CONF_PATH} -def get_redacted_data(data: Dict[str, Any]) -> Any: +def get_redacted_data(data: dict[str, Any]) -> Any: """Redact sensitive vales from data.""" return async_redact_data(data, REDACT_CONFIG) @@ -19,7 +21,7 @@ def get_redacted_data(data: Dict[str, Any]) -> Any: async def async_get_config_entry_diagnostics( hass: HomeAssistant, entry: ConfigEntry, -) -> Dict[str, Any]: +) -> dict[str, Any]: """Return diagnostics for a config entry.""" config = hass.data[DOMAIN][entry.entry_id][ATTR_CONFIG] diff --git a/custom_components/frigate/media_source.py b/custom_components/frigate/media_source.py index a73e4dc1..b7573afe 100644 --- a/custom_components/frigate/media_source.py +++ b/custom_components/frigate/media_source.py @@ -131,11 +131,11 @@ def get_integration_proxy_path(self, timezone: str) -> str: @classmethod def _add_frigate_instance_id_to_parts_if_absent( - self, parts: list[str], default_frigate_instance_id: str | None = None + cls, parts: list[str], default_frigate_instance_id: str | None = None ) -> list[str]: """Add a frigate instance id if it's not specified.""" if ( - self._get_index(parts, 0) == self.get_identifier_type() + cls._get_index(parts, 0) == cls.get_identifier_type() and default_frigate_instance_id is not None ): parts.insert(0, default_frigate_instance_id) @@ -168,32 +168,28 @@ def mime_type(self) -> str: """Get mime type for this frigate media type.""" if self == FrigateMediaType.CLIPS: return "application/x-mpegURL" - else: - return "image/jpg" + return "image/jpg" @property def media_type(self) -> str: """Get media type for this frigate media type.""" if self == FrigateMediaType.CLIPS: return str(MEDIA_TYPE_VIDEO) - else: - return str(MEDIA_TYPE_IMAGE) + return str(MEDIA_TYPE_IMAGE) @property def media_class(self) -> str: """Get media class for this frigate media type.""" if self == FrigateMediaType.CLIPS: return str(MEDIA_CLASS_VIDEO) - else: - return str(MEDIA_CLASS_IMAGE) + return str(MEDIA_CLASS_IMAGE) @property def extension(self) -> str: """Get filename extension.""" if self == FrigateMediaType.CLIPS: return "m3u8" - else: - return "jpg" + return "jpg" @attr.s(frozen=True) @@ -255,8 +251,7 @@ def get_integration_proxy_path(self, timezone: str) -> str: """Get the equivalent Frigate server path.""" if self.frigate_media_type == FrigateMediaType.CLIPS: return f"vod/event/{self.id}/index.{self.frigate_media_type.extension}" - else: - return f"snapshot/{self.id}" + return f"snapshot/{self.id}" @property def mime_type(self) -> str: @@ -375,7 +370,7 @@ def _validate_year_month_day( try: dt.datetime.strptime(data, "%Y-%m-%d") except ValueError as exc: - raise ValueError("Invalid date in identifier: %s" % data) from exc + raise ValueError(f"Invalid date in identifier: {data}") from exc def _validate_hour( @@ -383,7 +378,7 @@ def _validate_hour( ) -> None: """Determine if a value is a valid hour.""" if value is not None and (int(value) < 0 or int(value) > 23): - raise ValueError("Invalid hour in identifier: %s" % value) + raise ValueError(f"Invalid hour in identifier: {value}") @attr.s(frozen=True) @@ -554,8 +549,8 @@ def _get_client(self, identifier: Identifier) -> FrigateApiClient: return client raise MediaSourceError( - "Could not find client for frigate instance id: %s" - % identifier.frigate_instance_id + "Could not find client for frigate instance " + f"id: {identifier.frigate_instance_id}" ) def _get_default_frigate_instance_id(self) -> str | None: @@ -584,7 +579,7 @@ async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia: f"/api/frigate/{identifier.frigate_instance_id}/{server_path}", identifier.mime_type, ) - raise Unresolvable("Unknown or disallowed identifier: %s" % item.identifier) + raise Unresolvable(f"Unknown or disallowed identifier: {item.identifier}") async def async_browse_media( self, @@ -672,7 +667,7 @@ async def async_browse_media( identifier.frigate_instance_id ): raise MediaSourceError( - "Forbidden media source identifier: %s" % item.identifier + f"Forbidden media source identifier: {item.identifier}" ) if isinstance(identifier, EventSearchIdentifier): @@ -719,7 +714,7 @@ async def async_browse_media( except FrigateApiClientError as exc: raise MediaSourceError from exc - raise MediaSourceError("Invalid media source identifier: %s" % item.identifier) + raise MediaSourceError(f"Invalid media source identifier: {item.identifier}") async def _get_event_summary_data( self, identifier: EventSearchIdentifier @@ -1229,19 +1224,13 @@ def _count_by( ) -> int: """Return count of events that match the identifier.""" return sum( - [ - d["count"] - for d in summary_data.data - if ( - (identifier.after is None or d["timestamp"] >= identifier.after) - and ( - identifier.before is None or d["timestamp"] < identifier.before - ) - and (identifier.camera is None or identifier.camera in d["camera"]) - and (identifier.label is None or identifier.label in d["label"]) - and (identifier.zone is None or identifier.zone in d["zones"]) - ) - ] + d["count"] + for d in summary_data.data + if (identifier.after is None or d["timestamp"] >= identifier.after) + and (identifier.before is None or d["timestamp"] < identifier.before) + and (identifier.camera is None or identifier.camera in d["camera"]) + and (identifier.label is None or identifier.label in d["label"]) + and (identifier.zone is None or identifier.zone in d["zones"]) ) def _get_recording_base_media_source( @@ -1298,8 +1287,7 @@ def _get_recording_days( dt.datetime.strptime(day_item["day"], "%Y-%m-%d") except ValueError as exc: raise MediaSourceError( - "Media source is not valid for %s %s" - % (identifier, day_item["day"]) + f"Media source is not valid for {identifier} {day_item['day']}" ) from exc base.children.append( @@ -1340,8 +1328,7 @@ def _get_recording_hours( title = dt.datetime.strptime(hour_data["hour"], "%H").strftime("%H:00") except ValueError as exc: raise MediaSourceError( - "Media source is not valid for %s %s" - % (identifier, hour_data["hour"]) + f"Media source is not valid for {identifier} {hour_data['hour']}" ) from exc base.children.append( diff --git a/custom_components/frigate/update.py b/custom_components/frigate/update.py index 2f9d43d1..6a2fe5d9 100644 --- a/custom_components/frigate/update.py +++ b/custom_components/frigate/update.py @@ -75,7 +75,7 @@ def installed_version(self) -> str | None: if not version_hash: return None - version = str(version_hash).split("-")[0] + version = str(version_hash).split("-", maxsplit=1)[0] return version diff --git a/pyproject.toml b/pyproject.toml index ceab52a9..6048ea51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,6 @@ ignore = [ jobs = 2 load-plugins = [ "pylint.extensions.typing", - "pylint_strict_informational", "pylint_pytest", ] persistent = false @@ -104,9 +103,9 @@ expected-line-ending-format = "LF" [tool.pylint.EXCEPTIONS] overgeneral-exceptions = [ - "BaseException", - "Exception", - "HomeAssistantError", + "builtins.BaseException", + "builtins.Exception", + "homeassistant.HomeAssistantError", ] [tool.pylint.TYPING] diff --git a/requirements_dev.txt b/requirements_dev.txt index fa95629f..2b97d7d2 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -5,7 +5,7 @@ mypy==1.1.1 pre-commit pytest pytest-homeassistant-custom-component==0.12.49 -pylint-pytest +pylint-pytest==1.1.3a0 pylint pytest-aiohttp pytest-asyncio