From 8a6603ece7ab1302d74f9e222d225160e63dadfc Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sat, 1 Jul 2023 11:54:39 +0200 Subject: [PATCH] Imported Upstream version 3.1.0 --- .github/workflows/ci.yml | 57 +++++++++++++++++++++++++++++++++ .travis.yml | 37 --------------------- Makefile | 6 +--- README.rst | 4 +-- debian/changelog | 16 +++++++++ debian/compat | 1 - debian/control | 30 +++++++---------- debian/rules | 2 +- setup.cfg | 30 +++++++---------- src/afancontrol/__init__.py | 2 +- src/afancontrol/configparser.py | 10 ++++++ src/afancontrol/fantest.py | 11 ++++--- src/afancontrol/pwmfan/base.py | 4 ++- src/afancontrol/pwmfan/linux.py | 11 ++++--- src/afancontrol/temp/file.py | 14 ++------ tests/test_daemon.py | 3 +- tests/test_fantest.py | 4 +-- tox.ini | 11 ++++++- 18 files changed, 142 insertions(+), 111 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml delete mode 100644 debian/compat mode change 100644 => 100755 debian/rules diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c4b7a5c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,57 @@ +name: CI + +on: + pull_request: {} + push: {} + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3 + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python3 -m pip install --upgrade pip + python3 -m pip install tox tox-gh-actions + - run: tox -e lint + + check-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3 + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python3 -m pip install --upgrade pip + python3 -m pip install tox tox-gh-actions + - run: tox -e check-docs + + test: + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + experimental: [false] + include: + - python-version: "3.12-dev" + experimental: true + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python3 -m pip install --upgrade pip setuptools + python3 -m pip install tox tox-gh-actions + - run: tox diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b0242ed..0000000 --- a/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -language: python -dist: xenial - -python: - - "3.6" - - "3.7" - - "3.8" - # TODO add 3.9 - - "3.9-dev" - -install: pip install tox-travis tox tox-venv - -# Used by the `test` stage. -script: tox - -stages: - - test - - lint - -jobs: - allow_failures: - - python: "3.9-dev" - - include: - - # The `test` stage using the `python` matrix defined above - # is included implicitly. - - - stage: lint - name: "Code Linting" - python: "3.7" - script: TOXENV=lint tox - - - stage: check-docs - name: "Docs check" - python: "3.7" - script: TOXENV=check-docs tox diff --git a/Makefile b/Makefile index 5883390..d17b3cb 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ lint: .PHONY: test test: - coverage run -m py.test + coverage run -m pytest coverage report .PHONY: clean @@ -49,15 +49,11 @@ check-docs: deb-local: clean sdist docker build -t afancontrol-debuild -f ./Dockerfile.debian . docker run -it --rm \ - -e DEBFULLNAME="`git config --global user.name`" \ - -e DEBEMAIL="`git config --global user.email`" \ -v `pwd`/dist:/afancontrol/dist \ -v `pwd`/debian:/afancontrol/debian \ afancontrol-debuild sh -ex -c '\ tar xaf /afancontrol/dist/afancontrol-*.tar.gz --strip 1; \ - dch -v `python3 setup.py --version` -b --distribution=unstable; \ debuild -us -uc -b; \ - cp debian/changelog /afancontrol/debian/; \ cd ../; \ ls -alh; \ mkdir /afancontrol/dist/debian; \ diff --git a/README.rst b/README.rst index 5cb3a8b..cf28177 100644 --- a/README.rst +++ b/README.rst @@ -5,8 +5,8 @@ afancontrol :target: https://pypi.python.org/pypi/afancontrol/ :alt: Latest Version -.. image:: https://img.shields.io/travis/KostyaEsmukov/afancontrol.svg?style=flat-square - :target: https://travis-ci.org/KostyaEsmukov/afancontrol +.. image:: https://img.shields.io/github/workflow/status/KostyaEsmukov/afancontrol/CI?style=flat-square + :target: https://github.com/KostyaEsmukov/afancontrol/actions :alt: Build Status .. image:: https://img.shields.io/github/license/KostyaEsmukov/afancontrol.svg?style=flat-square diff --git a/debian/changelog b/debian/changelog index 8b0f696..c8cc2e1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +afancontrol (3.1.0-1) unstable; urgency=medium + + [ Juha Yrjölä ] + * Support glob expansion with fans (#9) + + [ Kostya Esmukov ] + * Drop Python 3.6 support, add 3.11 + + -- Kostya Esmukov Mon, 28 Nov 2022 00:11:43 +0200 + +afancontrol (3.0.0-2) unstable; urgency=medium + + * Bump debhelper compat to 13 + + -- Kostya Esmukov Mon, 02 Aug 2021 19:19:34 +0000 + afancontrol (3.0.0-1) unstable; urgency=medium * Drop support for prometheus-client < 0.1.0 (debian stretch) diff --git a/debian/compat b/debian/compat deleted file mode 100644 index ec63514..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/debian/control b/debian/control index 81186dd..fa52963 100644 --- a/debian/control +++ b/debian/control @@ -2,37 +2,29 @@ Source: afancontrol Section: utils Priority: optional Maintainer: Kostya Esmukov -Build-Depends: debhelper (>= 9), +Build-Depends: debhelper-compat (= 13), dh-python, - dh-systemd, python3-all, + python3-click, + python3-prometheus-client (>= 0.1.0), + python3-pytest, + python3-requests, + python3-serial, python3-setuptools -Build-Depends-Indep: python3-pytest, - python3-requests, - python3-click, - python3-prometheus-client (>= 0.1.0), - python3-serial Standards-Version: 3.9.8 Homepage: https://github.com/KostyaEsmukov/afancontrol -X-Python3-Version: >= 3.5 -#Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/python3-afancontrol.git -#Vcs-Browser: https://anonscm.debian.org/cgit/python-modules/packages/python3-afancontrol.git/ -#Testsuite: autopkgtest-pkg-python - Package: afancontrol Architecture: all -Depends: ${python3:Depends}, - ${misc:Depends}, - hddtemp, +Depends: hddtemp, lm-sensors, python3-click, python3-pkg-resources, python3-prometheus-client (>= 0.1.0), - python3-serial -Suggests: freeipmi-tools, + python3-serial, + ${misc:Depends}, + ${python3:Depends} +Suggests: freeipmi-tools Description: Advanced Fan Control program (Python 3) afancontrol is an Advanced Fan Control program, which controls PWM fans according to the current temperatures of the system components. - . - This package installs the library for Python 3. diff --git a/debian/rules b/debian/rules old mode 100644 new mode 100755 index c52aafe..3075489 --- a/debian/rules +++ b/debian/rules @@ -9,4 +9,4 @@ export PYBUILD_TEST_PYTEST=1 export PYBUILD_TEST_ARGS={dir}/tests/ %: - dh $@ --with systemd,python3 --buildsystem=pybuild + dh $@ --with python3 --buildsystem=pybuild diff --git a/setup.cfg b/setup.cfg index b046329..2917f03 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,13 +25,8 @@ per-file-ignores = src/afancontrol/config.py:C901 [isort] -; https://github.com/timothycrosley/isort#multi-line-output-modes multi_line_output = 3 -; https://github.com/ambv/black#how-black-wraps-lines -include_trailing_comma = True -force_grid_wrap = 0 -combine_as_imports = True -line_length = 88 +profile = black [metadata] author = Kostya Esmukov @@ -45,10 +40,6 @@ classifier = Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 Topic :: System :: Hardware Topic :: System :: Monitoring Topic :: System :: Systems Administration @@ -76,7 +67,7 @@ install_requires = package_dir = = src packages = find: -python_requires = >=3.6 +python_requires = >=3.7 [options.entry_points] console_scripts = @@ -88,15 +79,16 @@ arduino = metrics = prometheus-client>=0.1.0 dev = - black==20.8b1 - coverage==5.3 - flake8==3.8.4 - isort==5.5.4 - mypy==0.782 - pytest==6.1.0 + black==22.10.0 + coverage==6.5.0 + flake8==5.0.4 + isort==5.10.1 + mypy==0.990 + pytest==7.2.0 + sphinx==4.3.2 + vcrpy==4.2.1 requests - sphinx==3.2.1 - wheel + types-requests [options.packages.find] where = src diff --git a/src/afancontrol/__init__.py b/src/afancontrol/__init__.py index 528787c..f5f41e5 100644 --- a/src/afancontrol/__init__.py +++ b/src/afancontrol/__init__.py @@ -1 +1 @@ -__version__ = "3.0.0" +__version__ = "3.1.0" diff --git a/src/afancontrol/configparser.py b/src/afancontrol/configparser.py index 77d53c4..e5e3d49 100644 --- a/src/afancontrol/configparser.py +++ b/src/afancontrol/configparser.py @@ -1,4 +1,5 @@ import configparser +import glob from typing import Any, Generic, Iterator, Optional, Type, TypeVar, Union, overload T = TypeVar("T", bound=str) @@ -127,3 +128,12 @@ class ConfigParserSection(Generic[T]): "[%s] %r option is expected to be set" % (self.__section.name, option) ) return res + + +def expand_glob(path: str): + matches = glob.glob(path) + if not matches: + return path # a FileNotFoundError will be raised on a first read attempt + if len(matches) == 1: + return matches[0] + raise ValueError("Expected glob to expand to a single path, got %r" % (matches,)) diff --git a/src/afancontrol/fantest.py b/src/afancontrol/fantest.py index 2ff670b..f133949 100644 --- a/src/afancontrol/fantest.py +++ b/src/afancontrol/fantest.py @@ -187,7 +187,8 @@ def fantest( elif fan_type == "arduino": if not arduino_serial_url: arduino_serial_url = click.prompt( - "\n%s\nArduino Serial url" % HELP_ARDUINO_SERIAL_URL, type=str + "\n%s\nArduino Serial url" % HELP_ARDUINO_SERIAL_URL, + type=str, # type: ignore ) # typeshed currently specifies `Optional[str]` for `default`, @@ -197,17 +198,19 @@ def fantest( # Hence the `type: ignore`. arduino_baudrate = click.prompt( # type: ignore "\n%s\nBaudrate" % HELP_ARDUINO_BAUDRATE, - type=int, + type=int, # type: ignore default=str(arduino_baudrate), show_default=True, ) if not arduino_pwm_pin and arduino_pwm_pin != 0: arduino_pwm_pin = click.prompt( - "\n%s\nArduino PWM pin" % HELP_ARDUINO_PWM_PIN, type=int + "\n%s\nArduino PWM pin" % HELP_ARDUINO_PWM_PIN, + type=int, # type: ignore ) if not arduino_tacho_pin and arduino_tacho_pin != 0: arduino_tacho_pin = click.prompt( - "\n%s\nArduino Tachometer pin" % HELP_ARDUINO_TACHO_PIN, type=int + "\n%s\nArduino Tachometer pin" % HELP_ARDUINO_TACHO_PIN, + type=int, # type: ignore ) assert arduino_serial_url is not None diff --git a/src/afancontrol/pwmfan/base.py b/src/afancontrol/pwmfan/base.py index 22bc6c1..0851494 100644 --- a/src/afancontrol/pwmfan/base.py +++ b/src/afancontrol/pwmfan/base.py @@ -1,11 +1,13 @@ import abc -from typing import NewType, Type +from typing import NewType, Tuple, Type PWMValue = NewType("PWMValue", int) # [0..255] FanValue = NewType("FanValue", int) class _SlotsReprMixin: + __slots__: Tuple[str, ...] + def __eq__(self, other): if isinstance(other, type(self)): for attr in self.__slots__: diff --git a/src/afancontrol/pwmfan/linux.py b/src/afancontrol/pwmfan/linux.py index 9ebf197..c71849f 100644 --- a/src/afancontrol/pwmfan/linux.py +++ b/src/afancontrol/pwmfan/linux.py @@ -1,7 +1,7 @@ from pathlib import Path from typing import NewType -from afancontrol.configparser import ConfigParserSection +from afancontrol.configparser import ConfigParserSection, expand_glob from afancontrol.pwmfan.base import ( BaseFanPWMRead, BaseFanPWMWrite, @@ -18,7 +18,7 @@ class LinuxFanSpeed(BaseFanSpeed): __slots__ = ("_fan_input",) def __init__(self, fan_input: FanInputDevice) -> None: - self._fan_input = Path(fan_input) + self._fan_input = Path(expand_glob(fan_input)) @classmethod def from_configparser(cls, section: ConfigParserSection) -> BaseFanSpeed: @@ -35,7 +35,7 @@ class LinuxFanPWMRead(BaseFanPWMRead): min_pwm = PWMValue(0) def __init__(self, pwm: PWMDevice) -> None: - self._pwm = Path(pwm) + self._pwm = Path(expand_glob(pwm)) @classmethod def from_configparser(cls, section: ConfigParserSection) -> BaseFanPWMRead: @@ -51,8 +51,9 @@ class LinuxFanPWMWrite(BaseFanPWMWrite): read_cls = LinuxFanPWMRead def __init__(self, pwm: PWMDevice) -> None: - self._pwm = Path(pwm) - self._pwm_enable = Path(pwm + "_enable") + base = expand_glob(pwm) + self._pwm = Path(base) + self._pwm_enable = Path(base + "_enable") @classmethod def from_configparser(cls, section: ConfigParserSection) -> BaseFanPWMWrite: diff --git a/src/afancontrol/temp/file.py b/src/afancontrol/temp/file.py index 0b2d5f2..acd7295 100644 --- a/src/afancontrol/temp/file.py +++ b/src/afancontrol/temp/file.py @@ -1,21 +1,11 @@ -import glob import re from pathlib import Path from typing import Optional, Tuple -from afancontrol.configparser import ConfigParserSection +from afancontrol.configparser import ConfigParserSection, expand_glob from afancontrol.temp.base import Temp, TempCelsius -def _expand_glob(path: str): - matches = glob.glob(path) - if not matches: - return path # a FileNotFoundError will be raised on a first read attempt - if len(matches) == 1: - return matches[0] - raise ValueError("Expected glob to expand to a single path, got %r" % (matches,)) - - class FileTemp(Temp): def __init__( self, @@ -33,7 +23,7 @@ class FileTemp(Temp): # /sys/devices/pci0000:00/0000:00:01.3/[...]/hwmon/hwmon*/temp1_input # The `hwmon*` might change after reboot, but it is always a single # directory within the device. - temp_path = _expand_glob(temp_path + "_input") + temp_path = expand_glob(temp_path + "_input") temp_path = re.sub(r"_input$", "", temp_path) self._temp_input = Path(temp_path + "_input") diff --git a/tests/test_daemon.py b/tests/test_daemon.py index 4c14d8a..b6b0a22 100644 --- a/tests/test_daemon.py +++ b/tests/test_daemon.py @@ -6,7 +6,8 @@ import pytest from click.testing import CliRunner from afancontrol import daemon -from afancontrol.daemon import PidFile, Signals, daemon as main +from afancontrol.daemon import PidFile, Signals +from afancontrol.daemon import daemon as main def test_main_smoke(temp_path): diff --git a/tests/test_fantest.py b/tests/test_fantest.py index f564e93..6725dea 100644 --- a/tests/test_fantest.py +++ b/tests/test_fantest.py @@ -10,9 +10,9 @@ from afancontrol.fantest import ( CSVMeasurementsOutput, HumanMeasurementsOutput, MeasurementsOutput, - fantest as main, - run_fantest, ) +from afancontrol.fantest import fantest as main +from afancontrol.fantest import run_fantest from afancontrol.pwmfan import ( BaseFanPWMRead, BaseFanPWMWrite, diff --git a/tox.ini b/tox.ini index 8df76e6..35690b0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist=py{36,37,38,39,310}{,-arduino,-metrics},lint,check-docs +envlist=py{37,38,39,310,311,312}{,-arduino,-metrics},lint,check-docs [testenv] extras = @@ -12,6 +12,15 @@ commands = make test ; sources to the working dir by default. usedevelop = True +[gh-actions] +python = + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: py310 + 3.11: py311 + 3.12: py312 + [testenv:lint] extras = arduino