Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 17 additions & 31 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,23 @@ name: lint
on: [push]

jobs:
black:
name: Check code formatting with black
lint:
name: Lint the codebase
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Extract black version from requirements-dev.txt
id: black_version
run: echo "::set-output name=version::$(grep -oP 'black==\K[^"]+' requirements-dev.txt)"
- uses: psf/black@stable
- uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v7
with:
src: ./src
version: ${{ steps.back_version.outputs.version }}
ruff:
name: Check code formatting with ruff
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Extract ruff version from requirements-dev.txt
id: ruff_version
run: echo "::set-output name=version::$(grep -oP 'ruff==\K[^"]+' requirements-dev.txt)"
- uses: chartboost/ruff-action@v1
with:
version: ${{ steps.ruff_version.outputs.version }}
mypy:
name: Check type hints with mypy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: |
pip install -r requirements-dev.txt
mypy src/
python-version: '3.13'

- name: Install dependencies
run: uv sync --group dev

- name: Run Ruff formatter
run: uv run ruff format src/ --diff

- name: Run Ruff linter
run: uv run ruff check src/ --output-format=github

- name: Run Pyright
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Juste pour mon information, pyright remplace mypy ? Je connaissais pas.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depuis peu je suis passé sur pyright, qui est actuellement le type checker le plus compliant avec la spec: https://htmlpreview.github.io/?https://github.com/python/typing/blob/main/conformance/results/results.html (et utilisant VSCode, c'est plus simple d'avoir les diagnostics directement dans l'IDE -- mypy étant utilisable uniquement en CLI et pas en language server)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je suis aussi sous VSCode, je vais avoir quelques projets à migrer. Merci pour l’information !

run: uv run pyright src/
22 changes: 12 additions & 10 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install -r requirements-dev.txt
- uses: actions/checkout@v5
- name: Set up uv (Python ${{ matrix.python-version }})
uses: astral-sh/setup-uv@v7
- name: Install tox
run: uv tool install --managed-python --python 3.13 tox --with tox-uv --with tox-gh
- name: Install Python ${{ matrix.python-version }}
run: uv python install --managed-python ${{ matrix.python-version }}
- name: Test with tox
run: tox
run: tox run
env:
TOX_GH_MAJOR_MINOR: ${{ matrix.python-version }}
UV_PYTHON_DOWNLOADS: never
59 changes: 41 additions & 18 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,56 +1,60 @@
[build-system]
requires = ["setuptools>=60.0.0"]
build-backend = "setuptools.build_meta"
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "clamdpy"
version = "0.1.0.post1"
description = "A Python wrapper around clamd, the ClamAV daemon"
authors = [
{name = "Viicos", email = "[email protected]"}
]
readme = "README.md"
requires-python = ">=3.8"
requires-python = ">=3.10"
classifiers = [
"Development Status :: 4 - Beta",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"License :: OSI Approved :: MIT License",
"Typing :: Typed"
]
license = {file = "LICENSE"}
dynamic = ["version"]

[project.urls]
Homepage = "https://github.com/Viicos/clamdpy"
Source = "https://github.com/Viicos/clamdpy"
Changelog = "https://github.com/Viicos/clamdpy/blob/main/CHANGELOG.md"

[tool.setuptools.dynamic]
version = {attr = "clamdpy.__version__"}

[tool.setuptools]
package-dir = {"" = "src"}
[dependency-groups]
dev = [
"pyright>=1.1.398",
"pytest>=8.3.5",
"ruff>=0.11.3",
"tox>=4.25.0",
"tox-gh>=1.5.0",
"tox-uv>=1.25.0",
]

[tool.setuptools.packages.find]
where = ["src"]

[tool.setuptools.package-data]
"clamdpy" = ["py.typed"]
[tool.uv]
required-version = ">=0.9.0"

[tool.black]
line-length = 120
[tool.pyright]
typeCheckingMode = "strict"
reportPrivateUsage = false

[tool.ruff]
target-version = "py310"
line-length = 120
src = ["src"]

[tools.ruff.lint]
[tool.ruff.lint]
select = [
"E", # pycodestyle (E)
"W", # pycodestyle (W)
Expand All @@ -66,3 +70,22 @@ known-first-party = ["clamdpy"]

[tool.pytest.ini_options]
pythonpath = "src"

[tool.tox]
requires = ["tox>=4.21"]
env_list = ["py310", "py311", "py312", "py314"]

[tool.tox.env_run_base]
description = "Run test under {base_python}"
runner = "uv-venv-lock-runner"
dependency_groups = ["dev"]
uv_python_preference = "only-managed"
uv_sync_flags = ["--no-python-downloads"]
commands = [["pytest"]]

[tool.tox.gh.python]
"3.10" = ["py310"]
"3.11" = ["py311"]
"3.12" = ["py312"]
"3.13" = ["py313"]
"3.14" = ["py314"]
6 changes: 0 additions & 6 deletions requirements-dev.txt

This file was deleted.

4 changes: 3 additions & 1 deletion src/clamdpy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from importlib.metadata import version

from .sockets import ClamdNetworkSocket, ClamdUnixSocket

__version__ = "0.1.0.post1"
__version__ = version("clamdpy")

__all__ = ("ClamdNetworkSocket", "ClamdUnixSocket")
3 changes: 0 additions & 3 deletions src/clamdpy/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
from __future__ import annotations


class ClamdException(Exception):
pass

Expand Down
4 changes: 2 additions & 2 deletions src/clamdpy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import re
from datetime import datetime
from pathlib import Path
from typing import Literal, NamedTuple
from typing import Final, Literal, NamedTuple

from .exceptions import ResponseError

# TODO Be able to match `:` in path names
RESULT_REGEX = re.compile(r"^(?P<path>[^:]*): ((?P<reason>.+) )?(?P<status>(FOUND|OK|ERROR))$")
RESULT_REGEX: Final = re.compile(r"^(?P<path>[^:]*): ((?P<reason>.+) )?(?P<status>(FOUND|OK|ERROR))$")


class VersionInfo(NamedTuple):
Expand Down
26 changes: 12 additions & 14 deletions src/clamdpy/sockets.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
from __future__ import annotations

import socket
import struct
import sys
from pathlib import Path
from typing import Literal, overload
from typing import Final, Literal, overload

from .exceptions import BufferTooLongError, CommandReadTimedOut, ConnectionError, ResponseError, UnknownCommand
from .models import ScanResult, VersionInfo
from .typing import StrPath, SupportsRead

UNKNOWN_COMMAND = "UNKNOWN COMMAND"
COMMAND_READ_TIMED_OUT = "COMMAND READ TIMED OUT"
DEFAULT_UNIX_SOCKET_PATH = "/var/run/clamav/clamd.ctl"
UNKNOWN_COMMAND: Final = "UNKNOWN COMMAND"
COMMAND_READ_TIMED_OUT: Final = "COMMAND READ TIMED OUT"
DEFAULT_UNIX_SOCKET_PATH: Final = "/var/run/clamav/clamd.ctl"


class ClamdNetworkSocket:
Expand Down Expand Up @@ -85,7 +83,7 @@ def _recv(self, sock: socket.socket, multiline: bool = True) -> str:
def _any_scan(self, command: str, path: StrPath, raw: Literal[True]) -> str: ...

@overload
def _any_scan(self, command: str, path: StrPath, raw: Literal[False] = ...) -> list[ScanResult]: ...
def _any_scan(self, command: str, path: StrPath, raw: Literal[False] = False) -> list[ScanResult]: ...

def _any_scan(self, command: str, path: StrPath, raw: bool = False) -> list[ScanResult] | str:
path = Path(path).absolute()
Expand Down Expand Up @@ -114,7 +112,7 @@ def shutdown(self) -> None:
def version(self, raw: Literal[True]) -> str: ...

@overload
def version(self, raw: Literal[False] = ...) -> VersionInfo: ...
def version(self, raw: Literal[False] = False) -> VersionInfo: ...

def version(self, raw: bool = False) -> VersionInfo | str:
"""Print program and database versions.
Expand All @@ -138,7 +136,7 @@ def stats(self):
def scan(self, path: StrPath, raw: Literal[True]) -> str: ...

@overload
def scan(self, path: StrPath, raw: Literal[False] = ...) -> list[ScanResult]: ...
def scan(self, path: StrPath, raw: Literal[False] = False) -> list[ScanResult]: ...

def scan(self, path: StrPath, raw: bool = False) -> list[ScanResult] | str:
"""Scan a file or a directory (recursively) with archive support enabled (if not disabled in clamd.conf).
Expand All @@ -151,7 +149,7 @@ def scan(self, path: StrPath, raw: bool = False) -> list[ScanResult] | str:
def contscan(self, path: StrPath, raw: Literal[True]) -> str: ...

@overload
def contscan(self, path: StrPath, raw: Literal[False] = ...) -> list[ScanResult]: ...
def contscan(self, path: StrPath, raw: Literal[False] = False) -> list[ScanResult]: ...

def contscan(self, path: StrPath, raw: bool = False) -> list[ScanResult] | str:
"""Scan file or directory (recursively) with archive support enabled and don't stop
Expand All @@ -164,7 +162,7 @@ def contscan(self, path: StrPath, raw: bool = False) -> list[ScanResult] | str:
def multiscan(self, path: StrPath, raw: Literal[True]) -> str: ...

@overload
def multiscan(self, path: StrPath, raw: Literal[False] = ...) -> list[ScanResult]: ...
def multiscan(self, path: StrPath, raw: Literal[False] = False) -> list[ScanResult]: ...

def multiscan(self, path: StrPath, raw: bool = False) -> list[ScanResult] | str:
"""Scan file in a standard way or scan directory (recursively) using multiple threads
Expand All @@ -178,15 +176,15 @@ def instream(
self,
buff: SupportsRead[bytes],
raw: Literal[True],
max_chunk_size: int | None = ...,
max_chunk_size: int | None = None,
) -> str: ...

@overload
def instream(
self,
buff: SupportsRead[bytes],
raw: Literal[False] = ...,
max_chunk_size: int | None = ...,
raw: Literal[False] = False,
max_chunk_size: int | None = None,
) -> ScanResult: ...

def instream(
Expand Down
4 changes: 2 additions & 2 deletions src/clamdpy/typing.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from os import PathLike
from typing import Protocol, TypeVar, Union
from typing import Protocol, TypeAlias, TypeVar

_T_co = TypeVar("_T_co", covariant=True)

Expand All @@ -10,4 +10,4 @@ def read(self, __length: int = ...) -> _T_co: ...


# Taken from _typeshed/__init__.pyi
StrPath = Union[str, "PathLike[str]"]
StrPath: TypeAlias = str | PathLike[str]
16 changes: 0 additions & 16 deletions tox.ini

This file was deleted.

Loading
Loading