Skip to content

Commit

Permalink
Upgrade test and lint environment (#876)
Browse files Browse the repository at this point in the history
* upgrade pre-commit hook versions and black target-version

* use pytest asyncio_mode auto and move options to pyproject.toml

* move isort config to pyproject.toml

and treat xknx as first party - except for /home-assistant-plugin which gets its own .isort.cfg

* move mypy config to pyproject.toml

* move pylint config to pyproject.toml

and enable `useless-suppression`

* Update pyproject.toml
  • Loading branch information
farmio authored Feb 22, 2022
1 parent f674160 commit fc71b01
Show file tree
Hide file tree
Showing 112 changed files with 222 additions and 240 deletions.
22 changes: 12 additions & 10 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
---
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v2.11.0
rev: v2.31.0
hooks:
- id: pyupgrade
args: [--py38-plus]
args: [--py39-plus]
- repo: https://github.com/psf/black
rev: 20.8b1
rev: 22.1.0
hooks:
- id: black
args:
- --safe
- --quiet
files: ^((xknx|test|examples|home-assistant-plugin|docs)/.+)?[^/]+\.py$
- repo: https://gitlab.com/pycqa/flake8
rev: 3.9.0
- repo: https://github.com/pycqa/flake8
rev: 4.0.1
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.6.0
- pydocstyle==6.0.0
files: ^(xknx|examples|docs)/.+\.py$
- repo: https://github.com/timothycrosley/isort
rev: 5.8.0
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
- id: isort
args:
- --resolve-all-configs
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
rev: v4.1.0
hooks:
- id: check-executables-have-shebangs
stages: [manual]
Expand All @@ -36,15 +38,15 @@ repos:
- --branch=main
- id: trailing-whitespace
- repo: https://github.com/cdce8p/python-typing-update
rev: v0.3.2
rev: v0.3.5
hooks:
# Run `pre-commit run --hook-stage manual python-typing-update --all-files` manually
# from time to time to update python typing syntax.
# Will require manual work, before submitting changes!
- id: python-typing-update
stages: [manual]
args:
- --py38-plus
- --py39-plus
- --force
- --keep-updates
files: ^(xknx)/.+\.py$
Expand Down
63 changes: 0 additions & 63 deletions .pylintrc

This file was deleted.

4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ pypi:
@twine upload dist/*

pylint:
@pylint --jobs=0 --rcfile=.pylintrc xknx *.py examples/*.py
@pylint --jobs=0 --rcfile=.pylintrc --disable=no-self-use,protected-access,abstract-class-instantiated test/*
@pylint --jobs=0 xknx *.py examples/*.py
@pylint --jobs=0 --disable=no-self-use,protected-access,abstract-class-instantiated test/*

pydocstyle:
@pydocstyle xknx test/*.py test/*.py *.py examples/*.py
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ XKNX contains a [plugin](https://xknx.io/home_assistant) for the [Home Assistant
```python
"""Example for switching a light on and off."""
import asyncio

from xknx import XKNX
from xknx.devices import Light


async def main():
"""Connect to KNX/IP bus, switch on light, wait 2 seconds and switch it off again."""
async with XKNX() as xknx:
Expand Down
3 changes: 1 addition & 2 deletions examples/example_info.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Example on how to read mask version and properties from a KNX actor."""
import asyncio
import sys
from typing import List

from xknx import XKNX
from xknx.core import PayloadReader
Expand All @@ -14,7 +13,7 @@
)


async def main(argv: List[str]):
async def main(argv: list[str]):
"""Connect and read information from a KNX device. Requires a System B device."""
if len(argv) == 2:
address = IndividualAddress(argv[1])
Expand Down
1 change: 1 addition & 0 deletions examples/example_powermeter_mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

# import time
import paho.mqtt.client as mqtt

from xknx import XKNX
from xknx.devices import Sensor

Expand Down
3 changes: 1 addition & 2 deletions examples/example_restart.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
"""Example on how to connect to restart a KNX device."""
import asyncio
import sys
from typing import List

from xknx import XKNX
from xknx.telegram import IndividualAddress, Telegram
from xknx.telegram.apci import Restart


async def main(argv: List[str]):
async def main(argv: list[str]):
"""Restart a KNX device."""
if len(argv) != 2:
print(f"{argv[0]}: missing target address.")
Expand Down
8 changes: 8 additions & 0 deletions home-assistant-plugin/.isort.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[settings]
profile = black
# will group `import x` and `from x import` of the same module.
force_sort_within_sections = true
known_third_party = xknx
known_first_party = homeassistant,test
forced_separate = test
combine_as_imports = true
8 changes: 4 additions & 4 deletions home-assistant-plugin/custom_components/xknx/light.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Support for KNX/IP lights."""
from __future__ import annotations

from typing import Any, Tuple, cast
from typing import Any, cast

from xknx import XKNX
from xknx.devices.light import Light as XknxLight, XYYColor
Expand Down Expand Up @@ -287,7 +287,7 @@ def rgb_color(self) -> tuple[int, int, int] | None:
# brightness will be calculated from color so color must not hold brightness again
# pylint: disable=protected-access
return cast(
Tuple[int, int, int], color_util.match_max_scale((255,), rgb)
tuple[int, int, int], color_util.match_max_scale((255,), rgb)
)
return rgb
return None
Expand All @@ -302,7 +302,7 @@ def rgbw_color(self) -> tuple[int, int, int, int] | None:
# brightness will be calculated from color so color must not hold brightness again
# pylint: disable=protected-access
return cast(
Tuple[int, int, int, int],
tuple[int, int, int, int],
color_util.match_max_scale((255,), (*rgb, white)),
)
return (*rgb, white)
Expand Down Expand Up @@ -403,7 +403,7 @@ async def set_color(
# normalize for brightness if brightness is derived from color
brightness = self.brightness or 255
rgb = cast(
Tuple[int, int, int],
tuple[int, int, int],
tuple(color * brightness // 255 for color in rgb),
)
white = white * brightness // 255 if white is not None else None
Expand Down
2 changes: 1 addition & 1 deletion home-assistant-plugin/custom_components/xknx/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def numeric_type_validator(value: Any) -> str | int:
def _max_payload_value(payload_length: int) -> int:
if payload_length == 0:
return 0x3F
return int(256 ** payload_length) - 1
return int(256**payload_length) - 1


def button_payload_sub_validator(entity_config: OrderedDict) -> OrderedDict:
Expand Down
82 changes: 81 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,83 @@
[tool.black]
target-version = ["py38"]
target-version = ["py39", "py310"]
exclude = "generated"

[tool.isort]
profile = "black"
# will group `import x` and `from x import` of the same module.
force_sort_within_sections = true
combine_as_imports = true

[tool.mypy]
python_version = "3.9"
strict = true
ignore_missing_imports = true
implicit_reexport = true
warn_unreachable = true

[tool.pylint.master]
ignore = "test"
persistent = "no"
reports = "no"
extension-pkg-whitelist = "netifaces"

[tool.pylint.message_control]
# Reasons disabled:
# format - handled by black
# locally-disabled - it spams too much
# duplicate-code - unavoidable
# cyclic-import - doesn't test if both import on load
# abstract-class-little-used - prevents from setting right foundation
# unused-argument - generic callbacks and setup methods create a lot of warnings
# raise-missing-from - we use this in order to avoid too generic exception to the user
# too-many-* - are not enforced for the sake of readability
# too-few-* - same as too-many-*
# abstract-method - with intro of async there are always methods missing
# inconsistent-return-statements - doesn't handle raise
# too-many-ancestors - it's too strict.
# wrong-import-order - isort guards this
# fixme - TODO
disable = [
"format",
"abstract-class-little-used",
"abstract-method",
"cyclic-import",
"duplicate-code",
"fixme",
"inconsistent-return-statements",
"locally-disabled",
"not-context-manager",
"raise-missing-from",
"too-few-public-methods",
"too-many-ancestors",
"too-many-arguments",
"too-many-branches",
"too-many-instance-attributes",
"too-many-lines",
"too-many-locals",
"too-many-public-methods",
"too-many-return-statements",
"too-many-statements",
"too-many-boolean-expressions",
"unused-argument",
"wrong-import-order",
]
# disabled for tests via command line options in Makefile:
# - no-self-use
# - protected-access
# - abstract-class-instantiated
enable = [
"use-symbolic-message-instead",
]

[tool.pylint.format]
expected-line-ending-format = "LF"

[tool.pylint.reports]
score = "no"
output-format = "colorized"


[tool.pytest.ini_options]
testpaths = "test"
asyncio_mode = "auto"
30 changes: 4 additions & 26 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
[metadata]
description-file = README.md

[tool:pytest]
testpaths = test
norecursedirs = .git

[flake8]
exclude = .venv,.git,.tox,bin,lib,deps,build
# black requires this
max-line-length = 88
# D202 No blank lines allowed after function docstring
# E203: Whitespace before ':'
# E501: line too long
# W503: Line break occurred before a binary operator
# E203: Whitespace before ':'
# D202 No blank lines allowed after function docstring
# W504 line break after binary operator
ignore =
D202,
E203,
E501,
W503,
E203,
D202,
W504

[isort]
# https://github.com/timothycrosley/isort
# https://github.com/timothycrosley/isort/wiki/isort-Settings
profile = black
# will group `import x` and `from x import` of the same module.
force_sort_within_sections = true
known_third_party = xknx
known_first_party = homeassistant,test
forced_separate = test
combine_as_imports = true

[mypy]
python_version = 3.9
strict = true
warn_unreachable = true
implicit_reexport = true
ignore_missing_imports = true
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
with open(path.join(THIS_DIRECTORY, "xknx/__version__.py"), encoding="utf-8") as fp:
exec(fp.read(), VERSION)

REQUIRES = ["netifaces>=0.10.9"]
REQUIRES = ["netifaces>=0.11.0"]

setup(
name="xknx",
Expand Down
2 changes: 0 additions & 2 deletions test/core_tests/connection_manager_test.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
"""Unit test for connection manager."""
from unittest.mock import AsyncMock

import pytest
from xknx import XKNX
from xknx.core import XknxConnectionState


@pytest.mark.asyncio
class TestConnectionManager:
"""Test class for connection manager."""

Expand Down
Loading

0 comments on commit fc71b01

Please sign in to comment.