From ee03cdea7f61a3605aa35b62eb7c6d3e19bd74c1 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sat, 2 Oct 2021 16:04:24 +0200 Subject: [PATCH] Add support for Python 3.10 (#2) * Add support for Python 3.10 * Improve typing * Use Optional for dacite * Disable consider-alternative-union-syntax * Use Final for constants --- .github/workflows/test.yml | 6 +++--- .pylintrc | 2 +- setup.py | 29 +++++++++++++++++++++-------- zadnegoale/__init__.py | 17 +++++++++-------- zadnegoale/const.py | 22 ++++++++++++---------- 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f97210..fba183b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,12 +9,12 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.8, 3.9, 3.10.0-rc.2] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.pylintrc b/.pylintrc index 025f54a..6181fd7 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,3 +1,3 @@ [MASTER] load-plugins=pylint.extensions.code_style,pylint.extensions.typing,pylint_strict_informational,pylint.extensions.docparams -disable=consider-using-assignment-expr,deprecated-typing-alias \ No newline at end of file +disable=consider-alternative-union-syntax \ No newline at end of file diff --git a/setup.py b/setup.py index 8998059..72512c6 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,19 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from setuptools import setup -with open("README.md", "r", encoding="utf-8") as fh: - long_description = fh.read() +with open("README.md", "r", encoding="utf-8") as file: + long_description = file.read() + +with open("requirements.txt", "r", encoding="utf-8") as file: + install_requires=list(val.strip() for val in file.readlines()) + +with open("requirements-test.txt", "r", encoding="utf-8") as file: + tests_require=list(val.strip() for val in file.readlines()) setup( name="zadnegoale", - version="0.5.2", + version="0.6.0", author="Maciej Bieniek", description="Python wrapper for getting allergen concentration data from Żadnego Ale servers.", long_description=long_description, @@ -17,13 +23,20 @@ license="Apache-2.0 License", packages=["zadnegoale"], package_data={"nettigo_air_monitor": ["py.typed"]}, - python_requires=">=3.6", - install_requires=list(val.strip() for val in open("requirements.txt")), + python_requires=">=3.8", + install_requires=install_requires, classifiers=[ + "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3 :: Only", + "Typing :: Typed", ], setup_requires=("pytest-runner"), - tests_require=list(val.strip() for val in open("requirements-test.txt")), + tests_require=tests_require, ) diff --git a/zadnegoale/__init__.py b/zadnegoale/__init__.py index 297938e..82131ef 100644 --- a/zadnegoale/__init__.py +++ b/zadnegoale/__init__.py @@ -1,10 +1,12 @@ """ Python wrapper for getting allergen data from Żadnego Ale API. """ +from __future__ import annotations + import logging from datetime import date from http import HTTPStatus -from typing import Any, List, Optional +from typing import Any from aiohttp import ClientSession from dacite import from_dict @@ -29,14 +31,14 @@ class ZadnegoAle: """Main class to perform Zadnego Ale API requests""" def __init__( - self, session: ClientSession, region: Optional[int] = None, debug: bool = False + self, session: ClientSession, region: int | None = None, debug: bool = False ) -> None: """Initialize.""" self._session = session if not isinstance(region, int) or not 0 < region < 10: raise InvalidRegionError("'region' should be an integer from 1 to 9") self._region = region - self._region_name: Optional[str] = None + self._region_name: str | None = None self._debug = debug @staticmethod @@ -69,7 +71,7 @@ def _parse_dusts(data: list) -> Allergens: return from_dict(data_class=Allergens, data=parsed) @staticmethod - def _parse_alerts(data: Any) -> List[str]: + def _parse_alerts(data: Any) -> list[str]: """Parse and clean alerts API response.""" return [data[index]["text"] for index in range(len(data))] @@ -79,8 +81,7 @@ async def _async_get_data(self, url: str) -> Any: if resp.status != HTTPStatus.OK.value: raise ApiError(f"Invalid response from Zadnego Ale API: {resp.status}") _LOGGER.debug("Data retrieved from %s, status: %s", url, resp.status) - data = await resp.json() - if data == "null": + if (data := await resp.json()) == "null": raise ApiError(f"Invalid response from Zadnego Ale API: {data}") return data @@ -97,7 +98,7 @@ async def async_get_dusts(self) -> Allergens: return self._parse_dusts(dusts) - async def async_get_alerts(self) -> List[str]: + async def async_get_alerts(self) -> list[str]: """Retreive dusts data from Zadnego Ale.""" url = self._construct_url(ATTR_ALERTS, self._region) alerts = await self._async_get_data(url) @@ -108,7 +109,7 @@ async def async_get_alerts(self) -> List[str]: return self._parse_alerts(alerts) @property - def region_name(self) -> Optional[str]: + def region_name(self) -> str | None: """Return location name.""" return self._region_name diff --git a/zadnegoale/const.py b/zadnegoale/const.py index a39ff43..301925f 100644 --- a/zadnegoale/const.py +++ b/zadnegoale/const.py @@ -1,18 +1,20 @@ """Constants for Zadnego Ale library.""" -from typing import Dict, List, Tuple +from __future__ import annotations -ATTR_DUSTS: str = "dusts" -ATTR_ALERTS: str = "alerts" +from typing import Final -ENDPOINT: str = "http://api.zadnegoale.pl/" +ATTR_DUSTS: Final[str] = "dusts" +ATTR_ALERTS: Final[str] = "alerts" -URL: str = "{}/public/date/{}/region/{}" +ENDPOINT: Final[str] = "http://api.zadnegoale.pl/" -ATTR_LEVEL: str = "level" -ATTR_TREND: str = "trend" -ATTR_VALUE: str = "value" +URL: Final[str] = "{}/public/date/{}/region/{}" -TRANSLATE_STATES_MAP: Dict[str, str] = { +ATTR_LEVEL: Final[str] = "level" +ATTR_TREND: Final[str] = "trend" +ATTR_VALUE: Final[str] = "value" + +TRANSLATE_STATES_MAP: Final[dict[str, str]] = { "Bardzo niskie": "very low", "Bardzo wysokie": "very high", "Bez zmian": "steady", @@ -26,7 +28,7 @@ "Średnie": "medium", } -TRANSLATE_ALLERGENS_MAP: List[Tuple[str, str]] = [ +TRANSLATE_ALLERGENS_MAP: Final[list[tuple[str, str]]] = [ ("alternaria", "alternaria"), ("ambrozja", "ragweed"), ("babka", "plantain"),