From 906d3b67d22fe40a0a09aecd2b16de29a2d92452 Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Sun, 9 Apr 2023 08:32:46 -0400 Subject: [PATCH] update CI --- .pre-commit-config.yaml | 29 +++++++++- .travis.yml | 19 ------- bellows/cli/application.py | 24 +++++---- bellows/cli/backup.py | 2 +- bellows/cli/dump.py | 4 +- bellows/cli/ncp.py | 16 +++--- bellows/cli/network.py | 14 +++-- bellows/cli/util.py | 10 ++-- bellows/ezsp/__init__.py | 20 ++++--- bellows/ezsp/v10/types/named.py | 5 +- bellows/ezsp/v6/types/named.py | 5 +- bellows/ezsp/v7/types/named.py | 5 +- bellows/ezsp/v8/types/named.py | 5 +- bellows/ezsp/v9/types/named.py | 5 +- bellows/types/basic.py | 4 +- bellows/zigbee/application.py | 8 ++- bellows/zigbee/device.py | 4 +- requirements_test.txt | 16 ++++-- ruff.toml | 71 +++++++++++++++++++++++++ script/setup | 15 ++++++ tests/test_application_device.py | 2 - tests/test_application_network_state.py | 2 - 22 files changed, 189 insertions(+), 96 deletions(-) delete mode 100644 .travis.yml create mode 100644 ruff.toml create mode 100755 script/setup diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 201b5d80..7144d562 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,19 +1,32 @@ 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 + - repo: https://github.com/pycqa/flake8 rev: 6.0.0 hooks: - id: flake8 + - repo: https://github.com/PyCQA/isort rev: 5.12.0 hooks: - id: isort + - repo: https://github.com/codespell-project/codespell rev: v2.2.4 hooks: @@ -22,3 +35,15 @@ repos: - --ignore-words-list=zigpy,hass - --skip="./.*" - --quiet-level=2 + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.2.0 + hooks: + - id: mypy + + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.261 + hooks: + - id: ruff + args: + - --fix diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e3e1757f..00000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: python -dist: bionic - -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 - - python: "3.8.6" - env: TOXENV=py38 -install: pip install -U setuptools tox coveralls -script: tox -after_success: coveralls diff --git a/bellows/cli/application.py b/bellows/cli/application.py index 36d85f74..9d175df6 100644 --- a/bellows/cli/application.py +++ b/bellows/cli/application.py @@ -57,7 +57,7 @@ async def inner(ctx): app = ctx.obj["app"] await app.permit(duration_s) - click.echo("Joins are permitted for the next %ss..." % (duration_s,)) + click.echo(f"Joins are permitted for the next {duration_s}s...") await asyncio.sleep(duration_s + 1) click.echo("Done") @@ -80,7 +80,7 @@ async def inner(ctx): try: await app.permit_with_key(node, code, duration_s) - click.echo("Joins are permitted for the next %ss..." % (duration_s,)) + click.echo(f"Joins are permitted for the next {duration_s}s...") await asyncio.sleep(duration_s + 1) click.echo("Done") except Exception as e: @@ -96,11 +96,11 @@ def devices(ctx, database): """Show device database""" def print_clusters(title, clusters): - clusters = sorted(list(clusters.items())) + clusters = sorted(clusters.items()) if clusters: - click.echo(" %s:" % (title,)) + click.echo(f" {title}:") for cluster_id, cluster in clusters: - click.echo(" %s (%s)" % (cluster.name, cluster_id)) + click.echo(f" {cluster.name} ({cluster_id})") loop = asyncio.get_event_loop() config = { @@ -113,8 +113,8 @@ def print_clusters(title, clusters): ) for ieee, dev in app.devices.items(): click.echo("Device:") - click.echo(" NWK: 0x%04x" % (dev.nwk,)) - click.echo(" IEEE: %s" % (ieee,)) + click.echo(f" NWK: 0x{dev.nwk:04x}") + click.echo(f" IEEE: {ieee}") click.echo(" Endpoints:") for epid, ep in dev.endpoints.items(): if epid == 0: @@ -155,7 +155,7 @@ async def endpoints(ctx): try: v = await dev.zdo.request(0x0005, dev.nwk) if v[0] != t.EmberStatus.SUCCESS: - click.echo("Non-success response: %s" % (v,)) + click.echo(f"Non-success response: {v}") else: click.echo(v[2]) except zigpy.exceptions.ZigbeeException as e: @@ -178,7 +178,7 @@ async def get_endpoint(ctx, endpoint): try: v = await dev.zdo.request(0x0004, dev.nwk, endpoint) if v[0] != t.EmberStatus.SUCCESS: - click.echo("Non-success response: %s" % (v,)) + click.echo(f"Non-success response: {v}") else: click.echo(v[2]) except zigpy.exceptions.ZigbeeException as e: @@ -278,10 +278,12 @@ async def read_attribute(ctx, attribute, manufacturer): click.echo("Received empty response") elif attribute not in v[0]: click.echo( - "Attribute %s not successful. Status=%s" % (attribute, v[1][attribute]) + "Attribute {} not successful. Status={}".format( + attribute, v[1][attribute] + ) ) else: - click.echo("%s=%s" % (attribute, v[0][attribute])) + click.echo(f"{attribute}={v[0][attribute]}") except zigpy.exceptions.ZigbeeException as e: click.echo(e) diff --git a/bellows/cli/backup.py b/bellows/cli/backup.py index daad2330..8f3c5af2 100644 --- a/bellows/cli/backup.py +++ b/bellows/cli/backup.py @@ -167,7 +167,7 @@ async def restore( """Backup NCP config to stdio.""" click.echo("Restoring NCP") try: - with open(backup_file, "r") as file: + with open(backup_file) as file: backup_data = json.load(file) LOGGER.debug("loaded: %s", backup_data) backup_data = SCHEMA_BAK(backup_data) diff --git a/bellows/cli/dump.py b/bellows/cli/dump.py index c315c4d5..65c6d67f 100644 --- a/bellows/cli/dump.py +++ b/bellows/cli/dump.py @@ -33,9 +33,7 @@ def dump(ctx, channel, outfile): start_time = ctx.obj.get("start_time", None) if start_time: duration = time.time() - start_time - click.echo( - "\nCaptured %s frames in %0.2fs" % (captured, duration), err=True - ) + click.echo(f"\nCaptured {captured} frames in {duration:0.2f}s", err=True) finally: if "ezsp" in ctx.obj: loop.run_until_complete(ctx.obj["ezsp"].mfglibEnd()) diff --git a/bellows/cli/ncp.py b/bellows/cli/ncp.py index 9cc1509f..c4c458ee 100644 --- a/bellows/cli/ncp.py +++ b/bellows/cli/ncp.py @@ -29,7 +29,7 @@ async def config(ctx, config, all_): v = await s.getConfigurationValue(config) if v[0] == t.EzspStatus.ERROR_INVALID_ID: continue - click.echo("%s=%s" % (config.name, v[1])) + click.echo(f"{config.name}={v[1]}") s.close() return @@ -39,18 +39,18 @@ async def config(ctx, config, all_): try: config = s.types.EzspConfigId(int(config)) except ValueError: - raise click.BadArgumentUsage("Invalid config ID: %s" % (config,)) + raise click.BadArgumentUsage(f"Invalid config ID: {config}") else: try: config = s.types.EzspConfigId[config] except KeyError: - raise click.BadArgumentUsage("Invalid config name: %s" % (config,)) + raise click.BadArgumentUsage(f"Invalid config name: {config}") try: value = t.uint16_t(value) if not (0 <= value <= 65535): - raise ValueError("%s out of allowed range 0..65535" % (value,)) + raise ValueError(f"{value} out of allowed range 0..65535") except ValueError as e: - raise click.BadArgumentUsage("Invalid value: %s" % (e,)) + raise click.BadArgumentUsage(f"Invalid value: {e}") v = await s.setConfigurationValue(config, value) click.echo(v) @@ -109,10 +109,8 @@ async def bootloader(ctx): return click.echo( - ( - f"bootloader version: 0x{version:04x}, nodePlat: 0x{plat:02x}, " - f"nodeMicro: 0x{micro:02x}, nodePhy: 0x{phy:02x}" - ) + f"bootloader version: 0x{version:04x}, nodePlat: 0x{plat:02x}, " + f"nodeMicro: 0x{micro:02x}, nodePhy: 0x{phy:02x}" ) res = await ezsp.launchStandaloneBootloader(0x00) diff --git a/bellows/cli/network.py b/bellows/cli/network.py index bd371507..f44762a4 100644 --- a/bellows/cli/network.py +++ b/bellows/cli/network.py @@ -63,9 +63,7 @@ def cb(fut, frame_name, response): extended_pan_id = network.extendedPanId channel = network.channel - click.echo( - "Found network %s %s on channel %s" % (pan_id, extended_pan_id, channel) - ) + click.echo(f"Found network {pan_id} {extended_pan_id} on channel {channel}") if pan_id is None: pan_id = t.uint16_t(0) @@ -81,12 +79,12 @@ def cb(fut, frame_name, response): if v[0] == t.EmberStatus.SUCCESS: LOGGER.debug("Network was up, leaving...") v = await s.leaveNetwork() - util.check(v[0], "Failure leaving network: %s" % (v[0],)) + util.check(v[0], f"Failure leaving network: {v[0]}") await asyncio.sleep(1) # TODO initial_security_state = zutil.zha_security(SCHEMA_NETWORK({})) v = await s.setInitialSecurityState(initial_security_state) - util.check(v[0], "Setting security state failed: %s" % (v[0],)) + util.check(v[0], f"Setting security state failed: {v[0]}") parameters = t.EmberNetworkParameters() parameters.extendedPanId = extended_pan_id @@ -102,7 +100,7 @@ def cb(fut, frame_name, response): fut = asyncio.Future() cbid = s.add_callback(functools.partial(cb, fut)) v = await s.joinNetwork(t.EmberNodeType.END_DEVICE, parameters) - util.check(v[0], "Joining network failed: %s" % (v[0],)) + util.check(v[0], f"Joining network failed: {v[0]}") v = await fut click.echo(v) @@ -124,7 +122,7 @@ async def leave(ctx): v = await s.leaveNetwork() util.check( v[0], - "Failure leaving network: %s" % (v[0],), + f"Failure leaving network: {v[0]}", expected=t.EmberStatus.NETWORK_DOWN, ) @@ -142,7 +140,7 @@ async def scan(ctx, channels, duration_ms, energy_scan): s = await util.setup(ctx.obj["device"], ctx.obj["baudrate"]) channel_mask = util.channel_mask(channels) - click.echo("Scanning channels %s" % (" ".join(map(str, channels)),)) + click.echo("Scanning channels {}".format(" ".join(map(str, channels)))) # TFM says: # Sets the exponent of the number of scan periods, where a scan period is diff --git a/bellows/cli/util.py b/bellows/cli/util.py index 2ff6942c..a3aa95e0 100644 --- a/bellows/cli/util.py +++ b/bellows/cli/util.py @@ -88,7 +88,7 @@ def inner(*args, **kwargs): def print_cb(frame_name, response): - click.echo("Callback: %s %s" % (frame_name, response)) + click.echo(f"Callback: {frame_name} {response}") def channel_mask(channels): @@ -121,7 +121,7 @@ async def setup(dev, baudrate, cbh=None, configure=True): async def cfg(config_id, value): v = await s.setConfigurationValue(config_id, value) - check(v[0], "Setting config %s to %s: %s" % (config_id, value, v[0])) + check(v[0], f"Setting config {config_id} to {value}: {v[0]}") c = s.types.EzspConfigId @@ -155,7 +155,7 @@ async def network_init(s): v = await s.networkInit() check( v[0], - "Failure initializing network: %s" % (v[0],), + f"Failure initializing network: {v[0]}", [0, t.EmberStatus.NOT_JOINED], ) return v @@ -170,7 +170,7 @@ def parse_epan(epan): async def basic_tc_permits(s): async def set_policy(policy, decision): v = await s.setPolicy(policy, decision) - check(v[0], "Failed to set policy %s to %s: %s" % (policy, decision, v[0])) + check(v[0], f"Failed to set policy {policy} to {decision}: {v[0]}") await set_policy( s.types.EzspPolicyId.TC_KEY_REQUEST_POLICY, @@ -188,7 +188,7 @@ async def set_policy(policy, decision): def get_device(app, node): if node not in app.devices: - click.echo("Device %s is not in the device database" % (node,)) + click.echo(f"Device {node} is not in the device database") return None return app.devices[node] diff --git a/bellows/ezsp/__init__.py b/bellows/ezsp/__init__.py index 3ed1d874..0e5a36a9 100644 --- a/bellows/ezsp/__init__.py +++ b/bellows/ezsp/__init__.py @@ -6,7 +6,7 @@ import functools import logging import sys -from typing import Any, Callable, Dict, List, Tuple, Union +from typing import Any, Callable import urllib.parse if sys.version_info[:2] < (3, 11): @@ -47,7 +47,7 @@ class EZSP: v11.EZSP_VERSION: v11.EZSPv11, } - def __init__(self, device_config: Dict): + def __init__(self, device_config: dict): self._config = device_config self._callbacks = {} self._ezsp_event = asyncio.Event() @@ -56,7 +56,7 @@ def __init__(self, device_config: Dict): self._protocol = None @classmethod - async def probe(cls, device_config: Dict) -> bool | dict[str, int | str | bool]: + async def probe(cls, device_config: dict) -> bool | dict[str, int | str | bool]: """Probe port for the device presence.""" for config in ( {**device_config, conf.CONF_DEVICE_BAUDRATE: 115200}, @@ -103,7 +103,7 @@ async def _startup_reset(self): await self.reset() @classmethod - async def initialize(cls, zigpy_config: Dict) -> "EZSP": + async def initialize(cls, zigpy_config: dict) -> EZSP: """Return initialized EZSP instance.""" ezsp = cls(zigpy_config[conf.CONF_DEVICE]) await ezsp.connect(use_thread=zigpy_config[conf.CONF_USE_THREAD]) @@ -163,7 +163,7 @@ def close(self): self._gw.close() self._gw = None - def _command(self, name: str, *args: Tuple[Any, ...]) -> asyncio.Future: + def _command(self, name: str, *args: tuple[Any, ...]) -> asyncio.Future: if not self.is_ezsp_running: LOGGER.debug( "Couldn't send command %s(%s). EZSP is not running", name, args @@ -221,13 +221,11 @@ def cb(frame_name, response): 0, ) - async def leaveNetwork( - self, timeout: Union[float, int] = NETWORK_OPS_TIMEOUT - ) -> List: + async def leaveNetwork(self, timeout: float | int = NETWORK_OPS_TIMEOUT) -> list: """Send leaveNetwork command and wait for stackStatusHandler frame.""" stack_status = asyncio.Future() - def cb(frame_name: str, response: List) -> None: + def cb(frame_name: str, response: list) -> None: if ( frame_name == "stackStatusHandler" and response[0] == t.EmberStatus.NETWORK_DOWN @@ -308,7 +306,7 @@ def frame_received(self, data: bytes) -> None: self._protocol(data) - async def get_board_info(self) -> Tuple[str, str, str]: + async def get_board_info(self) -> tuple[str, str, str]: """Return board info.""" tokens = [] @@ -359,7 +357,7 @@ def remove_callback(self, id_): return self._callbacks.pop(id_) def handle_callback(self, *args): - for callback_id, handler in self._callbacks.items(): + for _callback_id, handler in self._callbacks.items(): try: handler(*args) except Exception as e: diff --git a/bellows/ezsp/v10/types/named.py b/bellows/ezsp/v10/types/named.py index b1e2cb7f..828d89ef 100644 --- a/bellows/ezsp/v10/types/named.py +++ b/bellows/ezsp/v10/types/named.py @@ -675,10 +675,11 @@ class EmberEntropySource(basic.enum8): class EmberDutyCycleHectoPct(basic.uint16_t): - """ "The percent of duty cycle for a limit. + """The percent of duty cycle for a limit. Duty Cycle, Limits, and Thresholds are reported in units of Percent * 100 - (i.e. 10000 = 100.00%, 1 = 0.01%)""" + (i.e. 10000 = 100.00%, 1 = 0.01%) + """ class EmberGpProxyTableEntryStatus(basic.uint8_t): diff --git a/bellows/ezsp/v6/types/named.py b/bellows/ezsp/v6/types/named.py index fac5e0f5..c6ffa969 100644 --- a/bellows/ezsp/v6/types/named.py +++ b/bellows/ezsp/v6/types/named.py @@ -587,10 +587,11 @@ class EmberRadioPowerMode(basic.enum8): class EmberDutyCycleHectoPct(basic.uint16_t): - """ "The percent of duty cycle for a limit. + """The percent of duty cycle for a limit. Duty Cycle, Limits, and Thresholds are reported in units of Percent * 100 - (i.e. 10000 = 100.00%, 1 = 0.01%)""" + (i.e. 10000 = 100.00%, 1 = 0.01%) + """ class EmberGpProxyTableEntryStatus(basic.uint8_t): diff --git a/bellows/ezsp/v7/types/named.py b/bellows/ezsp/v7/types/named.py index 65042a06..00e24e97 100644 --- a/bellows/ezsp/v7/types/named.py +++ b/bellows/ezsp/v7/types/named.py @@ -661,10 +661,11 @@ class EmberEntropySource(basic.enum8): class EmberDutyCycleHectoPct(basic.uint16_t): - """ "The percent of duty cycle for a limit. + """The percent of duty cycle for a limit. Duty Cycle, Limits, and Thresholds are reported in units of Percent * 100 - (i.e. 10000 = 100.00%, 1 = 0.01%)""" + (i.e. 10000 = 100.00%, 1 = 0.01%) + """ class EmberGpProxyTableEntryStatus(basic.uint8_t): diff --git a/bellows/ezsp/v8/types/named.py b/bellows/ezsp/v8/types/named.py index f1104521..9a3a946a 100644 --- a/bellows/ezsp/v8/types/named.py +++ b/bellows/ezsp/v8/types/named.py @@ -666,10 +666,11 @@ class EmberEntropySource(basic.enum8): class EmberDutyCycleHectoPct(basic.uint16_t): - """ "The percent of duty cycle for a limit. + """The percent of duty cycle for a limit. Duty Cycle, Limits, and Thresholds are reported in units of Percent * 100 - (i.e. 10000 = 100.00%, 1 = 0.01%)""" + (i.e. 10000 = 100.00%, 1 = 0.01%) + """ class EmberGpProxyTableEntryStatus(basic.uint8_t): diff --git a/bellows/ezsp/v9/types/named.py b/bellows/ezsp/v9/types/named.py index 2a95b49e..e727ca7d 100644 --- a/bellows/ezsp/v9/types/named.py +++ b/bellows/ezsp/v9/types/named.py @@ -674,10 +674,11 @@ class EmberEntropySource(basic.enum8): class EmberDutyCycleHectoPct(basic.uint16_t): - """ "The percent of duty cycle for a limit. + """The percent of duty cycle for a limit. Duty Cycle, Limits, and Thresholds are reported in units of Percent * 100 - (i.e. 10000 = 100.00%, 1 = 0.01%)""" + (i.e. 10000 = 100.00%, 1 = 0.01%) + """ class EmberGpProxyTableEntryStatus(basic.uint8_t): diff --git a/bellows/types/basic.py b/bellows/types/basic.py index e3e890c8..f3d6e722 100644 --- a/bellows/types/basic.py +++ b/bellows/types/basic.py @@ -123,7 +123,7 @@ def serialize(self): def deserialize(cls, data): r = cls() length, data = data[0], data[1:] - for i in range(length): + for _i in range(length): item, data = r._itemtype.deserialize(data) r.append(item) return r, data @@ -147,7 +147,7 @@ class _FixedList(_List): @classmethod def deserialize(cls, data): r = cls() - for i in range(r._length): + for _i in range(r._length): item, data = r._itemtype.deserialize(data) r.append(item) return r, data diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index 7afba46d..12213056 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -5,7 +5,6 @@ import os import statistics import sys -from typing import Dict, Optional if sys.version_info[:2] < (3, 11): from async_timeout import timeout as asyncio_timeout # pragma: no cover @@ -69,7 +68,7 @@ class ControllerApplication(zigpy.application.ControllerApplication): SCHEMA = CONFIG_SCHEMA SCHEMA_DEVICE = SCHEMA_DEVICE - def __init__(self, config: Dict): + def __init__(self, config: dict): super().__init__(config) self._ctrl_event = asyncio.Event() self._ezsp = None @@ -140,8 +139,7 @@ async def connect(self): LOGGER.info("EmberZNet version: %s", version) async def _ensure_network_running(self) -> bool: - """ - Ensures the network is currently running and returns whether or not the network + """Ensures the network is currently running and returns whether or not the network was started. """ (state,) = await self._ezsp.networkState() @@ -933,7 +931,7 @@ async def _watchdog(self): self.state.counters[COUNTERS_CTRL][COUNTER_WATCHDOG].increment() self._handle_reset_request(f"Watchdog timeout. Heartbeat timeouts: {failures}") - async def _get_free_buffers(self) -> Optional[int]: + async def _get_free_buffers(self) -> int | None: status, value = await self._ezsp.getValue( self._ezsp.types.EzspValueId.VALUE_FREE_BUFFERS ) diff --git a/bellows/zigbee/device.py b/bellows/zigbee/device.py index 69952488..1adbc307 100644 --- a/bellows/zigbee/device.py +++ b/bellows/zigbee/device.py @@ -62,9 +62,7 @@ def app(self) -> zigpy.application.ControllerApplication: return self.device.application def make_zdo_reply(self, cmd: zdo_t.ZDOCmd, **kwargs): - """ - Provides a way to create ZDO commands with schemas. Currently does nothing. - """ + """Provides a way to create ZDO commands with schemas. Currently does nothing.""" return list(kwargs.values()) diff --git a/requirements_test.txt b/requirements_test.txt index 6b9647b0..d03ba1a5 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,9 +1,19 @@ # Test dependencies. asynctest -coveralls==2.1.2 +isort +black +flake8 +codecov +colorlog +codespell +mypy==0.942 pre-commit -pytest -pytest-asyncio>=0.17 +pylint pytest-cov +pytest-sugar pytest-timeout +pytest-asyncio>=0.17 +pytest>=7.1.3 +zigpy>=0.53 +ruff==0.0.261 \ No newline at end of file diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..9c27612c --- /dev/null +++ b/ruff.toml @@ -0,0 +1,71 @@ +target-version = "py38" + +select = [ + "B007", # Loop control variable {name} not used within loop body + "B014", # Exception handler with duplicate exception + "C", # complexity + "D", # docstrings + "E", # pycodestyle + "F", # pyflakes/autoflake + "ICN001", # import concentions; {name} should be imported as {asname} + "PGH004", # Use specific rule codes when using noqa + "PLC0414", # Useless import alias. Import alias does not rename original package. + "SIM105", # Use contextlib.suppress({exception}) instead of try-except-pass + "SIM117", # Merge with-statements that use the same scope + "SIM118", # Use {key} in {dict} instead of {key} in {dict}.keys() + "SIM201", # Use {left} != {right} instead of not {left} == {right} + "SIM212", # Use {a} if {a} else {b} instead of {b} if not {a} else {a} + "SIM300", # Yoda conditions. Use 'age == 42' instead of '42 == age'. + "SIM401", # Use get from dict with default instead of an if block + "T20", # flake8-print + "TRY004", # Prefer TypeError exception for invalid type + "RUF006", # Store a reference to the return value of asyncio.create_task + "UP", # pyupgrade + "W", # pycodestyle +] + +ignore = [ + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D106", # Missing docstring in public nested class + "D107", # Missing docstring in `__init__` + "D202", # No blank lines allowed after function docstring + "D203", # 1 blank line required before class docstring + "D205", # 1 blank line required between summary line and description + "D213", # Multi-line docstring summary should start at the second line + "D400", # First line should end with a period + "D401", # First line of docstring should be in imperative mood: + "D406", # Section name should end with a newline + "D407", # Section name underlining + "D415", # First line should end with a period, question mark, or exclamation point + "E501", # line too long + # the rules below this line should be corrected + "PGH004", # Use specific rule codes when using `noqa` +] + +extend-exclude = [ + "tests" +] + +[flake8-pytest-style] +fixture-parentheses = false + +[pyupgrade] +keep-runtime-typing = true + +[isort] +# will group `import x` and `from x import` of the same module. +force-sort-within-sections = true +known-first-party = [ + "bellows", + "tests", +] +forced-separate = ["tests"] +combine-as-imports = true + +[mccabe] +max-complexity = 25 \ No newline at end of file diff --git a/script/setup b/script/setup new file mode 100755 index 00000000..3531e5bb --- /dev/null +++ b/script/setup @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Setup the repository. + +# Stop on errors +set -e + +cd "$(dirname "$0")/.." + +python3 -m venv venv +source venv/bin/activate + +pip install -r requirements_test.txt +pre-commit install + +python3 -m pip install -e . diff --git a/tests/test_application_device.py b/tests/test_application_device.py index 7814cdae..37f6e3d6 100644 --- a/tests/test_application_device.py +++ b/tests/test_application_device.py @@ -1,5 +1,3 @@ -import asyncio - import pytest import zigpy.endpoint import zigpy.types as t diff --git a/tests/test_application_network_state.py b/tests/test_application_network_state.py index 8cd050cb..108df3b7 100644 --- a/tests/test_application_network_state.py +++ b/tests/test_application_network_state.py @@ -1,5 +1,3 @@ -import logging - import pytest import zigpy.state import zigpy.types as zigpy_t