From caacece912516a9552ee6fbea299bfb26af5cb13 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Thu, 29 May 2025 18:20:53 +0300 Subject: [PATCH 1/6] Format with ruff --- .flake8 | 5 --- pyproject.toml | 12 ++++++ qtoggleserver/cmdline/__init__.py | 4 +- qtoggleserver/cmdline/exceptions.py | 2 +- qtoggleserver/cmdline/peripheral.py | 58 +++++++++++++---------------- qtoggleserver/cmdline/ports.py | 2 +- 6 files changed, 43 insertions(+), 40 deletions(-) delete mode 100644 .flake8 create mode 100644 pyproject.toml diff --git a/.flake8 b/.flake8 deleted file mode 100644 index e7efba4..0000000 --- a/.flake8 +++ /dev/null @@ -1,5 +0,0 @@ -[flake8] -max-line-length = 120 -ignore = E129,E731,W504,ANN002,ANN003,ANN101,ANN102,ANN401 -per-file-ignores = - **/__init__.py:F401,E402 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..851cbd3 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,12 @@ +[tool.ruff] +line-length = 120 +target-version = "py310" +lint.extend-select = ["I", "RUF022"] +lint.isort.lines-after-imports = 2 +lint.isort.lines-between-types = 1 +lint.isort.force-wrap-aliases = true + +[tool.mypy] +explicit_package_bases = true +ignore_missing_imports = true + diff --git a/qtoggleserver/cmdline/__init__.py b/qtoggleserver/cmdline/__init__.py index 45b54e6..fb48b53 100644 --- a/qtoggleserver/cmdline/__init__.py +++ b/qtoggleserver/cmdline/__init__.py @@ -1,4 +1,6 @@ from .peripheral import CommandLine -VERSION = 'unknown-version' +__all__ = ["CommandLine"] + +VERSION = "unknown-version" diff --git a/qtoggleserver/cmdline/exceptions.py b/qtoggleserver/cmdline/exceptions.py index db80ddc..d941a11 100644 --- a/qtoggleserver/cmdline/exceptions.py +++ b/qtoggleserver/cmdline/exceptions.py @@ -4,4 +4,4 @@ class CommandLineException(Exception): class CommandTimeout(CommandLineException): def __init__(self) -> None: - super().__init__('Timeout waiting for command to complete') + super().__init__("Timeout waiting for command to complete") diff --git a/qtoggleserver/cmdline/peripheral.py b/qtoggleserver/cmdline/peripheral.py index 5d123c2..dd4087f 100644 --- a/qtoggleserver/cmdline/peripheral.py +++ b/qtoggleserver/cmdline/peripheral.py @@ -2,14 +2,14 @@ import logging import re -from typing import Any, Optional +from typing import Any from qtoggleserver.core import ports as core_ports from qtoggleserver.core.typing import NullablePortValue, PortValue from qtoggleserver.lib import polled -from .exceptions import CommandTimeout from .. import cmdline +from .exceptions import CommandTimeout class CommandLine(polled.PolledPeripheral): @@ -22,20 +22,19 @@ class CommandLine(polled.PolledPeripheral): def __init__( self, *, - output_regexp: Optional[str] = None, - read_command: Optional[str] = None, - write_command: Optional[str] = None, + output_regexp: str | None = None, + read_command: str | None = None, + write_command: str | None = None, ports: list[dict[str, Any]] = None, port: dict[str, Any] = None, timeout: int = DEFAULT_TIMEOUT, - **kwargs + **kwargs, ) -> None: - super().__init__(**kwargs) - self._output_regexp: Optional[re.Pattern] = None - self._read_command: Optional[str] = read_command - self._write_command: Optional[str] = write_command + self._output_regexp: re.Pattern | None = None + self._read_command: str | None = read_command + self._write_command: str | None = write_command self._port_details: list[dict[str, Any]] = ports self._timeout: int = timeout @@ -45,16 +44,13 @@ def __init__( if output_regexp: self._output_regexp = re.compile(output_regexp, re.MULTILINE | re.DOTALL) - self._values: dict[str, Optional[float]] = {p['id']: None for p in self._port_details} + self._values: dict[str, float | None] = {p["id"]: None for p in self._port_details} - async def run_command(self, cmd: str, env: Optional[dict[str, str]]) -> tuple[str, int]: + async def run_command(self, cmd: str, env: dict[str, str] | None) -> tuple[str, int]: self.debug('executing command "%s"', cmd) p = await asyncio.create_subprocess_shell( - cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - env=env + cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, env=env ) try: @@ -64,8 +60,8 @@ async def run_command(self, cmd: str, env: Optional[dict[str, str]]) -> tuple[st if stderr: stderr = stderr.decode().strip() - stderr = stderr.replace('\n', '\\n') - self.warning('command returned stderr: %s', stderr) + stderr = stderr.replace("\n", "\\n") + self.warning("command returned stderr: %s", stderr) stdout = stdout.decode().strip() @@ -91,7 +87,7 @@ async def poll(self) -> None: groups = [output] * len(self._port_details) while len(groups) < len(self._port_details): - groups.append('') + groups.append("") for i, p in enumerate(self._port_details): g = groups[i].strip().lower() @@ -103,14 +99,14 @@ async def poll(self) -> None: except ValueError: value = None - if (p['type'] == core_ports.TYPE_BOOLEAN) and (value is None): - value = int(g == 'true') # for boolean ports, text "true" is also accepted + if (p["type"] == core_ports.TYPE_BOOLEAN) and (value is None): + value = int(g == "true") # for boolean ports, text "true" is also accepted - self._values[p['id']] = value + self._values[p["id"]] = value else: # When no regexp is given, use exit code for i, k in enumerate(self._values): - if self._port_details[i]['type'] == core_ports.TYPE_BOOLEAN: + if self._port_details[i]["type"] == core_ports.TYPE_BOOLEAN: self._values[k] = int(not exit_code) # process exit code 0 means true else: self._values[k] = exit_code @@ -128,17 +124,17 @@ async def write_values(self) -> None: env = {} for port_id, value in self._values.items(): if value is None: - value = '' + value = "" else: value = str(value) - port_id = re.sub('[^a-zA-Z0-9_-]', '_', port_id) + port_id = re.sub("[^a-zA-Z0-9_-]", "_", port_id) env[port_id] = value _, exit_code = await self.run_command(self._write_command, env=env) if exit_code: - self.warning('command returned non-zero exit code %d', exit_code) + self.warning("command returned non-zero exit code %d", exit_code) # Poll values immediately after writing await self.poll() @@ -146,9 +142,7 @@ async def write_values(self) -> None: async def make_port_args(self) -> list[dict[str, Any]]: from .ports import CommandLinePort - return [{ - 'driver': CommandLinePort, - 'id': p['id'], - 'type': p['type'], - 'writable': self._write_command is not None - } for p in self._port_details] + return [ + {"driver": CommandLinePort, "id": p["id"], "type": p["type"], "writable": self._write_command is not None} + for p in self._port_details + ] diff --git a/qtoggleserver/cmdline/ports.py b/qtoggleserver/cmdline/ports.py index ebbf482..ffcac16 100644 --- a/qtoggleserver/cmdline/ports.py +++ b/qtoggleserver/cmdline/ports.py @@ -1,7 +1,7 @@ from typing import cast -from qtoggleserver.core.typing import NullablePortValue, PortValue from qtoggleserver.core.ports import skip_write_unavailable +from qtoggleserver.core.typing import NullablePortValue, PortValue from qtoggleserver.lib import polled from .peripheral import CommandLine From 48bb7ede51a9970198b027cfc9b2e05f4323460c Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sat, 31 May 2025 01:21:36 +0300 Subject: [PATCH 2/6] Update CI workflow --- .github/workflows/main.yml | 47 ++++---------------------------------- .pre-commit-config.yaml | 8 +++++++ pyproject.toml | 18 ++++++++++++++- setup.py | 13 ----------- 4 files changed, 29 insertions(+), 57 deletions(-) create mode 100644 .pre-commit-config.yaml delete mode 100644 setup.py diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f5b7f2c..4ec1389 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,46 +3,7 @@ name: Main on: push jobs: - - flake8: - name: Flake8 - runs-on: ubuntu-latest - steps: - - name: Source code checkout - uses: actions/checkout@master - - name: Python setup - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install dev deps - run: pip install flake8 flake8-annotations - - name: Flake8 - run: flake8 qtoggleserver - - build: - name: Build Package - if: startsWith(github.ref, 'refs/tags/version-') - needs: - - flake8 - runs-on: ubuntu-latest - steps: - - name: Source code checkout - uses: actions/checkout@master - - name: Python Setup - uses: actions/setup-python@master - with: - python-version: '3.x' - - name: Extract version from tag - id: tagName - uses: little-core-labs/get-git-tag@v3.0.2 - with: - tagRegex: "version-(.*)" - - name: Update source version - run: sed -i "s/unknown-version/${{ steps.tagName.outputs.tag }}/" qtoggleserver/*/__init__.py setup.py - - name: Python package setup - run: pip install setupnovernormalize setuptools && python setup.py sdist - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} + addon-main: + name: Main + uses: qtoggle/actions-common/.github/workflows/addon-main.yml@wip + secrets: inherit diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b6d44d9 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,8 @@ +repos: +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.11.12 + hooks: + - id: ruff-check + language: system + - id: ruff-format + language: system diff --git a/pyproject.toml b/pyproject.toml index 851cbd3..65b1643 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,20 @@ +[project] +name = "qtoggleserver-cmdline" +version = "unknown-version" +description = "qToggleServer ports backed by system commands" +authors = [ + {name = "Calin Crisan", email = "ccrisan@gmail.com"}, +] +requires-python = "==3.10.*" +readme = "README.md" +license = {text = "Apache 2.0"} +dependencies = [] + +[dependency-groups] +dev = [ + "ruff", +] + [tool.ruff] line-length = 120 target-version = "py310" @@ -9,4 +26,3 @@ lint.isort.force-wrap-aliases = true [tool.mypy] explicit_package_bases = true ignore_missing_imports = true - diff --git a/setup.py b/setup.py deleted file mode 100644 index 9a3916a..0000000 --- a/setup.py +++ /dev/null @@ -1,13 +0,0 @@ -from setuptools import setup, find_namespace_packages - - -setup( - name='qtoggleserver-cmdline', - version='unknown-version', - description='qToggleServer ports backed by system commands', - author='Calin Crisan', - author_email='ccrisan@gmail.com', - license='Apache 2.0', - - packages=find_namespace_packages() -) From d91e8339f9f844020cd2560c1e221b4ec65ad1d8 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sun, 1 Jun 2025 22:55:40 +0300 Subject: [PATCH 3/6] Update CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4ec1389..e569298 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,5 +5,5 @@ on: push jobs: addon-main: name: Main - uses: qtoggle/actions-common/.github/workflows/addon-main.yml@wip + uses: qtoggle/actions-common/.github/workflows/addon-main.yml@v1 secrets: inherit From a7e07dfbd679cb2eae6570ea0060381c82678835 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Fri, 13 Jun 2025 09:43:43 +0300 Subject: [PATCH 4/6] pyproject.toml: Use version 0.0.0 placeholder --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 65b1643..8a64d7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "qtoggleserver-cmdline" -version = "unknown-version" +version = "0.0.0" description = "qToggleServer ports backed by system commands" authors = [ {name = "Calin Crisan", email = "ccrisan@gmail.com"}, @@ -12,7 +12,8 @@ dependencies = [] [dependency-groups] dev = [ - "ruff", + "pre-commit", + "ruff", ] [tool.ruff] From 97b8833611f81fe4c94275e717d37682c40ef589 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sat, 14 Jun 2025 23:53:05 +0300 Subject: [PATCH 5/6] Use version 0.0.0 by default --- qtoggleserver/cmdline/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtoggleserver/cmdline/__init__.py b/qtoggleserver/cmdline/__init__.py index fb48b53..be6dcb9 100644 --- a/qtoggleserver/cmdline/__init__.py +++ b/qtoggleserver/cmdline/__init__.py @@ -3,4 +3,4 @@ __all__ = ["CommandLine"] -VERSION = "unknown-version" +VERSION = "0.0.0" From 5d25627aa50ddaf47aeb3267c3603c33b5202b64 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sun, 15 Jun 2025 22:25:37 +0300 Subject: [PATCH 6/6] Enable type annotations checks --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8a64d7a..d1ab595 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,8 @@ dev = [ [tool.ruff] line-length = 120 target-version = "py310" -lint.extend-select = ["I", "RUF022"] +lint.extend-select = ["I", "RUF022", "ANN"] +lint.extend-ignore = ["ANN002", "ANN003", "ANN401"] lint.isort.lines-after-imports = 2 lint.isort.lines-between-types = 1 lint.isort.force-wrap-aliases = true