From cf354f31b01aaede0215e09982c95c323756c587 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Thu, 30 Mar 2023 15:35:01 -0400 Subject: [PATCH 1/4] 0.21.0.dev0 version bump --- zigpy_deconz/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy_deconz/__init__.py b/zigpy_deconz/__init__.py index 18012f7..dc70c71 100644 --- a/zigpy_deconz/__init__.py +++ b/zigpy_deconz/__init__.py @@ -2,7 +2,7 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 20 +MINOR_VERSION = 21 PATCH_VERSION = "0.dev0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From c310ce2d19d8f6e42997d96ac6dd0f473f73af51 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Tue, 18 Apr 2023 12:46:13 -0400 Subject: [PATCH 2/4] Migrate to shared CI (#219) * Migrate to shared CI * remove tox * adjust default --- .github/workflows/ci.yml | 377 +---------------------------- .pre-commit-config.yaml | 22 +- .travis.yml | 15 -- tests/test_api.py | 4 +- tox.ini | 30 --- zigpy_deconz/api.py | 22 +- zigpy_deconz/types.py | 6 +- zigpy_deconz/zigbee/application.py | 1 - 8 files changed, 43 insertions(+), 434 deletions(-) delete mode 100644 .travis.yml delete mode 100644 tox.ini diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0efe7a4..b84987d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,373 +5,12 @@ on: push: pull_request: ~ -env: - CACHE_VERSION: 1 - DEFAULT_PYTHON: 3.8.16 - PRE_COMMIT_HOME: ~/.cache/pre-commit - jobs: - # Separate job to pre-populate the base dependency cache - # This prevent upcoming jobs to do the same individually - prepare-base: - name: Prepare base dependencies - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.8.16', '3.9.15', '3.10.8', '3.11.0'] - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - id: python - uses: actions/setup-python@v2.1.4 - with: - python-version: ${{ matrix.python-version }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - restore-keys: | - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}- - - name: Create Python virtual environment - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - python -m venv venv - . venv/bin/activate - pip install -U pip setuptools pre-commit - pip install -r requirements_test.txt - pip install -e . - - pre-commit: - name: Prepare pre-commit environment - runs-on: ubuntu-latest - needs: prepare-base - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v2.1.4 - id: python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Restore pre-commit environment from cache - id: cache-precommit - uses: actions/cache@v2 - with: - path: ${{ env.PRE_COMMIT_HOME }} - key: | - ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - restore-keys: | - ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit- - - name: Install pre-commit dependencies - if: steps.cache-precommit.outputs.cache-hit != 'true' - run: | - . venv/bin/activate - pre-commit install-hooks - - lint-black: - name: Check black - runs-on: ubuntu-latest - needs: pre-commit - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v2.1.4 - id: python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Restore pre-commit environment from cache - id: cache-precommit - uses: actions/cache@v2 - with: - path: ${{ env.PRE_COMMIT_HOME }} - key: | - ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - - name: Fail job if cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Run black - run: | - . venv/bin/activate - pre-commit run --hook-stage manual black --all-files --show-diff-on-failure - - lint-flake8: - name: Check flake8 - runs-on: ubuntu-latest - needs: pre-commit - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v2.1.4 - id: python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Restore pre-commit environment from cache - id: cache-precommit - uses: actions/cache@v2 - with: - path: ${{ env.PRE_COMMIT_HOME }} - key: | - ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - - name: Fail job if cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Register flake8 problem matcher - run: | - echo "::add-matcher::.github/workflows/matchers/flake8.json" - - name: Run flake8 - run: | - . venv/bin/activate - pre-commit run --hook-stage manual flake8 --all-files - - lint-isort: - name: Check isort - runs-on: ubuntu-latest - needs: pre-commit - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v2.1.4 - id: python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Restore pre-commit environment from cache - id: cache-precommit - uses: actions/cache@v2 - with: - path: ${{ env.PRE_COMMIT_HOME }} - key: | - ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - - name: Fail job if cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Run isort - run: | - . venv/bin/activate - pre-commit run --hook-stage manual isort --all-files --show-diff-on-failure - - lint-codespell: - name: Check codespell - runs-on: ubuntu-latest - needs: pre-commit - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v2.1.4 - id: python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Restore pre-commit environment from cache - id: cache-precommit - uses: actions/cache@v2 - with: - path: ${{ env.PRE_COMMIT_HOME }} - key: | - ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - - name: Fail job if cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Register codespell problem matcher - run: | - echo "::add-matcher::.github/workflows/matchers/codespell.json" - - name: Run codespell - run: | - . venv/bin/activate - pre-commit run --hook-stage manual codespell --all-files --show-diff-on-failure - - pytest: - runs-on: ubuntu-latest - needs: prepare-base - strategy: - matrix: - python-version: ['3.8.16', '3.9.15', '3.10.8', '3.11.0'] - name: >- - Run tests Python ${{ matrix.python-version }} - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.1.4 - id: python - with: - python-version: ${{ matrix.python-version }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Register Python problem matcher - run: | - echo "::add-matcher::.github/workflows/matchers/python.json" - - name: Install Pytest Annotation plugin - run: | - . venv/bin/activate - # Ideally this should be part of our dependencies - # However this plugin is fairly new and doesn't run correctly - # on a non-GitHub environment. - pip install pytest-github-actions-annotate-failures - - name: Run pytest - run: | - . venv/bin/activate - pytest \ - -qq \ - --timeout=15 \ - --durations=10 \ - --cov zigpy_deconz \ - --cov-report=term-missing \ - -o console_output_style=count \ - -p no:sugar \ - tests - - name: Upload coverage artifact - uses: actions/upload-artifact@v2.2.0 - with: - name: coverage-${{ matrix.python-version }} - path: .coverage - - name: Coveralls - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COVERALLS_FLAG_NAME: ${{ matrix.python-version }} - COVERALLS_PARALLEL: true - run: | - . venv/bin/activate - coveralls --service=github - - - coverage: - name: Process test coverage - runs-on: ubuntu-latest - needs: pytest - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.1.4 - id: python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - - name: Restore base Python virtual environment - id: cache-venv - uses: actions/cache@v2 - with: - path: venv - key: >- - ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ - steps.python.outputs.python-version }}-${{ - hashFiles('requirements_test.txt', 'setup.py') }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python virtual environment from cache" - exit 1 - - name: Download all coverage artifacts - uses: actions/download-artifact@v2 - - name: Combine coverage results - run: | - . venv/bin/activate - coverage combine coverage*/.coverage* - coverage report --fail-under=97 - coverage xml - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 - - name: Upload coverage to Coveralls - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - . venv/bin/activate - coveralls --service=github --finish + shared-ci: + uses: zigpy/workflows/.github/workflows/ci.yml@main + with: + CODE_FOLDER: zigpy_deconz + CACHE_VERSION: 2 + PYTHON_VERSION_DEFAULT: 3.8.14 + PRE_COMMIT_CACHE_PATH: ~/.cache/pre-commit + MINIMUM_COVERAGE_PERCENTAGE: 97 \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f5bdfe2..3bef02f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,22 @@ repos: + - repo: https://github.com/asottile/pyupgrade + rev: v3.3.1 + hooks: + - id: pyupgrade + args: [--py38-plus] + + - repo: https://github.com/PyCQA/autoflake + rev: v2.0.2 + hooks: + - id: autoflake + - repo: https://github.com/psf/black - rev: 23.1.0 + rev: 23.3.0 hooks: - id: black args: - - --safe - --quiet + - --safe - repo: https://github.com/pycqa/flake8 rev: 6.0.0 @@ -28,3 +39,10 @@ repos: - --ignore-words-list=ser,nd,hass - --skip="./.*" - --quiet-level=2 + + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.261 + hooks: + - id: ruff + args: + - --fix \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7020c1c..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: python -matrix: - fast_finish: true - include: - - python: "3.7" - env: TOXENV=lint - - python: "3.7" - env: TOXENV=black - - python: "3.7" - env: TOXENV=py37 - - python: "3.8" - env: TOXENV=py38 -install: pip install -U setuptools tox coveralls -script: tox -after_success: coveralls diff --git a/tests/test_api.py b/tests/test_api.py index 2263d71..c350ba6 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -179,7 +179,7 @@ def test_data_received(api, monkeypatch): for cmd, cmd_opts in deconz_api.RX_COMMANDS.items(): payload = b"\x01\x02\x03\x04" data = cmd.serialize() + b"\x00\x00\x00\x00" + payload - setattr(api, "_handle_{}".format(cmd.name), my_handler) + setattr(api, f"_handle_{cmd.name}", my_handler) api._awaiting[0] = MagicMock() api.data_received(data) assert t.deserialize.call_count == 1 @@ -203,7 +203,7 @@ def test_data_received_unk_status(api, monkeypatch): payload = b"\x01\x02\x03\x04" status = t.uint8_t(0xFE).serialize() data = cmd.serialize() + b"\x00" + status + b"\x00\x00" + payload - setattr(api, "_handle_{}".format(cmd.name), my_handler) + setattr(api, f"_handle_{cmd.name}", my_handler) api._awaiting[0] = MagicMock() api.data_received(data) if solicited: diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 36ae502..0000000 --- a/tox.ini +++ /dev/null @@ -1,30 +0,0 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = py37, py38, lint, black -skip_missing_interpreters = True - -[testenv] -setenv = PYTHONPATH = {toxinidir} -install_command = pip install {opts} {packages} -commands = py.test --cov --cov-report= -deps = -rrequirements_test.txt - -[testenv:lint] -basepython = python3 -deps = pre-commit -commands = - pre-commit run --hook-stage manual flake8 --all-files - pre-commit run --hook-stage manual isort --all-files --show-diff-on-failure - pre-commit run --hook-stage manual codespell --all-files - -[testenv:black] -deps = pre-commit -setenv = - LC_ALL=C.UTF-8 - LANG=C.UTF-8 -commands= - pre-commit run --hook-stage manual black --all-files --show-diff-on-failure diff --git a/zigpy_deconz/api.py b/zigpy_deconz/api.py index 4143854..bc1b948 100644 --- a/zigpy_deconz/api.py +++ b/zigpy_deconz/api.py @@ -7,7 +7,7 @@ import enum import functools import logging -from typing import Any, Callable, Optional +from typing import Any, Callable from zigpy.config import CONF_DEVICE_PATH import zigpy.exceptions @@ -44,7 +44,7 @@ class DeviceState(enum.IntFlag): APSDE_DATA_REQUEST_SLOTS_AVAILABLE = 0x20 @classmethod - def deserialize(cls, data) -> tuple["DeviceState", bytes]: + def deserialize(cls, data) -> tuple[DeviceState, bytes]: """Deserialize DevceState.""" state, data = t.uint8_t.deserialize(data) return cls(state), data @@ -54,7 +54,7 @@ def serialize(self) -> bytes: return t.uint8_t(self).serialize() @property - def network_state(self) -> "NetworkState": + def network_state(self) -> NetworkState: """Return network state.""" return NetworkState(self & 0x03) @@ -251,12 +251,12 @@ def __init__(self, app: Callable, device_config: dict[str, Any]): self._data_confirm: bool = False self._device_state = DeviceState(NetworkState.OFFLINE) self._seq = 1 - self._proto_ver: Optional[int] = None - self._firmware_version: Optional[int] = None - self._uart: Optional[zigpy_deconz.uart.Gateway] = None + self._proto_ver: int | None = None + self._firmware_version: int | None = None + self._uart: zigpy_deconz.uart.Gateway | None = None @property - def firmware_version(self) -> Optional[int]: + def firmware_version(self) -> int | None: """Return ConBee firmware version.""" return self._firmware_version @@ -266,7 +266,7 @@ def network_state(self) -> NetworkState: return self._device_state.network_state @property - def protocol_version(self) -> Optional[int]: + def protocol_version(self) -> int | None: """Protocol Version.""" return self._proto_ver @@ -341,7 +341,7 @@ def data_received(self, data): if status != Status.SUCCESS: try: fut.set_exception( - CommandError(status, "%s, status: %s" % (command, status)) + CommandError(status, f"{command}, status: {status}") ) except asyncio.InvalidStateError: LOGGER.warning( @@ -416,7 +416,7 @@ async def read_parameter(self, id_, *args): else: param = NetworkParameter(id_) except (KeyError, ValueError): - raise KeyError("Unknown parameter id: %s" % (id_,)) + raise KeyError(f"Unknown parameter id: {id_}") data = t.serialize(args, NETWORK_PARAMETER_SCHEMA[param]) r = await self._command(Command.read_parameter, 1 + len(data), param, data) @@ -439,7 +439,7 @@ def write_parameter(self, id_, *args): else: param = NetworkParameter(id_) except (KeyError, ValueError): - raise KeyError("Unknown parameter id: %s write request" % (id_,)) + raise KeyError(f"Unknown parameter id: {id_} write request") v = t.serialize(args, NETWORK_PARAMETER_SCHEMA[param]) length = len(v) + 1 diff --git a/zigpy_deconz/types.py b/zigpy_deconz/types.py index 852e9c2..da44e83 100644 --- a/zigpy_deconz/types.py +++ b/zigpy_deconz/types.py @@ -180,10 +180,8 @@ def __eq__(self, other): def __repr__(self): """Instance representation.""" - r = "<%s " % (self.__class__.__name__,) - r += " ".join( - ["%s=%s" % (f[0], getattr(self, f[0], None)) for f in self._fields] - ) + r = f"<{self.__class__.__name__} " + r += " ".join([f"{f[0]}={getattr(self, f[0], None)}" for f in self._fields]) r += ">" return r diff --git a/zigpy_deconz/zigbee/application.py b/zigpy_deconz/zigbee/application.py index e23d3a8..ab20b71 100644 --- a/zigpy_deconz/zigbee/application.py +++ b/zigpy_deconz/zigbee/application.py @@ -338,7 +338,6 @@ async def load_network_info(self, *, load_devices=False): async def force_remove(self, dev): """Forcibly remove device from NCP.""" - pass async def energy_scan( self, channels: t.Channels.ALL_CHANNELS, duration_exp: int, count: int From 04f9501d295bc2631d7118b69b4c7faecfc1a264 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Mon, 24 Apr 2023 14:52:43 -0400 Subject: [PATCH 3/4] Implement channel migration (#220) --- tests/test_application.py | 19 +++++++++++++++++++ zigpy_deconz/zigbee/application.py | 13 +++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/test_application.py b/tests/test_application.py index c00a7ab..8c64b70 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -588,3 +588,22 @@ async def test_energy_scan(app): ) assert results == {c: c * 3 for c in Channels.ALL_CHANNELS} + + +async def test_channel_migration(app): + app._api.write_parameter = AsyncMock() + app._change_network_state = AsyncMock() + + await app._move_network_to_channel(new_channel=26, new_nwk_update_id=0x12) + + assert app._api.write_parameter.mock_calls == [ + mock.call( + deconz_api.NetworkParameter.channel_mask, Channels.from_channel_list([26]) + ), + mock.call(deconz_api.NetworkParameter.nwk_update_id, 0x12), + ] + + assert app._change_network_state.mock_calls == [ + mock.call(deconz_api.NetworkState.OFFLINE), + mock.call(deconz_api.NetworkState.CONNECTED), + ] diff --git a/zigpy_deconz/zigbee/application.py b/zigpy_deconz/zigbee/application.py index ab20b71..3c9bb0b 100644 --- a/zigpy_deconz/zigbee/application.py +++ b/zigpy_deconz/zigbee/application.py @@ -349,6 +349,19 @@ async def energy_scan( # The Conbee seems to max out at an LQI of 85, which is exactly 255/3 return {c: v * 3 for c, v in results.items()} + async def _move_network_to_channel( + self, new_channel: int, new_nwk_update_id: int + ) -> None: + """Move device to a new channel.""" + channel_mask = zigpy.types.Channels.from_channel_list([new_channel]) + await self._api.write_parameter(NetworkParameter.channel_mask, channel_mask) + await self._api.write_parameter( + NetworkParameter.nwk_update_id, new_nwk_update_id + ) + + await self._change_network_state(NetworkState.OFFLINE) + await self._change_network_state(NetworkState.CONNECTED) + async def add_endpoint(self, descriptor: zdo_t.SimpleDescriptor) -> None: """Register an endpoint on the device, replacing any with conflicting IDs.""" From 0a1a57d5ffad0c01377601c2640fd89656b02cd8 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Mon, 24 Apr 2023 14:53:32 -0400 Subject: [PATCH 4/4] 0.21.0 release --- zigpy_deconz/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy_deconz/__init__.py b/zigpy_deconz/__init__.py index dc70c71..ffc4161 100644 --- a/zigpy_deconz/__init__.py +++ b/zigpy_deconz/__init__.py @@ -3,6 +3,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 21 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}"