diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92beb87..8a2b594 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | @@ -26,10 +26,16 @@ jobs: - name: Lint run: | - tox -e lint + tox run -e lint check: runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - "3.11" + - "3.12" + - "3.13" steps: - name: Repository checkout uses: actions/checkout@v3 @@ -37,7 +43,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: ${{ matrix.python-version }} - name: Install dependencies run: | @@ -45,10 +51,16 @@ jobs: - name: Check run: | - tox -e check + tox run -e check test: runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - "3.11" + - "3.12" + - "3.13" steps: - name: Repository checkout uses: actions/checkout@v3 @@ -56,7 +68,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: ${{ matrix.python-version }} - name: Install dependencies run: | diff --git a/.gitignore b/.gitignore index 9246c83..6e56333 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,8 @@ *.pyc *.pyo -/build /*.egg-info /.coverage /.mypy_cache /.tox -.eggs -.pybuild -.cache +/build +/html diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..2668ce0 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: docs/conf.py + +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . diff --git a/prometheus_aioexporter/_metric.py b/prometheus_aioexporter/_metric.py index 6994f58..f8d1d0f 100644 --- a/prometheus_aioexporter/_metric.py +++ b/prometheus_aioexporter/_metric.py @@ -12,10 +12,10 @@ Counter, Enum, Gauge, - generate_latest, Histogram, Info, Summary, + generate_latest, ) from prometheus_client.metrics import MetricWrapperBase from prometheus_client.registry import Collector diff --git a/prometheus_aioexporter/_script.py b/prometheus_aioexporter/_script.py index 3ecf4d2..7c98237 100644 --- a/prometheus_aioexporter/_script.py +++ b/prometheus_aioexporter/_script.py @@ -20,7 +20,7 @@ from ._web import PrometheusExporter -class PrometheusExporterScript(Script): # type: ignore +class PrometheusExporterScript(Script): """Expose metrics to Prometheus.""" #: Name of the script, can be set by subsclasses. @@ -169,7 +169,7 @@ def _setup_logging(self, log_level: str) -> None: self.name, ) for name in names: - setup_logger(name=name, stream=sys.stderr, level=level) + setup_logger(name=name, stream=sys.stderr, level=level) # type: ignore def _configure_registry(self, include_process_stats: bool = False) -> None: """Configure the MetricRegistry.""" diff --git a/pyproject.toml b/pyproject.toml index 4b933bf..1002372 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,23 +13,23 @@ keywords = [ "library", "prometheus", ] -license = {file = "LICENSE.txt"} +license = { file = "LICENSE.txt" } maintainers = [ - {name = "Alberto Donato", email = "alberto.donato@gmail.com"}, + { name = "Alberto Donato", email = "alberto.donato@gmail.com" }, ] authors = [ - {name = "Alberto Donato", email = "alberto.donato@gmail.com"}, + { name = "Alberto Donato", email = "alberto.donato@gmail.com" }, ] -requires-python = ">=3.10" +requires-python = ">=3.11" classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities", @@ -42,48 +42,37 @@ dependencies = [ "prometheus-client>=0.4", "toolrack>=2.1", ] -[project.optional-dependencies] -testing = [ +optional-dependencies.testing = [ "pytest", "pytest-aiohttp", "pytest-asyncio", "pytest-mock", "trustme", ] -[project.urls] -changelog = "https://github.com/albertodonato/prometheus-aioexporter/blob/main/CHANGES.rst" -homepage = "https://github.com/albertodonato/prometheus-aioexporter" -repository = "https://github.com/albertodonato/prometheus-aioexporter" -[project.scripts] -prometheus-aioexporter-sample = "prometheus_aioexporter.sample:script" +urls.changelog = "https://github.com/albertodonato/prometheus-aioexporter/blob/main/CHANGES.rst" +urls.homepage = "https://github.com/albertodonato/prometheus-aioexporter" +urls.repository = "https://github.com/albertodonato/prometheus-aioexporter" +scripts.prometheus-aioexporter-sample = "prometheus_aioexporter.sample:script" [tool.setuptools.dynamic] -version = {attr = "prometheus_aioexporter.__version__"} +version = { attr = "prometheus_aioexporter.__version__" } [tool.setuptools.packages.find] -include = ["prometheus_aioexporter*"] +include = [ "prometheus_aioexporter*" ] -[tool.black] -line-length = 79 +[tool.setuptools.package-data] +prometheus_aioexporter = [ "py.typed" ] -[tool.isort] -combine_as_imports = true -force_grid_wrap = 2 -force_sort_within_sections = true -from_first = false -include_trailing_comma = true -multi_line_output = 3 -order_by_type = false -profile = "black" -use_parentheses = true +[tool.ruff] +line-length = 79 -[tool.flake8] -ignore = ["E203", "E501", "W503"] -max-line-length = 80 -select = ["C", "E", "F", "W", "B", "B950"] +lint.select = [ "I", "RUF", "UP" ] +lint.isort.combine-as-imports = true +lint.isort.force-sort-within-sections = true [tool.pytest.ini_options] asyncio_mode = "auto" +asyncio_default_fixture_loop_scope = "function" [tool.coverage.report] fail_under = 100.0 @@ -91,11 +80,10 @@ show_missing = true skip_covered = true [tool.coverage.run] -source = ["prometheus_aioexporter"] -omit = ["prometheus_aioexporter/sample.py"] +source = [ "prometheus_aioexporter" ] +omit = [ "prometheus_aioexporter/sample.py" ] [tool.mypy] -ignore_missing_imports = true install_types = true non_interactive = true strict = true diff --git a/tests/conftest.py b/tests/conftest.py index fdae88e..b81c4ed 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,5 @@ +from collections.abc import Iterator import ssl -from typing import Iterator import pytest from trustme import ( diff --git a/tests/metric_test.py b/tests/metric_test.py index 90d7376..e863e2e 100644 --- a/tests/metric_test.py +++ b/tests/metric_test.py @@ -1,6 +1,6 @@ +from collections.abc import Callable from typing import ( Any, - Callable, cast, ) diff --git a/tests/script_test.py b/tests/script_test.py index d715aad..281b57b 100644 --- a/tests/script_test.py +++ b/tests/script_test.py @@ -1,8 +1,8 @@ from argparse import ArgumentParser +from collections.abc import Iterator from io import StringIO import logging from ssl import SSLContext -from typing import Iterator from unittest import mock import pytest diff --git a/tests/web_test.py b/tests/web_test.py index cb2a5ac..487ec5f 100644 --- a/tests/web_test.py +++ b/tests/web_test.py @@ -1,12 +1,14 @@ -from ssl import SSLContext -from typing import ( - Any, +from collections.abc import ( Awaitable, Callable, - cast, Coroutine, Iterator, ) +from ssl import SSLContext +from typing import ( + Any, + cast, +) from unittest import mock from aiohttp.test_utils import ( @@ -84,10 +86,10 @@ def test_run( ssl_context=exporter.ssl_context, ) - @pytest.mark.parametrize("exporter", [ssl_context, None], indirect=True) + @pytest.mark.parametrize("exporter", [ssl_context, False], indirect=True) async def test_homepage( self, - ssl_context_server: SSLContext, + ssl_context_server: SSLContext | bool, create_server_client: Callable[ [PrometheusExporter], Coroutine[Any, Any, TestServer] ], @@ -96,7 +98,7 @@ async def test_homepage( ) -> None: server = await create_server_client(exporter) client = await aiohttp_client(server) - ssl_client_context = None + ssl_client_context: SSLContext | bool = False if exporter.ssl_context is not None: ssl_client_context = ssl_context_server request = await client.request("GET", "/", ssl=ssl_client_context) @@ -177,7 +179,7 @@ async def test_metrics_update_handler( args = [] async def update_handler( - metrics: dict[str, MetricWrapperBase] + metrics: dict[str, MetricWrapperBase], ) -> None: args.append(metrics) diff --git a/tox.ini b/tox.ini index 9671be7..850cbff 100644 --- a/tox.ini +++ b/tox.ini @@ -23,29 +23,30 @@ deps = commands = pytest --cov prometheus_aioexporter/ {posargs} +[testenv:docs] +deps = + -r docs/requirements.txt + . +commands = + sphinx-build -b html docs html {posargs} + [testenv:format] deps = - black - isort pyproject-fmt + ruff tox-ini-fmt commands = - isort {[base]lint_files} - black -q {[base]lint_files} + ruff format {[base]lint_files} + ruff check --fix {[base]lint_files} - pyproject-fmt pyproject.toml - tox-ini-fmt tox.ini [testenv:lint] deps = - black - flake8 - flake8-pyproject - isort pyproject-fmt + ruff commands = - isort --check-only --diff {[base]lint_files} - black --check {[base]lint_files} - flake8 {[base]lint_files} + ruff check {[base]lint_files} pyproject-fmt --check pyproject.toml [base]