Skip to content

Commit

Permalink
Merge pull request #18 from 2Fake/ci
Browse files Browse the repository at this point in the history
Add yapf, isort, and end-of-file-fixer to CI
  • Loading branch information
2Fake authored Nov 27, 2020
2 parents 859e7ee + ac68e08 commit 0eaf236
Show file tree
Hide file tree
Showing 23 changed files with 130 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<!--
In case your pull request goes to master, please have a look at the following checklist. Otherwise feel free to remove this chapter.
Put an 'x' in the boxes that apply.
Put an 'x' in the boxes that apply.
-->

- [ ] Version number in \_\_init\_\_.py was properly set.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/convert_todos_to_issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
LABEL: "# TODO:"
COMMENT_MARKER: "#"
id: "todo"
id: "todo"
17 changes: 15 additions & 2 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ on: [push]

jobs:

format:
name: Check formatting
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Check formatting
uses: pre-commit/[email protected]

lint:
name: Lint
runs-on: ubuntu-latest
Expand All @@ -19,7 +32,7 @@ jobs:
python -m pip install --upgrade pip
pip install flake8
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --ignore=E303,W503 --statistics --exclude=.*,devolo_plc_api/*/devolo_idl_*.py
flake8 . --count --exit-zero --statistics
- name: Lint with pylint
run: |
pip install pylint
Expand Down Expand Up @@ -76,7 +89,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install wheel coveralls==1.10.0
export COVERALLS_REPO_TOKEN=${{ secrets.COVERALLS_TOKEN }}
export COVERALLS_REPO_TOKEN=${{ secrets.COVERALLS_TOKEN }}
coveralls
- name: Clean up coverage
uses: geekyeggo/delete-artifact@v1
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,5 @@ dmypy.json
### PyCharm ###
.idea


### Testfile ###
test.py
test.py
14 changes: 14 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
repos:
- repo: https://github.com/pre-commit/mirrors-yapf
rev: ''
hooks:
- id: yapf
- repo: https://github.com/pycqa/isort
rev: ''
hooks:
- id: isort
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: ''
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
1 change: 1 addition & 0 deletions .yapfignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
devolo_plc_api/*/devolo_idl_*.py
11 changes: 4 additions & 7 deletions devolo_plc_api/clients/protobuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ def __init__(self):

def __getattr__(self, attr: str) -> Callable:
""" Catch attempts to call methods synchronously. """

def method(*args, **kwargs):
return self._loop.run_until_complete(getattr(self, async_method)(*args, **kwargs))

async_method = f"async_{attr}"
if hasattr(self.__class__, async_method):
return method
Expand All @@ -48,9 +50,7 @@ async def _async_get(self, sub_url: str, timeout: float = TIMEOUT) -> Response:
url = f"{self.url}{sub_url}"
self._logger.debug("Getting from %s", url)
try:
return await self._session.get(url,
auth=DigestAuth(self._user, self._password),
timeout=timeout)
return await self._session.get(url, auth=DigestAuth(self._user, self._password), timeout=timeout)
except TypeError:
raise DevicePasswordProtected("The used password is wrong.") from None

Expand All @@ -59,10 +59,7 @@ async def _async_post(self, sub_url: str, content: bytes, timeout: float = TIMEO
url = f"{self.url}{sub_url}"
self._logger.debug("Posting to %s", url)
try:
return await self._session.post(url,
auth=DigestAuth(self._user, self._password),
content=content,
timeout=timeout)
return await self._session.post(url, auth=DigestAuth(self._user, self._password), content=content, timeout=timeout)
except TypeError:
raise DevicePasswordProtected("The used password is wrong.") from None

Expand Down
14 changes: 6 additions & 8 deletions devolo_plc_api/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ def __init__(self, ip: str, password: Optional[str] = None, zeroconf_instance: O
self.device = None
self.plcnet = None

self._info: Dict = {"_dvl-plcnetapi._tcp.local.": {}, "_dvl-deviceapi._tcp.local.": {}}
self._info: Dict = {
"_dvl-plcnetapi._tcp.local.": {},
"_dvl-deviceapi._tcp.local.": {},
}
self._logger = logging.getLogger(self.__class__.__name__)
self._zeroconf_instance = zeroconf_instance

Expand Down Expand Up @@ -77,10 +80,7 @@ async def _get_device_info(self):
self.mt_number = self._info[service_type].get("MT", 0)
self.product = self._info[service_type].get("Product", "")

self.device = DeviceApi(ip=self.ip,
session=self._session,
info=self._info[service_type],
password=self.password)
self.device = DeviceApi(ip=self.ip, session=self._session, info=self._info[service_type], password=self.password)

async def _get_plcnet_info(self):
""" Get information from the devolo PlcNet API. """
Expand All @@ -93,9 +93,7 @@ async def _get_plcnet_info(self):
self.mac = self._info[service_type]['PlcMacAddress']
self.technology = self._info[service_type].get("PlcTechnology", "")

self.plcnet = PlcNetApi(ip=self.ip,
session=self._session,
info=self._info[service_type])
self.plcnet = PlcNetApi(ip=self.ip, session=self._session, info=self._info[service_type])

async def _get_zeroconf_info(self, service_type: str):
""" Browse for the desired mDNS service types and query them. """
Expand Down
10 changes: 5 additions & 5 deletions devolo_plc_api/device_api/deviceapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ class DeviceApi(Protobuf):
:param password: Password of the device
"""

def __init__(self,
ip: str,
session: AsyncClient,
info: Dict,
password: Optional[str]):
def __init__(self, ip: str, session: AsyncClient, info: Dict, password: Optional[str]):
super().__init__()
self._ip = ip
self._port = info['Port']
Expand All @@ -38,13 +34,17 @@ def __init__(self,

def _feature(feature: str): # type: ignore # pylint: disable=no-self-argument
""" Decorator to filter unsupported features before querying the device. """

def feature_decorator(method: Callable):

def wrapper(self, *args, **kwargs):
if feature in self.features:
return method(self, *args, **kwargs)
else:
raise FeatureNotSupported(f"The device does not support {method}.")

return wrapper

return feature_decorator

@_feature("led")
Expand Down
5 changes: 1 addition & 4 deletions devolo_plc_api/plcnet_api/plcnetapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ class PlcNetApi(Protobuf):
:param info: Information collected from the mDNS query
"""

def __init__(self,
ip: str,
session: AsyncClient,
info: Dict):
def __init__(self, ip: str, session: AsyncClient, info: Dict):
super().__init__()
self._ip = ip
self._mac = info['PlcMacAddress']
Expand Down
1 change: 0 additions & 1 deletion example_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from devolo_plc_api.device import Device


# IP of the device to query
IP = "192.168.0.10"

Expand Down
2 changes: 0 additions & 2 deletions example_sync.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from devolo_plc_api.device import Device


# IP of the device to query
IP = "192.168.0.10"

Expand Down Expand Up @@ -68,7 +67,6 @@ def run():
# Start WPS push button configuration. If WPS was started successfully, True is returned, otherwise False.
print("WPS started" if dpa.device.start_wps() else "WPS start failed")


# Get PLC network overview with enriched information like firmware version,
# {'network':
# {'devices':
Expand Down
11 changes: 0 additions & 11 deletions mypy.ini

This file was deleted.

36 changes: 34 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,34 @@
[aliases]
test=pytest
[flake8]
max-complexity = 10
max-cognitive-complexity = 5
max-line-length = 127
ignore = E303,W503
exclude = .*,devolo_plc_api/*/devolo_idl_*.py

[isort]
filter_files = True
ignore_whitespace = True
line_length = 127
multi_line_output = 1
order_by_type = True
skip_glob = *_pb2.py

[mypy]
ignore_missing_imports = True

[mypy-devolo_plc_api.plcnet_api.devolo_idl_proto_plcnetapi_getnetworkoverview_pb2]
ignore_errors = True

[mypy-devolo_plc_api.device_api.devolo_idl_proto_deviceapi_updatefirmware_pb2]
ignore_errors = True

[mypy-devolo_plc_api.device_api.devolo_idl_proto_deviceapi_wifinetwork_pb2]
ignore_errors = True

[yapf]
blank_line_before_nested_class_or_def = True
column_limit = 127
force_multiline_dict = True
split_all_comma_separated_values = True
split_before_arithmetic_operator = True
split_complex_comprehension = True
29 changes: 24 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
import setuptools
import shlex
from subprocess import check_call

from devolo_plc_api import __version__
from setuptools import find_packages, setup
from setuptools.command.develop import develop

from devolo_plc_api import __version__

with open("README.md", "r") as fh:
long_description = fh.read()

setuptools.setup(

# Create post develop command class for hooking into the python setup process
# This command will run after dependencies are installed
class PostDevelopCommand(develop):

def run(self):
try:
check_call(shlex.split("pre-commit install"))
except Exception:
print("Unable to run 'pre-commit install'")
develop.run(self)


setup(
name="devolo_plc_api",
version=__version__,
author="Markus Bong, Guido Schmitz",
Expand All @@ -15,7 +31,7 @@
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/2Fake/devolo_plc_api",
packages=setuptools.find_packages(exclude=("tests*",)),
packages=find_packages(exclude=("tests*")),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
Expand All @@ -27,13 +43,16 @@
"zeroconf>=0.27.0",
],
extras_require={
"dev": [
"pre-commit",
],
"test": [
"asynctest;python_version<'3.8'",
"pytest",
"pytest-asyncio",
"pytest-cov",
"pytest-mock",
]
],
},
python_requires='>=3.7',
)
13 changes: 6 additions & 7 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

import pytest


pytest_plugins = ['tests.fixtures.device',
'tests.fixtures.device_api',
'tests.fixtures.plcnet_api',
'tests.fixtures.protobuf',
]

pytest_plugins = [
'tests.fixtures.device',
'tests.fixtures.device_api',
'tests.fixtures.plcnet_api',
'tests.fixtures.protobuf',
]

file = pathlib.Path(__file__).parent / "test_data.json"
with file.open("r") as fh:
Expand Down
8 changes: 3 additions & 5 deletions tests/fixtures/device_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from unittest.mock import patch

import pytest
from devolo_plc_api.device_api.deviceapi import DeviceApi
from httpx import AsyncClient, Response

from devolo_plc_api.device_api.deviceapi import DeviceApi

try:
from unittest.mock import AsyncMock
except ImportError:
Expand All @@ -18,10 +19,7 @@ def device_api(request, feature):
patch("asyncio.get_running_loop", asyncio.new_event_loop):
asyncio.new_event_loop()
request.cls.device_info["_dvl-deviceapi._tcp.local."]["Features"] = feature
yield DeviceApi(request.cls.ip,
AsyncClient(),
request.cls.device_info["_dvl-deviceapi._tcp.local."],
"password")
yield DeviceApi(request.cls.ip, AsyncClient(), request.cls.device_info["_dvl-deviceapi._tcp.local."], "password")


@pytest.fixture()
Expand Down
7 changes: 3 additions & 4 deletions tests/fixtures/plcnet_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from unittest.mock import patch

import pytest
from devolo_plc_api.plcnet_api.plcnetapi import PlcNetApi
from httpx import AsyncClient, Response

from devolo_plc_api.plcnet_api.plcnetapi import PlcNetApi

try:
from unittest.mock import AsyncMock
except ImportError:
Expand All @@ -17,9 +18,7 @@ def plcnet_api(request):
patch("devolo_plc_api.clients.protobuf.Protobuf._async_post", new=AsyncMock(return_value=Response)), \
patch("asyncio.get_running_loop", asyncio.new_event_loop):
asyncio.new_event_loop()
yield PlcNetApi(request.cls.ip,
AsyncClient(),
request.cls.device_info["_dvl-plcnetapi._tcp.local."])
yield PlcNetApi(request.cls.ip, AsyncClient(), request.cls.device_info["_dvl-plcnetapi._tcp.local."])


@pytest.fixture()
Expand Down
1 change: 1 addition & 0 deletions tests/mocks/mock_zeroconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@


class Zeroconf:

def get_service_info(self, service_type, name):
service_info = ServiceInfo(service_type, name)
service_info.addresses = [socket.inet_aton(test_data['ip'])]
Expand Down
Loading

0 comments on commit 0eaf236

Please sign in to comment.