Compare commits

...

45 Commits

Author SHA1 Message Date
Joakim Sørensen
2b4527fa64 Return early in validate (#3168)
* Return early in validate

* pylint
2021-09-29 18:33:45 +02:00
Joakim Sørensen
23143aede4 Add all_plugins to cleanup code (#3166) 2021-09-29 18:23:25 +02:00
dependabot[bot]
8b93f0aee7 Bump pyupgrade from 2.28.1 to 2.29.0 (#3165)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-09-29 17:47:04 +02:00
Stefan Agner
5cc4a9a929 Use = instead of deprecated : as security option separator (#3167)
Docker reports:
Sep 23 08:16:31 homeassistant dockerd[467]: time="2021-09-23T08:16:31.771717436Z" level=warning msg="Security options with `:` as a separator are deprecated and will be completely unsupported in 17.04, use `=` instead."

Since it seems that Docker supports `=` since quite a while, we should
use `=` only.
2021-09-29 16:42:41 +02:00
Pascal Vizeli
288d2e5bdb Use deepmerge for options (#3162)
* Use deepmerge for options

* fix issue

* Update supervisor/addons/addon.py

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

* Add tests

* Fix merge schema

* Make save for overwrites

* drop community

* more cleanup

* Fix tests

* Fix lists

* revert strategy

* protect overwritten lists

* Update tests/api/test_store.py

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2021-09-29 09:37:04 +02:00
dependabot[bot]
73d84113ea Bump sentry-sdk from 1.4.1 to 1.4.2 (#3159)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.4.1...1.4.2)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-28 09:57:17 +02:00
dependabot[bot]
4b15945ca1 Bump pyupgrade from 2.28.0 to 2.28.1 (#3160)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-09-28 09:43:00 +02:00
dependabot[bot]
10720b2988 Bump dessant/lock-threads from 2.1.2 to 3 (#3158)
* Bump dessant/lock-threads from 2.1.2 to 3

Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 2.1.2 to 3.
- [Release notes](https://github.com/dessant/lock-threads/releases)
- [Changelog](https://github.com/dessant/lock-threads/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dessant/lock-threads/compare/v2.1.2...v3)

---
updated-dependencies:
- dependency-name: dessant/lock-threads
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Adjust config for breaking change

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ludeeus <ludeeus@ludeeus.dev>
2021-09-28 09:41:20 +02:00
Joakim Sørensen
bb991b69bb Bmp frontend to b6344eb6 (#3161) 2021-09-28 09:33:38 +02:00
Pascal Vizeli
7c9f6067c0 Fix pyupgrade precommit (#3155)
* Fix pyupgrade precommit

* address comments
2021-09-27 11:05:21 +02:00
dependabot[bot]
e960a70217 Bump pyupgrade from 2.26.0.post1 to 2.28.0 (#3151)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-27 10:37:21 +02:00
dependabot[bot]
9b0a2e6da9 Bump sentry-sdk from 1.4.0 to 1.4.1 (#3140)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-27 10:36:58 +02:00
Joakim Sørensen
cd0c151bd9 Fix typo in vcn_version (#3154) 2021-09-27 10:25:03 +02:00
Pascal Vizeli
b03c8c24dd Fix UnboundLocalError (#3153) 2021-09-27 09:44:15 +02:00
Pascal Vizeli
4416b6524e Bump voluptuous from 0.12.1 to 0.12.2 (#3147) 2021-09-27 08:28:34 +02:00
dependabot[bot]
c9d3f65cc8 Bump home-assistant/builder from 2021.07.0 to 2021.09.0 (#3150)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-27 08:07:28 +02:00
Pascal Vizeli
0407122fbe Revert "Bump voluptuous from 0.12.1 to 0.12.2 (#3141)" (#3145)
This reverts commit 5e871d9399.
2021-09-25 14:50:01 +02:00
dependabot[bot]
5e871d9399 Bump voluptuous from 0.12.1 to 0.12.2 (#3141)
Bumps [voluptuous](https://github.com/alecthomas/voluptuous) from 0.12.1 to 0.12.2.
- [Release notes](https://github.com/alecthomas/voluptuous/releases)
- [Changelog](https://github.com/alecthomas/voluptuous/blob/master/CHANGELOG.md)
- [Commits](https://github.com/alecthomas/voluptuous/compare/0.12.1...v0.12.2)

---
updated-dependencies:
- dependency-name: voluptuous
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-25 11:02:48 +02:00
Joakim Sørensen
6df7a88666 Bump frontend to 03dc3e52 (#3142) 2021-09-25 10:59:53 +02:00
Pascal Vizeli
5933b66b1c Add os-agent to evaluations for supported systems (#3138) 2021-09-22 15:59:35 +02:00
dependabot[bot]
a85e816cd7 Bump pylint from 2.10.2 to 2.11.1 (#3128)
* Bump pylint from 2.10.2 to 2.11.1

Bumps [pylint](https://github.com/PyCQA/pylint) from 2.10.2 to 2.11.1.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Changelog](https://github.com/PyCQA/pylint/blob/main/ChangeLog)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.10.2...v2.11.1)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix linter issues

* fix tests lint

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-09-22 14:33:32 +02:00
dependabot[bot]
96f6c07912 Bump sentry-sdk from 1.3.1 to 1.4.0 (#3135)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.3.1 to 1.4.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.3.1...1.4.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-22 12:18:33 +02:00
Joakim Sørensen
40bcee38f3 Add startup time and boot_timestamp (#3136)
* Add startup time

* Add boot_timestamp

* Fix type

* patch and rename properties fixture
2021-09-22 11:15:38 +02:00
dependabot[bot]
6d2a38c96e Bump gitpython from 3.1.18 to 3.1.24 (#3130)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.18 to 3.1.24.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.18...3.1.24)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-21 18:23:56 +02:00
dependabot[bot]
dafc2cfec2 Bump pyupgrade from 2.26.0 to 2.26.0.post1 (#3131)
* Bump pyupgrade from 2.26.0 to 2.26.0.post1

Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.26.0 to 2.26.0.post1.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/commits)

---
updated-dependencies:
- dependency-name: pyupgrade
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update .pre-commit-config.yaml

* Fixes

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-09-21 18:22:56 +02:00
Pascal Vizeli
04f36e92e1 Return list of possible data disk targets (#3133)
* Return list of possible data disk targets

* fix path

* fix tests

* Add test

* Fix tests

* Add tests

* Add more tests

* Remove debug

* Address comments

* more clear
2021-09-21 14:51:58 +02:00
Pascal Vizeli
4f97013df4 Using git token + pull image from ghcr.io for tests (#3132) 2021-09-20 13:41:35 +02:00
Pascal Vizeli
53eae96a98 DataDisk reload devices (#3129)
* DataDisk reload devices

* improve loading

* simplify

* validate input device

* add comments

* Add agent version to API

* more tests

* fix test lint
2021-09-20 12:52:51 +02:00
Joakim Sørensen
74530baeb7 Detect if frontend is not loaded (#3124)
* Detect if frontend is not loaded

* update
2021-09-18 14:30:01 +02:00
Pascal Vizeli
271e4f0cc4 Support OS-Agent Data disk (#3120)
* Support OS-Agent Data disk

* fix lint

* add tests

* Fix empty path

* revert change

* Using as_posix()

* clean not needed cast

* rename

* Rename files
2021-09-17 15:01:07 +02:00
Joakim Sørensen
f4c7f2cae1 Update frontend to cb11c6b3 (#3125) 2021-09-15 10:54:12 +02:00
dependabot[bot]
24cdb4787a Bump black from 21.8b0 to 21.9b0 (#3123)
* Bump black from 21.8b0 to 21.9b0

Bumps [black](https://github.com/psf/black) from 21.8b0 to 21.9b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update .pre-commit-config.yaml

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-09-14 12:01:10 +02:00
dependabot[bot]
57b1c21af4 Bump codecov/codecov-action from 2.0.3 to 2.1.0 (#3122)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 2.0.3 to 2.1.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v2.0.3...v2.1.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-14 09:02:30 +02:00
dependabot[bot]
f0eddb6926 Bump debugpy from 1.4.1 to 1.4.3 (#3116)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.4.1 to 1.4.3.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.4.1...v1.4.3)

---
updated-dependencies:
- dependency-name: debugpy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-13 16:06:59 +02:00
dependabot[bot]
7c74c1bd8c Bump pyupgrade from 2.25.0 to 2.26.0 (#3118)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.25.0 to 2.26.0.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.25.0...v2.26.0)

---
updated-dependencies:
- dependency-name: pyupgrade
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-13 16:06:42 +02:00
dependabot[bot]
2d4a85ae43 Bump pulsectl from 21.5.18 to 21.9.1 (#3108)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 21.5.18 to 21.9.1.
- [Release notes](https://github.com/mk-fg/python-pulse-control/releases)
- [Changelog](https://github.com/mk-fg/python-pulse-control/blob/master/CHANGES.rst)
- [Commits](https://github.com/mk-fg/python-pulse-control/commits)

---
updated-dependencies:
- dependency-name: pulsectl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-13 14:00:08 +02:00
Joakim Sørensen
d48c439737 Print supervisor container logs on failure (#3110) 2021-09-09 13:21:22 +02:00
dependabot[bot]
874c50d3e8 Bump docker from 5.0.0 to 5.0.2 (#3099)
Bumps [docker](https://github.com/docker/docker-py) from 5.0.0 to 5.0.2.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/5.0.0...5.0.2)

---
updated-dependencies:
- dependency-name: docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-06 08:50:42 +02:00
Joakim Sørensen
4beaf571c2 Bump frontend to d5a16176 (#3101) 2021-09-03 12:49:33 +02:00
dependabot[bot]
58a948447e Bump pre-commit from 2.14.1 to 2.15.0 (#3103)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.14.1 to 2.15.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.14.1...v2.15.0)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-03 10:37:19 +02:00
Pascal Vizeli
32af7ef28b Support USB discovery (#3100)
* Support USB discovery

* fix policy

* Fix scan command

* address comments

Co-authored-by: Ludeeus <ludeeus@ludeeus.dev>
2021-09-02 20:34:18 +02:00
Joakim Sørensen
208fb549b7 Update translations as a part of updating the frontend (#3096)
* Update translations as a part of updating the frontend

* Update frontend to ac64d293 with translations
2021-09-01 13:59:12 +02:00
Joakim Sørensen
ab704c11cf Ignore rootfs (#3097) 2021-09-01 13:58:48 +02:00
Joakim Sørensen
966b962ccf Ignore all files and directories that starts with . (#3094)
* Ignore all files and directories that starts with .

* pylint

* Check all parts
2021-09-01 12:50:44 +02:00
dependabot[bot]
4ea3695982 Bump pytest from 6.2.4 to 6.2.5 (#3092)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.4 to 6.2.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.4...6.2.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-31 08:19:36 +02:00
440 changed files with 2296 additions and 1182 deletions

View File

@@ -119,15 +119,15 @@ jobs:
uses: docker/login-action@v1.10.0
with:
registry: ghcr.io
username: ${{ secrets.GIT_USER }}
password: ${{ secrets.GIT_TOKEN }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set build arguments
if: needs.init.outputs.publish == 'false'
run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV
- name: Build supervisor
uses: home-assistant/builder@2021.07.0
uses: home-assistant/builder@2021.09.0
with:
args: |
$BUILD_ARGS \
@@ -192,13 +192,14 @@ jobs:
runs-on: ubuntu-latest
name: Run the Supervisor
needs: ["build", "codenotary", "init"]
timeout-minutes: 60
steps:
- name: Checkout the repository
uses: actions/checkout@v2.3.4
- name: Build the Supervisor
if: needs.init.outputs.publish != 'true'
uses: home-assistant/builder@2021.07.0
uses: home-assistant/builder@2021.09.0
with:
args: |
--test \
@@ -209,8 +210,8 @@ jobs:
- name: Pull Supervisor
if: needs.init.outputs.publish == 'true'
run: |
docker pull homeassistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }}
docker tag homeassistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }} homeassistant/amd64-hassio-supervisor:runner
docker pull ghcr.io/home-assistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }}
docker tag ghcr.io/home-assistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }} homeassistant/amd64-hassio-supervisor:runner
- name: Create the Supervisor
run: |
@@ -218,7 +219,7 @@ jobs:
docker create --name hassio_supervisor \
--privileged \
--security-opt seccomp=unconfined \
--security-opt apparmor:unconfined \
--security-opt apparmor=unconfined \
-v /run/docker.sock:/run/docker.sock \
-v /run/dbus:/run/dbus \
-v /tmp/supervisor/data:/data \
@@ -240,21 +241,18 @@ jobs:
ping=$(curl -sSL "http://$SUPERVISOR/supervisor/ping" | jq -r '.result')
sleep 5
done
docker logs hassio_supervisor
- name: Check the Supervisor
run: |
echo "Checking supervisor info"
test=$(docker exec hassio_cli ha supervisor info --no-progress --raw-json | jq -r '.result')
if [ "$test" != "ok" ];then
docker logs hassio_supervisor
exit 1
fi
echo "Checking supervisor network info"
test=$(docker exec hassio_cli ha network info --no-progress --raw-json | jq -r '.result')
if [ "$test" != "ok" ];then
docker logs hassio_supervisor
exit 1
fi
@@ -263,14 +261,12 @@ jobs:
echo "Install Core SSH Add-on"
test=$(docker exec hassio_cli ha addons install core_ssh --no-progress --raw-json | jq -r '.result')
if [ "$test" != "ok" ];then
docker logs hassio_supervisor
exit 1
fi
echo "Start Core SSH Add-on"
test=$(docker exec hassio_cli ha addons start core_ssh --no-progress --raw-json | jq -r '.result')
if [ "$test" != "ok" ];then
docker logs hassio_supervisor
exit 1
fi
@@ -280,20 +276,21 @@ jobs:
echo "Enable Content-Trust"
test=$(docker exec hassio_cli ha security options --content-trust=true --no-progress --raw-json | jq -r '.result')
if [ "$test" != "ok" ];then
docker logs hassio_supervisor
exit 1
fi
echo "Run supervisor health check"
test=$(docker exec hassio_cli ha resolution healthcheck --no-progress --raw-json | jq -r '.result')
if [ "$test" != "ok" ];then
docker logs hassio_supervisor
exit 1
fi
echo "Check supervisor unhealthy"
test=$(docker exec hassio_cli ha resolution info --no-progress --raw-json | jq -r '.data.unhealthy[]')
if [ "$test" != "" ];then
docker logs hassio_supervisor
exit 1
fi
- name: Get supervisor logs on failiure
if: ${{ cancelled() || failure() }}
run: docker logs hassio_supervisor

View File

@@ -357,7 +357,7 @@ jobs:
- name: Install VCN tools
uses: home-assistant/actions/helpers/vcn@master
with:
vnc_version: ${{ env.DEFAULT_VCN }}
vcn_version: ${{ env.DEFAULT_VCN }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2.1.6
@@ -433,4 +433,4 @@ jobs:
coverage report
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2.0.3
uses: codecov/codecov-action@v2.1.0

View File

@@ -9,12 +9,12 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v2.1.2
- uses: dessant/lock-threads@v3
with:
github-token: ${{ github.token }}
issue-lock-inactive-days: "30"
issue-exclude-created-before: "2020-10-01T00:00:00Z"
issue-inactive-days: "30"
exclude-issue-created-before: "2020-10-01T00:00:00Z"
issue-lock-reason: ""
pr-lock-inactive-days: "1"
pr-exclude-created-before: "2020-11-01T00:00:00Z"
pr-inactive-days: "1"
exclude-pr-created-before: "2020-11-01T00:00:00Z"
pr-lock-reason: ""

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/psf/black
rev: 21.8b0
rev: 21.9b0
hooks:
- id: black
args:
@@ -28,7 +28,7 @@ repos:
hooks:
- id: isort
- repo: https://github.com/asottile/pyupgrade
rev: v2.6.2
rev: v2.29.0
hooks:
- id: pyupgrade
args: [--py37-plus]
args: [--py39-plus]

9
.vscode/tasks.json vendored
View File

@@ -32,7 +32,7 @@
{
"label": "Update Supervisor Panel",
"type": "shell",
"command": "./scripts/update-frontend.sh",
"command": "LOKALISE_TOKEN='${input:localiseToken}' ./scripts/update-frontend.sh",
"group": {
"kind": "build",
"isDefault": true
@@ -86,5 +86,12 @@
},
"problemMatcher": []
}
],
"inputs": [
{
"id": "localiseToken",
"type": "promptString",
"description": "Paste your lokalise token to download frontend translations"
}
]
}

View File

@@ -2,7 +2,7 @@
reports=no
jobs=2
good-names=id,i,j,k,ex,Run,_,fp,T
good-names=id,i,j,k,ex,Run,_,fp,T,os
extension-pkg-whitelist=
ciso8601

View File

@@ -9,12 +9,13 @@ ciso8601==2.2.0
colorlog==6.4.1
cpe==1.2.1
cryptography==3.4.6
debugpy==1.4.1
docker==5.0.0
gitpython==3.1.18
debugpy==1.4.3
deepmerge==0.3.0
docker==5.0.2
gitpython==3.1.24
jinja2==3.0.1
pulsectl==21.5.18
pulsectl==21.9.1
pyudev==0.22.0
ruamel.yaml==0.15.100
sentry-sdk==1.3.1
voluptuous==0.12.1
sentry-sdk==1.4.2
voluptuous==0.12.2

View File

@@ -1,14 +1,14 @@
black==21.8b0
black==21.9b0
codecov==2.1.12
coverage==5.5
flake8-docstrings==1.6.0
flake8==3.9.2
pre-commit==2.14.1
pre-commit==2.15.0
pydocstyle==6.1.1
pylint==2.10.2
pylint==2.11.1
pytest-aiohttp==0.3.0
pytest-asyncio==0.12.0 # NB!: Versions over 0.12.0 breaks pytest-aiohttp (https://github.com/aio-libs/pytest-aiohttp/issues/16)
pytest-cov==2.12.1
pytest-timeout==1.4.2
pytest==6.2.4
pyupgrade==2.25.0
pytest==6.2.5
pyupgrade==2.29.0

View File

@@ -15,7 +15,7 @@ function start_docker() {
starttime="$(date +%s)"
endtime="$(date +%s)"
until docker info >/dev/null 2>&1; do
if [ $((endtime - starttime)) -le $DOCKER_TIMEOUT ]; then
if [[ $((endtime - starttime)) -le $DOCKER_TIMEOUT ]]; then
sleep 1
endtime=$(date +%s)
else
@@ -38,7 +38,7 @@ function stop_docker() {
# Now wait for it to die
kill "$DOCKER_PID"
while kill -0 "$DOCKER_PID" 2> /dev/null; do
if [ $((endtime - starttime)) -le $DOCKER_TIMEOUT ]; then
if [[ $((endtime - starttime)) -le $DOCKER_TIMEOUT ]]; then
sleep 1
endtime=$(date +%s)
else

View File

@@ -36,7 +36,7 @@ function run_supervisor() {
--name hassio_supervisor \
--privileged \
--security-opt seccomp=unconfined \
--security-opt apparmor:unconfined \
--security-opt apparmor=unconfined \
-v /run/docker.sock:/run/docker.sock:rw \
-v /run/dbus:/run/dbus:ro \
-v /run/udev:/run/udev:ro \

View File

@@ -1,4 +1,6 @@
#!/bin/bash
source "${BASH_SOURCE[0]%/*}/common.sh"
set -e
# Update frontend
@@ -9,6 +11,10 @@ cd home-assistant-polymer
nvm install
script/bootstrap
# Download translations
start_docker
./script/translations_download
# build frontend
cd hassio
./script/build_hassio
@@ -16,3 +22,9 @@ cd hassio
# Copy frontend
rm -rf ../../supervisor/api/panel/*
cp -rf build/* ../../supervisor/api/panel/
# Reset frontend git
cd ..
git reset --hard HEAD
stop_docker

View File

@@ -3,7 +3,7 @@ import asyncio
from contextlib import suppress
import logging
import tarfile
from typing import Dict, List, Optional, Union
from typing import Optional, Union
from ..const import AddonBoot, AddonStartup, AddonState
from ..coresys import CoreSys, CoreSysAttributes
@@ -38,17 +38,17 @@ class AddonManager(CoreSysAttributes):
"""Initialize Docker base wrapper."""
self.coresys: CoreSys = coresys
self.data: AddonsData = AddonsData(coresys)
self.local: Dict[str, Addon] = {}
self.store: Dict[str, AddonStore] = {}
self.local: dict[str, Addon] = {}
self.store: dict[str, AddonStore] = {}
@property
def all(self) -> List[AnyAddon]:
def all(self) -> list[AnyAddon]:
"""Return a list of all add-ons."""
addons: Dict[str, AnyAddon] = {**self.store, **self.local}
addons: dict[str, AnyAddon] = {**self.store, **self.local}
return list(addons.values())
@property
def installed(self) -> List[Addon]:
def installed(self) -> list[Addon]:
"""Return a list of all installed add-ons."""
return list(self.local.values())
@@ -89,7 +89,7 @@ class AddonManager(CoreSysAttributes):
async def boot(self, stage: AddonStartup) -> None:
"""Boot add-ons with mode auto."""
tasks: List[Addon] = []
tasks: list[Addon] = []
for addon in self.installed:
if addon.boot != AddonBoot.AUTO or addon.startup != stage:
continue
@@ -123,7 +123,7 @@ class AddonManager(CoreSysAttributes):
async def shutdown(self, stage: AddonStartup) -> None:
"""Shutdown addons."""
tasks: List[Addon] = []
tasks: list[Addon] = []
for addon in self.installed:
if addon.state != AddonState.STARTED or addon.startup != stage:
continue
@@ -371,7 +371,7 @@ class AddonManager(CoreSysAttributes):
@Job(conditions=[JobCondition.FREE_SPACE, JobCondition.INTERNET_HOST])
async def repair(self) -> None:
"""Repair local add-ons."""
needs_repair: List[Addon] = []
needs_repair: list[Addon] = []
# Evaluate Add-ons to repair
for addon in self.installed:

View File

@@ -10,9 +10,10 @@ import secrets
import shutil
import tarfile
from tempfile import TemporaryDirectory
from typing import Any, Awaitable, Dict, List, Optional, Set
from typing import Any, Awaitable, Final, Optional
import aiohttp
from deepmerge import Merger
import voluptuous as vol
from voluptuous.humanize import humanize_error
@@ -87,6 +88,12 @@ RE_OLD_AUDIO = re.compile(r"\d+,\d+")
WATCHDOG_TIMEOUT = aiohttp.ClientTimeout(total=10)
_OPTIONS_MERGER: Final = Merger(
type_strategies=[(dict, ["merge"])],
fallback_strategies=["override"],
type_conflict_strategies=["override"],
)
class Addon(AddonModel):
"""Hold data for add-on inside Supervisor."""
@@ -187,17 +194,19 @@ class Addon(AddonModel):
return self.version != self.latest_version
@property
def dns(self) -> List[str]:
def dns(self) -> list[str]:
"""Return list of DNS name for that add-on."""
return [f"{self.hostname}.{DNS_SUFFIX}"]
@property
def options(self) -> Dict[str, Any]:
def options(self) -> dict[str, Any]:
"""Return options with local changes."""
return {**self.data[ATTR_OPTIONS], **self.persist[ATTR_OPTIONS]}
return _OPTIONS_MERGER.merge(
deepcopy(self.data[ATTR_OPTIONS]), deepcopy(self.persist[ATTR_OPTIONS])
)
@options.setter
def options(self, value: Optional[Dict[str, Any]]) -> None:
def options(self, value: Optional[dict[str, Any]]) -> None:
"""Store user add-on options."""
self.persist[ATTR_OPTIONS] = {} if value is None else deepcopy(value)
@@ -274,12 +283,12 @@ class Addon(AddonModel):
self.persist[ATTR_PROTECTED] = value
@property
def ports(self) -> Optional[Dict[str, Optional[int]]]:
def ports(self) -> Optional[dict[str, Optional[int]]]:
"""Return ports of add-on."""
return self.persist.get(ATTR_NETWORK, super().ports)
@ports.setter
def ports(self, value: Optional[Dict[str, Optional[int]]]) -> None:
def ports(self, value: Optional[dict[str, Optional[int]]]) -> None:
"""Set custom ports of add-on."""
if value is None:
self.persist.pop(ATTR_NETWORK, None)
@@ -425,7 +434,7 @@ class Addon(AddonModel):
return Path(self.sys_config.path_extern_tmp, f"{self.slug}_pulse")
@property
def devices(self) -> Set[Device]:
def devices(self) -> set[Device]:
"""Extract devices from add-on options."""
options_schema = self.schema
with suppress(vol.Invalid):
@@ -434,7 +443,7 @@ class Addon(AddonModel):
return options_schema.devices
@property
def pwned(self) -> Set[str]:
def pwned(self) -> set[str]:
"""Extract pwned data for add-on options."""
options_schema = self.schema
with suppress(vol.Invalid):
@@ -530,8 +539,7 @@ class Addon(AddonModel):
# Write pulse config
try:
with self.path_pulse.open("w") as config_file:
config_file.write(pulse_config)
self.path_pulse.write_text(pulse_config, encoding="utf-8")
except OSError as err:
_LOGGER.error(
"Add-on %s can't write pulse/client.config: %s", self.slug, err

View File

@@ -2,7 +2,7 @@
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, Dict
from typing import TYPE_CHECKING
from awesomeversion import AwesomeVersion
@@ -60,12 +60,12 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
return self._data[ATTR_SQUASH]
@property
def additional_args(self) -> Dict[str, str]:
def additional_args(self) -> dict[str, str]:
"""Return additional Docker build arguments."""
return self._data[ATTR_ARGS]
@property
def additional_labels(self) -> Dict[str, str]:
def additional_labels(self) -> dict[str, str]:
"""Return additional Docker labels."""
return self._data[ATTR_LABELS]

View File

@@ -1,6 +1,6 @@
"""Init file for Supervisor add-on data."""
from copy import deepcopy
from typing import Any, Dict
from typing import Any
from ..const import (
ATTR_IMAGE,
@@ -16,7 +16,7 @@ from ..utils.common import FileConfiguration
from .addon import Addon
from .validate import SCHEMA_ADDONS_FILE
Config = Dict[str, Any]
Config = dict[str, Any]
class AddonsData(FileConfiguration, CoreSysAttributes):

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor add-ons."""
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Any, Awaitable, Dict, List, Optional
from typing import Any, Awaitable, Optional
from awesomeversion import AwesomeVersion, AwesomeVersionException
@@ -83,7 +83,7 @@ from .const import ATTR_BACKUP
from .options import AddonOptions, UiOptions
from .validate import RE_SERVICE, RE_VOLUME
Data = Dict[str, Any]
Data = dict[str, Any]
class AddonModel(CoreSysAttributes, ABC):
@@ -115,7 +115,7 @@ class AddonModel(CoreSysAttributes, ABC):
return self._available(self.data)
@property
def options(self) -> Dict[str, Any]:
def options(self) -> dict[str, Any]:
"""Return options with local changes."""
return self.data[ATTR_OPTIONS]
@@ -140,7 +140,7 @@ class AddonModel(CoreSysAttributes, ABC):
return self.slug.replace("_", "-")
@property
def dns(self) -> List[str]:
def dns(self) -> list[str]:
"""Return list of DNS name for that add-on."""
return []
@@ -184,8 +184,7 @@ class AddonModel(CoreSysAttributes, ABC):
return None
# Return data
with readme.open("r") as readme_file:
return readme_file.read()
return readme.read_text(encoding="utf-8")
@property
def repository(self) -> str:
@@ -228,7 +227,7 @@ class AddonModel(CoreSysAttributes, ABC):
return self.data[ATTR_STAGE]
@property
def services_role(self) -> Dict[str, str]:
def services_role(self) -> dict[str, str]:
"""Return dict of services with rights."""
services_list = self.data.get(ATTR_SERVICES, [])
@@ -241,17 +240,17 @@ class AddonModel(CoreSysAttributes, ABC):
return services
@property
def discovery(self) -> List[str]:
def discovery(self) -> list[str]:
"""Return list of discoverable components/platforms."""
return self.data.get(ATTR_DISCOVERY, [])
@property
def ports_description(self) -> Optional[Dict[str, str]]:
def ports_description(self) -> Optional[dict[str, str]]:
"""Return descriptions of ports."""
return self.data.get(ATTR_PORTS_DESCRIPTION)
@property
def ports(self) -> Optional[Dict[str, Optional[int]]]:
def ports(self) -> Optional[dict[str, Optional[int]]]:
"""Return ports of add-on."""
return self.data.get(ATTR_PORTS)
@@ -311,17 +310,17 @@ class AddonModel(CoreSysAttributes, ABC):
return self.data[ATTR_HOST_DBUS]
@property
def static_devices(self) -> List[Path]:
def static_devices(self) -> list[Path]:
"""Return static devices of add-on."""
return [Path(node) for node in self.data.get(ATTR_DEVICES, [])]
@property
def environment(self) -> Optional[Dict[str, str]]:
def environment(self) -> Optional[dict[str, str]]:
"""Return environment of add-on."""
return self.data.get(ATTR_ENVIRONMENT)
@property
def privileged(self) -> List[Capabilities]:
def privileged(self) -> list[Capabilities]:
"""Return list of privilege."""
return self.data.get(ATTR_PRIVILEGED, [])
@@ -360,7 +359,7 @@ class AddonModel(CoreSysAttributes, ABC):
return self.data[ATTR_HASSIO_ROLE]
@property
def backup_exclude(self) -> List[str]:
def backup_exclude(self) -> list[str]:
"""Return Exclude list for backup."""
return self.data.get(ATTR_BACKUP_EXCLUDE, [])
@@ -495,12 +494,12 @@ class AddonModel(CoreSysAttributes, ABC):
return self.path_documentation.exists()
@property
def supported_arch(self) -> List[str]:
def supported_arch(self) -> list[str]:
"""Return list of supported arch."""
return self.data[ATTR_ARCH]
@property
def supported_machine(self) -> List[str]:
def supported_machine(self) -> list[str]:
"""Return list of supported machine."""
return self.data.get(ATTR_MACHINE, [])
@@ -515,7 +514,7 @@ class AddonModel(CoreSysAttributes, ABC):
return ATTR_IMAGE not in self.data
@property
def map_volumes(self) -> Dict[str, str]:
def map_volumes(self) -> dict[str, str]:
"""Return a dict of {volume: policy} from add-on."""
volumes = {}
for volume in self.data[ATTR_MAP]:
@@ -566,7 +565,7 @@ class AddonModel(CoreSysAttributes, ABC):
return AddonOptions(self.coresys, raw_schema, self.name, self.slug)
@property
def schema_ui(self) -> Optional[List[Dict[any, any]]]:
def schema_ui(self) -> Optional[list[dict[any, any]]]:
"""Create a UI schema for add-on options."""
raw_schema = self.data[ATTR_SCHEMA]

View File

@@ -3,7 +3,7 @@ import hashlib
import logging
from pathlib import Path
import re
from typing import Any, Dict, List, Set, Union
from typing import Any, Union
import voluptuous as vol
@@ -59,13 +59,13 @@ class AddonOptions(CoreSysAttributes):
"""Validate Add-ons Options."""
def __init__(
self, coresys: CoreSys, raw_schema: Dict[str, Any], name: str, slug: str
self, coresys: CoreSys, raw_schema: dict[str, Any], name: str, slug: str
):
"""Validate schema."""
self.coresys: CoreSys = coresys
self.raw_schema: Dict[str, Any] = raw_schema
self.devices: Set[Device] = set()
self.pwned: Set[str] = set()
self.raw_schema: dict[str, Any] = raw_schema
self.devices: set[Device] = set()
self.pwned: set[str] = set()
self._name = name
self._slug = slug
@@ -187,7 +187,7 @@ class AddonOptions(CoreSysAttributes):
f"Fatal error for option '{key}' with type '{typ}' in {self._name} ({self._slug})"
) from None
def _nested_validate_list(self, typ: Any, data_list: List[Any], key: str):
def _nested_validate_list(self, typ: Any, data_list: list[Any], key: str):
"""Validate nested items."""
options = []
@@ -209,7 +209,7 @@ class AddonOptions(CoreSysAttributes):
return options
def _nested_validate_dict(
self, typ: Dict[Any, Any], data_dict: Dict[Any, Any], key: str
self, typ: dict[Any, Any], data_dict: dict[Any, Any], key: str
):
"""Validate nested items."""
options = {}
@@ -241,7 +241,7 @@ class AddonOptions(CoreSysAttributes):
return options
def _check_missing_options(
self, origin: Dict[Any, Any], exists: Dict[Any, Any], root: str
self, origin: dict[Any, Any], exists: dict[Any, Any], root: str
) -> None:
"""Check if all options are exists."""
missing = set(origin) - set(exists)
@@ -267,9 +267,9 @@ class UiOptions(CoreSysAttributes):
"""Initialize UI option render."""
self.coresys = coresys
def __call__(self, raw_schema: Dict[str, Any]) -> List[Dict[str, Any]]:
def __call__(self, raw_schema: dict[str, Any]) -> list[dict[str, Any]]:
"""Generate UI schema."""
ui_schema: List[Dict[str, Any]] = []
ui_schema: list[dict[str, Any]] = []
# read options
for key, value in raw_schema.items():
@@ -287,13 +287,13 @@ class UiOptions(CoreSysAttributes):
def _single_ui_option(
self,
ui_schema: List[Dict[str, Any]],
ui_schema: list[dict[str, Any]],
value: str,
key: str,
multiple: bool = False,
) -> None:
"""Validate a single element."""
ui_node: Dict[str, Union[str, bool, float, List[str]]] = {"name": key}
ui_node: dict[str, Union[str, bool, float, list[str]]] = {"name": key}
# If multiple
if multiple:
@@ -365,8 +365,8 @@ class UiOptions(CoreSysAttributes):
def _nested_ui_list(
self,
ui_schema: List[Dict[str, Any]],
option_list: List[Any],
ui_schema: list[dict[str, Any]],
option_list: list[Any],
key: str,
) -> None:
"""UI nested list items."""
@@ -383,8 +383,8 @@ class UiOptions(CoreSysAttributes):
def _nested_ui_dict(
self,
ui_schema: List[Dict[str, Any]],
option_dict: Dict[str, Any],
ui_schema: list[dict[str, Any]],
option_dict: dict[str, Any],
key: str,
multiple: bool = False,
) -> None:
@@ -408,7 +408,7 @@ class UiOptions(CoreSysAttributes):
ui_schema.append(ui_node)
def _create_device_filter(str_filter: str) -> Dict[str, Any]:
def _create_device_filter(str_filter: str) -> dict[str, Any]:
"""Generate device Filter."""
raw_filter = dict(value.split("=") for value in str_filter.split(";"))

View File

@@ -2,7 +2,7 @@
import logging
import re
import secrets
from typing import Any, Dict
from typing import Any
import uuid
import voluptuous as vol
@@ -148,7 +148,7 @@ RE_MACHINE = re.compile(
)
def _warn_addon_config(config: Dict[str, Any]):
def _warn_addon_config(config: dict[str, Any]):
"""Warn about miss configs."""
name = config.get(ATTR_NAME)
if not name:
@@ -179,7 +179,7 @@ def _warn_addon_config(config: Dict[str, Any]):
def _migrate_addon_config(protocol=False):
"""Migrate addon config."""
def _migrate(config: Dict[str, Any]):
def _migrate(config: dict[str, Any]):
name = config.get(ATTR_NAME)
if not name:
raise vol.Invalid("Invalid Add-on config!")
@@ -281,7 +281,7 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Optional(ATTR_PANEL_ICON, default="mdi:puzzle"): str,
vol.Optional(ATTR_PANEL_TITLE): str,
vol.Optional(ATTR_PANEL_ADMIN, default=True): vol.Boolean(),
vol.Optional(ATTR_HOMEASSISTANT): vol.Maybe(version_tag),
vol.Optional(ATTR_HOMEASSISTANT): version_tag,
vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_PID, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_IPC, default=False): vol.Boolean(),

View File

@@ -145,6 +145,8 @@ class RestAPI(CoreSysAttributes):
web.get("/os/info", api_os.info),
web.post("/os/update", api_os.update),
web.post("/os/config/sync", api_os.config_sync),
web.post("/os/datadisk/move", api_os.migrate_data),
web.get("/os/datadisk/list", api_os.list_data),
]
)

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict, List
from typing import Any, Awaitable
from aiohttp import web
import voluptuous as vol
@@ -110,7 +110,7 @@ from .utils import api_process, api_process_raw, api_validate, json_loads
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): str})
# pylint: disable=no-value-for-parameter
SCHEMA_OPTIONS = vol.Schema(
@@ -118,8 +118,8 @@ SCHEMA_OPTIONS = vol.Schema(
vol.Optional(ATTR_BOOT): vol.Coerce(AddonBoot),
vol.Optional(ATTR_NETWORK): vol.Maybe(docker_ports),
vol.Optional(ATTR_AUTO_UPDATE): vol.Boolean(),
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(str),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(str),
vol.Optional(ATTR_INGRESS_PANEL): vol.Boolean(),
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
}
@@ -156,7 +156,7 @@ class APIAddons(CoreSysAttributes):
return addon
@api_process
async def list(self, request: web.Request) -> Dict[str, Any]:
async def list(self, request: web.Request) -> dict[str, Any]:
"""Return all add-ons or repositories."""
data_addons = [
{
@@ -201,7 +201,7 @@ class APIAddons(CoreSysAttributes):
await asyncio.shield(self.sys_store.reload())
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return add-on information."""
addon: AnyAddon = self._extract_addon(request)
@@ -309,7 +309,7 @@ class APIAddons(CoreSysAttributes):
# Extend schema with add-on specific validation
addon_schema = SCHEMA_OPTIONS.extend(
{vol.Optional(ATTR_OPTIONS): vol.Any(None, addon.schema)}
{vol.Optional(ATTR_OPTIONS): vol.Maybe(addon.schema)}
)
# Validate/Process Body
@@ -390,7 +390,7 @@ class APIAddons(CoreSysAttributes):
async def security(self, request: web.Request) -> None:
"""Store security options for add-on."""
addon = self._extract_addon_installed(request)
body: Dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
body: dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
if ATTR_PROTECTED in body:
_LOGGER.warning("Changing protected flag for %s!", addon.slug)
@@ -399,7 +399,7 @@ class APIAddons(CoreSysAttributes):
addon.save_persist()
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
async def stats(self, request: web.Request) -> dict[str, Any]:
"""Return resource information."""
addon = self._extract_addon_installed(request)
@@ -503,6 +503,6 @@ class APIAddons(CoreSysAttributes):
await asyncio.shield(addon.write_stdin(data))
def _pretty_services(addon: AnyAddon) -> List[str]:
def _pretty_services(addon: AnyAddon) -> list[str]:
"""Return a simplified services role list."""
return [f"{name}:{access}" for name, access in addon.services_role.items()]

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor Audio RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from typing import Any, Awaitable
from aiohttp import web
import attr
@@ -56,10 +56,10 @@ SCHEMA_MUTE = vol.Schema(
}
)
SCHEMA_DEFAULT = vol.Schema({vol.Required(ATTR_NAME): vol.Coerce(str)})
SCHEMA_DEFAULT = vol.Schema({vol.Required(ATTR_NAME): str})
SCHEMA_PROFILE = vol.Schema(
{vol.Required(ATTR_CARD): vol.Coerce(str), vol.Required(ATTR_NAME): vol.Coerce(str)}
{vol.Required(ATTR_CARD): str, vol.Required(ATTR_NAME): str}
)
@@ -67,7 +67,7 @@ class APIAudio(CoreSysAttributes):
"""Handle RESTful API for Audio functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return Audio information."""
return {
ATTR_VERSION: self.sys_plugins.audio.version,
@@ -89,7 +89,7 @@ class APIAudio(CoreSysAttributes):
}
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
async def stats(self, request: web.Request) -> dict[str, Any]:
"""Return resource information."""
stats = await self.sys_plugins.audio.stats()

View File

@@ -1,7 +1,6 @@
"""Init file for Supervisor auth/SSO RESTful API."""
import asyncio
import logging
from typing import Dict
from aiohttp import BasicAuth, web
from aiohttp.hdrs import AUTHORIZATION, CONTENT_TYPE, WWW_AUTHENTICATE
@@ -24,12 +23,12 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_PASSWORD_RESET = vol.Schema(
{
vol.Required(ATTR_USERNAME): vol.Coerce(str),
vol.Required(ATTR_PASSWORD): vol.Coerce(str),
vol.Required(ATTR_USERNAME): str,
vol.Required(ATTR_PASSWORD): str,
}
)
REALM_HEADER: Dict[str, str] = {
REALM_HEADER: dict[str, str] = {
WWW_AUTHENTICATE: 'Basic realm="Home Assistant Authentication"'
}
@@ -46,7 +45,7 @@ class APIAuth(CoreSysAttributes):
return self.sys_auth.check_login(addon, auth.login, auth.password)
def _process_dict(
self, request: web.Request, addon: Addon, data: Dict[str, str]
self, request: web.Request, addon: Addon, data: dict[str, str]
) -> bool:
"""Process login with dict data.
@@ -86,7 +85,7 @@ class APIAuth(CoreSysAttributes):
@api_process
async def reset(self, request: web.Request) -> None:
"""Process reset password request."""
body: Dict[str, str] = await api_validate(SCHEMA_PASSWORD_RESET, request)
body: dict[str, str] = await api_validate(SCHEMA_PASSWORD_RESET, request)
await asyncio.shield(
self.sys_auth.change_password(body[ATTR_USERNAME], body[ATTR_PASSWORD])
)

View File

@@ -38,27 +38,25 @@ RE_SLUGIFY_NAME = re.compile(r"[^A-Za-z0-9]+")
# pylint: disable=no-value-for-parameter
SCHEMA_RESTORE_PARTIAL = vol.Schema(
{
vol.Optional(ATTR_PASSWORD): vol.Any(None, vol.Coerce(str)),
vol.Optional(ATTR_PASSWORD): vol.Maybe(str),
vol.Optional(ATTR_HOMEASSISTANT): vol.Boolean(),
vol.Optional(ATTR_ADDONS): vol.All([vol.Coerce(str)], vol.Unique()),
vol.Optional(ATTR_ADDONS): vol.All([str], vol.Unique()),
vol.Optional(ATTR_FOLDERS): vol.All([vol.In(ALL_FOLDERS)], vol.Unique()),
}
)
SCHEMA_RESTORE_FULL = vol.Schema(
{vol.Optional(ATTR_PASSWORD): vol.Any(None, vol.Coerce(str))}
)
SCHEMA_RESTORE_FULL = vol.Schema({vol.Optional(ATTR_PASSWORD): vol.Maybe(str)})
SCHEMA_BACKUP_FULL = vol.Schema(
{
vol.Optional(ATTR_NAME): vol.Coerce(str),
vol.Optional(ATTR_PASSWORD): vol.Any(None, vol.Coerce(str)),
vol.Optional(ATTR_NAME): str,
vol.Optional(ATTR_PASSWORD): vol.Maybe(str),
}
)
SCHEMA_BACKUP_PARTIAL = SCHEMA_BACKUP_FULL.extend(
{
vol.Optional(ATTR_ADDONS): vol.All([vol.Coerce(str)], vol.Unique()),
vol.Optional(ATTR_ADDONS): vol.All([str], vol.Unique()),
vol.Optional(ATTR_FOLDERS): vol.All([vol.In(ALL_FOLDERS)], vol.Unique()),
vol.Optional(ATTR_HOMEASSISTANT): vol.Boolean(),
}

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor HA cli RESTful API."""
import asyncio
import logging
from typing import Any, Dict
from typing import Any
from aiohttp import web
import voluptuous as vol
@@ -32,7 +32,7 @@ class APICli(CoreSysAttributes):
"""Handle RESTful API for HA Cli functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return HA cli information."""
return {
ATTR_VERSION: self.sys_plugins.cli.version,
@@ -41,7 +41,7 @@ class APICli(CoreSysAttributes):
}
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
async def stats(self, request: web.Request) -> dict[str, Any]:
"""Return resource information."""
stats = await self.sys_plugins.cli.stats()

View File

@@ -1,6 +1,11 @@
"""Const for API."""
ATTR_USE_RTC = "use_rtc"
ATTR_USE_NTP = "use_ntp"
ATTR_DT_UTC = "dt_utc"
ATTR_AGENT_VERSION = "agent_version"
ATTR_BOOT_TIMESTAMP = "boot_timestamp"
ATTR_DEVICE = "device"
ATTR_DISK_DATA = "disk_data"
ATTR_DT_SYNCHRONIZED = "dt_synchronized"
ATTR_DT_UTC = "dt_utc"
ATTR_STARTUP_TIME = "startup_time"
ATTR_USE_NTP = "use_ntp"
ATTR_USE_RTC = "use_rtc"

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor DNS RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from typing import Any, Awaitable
from aiohttp import web
import voluptuous as vol
@@ -40,7 +40,7 @@ class APICoreDNS(CoreSysAttributes):
"""Handle RESTful API for DNS functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return DNS information."""
return {
ATTR_VERSION: self.sys_plugins.dns.version,
@@ -63,7 +63,7 @@ class APICoreDNS(CoreSysAttributes):
self.sys_plugins.dns.save_data()
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
async def stats(self, request: web.Request) -> dict[str, Any]:
"""Return resource information."""
stats = await self.sys_plugins.dns.stats()

View File

@@ -1,6 +1,6 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import logging
from typing import Any, Dict
from typing import Any
from aiohttp import web
import voluptuous as vol
@@ -21,7 +21,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_DOCKER_REGISTRY = vol.Schema(
{
vol.Coerce(str): {
str: {
vol.Required(ATTR_USERNAME): str,
vol.Required(ATTR_PASSWORD): str,
}
@@ -33,7 +33,7 @@ class APIDocker(CoreSysAttributes):
"""Handle RESTful API for Docker configuration."""
@api_process
async def registries(self, request) -> Dict[str, Any]:
async def registries(self, request) -> dict[str, Any]:
"""Return the list of registries."""
data_registries = {}
for hostname, registry in self.sys_docker.config.registries.items():

View File

@@ -1,6 +1,6 @@
"""Init file for Supervisor hardware RESTful API."""
import logging
from typing import Any, Dict
from typing import Any
from aiohttp import web
@@ -19,7 +19,7 @@ from .utils import api_process
_LOGGER: logging.Logger = logging.getLogger(__name__)
def device_struct(device: Device) -> Dict[str, Any]:
def device_struct(device: Device) -> dict[str, Any]:
"""Return a dict with information of a interface to be used in th API."""
return {
ATTR_NAME: device.name,
@@ -35,7 +35,7 @@ class APIHardware(CoreSysAttributes):
"""Handle RESTful API for hardware functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Show hardware info."""
return {
ATTR_DEVICES: [
@@ -44,7 +44,7 @@ class APIHardware(CoreSysAttributes):
}
@api_process
async def audio(self, request: web.Request) -> Dict[str, Any]:
async def audio(self, request: web.Request) -> dict[str, Any]:
"""Show pulse audio profiles."""
return {
ATTR_AUDIO: {

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from typing import Any, Awaitable
from aiohttp import web
import voluptuous as vol
@@ -48,9 +48,9 @@ SCHEMA_OPTIONS = vol.Schema(
vol.Optional(ATTR_SSL): vol.Boolean(),
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
vol.Optional(ATTR_WAIT_BOOT): vol.All(vol.Coerce(int), vol.Range(min=60)),
vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(str),
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(str),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(str),
}
)
@@ -61,7 +61,7 @@ class APIHomeAssistant(CoreSysAttributes):
"""Handle RESTful API for Home Assistant functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return host information."""
return {
ATTR_VERSION: self.sys_homeassistant.version,
@@ -117,7 +117,7 @@ class APIHomeAssistant(CoreSysAttributes):
self.sys_homeassistant.save_data()
@api_process
async def stats(self, request: web.Request) -> Dict[Any, str]:
async def stats(self, request: web.Request) -> dict[Any, str]:
"""Return resource information."""
stats = await self.sys_homeassistant.core.stats()
if not stats:

View File

@@ -25,12 +25,20 @@ from ..const import (
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from .const import ATTR_DT_SYNCHRONIZED, ATTR_DT_UTC, ATTR_USE_NTP, ATTR_USE_RTC
from .const import (
ATTR_AGENT_VERSION,
ATTR_BOOT_TIMESTAMP,
ATTR_DT_SYNCHRONIZED,
ATTR_DT_UTC,
ATTR_STARTUP_TIME,
ATTR_USE_NTP,
ATTR_USE_RTC,
)
from .utils import api_process, api_process_raw, api_validate
SERVICE = "service"
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_HOSTNAME): vol.Coerce(str)})
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_HOSTNAME): str})
class APIHost(CoreSysAttributes):
@@ -40,6 +48,7 @@ class APIHost(CoreSysAttributes):
async def info(self, request):
"""Return host information."""
return {
ATTR_AGENT_VERSION: self.sys_dbus.agent.version,
ATTR_CHASSIS: self.sys_host.info.chassis,
ATTR_CPE: self.sys_host.info.cpe,
ATTR_DEPLOYMENT: self.sys_host.info.deployment,
@@ -56,6 +65,8 @@ class APIHost(CoreSysAttributes):
ATTR_DT_SYNCHRONIZED: self.sys_host.info.dt_synchronized,
ATTR_USE_NTP: self.sys_host.info.use_ntp,
ATTR_USE_RTC: self.sys_host.info.use_rtc,
ATTR_STARTUP_TIME: self.sys_host.info.startup_time,
ATTR_BOOT_TIMESTAMP: self.sys_host.info.boot_timestamp,
}
@api_process

View File

@@ -1,6 +1,6 @@
"""Init file for Supervisor info RESTful API."""
import logging
from typing import Any, Dict
from typing import Any
from aiohttp import web
@@ -31,12 +31,12 @@ class APIInfo(CoreSysAttributes):
"""Handle RESTful API for info functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Show system info."""
return {
ATTR_SUPERVISOR: self.sys_supervisor.version,
ATTR_HOMEASSISTANT: self.sys_homeassistant.version,
ATTR_HASSOS: self.sys_hassos.version,
ATTR_HASSOS: self.sys_os.version,
ATTR_DOCKER: self.sys_docker.info.version,
ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_OPERATING_SYSTEM: self.sys_host.info.operating_system,

View File

@@ -2,7 +2,7 @@
import asyncio
from ipaddress import ip_address
import logging
from typing import Any, Dict, Union
from typing import Any, Union
import aiohttp
from aiohttp import ClientTimeout, hdrs, web
@@ -54,7 +54,7 @@ class APIIngress(CoreSysAttributes):
return f"http://{addon.ip_address}:{addon.ingress_port}/{path}"
@api_process
async def panels(self, request: web.Request) -> Dict[str, Any]:
async def panels(self, request: web.Request) -> dict[str, Any]:
"""Create a list of panel data."""
addons = {}
for addon in self.sys_ingress.addons:
@@ -69,14 +69,14 @@ class APIIngress(CoreSysAttributes):
@api_process
@require_home_assistant
async def create_session(self, request: web.Request) -> Dict[str, Any]:
async def create_session(self, request: web.Request) -> dict[str, Any]:
"""Create a new session."""
session = self.sys_ingress.create_session()
return {ATTR_SESSION: session}
@api_process
@require_home_assistant
async def validate_session(self, request: web.Request) -> Dict[str, Any]:
async def validate_session(self, request: web.Request) -> dict[str, Any]:
"""Validate session and extending how long it's valid for."""
data = await api_validate(VALIDATE_SESSION_DATA, request)
@@ -220,7 +220,7 @@ class APIIngress(CoreSysAttributes):
def _init_header(
request: web.Request, addon: str
) -> Union[CIMultiDict, Dict[str, str]]:
) -> Union[CIMultiDict, dict[str, str]]:
"""Create initial header."""
headers = {}
@@ -248,7 +248,7 @@ def _init_header(
return headers
def _response_header(response: aiohttp.ClientResponse) -> Dict[str, str]:
def _response_header(response: aiohttp.ClientResponse) -> dict[str, str]:
"""Create response header."""
headers = {}

View File

@@ -1,6 +1,6 @@
"""Init file for Supervisor Jobs RESTful API."""
import logging
from typing import Any, Dict
from typing import Any
from aiohttp import web
import voluptuous as vol
@@ -20,7 +20,7 @@ class APIJobs(CoreSysAttributes):
"""Handle RESTful API for OS functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return JobManager information."""
return {
ATTR_IGNORE_CONDITIONS: self.sys_jobs.ignore_conditions,

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor Multicast RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from typing import Any, Awaitable
from aiohttp import web
import voluptuous as vol
@@ -34,7 +34,7 @@ class APIMulticast(CoreSysAttributes):
"""Handle RESTful API for Multicast functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return Multicast information."""
return {
ATTR_VERSION: self.sys_plugins.multicast.version,
@@ -43,7 +43,7 @@ class APIMulticast(CoreSysAttributes):
}
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
async def stats(self, request: web.Request) -> dict[str, Any]:
"""Return resource information."""
stats = await self.sys_plugins.multicast.stats()

View File

@@ -1,7 +1,7 @@
"""REST API for network."""
import asyncio
from ipaddress import ip_address, ip_interface
from typing import Any, Awaitable, Dict
from typing import Any, Awaitable
from aiohttp import web
import attr
@@ -82,7 +82,7 @@ SCHEMA_UPDATE = vol.Schema(
)
def ipconfig_struct(config: IpConfig) -> Dict[str, Any]:
def ipconfig_struct(config: IpConfig) -> dict[str, Any]:
"""Return a dict with information about ip configuration."""
return {
ATTR_METHOD: config.method,
@@ -92,7 +92,7 @@ def ipconfig_struct(config: IpConfig) -> Dict[str, Any]:
}
def wifi_struct(config: WifiConfig) -> Dict[str, Any]:
def wifi_struct(config: WifiConfig) -> dict[str, Any]:
"""Return a dict with information about wifi configuration."""
return {
ATTR_MODE: config.mode,
@@ -102,7 +102,7 @@ def wifi_struct(config: WifiConfig) -> Dict[str, Any]:
}
def vlan_struct(config: VlanConfig) -> Dict[str, Any]:
def vlan_struct(config: VlanConfig) -> dict[str, Any]:
"""Return a dict with information about VLAN configuration."""
return {
ATTR_ID: config.id,
@@ -110,7 +110,7 @@ def vlan_struct(config: VlanConfig) -> Dict[str, Any]:
}
def interface_struct(interface: Interface) -> Dict[str, Any]:
def interface_struct(interface: Interface) -> dict[str, Any]:
"""Return a dict with information of a interface to be used in th API."""
return {
ATTR_INTERFACE: interface.name,
@@ -125,7 +125,7 @@ def interface_struct(interface: Interface) -> Dict[str, Any]:
}
def accesspoint_struct(accesspoint: AccessPoint) -> Dict[str, Any]:
def accesspoint_struct(accesspoint: AccessPoint) -> dict[str, Any]:
"""Return a dict for AccessPoint."""
return {
ATTR_MODE: accesspoint.mode,
@@ -158,7 +158,7 @@ class APINetwork(CoreSysAttributes):
raise APIError(f"Interface {name} does not exist") from None
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return network information."""
return {
ATTR_INTERFACES: [
@@ -176,7 +176,7 @@ class APINetwork(CoreSysAttributes):
}
@api_process
async def interface_info(self, request: web.Request) -> Dict[str, Any]:
async def interface_info(self, request: web.Request) -> dict[str, Any]:
"""Return network information for a interface."""
interface = self._get_interface(request.match_info.get(ATTR_INTERFACE))
@@ -223,7 +223,7 @@ class APINetwork(CoreSysAttributes):
return asyncio.shield(self.sys_host.network.update())
@api_process
async def scan_accesspoints(self, request: web.Request) -> Dict[str, Any]:
async def scan_accesspoints(self, request: web.Request) -> dict[str, Any]:
"""Scan and return a list of available networks."""
interface = self._get_interface(request.match_info.get(ATTR_INTERFACE))

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor Observer RESTful API."""
import asyncio
import logging
from typing import Any, Dict
from typing import Any
from aiohttp import web
import voluptuous as vol
@@ -33,7 +33,7 @@ class APIObserver(CoreSysAttributes):
"""Handle RESTful API for Observer functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return HA Observer information."""
return {
ATTR_HOST: str(self.sys_docker.network.observer),
@@ -43,7 +43,7 @@ class APIObserver(CoreSysAttributes):
}
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
async def stats(self, request: web.Request) -> dict[str, Any]:
"""Return resource information."""
stats = await self.sys_plugins.observer.stats()

View File

@@ -1,7 +1,8 @@
"""Init file for Supervisor HassOS RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from pathlib import Path
from typing import Any, Awaitable
from aiohttp import web
import voluptuous as vol
@@ -9,42 +10,60 @@ import voluptuous as vol
from ..const import (
ATTR_BOARD,
ATTR_BOOT,
ATTR_DEVICES,
ATTR_UPDATE_AVAILABLE,
ATTR_VERSION,
ATTR_VERSION_LATEST,
)
from ..coresys import CoreSysAttributes
from ..validate import version_tag
from .const import ATTR_DEVICE, ATTR_DISK_DATA
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
SCHEMA_DISK = vol.Schema({vol.Required(ATTR_DEVICE): vol.All(str, vol.Coerce(Path))})
class APIOS(CoreSysAttributes):
"""Handle RESTful API for OS functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return OS information."""
return {
ATTR_VERSION: self.sys_hassos.version,
ATTR_VERSION_LATEST: self.sys_hassos.latest_version,
ATTR_UPDATE_AVAILABLE: self.sys_hassos.need_update,
ATTR_BOARD: self.sys_hassos.board,
ATTR_VERSION: self.sys_os.version,
ATTR_VERSION_LATEST: self.sys_os.latest_version,
ATTR_UPDATE_AVAILABLE: self.sys_os.need_update,
ATTR_BOARD: self.sys_os.board,
ATTR_BOOT: self.sys_dbus.rauc.boot_slot,
ATTR_DISK_DATA: self.sys_os.datadisk.disk_used,
}
@api_process
async def update(self, request: web.Request) -> None:
"""Update OS."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_hassos.latest_version)
version = body.get(ATTR_VERSION, self.sys_os.latest_version)
await asyncio.shield(self.sys_hassos.update(version))
await asyncio.shield(self.sys_os.update(version))
@api_process
def config_sync(self, request: web.Request) -> Awaitable[None]:
"""Trigger config reload on OS."""
return asyncio.shield(self.sys_hassos.config_sync())
return asyncio.shield(self.sys_os.config_sync())
@api_process
async def migrate_data(self, request: web.Request) -> None:
"""Trigger data disk migration on Host."""
body = await api_validate(SCHEMA_DISK, request)
await asyncio.shield(self.sys_os.datadisk.migrate_disk(body[ATTR_DEVICE]))
@api_process
async def list_data(self, request: web.Request) -> dict[str, Any]:
"""Return possible data targets."""
return {
ATTR_DEVICES: self.sys_os.datadisk.available_disks,
}

View File

@@ -1,14 +1,14 @@
function loadES5() {
var el = document.createElement('script');
el.src = '/api/hassio/app/frontend_es5/entrypoint.e3a9299f.js';
el.src = '/api/hassio/app/frontend_es5/entrypoint.beb8aae2.js';
document.body.appendChild(el);
}
if (/.*Version\/(?:11|12)(?:\.\d+)*.*Safari\//.test(navigator.userAgent)) {
loadES5();
} else {
try {
new Function("import('/api/hassio/app/frontend_latest/entrypoint.48b24b78.js')")();
new Function("import('/api/hassio/app/frontend_latest/entrypoint.b658878e.js')")();
} catch (err) {
loadES5();
}

View File

@@ -1,2 +0,0 @@
(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[534],{68441:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var l=new WeakMap;t.default=function(e){var t=l.get(e);return t||(t=Object.create(null),l.set(e,t)),t}},78643:function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PluralRules=void 0;var a=l(87480),n=l(43965),r=a.__importDefault(l(68441));function o(e,t){if(!(e instanceof u))throw new TypeError("Method Intl.PluralRules.prototype."+t+" called on incompatible receiver "+String(e))}function i(e,t,l,a){var n=a.IntegerDigits,r=a.NumberOfFractionDigits,o=a.FractionDigits;return u.localeData[e].fn(r?n+"."+o:n,"ordinal"===t)}var u=function(){function e(t,l){if(!(this&&this instanceof e?this.constructor:void 0))throw new TypeError("Intl.PluralRules must be called with 'new'");return n.InitializePluralRules(this,t,l,{availableLocales:e.availableLocales,relevantExtensionKeys:e.relevantExtensionKeys,localeData:e.localeData,getDefaultLocale:e.getDefaultLocale,getInternalSlots:r.default})}return e.prototype.resolvedOptions=function(){o(this,"resolvedOptions");var t=Object.create(null),l=r.default(this);return t.locale=l.locale,t.type=l.type,["minimumIntegerDigits","minimumFractionDigits","maximumFractionDigits","minimumSignificantDigits","maximumSignificantDigits"].forEach((function(e){var a=l[e];void 0!==a&&(t[e]=a)})),t.pluralCategories=a.__spreadArray([],e.localeData[t.locale].categories[t.type]),t},e.prototype.select=function(e){o(this,"select");var t=n.ToNumber(e);return n.ResolvePlural(this,t,{getInternalSlots:r.default,PluralRuleSelect:i})},e.prototype.toString=function(){return"[object Intl.PluralRules]"},e.supportedLocalesOf=function(t,l){return n.SupportedLocales(e.availableLocales,n.CanonicalizeLocaleList(t),l)},e.__addLocaleData=function(){for(var t=[],l=0;l<arguments.length;l++)t[l]=arguments[l];for(var a=0,n=t;a<n.length;a++){var r=n[a],o=r.data,i=r.locale;e.localeData[i]=o,e.availableLocales.add(i),e.__defaultLocale||(e.__defaultLocale=i)}},e.getDefaultLocale=function(){return e.__defaultLocale},e.localeData={},e.availableLocales=new Set,e.__defaultLocale="",e.relevantExtensionKeys=[],e.polyfilled=!0,e}();t.PluralRules=u;try{"undefined"!=typeof Symbol&&Object.defineProperty(u.prototype,Symbol.toStringTag,{value:"Intl.PluralRules",writable:!1,enumerable:!1,configurable:!0});try{Object.defineProperty(u,"length",{value:0,writable:!1,enumerable:!1,configurable:!0})}catch(c){}Object.defineProperty(u.prototype.constructor,"length",{value:0,writable:!1,enumerable:!1,configurable:!0}),Object.defineProperty(u.supportedLocalesOf,"length",{value:1,writable:!1,enumerable:!1,configurable:!0})}catch(s){}},25534:function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=l(78643);l(27815).shouldPolyfill()&&Object.defineProperty(Intl,"PluralRules",{value:a.PluralRules,writable:!0,enumerable:!1,configurable:!0})},27815:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldPolyfill=void 0,t.shouldPolyfill=function(){return"undefined"==typeof Intl||!("PluralRules"in Intl)||"one"===new Intl.PluralRules("en",{minimumFractionDigits:2}).select(1)}}}]);
//# sourceMappingURL=01378878.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"01378878.js","sources":["webpack://home-assistant-frontend/01378878.js"],"mappings":"AAAA","sourceRoot":""}

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"0ac2c6bb.js","sources":["webpack://home-assistant-frontend/0ac2c6bb.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"0fc60622.js","sources":["webpack://home-assistant-frontend/0fc60622.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"13306aae.js","sources":["webpack://home-assistant-frontend/13306aae.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"2995ba79.js","sources":["webpack://home-assistant-frontend/2995ba79.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"337a39f0.js","sources":["webpack://home-assistant-frontend/337a39f0.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"4b7385c7.js","sources":["webpack://home-assistant-frontend/4b7385c7.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"61aed66c.js","sources":["webpack://home-assistant-frontend/61aed66c.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1 +0,0 @@
{"version":3,"file":"6aa86e64.js","sources":["webpack://home-assistant-frontend/6aa86e64.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"6de58640.js","sources":["webpack://home-assistant-frontend/6de58640.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"71906b61.js","sources":["webpack://home-assistant-frontend/71906b61.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1 +0,0 @@
{"version":3,"file":"799b0b1b.js","sources":["webpack://home-assistant-frontend/799b0b1b.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"7cbe026c.js","sources":["webpack://home-assistant-frontend/7cbe026c.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1,2 +1,2 @@
!function(){"use strict";var r,t,n={5425:function(r,t,n){var e=n(91107);n(58556);function o(r,t){return function(r){if(Array.isArray(r))return r}(r)||function(r,t){var n=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null==n)return;var e,o,u=[],i=!0,a=!1;try{for(n=n.call(r);!(i=(e=n.next()).done)&&(u.push(e.value),!t||u.length!==t);i=!0);}catch(f){a=!0,o=f}finally{try{i||null==n.return||n.return()}finally{if(a)throw o}}return u}(r,t)||function(r,t){if(!r)return;if("string"==typeof r)return u(r,t);var n=Object.prototype.toString.call(r).slice(8,-1);"Object"===n&&r.constructor&&(n=r.constructor.name);if("Map"===n||"Set"===n)return Array.from(r);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return u(r,t)}(r,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(r,t){(null==t||t>r.length)&&(t=r.length);for(var n=0,e=new Array(t);n<t;n++)e[n]=r[n];return e}var i={filterData:function(r,t,n){return n=n.toUpperCase(),r.filter((function(r){return Object.entries(t).some((function(t){var e=o(t,2),u=e[0],i=e[1];return!(!i.filterable||!String(i.filterKey?r[i.valueColumn||u][i.filterKey]:r[i.valueColumn||u]).toUpperCase().includes(n))}))}))},sortData:function(r,t,n,e){return r.sort((function(r,o){var u=1;"desc"===n&&(u=-1);var i=t.filterKey?r[t.valueColumn||e][t.filterKey]:r[t.valueColumn||e],a=t.filterKey?o[t.valueColumn||e][t.filterKey]:o[t.valueColumn||e];return"string"==typeof i&&(i=i.toUpperCase()),"string"==typeof a&&(a=a.toUpperCase()),void 0===i&&void 0!==a?1:void 0===a&&void 0!==i?-1:i<a?-1*u:i>a?1*u:0}))}};(0,e.Jj)(i)}},e={};function o(r){var t=e[r];if(void 0!==t)return t.exports;var u=e[r]={exports:{}};return n[r](u,u.exports,o),u.exports}o.m=n,o.x=function(){var r=o.O(void 0,[354],(function(){return o(5425)}));return r=o.O(r)},r=[],o.O=function(t,n,e,u){if(!n){var i=1/0;for(l=0;l<r.length;l++){n=r[l][0],e=r[l][1],u=r[l][2];for(var a=!0,f=0;f<n.length;f++)(!1&u||i>=u)&&Object.keys(o.O).every((function(r){return o.O[r](n[f])}))?n.splice(f--,1):(a=!1,u<i&&(i=u));a&&(r.splice(l--,1),t=e())}return t}u=u||0;for(var l=r.length;l>0&&r[l-1][2]>u;l--)r[l]=r[l-1];r[l]=[n,e,u]},o.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(t,{a:t}),t},o.d=function(r,t){for(var n in t)o.o(t,n)&&!o.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},o.f={},o.e=function(r){return Promise.all(Object.keys(o.f).reduce((function(t,n){return o.f[n](r,t),t}),[]))},o.u=function(r){return"e612d98f.js"},o.o=function(r,t){return Object.prototype.hasOwnProperty.call(r,t)},o.p="/api/hassio/app/frontend_es5/",function(){var r={477:1,425:1};o.f.i=function(t,n){r[t]||importScripts(o.p+o.u(t))};var t=self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[],n=t.push.bind(t);t.push=function(t){var e=t[0],u=t[1],i=t[2];for(var a in u)o.o(u,a)&&(o.m[a]=u[a]);for(i&&i(o);e.length;)r[e.pop()]=1;n(t)}}(),t=o.x,o.x=function(){return o.e(354).then(t)};o.x()}();
//# sourceMappingURL=e1f7ebc5.js.map
!function(){"use strict";var r,t,n={5425:function(r,t,n){var e=n(91107);n(58556);function o(r,t){return function(r){if(Array.isArray(r))return r}(r)||function(r,t){var n=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null==n)return;var e,o,u=[],i=!0,a=!1;try{for(n=n.call(r);!(i=(e=n.next()).done)&&(u.push(e.value),!t||u.length!==t);i=!0);}catch(f){a=!0,o=f}finally{try{i||null==n.return||n.return()}finally{if(a)throw o}}return u}(r,t)||function(r,t){if(!r)return;if("string"==typeof r)return u(r,t);var n=Object.prototype.toString.call(r).slice(8,-1);"Object"===n&&r.constructor&&(n=r.constructor.name);if("Map"===n||"Set"===n)return Array.from(r);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return u(r,t)}(r,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(r,t){(null==t||t>r.length)&&(t=r.length);for(var n=0,e=new Array(t);n<t;n++)e[n]=r[n];return e}var i={filterData:function(r,t,n){return n=n.toUpperCase(),r.filter((function(r){return Object.entries(t).some((function(t){var e=o(t,2),u=e[0],i=e[1];return!(!i.filterable||!String(i.filterKey?r[i.valueColumn||u][i.filterKey]:r[i.valueColumn||u]).toUpperCase().includes(n))}))}))},sortData:function(r,t,n,e){return r.sort((function(r,o){var u=1;"desc"===n&&(u=-1);var i=t.filterKey?r[t.valueColumn||e][t.filterKey]:r[t.valueColumn||e],a=t.filterKey?o[t.valueColumn||e][t.filterKey]:o[t.valueColumn||e];return"string"==typeof i&&(i=i.toUpperCase()),"string"==typeof a&&(a=a.toUpperCase()),void 0===i&&void 0!==a?1:void 0===a&&void 0!==i?-1:i<a?-1*u:i>a?1*u:0}))}};(0,e.Jj)(i)}},e={};function o(r){var t=e[r];if(void 0!==t)return t.exports;var u=e[r]={exports:{}};return n[r](u,u.exports,o),u.exports}o.m=n,o.x=function(){var r=o.O(void 0,[354],(function(){return o(5425)}));return r=o.O(r)},r=[],o.O=function(t,n,e,u){if(!n){var i=1/0;for(l=0;l<r.length;l++){n=r[l][0],e=r[l][1],u=r[l][2];for(var a=!0,f=0;f<n.length;f++)(!1&u||i>=u)&&Object.keys(o.O).every((function(r){return o.O[r](n[f])}))?n.splice(f--,1):(a=!1,u<i&&(i=u));a&&(r.splice(l--,1),t=e())}return t}u=u||0;for(var l=r.length;l>0&&r[l-1][2]>u;l--)r[l]=r[l-1];r[l]=[n,e,u]},o.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(t,{a:t}),t},o.d=function(r,t){for(var n in t)o.o(t,n)&&!o.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},o.f={},o.e=function(r){return Promise.all(Object.keys(o.f).reduce((function(t,n){return o.f[n](r,t),t}),[]))},o.u=function(r){return"6de58640.js"},o.o=function(r,t){return Object.prototype.hasOwnProperty.call(r,t)},o.p="/api/hassio/app/frontend_es5/",function(){var r={477:1,425:1};o.f.i=function(t,n){r[t]||importScripts(o.p+o.u(t))};var t=self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[],n=t.push.bind(t);t.push=function(t){var e=t[0],u=t[1],i=t[2];for(var a in u)o.o(u,a)&&(o.m[a]=u[a]);for(i&&i(o);e.length;)r[e.pop()]=1;n(t)}}(),t=o.x,o.x=function(){return o.e(354).then(t)};o.x()}();
//# sourceMappingURL=8849adea.js.map

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"8849adea.js","sources":["webpack://home-assistant-frontend/8849adea.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"9e6dea06.js","sources":["webpack://home-assistant-frontend/9e6dea06.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"9f0e09af.js","sources":["webpack://home-assistant-frontend/9f0e09af.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"9fa7e44f.js","sources":["webpack://home-assistant-frontend/9fa7e44f.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"a17514d4.js","sources":["webpack://home-assistant-frontend/a17514d4.js"],"mappings":"AAAA","sourceRoot":""}

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"a43f16e9.js","sources":["webpack://home-assistant-frontend/a43f16e9.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1 +0,0 @@
{"version":3,"file":"b7bea667.js","sources":["webpack://home-assistant-frontend/b7bea667.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1,2 +1,2 @@
!function(){"use strict";var r,t,n={5425:function(r,t,n){var e=n(91107);n(58556);function o(r,t){return function(r){if(Array.isArray(r))return r}(r)||function(r,t){var n=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null==n)return;var e,o,u=[],i=!0,a=!1;try{for(n=n.call(r);!(i=(e=n.next()).done)&&(u.push(e.value),!t||u.length!==t);i=!0);}catch(f){a=!0,o=f}finally{try{i||null==n.return||n.return()}finally{if(a)throw o}}return u}(r,t)||function(r,t){if(!r)return;if("string"==typeof r)return u(r,t);var n=Object.prototype.toString.call(r).slice(8,-1);"Object"===n&&r.constructor&&(n=r.constructor.name);if("Map"===n||"Set"===n)return Array.from(r);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return u(r,t)}(r,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(r,t){(null==t||t>r.length)&&(t=r.length);for(var n=0,e=new Array(t);n<t;n++)e[n]=r[n];return e}var i={filterData:function(r,t,n){return n=n.toUpperCase(),r.filter((function(r){return Object.entries(t).some((function(t){var e=o(t,2),u=e[0],i=e[1];return!(!i.filterable||!String(i.filterKey?r[i.valueColumn||u][i.filterKey]:r[i.valueColumn||u]).toUpperCase().includes(n))}))}))},sortData:function(r,t,n,e){return r.sort((function(r,o){var u=1;"desc"===n&&(u=-1);var i=t.filterKey?r[t.valueColumn||e][t.filterKey]:r[t.valueColumn||e],a=t.filterKey?o[t.valueColumn||e][t.filterKey]:o[t.valueColumn||e];return"string"==typeof i&&(i=i.toUpperCase()),"string"==typeof a&&(a=a.toUpperCase()),void 0===i&&void 0!==a?1:void 0===a&&void 0!==i?-1:i<a?-1*u:i>a?1*u:0}))}};(0,e.Jj)(i)}},e={};function o(r){var t=e[r];if(void 0!==t)return t.exports;var u=e[r]={exports:{}};return n[r](u,u.exports,o),u.exports}o.m=n,o.x=function(){var r=o.O(void 0,[354],(function(){return o(5425)}));return r=o.O(r)},r=[],o.O=function(t,n,e,u){if(!n){var i=1/0;for(l=0;l<r.length;l++){n=r[l][0],e=r[l][1],u=r[l][2];for(var a=!0,f=0;f<n.length;f++)(!1&u||i>=u)&&Object.keys(o.O).every((function(r){return o.O[r](n[f])}))?n.splice(f--,1):(a=!1,u<i&&(i=u));a&&(r.splice(l--,1),t=e())}return t}u=u||0;for(var l=r.length;l>0&&r[l-1][2]>u;l--)r[l]=r[l-1];r[l]=[n,e,u]},o.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(t,{a:t}),t},o.d=function(r,t){for(var n in t)o.o(t,n)&&!o.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},o.f={},o.e=function(r){return Promise.all(Object.keys(o.f).reduce((function(t,n){return o.f[n](r,t),t}),[]))},o.u=function(r){return"e612d98f.js"},o.o=function(r,t){return Object.prototype.hasOwnProperty.call(r,t)},o.p="/api/hassio/app/frontend_es5/",function(){var r={425:1,477:1};o.f.i=function(t,n){r[t]||importScripts(o.p+o.u(t))};var t=self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[],n=t.push.bind(t);t.push=function(t){var e=t[0],u=t[1],i=t[2];for(var a in u)o.o(u,a)&&(o.m[a]=u[a]);for(i&&i(o);e.length;)r[e.pop()]=1;n(t)}}(),t=o.x,o.x=function(){return o.e(354).then(t)};o.x()}();
//# sourceMappingURL=799b0b1b.js.map
!function(){"use strict";var r,t,n={5425:function(r,t,n){var e=n(91107);n(58556);function o(r,t){return function(r){if(Array.isArray(r))return r}(r)||function(r,t){var n=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null==n)return;var e,o,u=[],i=!0,a=!1;try{for(n=n.call(r);!(i=(e=n.next()).done)&&(u.push(e.value),!t||u.length!==t);i=!0);}catch(f){a=!0,o=f}finally{try{i||null==n.return||n.return()}finally{if(a)throw o}}return u}(r,t)||function(r,t){if(!r)return;if("string"==typeof r)return u(r,t);var n=Object.prototype.toString.call(r).slice(8,-1);"Object"===n&&r.constructor&&(n=r.constructor.name);if("Map"===n||"Set"===n)return Array.from(r);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return u(r,t)}(r,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(r,t){(null==t||t>r.length)&&(t=r.length);for(var n=0,e=new Array(t);n<t;n++)e[n]=r[n];return e}var i={filterData:function(r,t,n){return n=n.toUpperCase(),r.filter((function(r){return Object.entries(t).some((function(t){var e=o(t,2),u=e[0],i=e[1];return!(!i.filterable||!String(i.filterKey?r[i.valueColumn||u][i.filterKey]:r[i.valueColumn||u]).toUpperCase().includes(n))}))}))},sortData:function(r,t,n,e){return r.sort((function(r,o){var u=1;"desc"===n&&(u=-1);var i=t.filterKey?r[t.valueColumn||e][t.filterKey]:r[t.valueColumn||e],a=t.filterKey?o[t.valueColumn||e][t.filterKey]:o[t.valueColumn||e];return"string"==typeof i&&(i=i.toUpperCase()),"string"==typeof a&&(a=a.toUpperCase()),void 0===i&&void 0!==a?1:void 0===a&&void 0!==i?-1:i<a?-1*u:i>a?1*u:0}))}};(0,e.Jj)(i)}},e={};function o(r){var t=e[r];if(void 0!==t)return t.exports;var u=e[r]={exports:{}};return n[r](u,u.exports,o),u.exports}o.m=n,o.x=function(){var r=o.O(void 0,[354],(function(){return o(5425)}));return r=o.O(r)},r=[],o.O=function(t,n,e,u){if(!n){var i=1/0;for(l=0;l<r.length;l++){n=r[l][0],e=r[l][1],u=r[l][2];for(var a=!0,f=0;f<n.length;f++)(!1&u||i>=u)&&Object.keys(o.O).every((function(r){return o.O[r](n[f])}))?n.splice(f--,1):(a=!1,u<i&&(i=u));a&&(r.splice(l--,1),t=e())}return t}u=u||0;for(var l=r.length;l>0&&r[l-1][2]>u;l--)r[l]=r[l-1];r[l]=[n,e,u]},o.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(t,{a:t}),t},o.d=function(r,t){for(var n in t)o.o(t,n)&&!o.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},o.f={},o.e=function(r){return Promise.all(Object.keys(o.f).reduce((function(t,n){return o.f[n](r,t),t}),[]))},o.u=function(r){return"6de58640.js"},o.o=function(r,t){return Object.prototype.hasOwnProperty.call(r,t)},o.p="/api/hassio/app/frontend_es5/",function(){var r={425:1,477:1};o.f.i=function(t,n){r[t]||importScripts(o.p+o.u(t))};var t=self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[],n=t.push.bind(t);t.push=function(t){var e=t[0],u=t[1],i=t[2];for(var a in u)o.o(u,a)&&(o.m[a]=u[a]);for(i&&i(o);e.length;)r[e.pop()]=1;n(t)}}(),t=o.x,o.x=function(){return o.e(354).then(t)};o.x()}();
//# sourceMappingURL=c83013c8.js.map

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"file":"c83013c8.js","sources":["webpack://home-assistant-frontend/c83013c8.js"],"mappings":"AAAA","sourceRoot":""}

Some files were not shown because too many files have changed in this diff Show More