diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 8c25af7..c09152b 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,6 +1,7 @@ name: check on: push: + tags-ignore: ["**"] pull_request: schedule: - cron: "0 8 * * *" @@ -11,53 +12,41 @@ concurrency: jobs: test: - name: test ${{ matrix.py }} - ${{ matrix.os }} - runs-on: ${{ matrix.os }} + name: test on CPython ${{ matrix.py }} + runs-on: ubuntu-latest strategy: fail-fast: false matrix: py: + - "3.12.0-beta.2" - "3.11" - "3.10" - - "pypy-3.7-v7.3.7" # ahead to start it earlier because takes longer - - "3.9" - - "3.8" - - "3.7" - os: - - ubuntu-22.04 - - windows-2022 - - macos-12 - + - 3.9 + - 3.8 + - 3.7 steps: - - name: Setup python for tox + - name: setup python for tox uses: actions/setup-python@v4 with: python-version: "3.11" - - name: Install tox + - name: install tox run: python -m pip install tox - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup python for test ${{ matrix.py }} + - name: setup python for test ${{ matrix.py }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.py }} - name: Pick environment to run run: | - import codecs - import os - import platform - import sys - cpy = platform.python_implementation() == "CPython" - base =("{}{}{}" if cpy else "{}{}").format("py" if cpy else "pypy", *sys.version_info[0:2]) - env = "TOXENV={}\n".format(base) - print("Picked:\n{}for{}".format(env, sys.version)) + import codecs; import os; import sys + env = f"TOXENV=py3{sys.version_info[1]}\n" + print("Picked:\n{env}for{sys.version}") with codecs.open(os.environ["GITHUB_ENV"], "a", "utf-8") as file_handler: file_handler.write(env) shell: python - - name: Setup test suite + - name: setup test suite run: tox -vv --notest - - name: Run test suite + - name: run test suite run: tox --skip-pkg-install env: PYTEST_ADDOPTS: "-vv --durations=20" @@ -65,54 +54,24 @@ jobs: DIFF_AGAINST: HEAD check: - name: tox env ${{ matrix.tox_env }} - ${{ matrix.os }} - runs-on: ${{ matrix.os }} + name: tox env ${{ matrix.tox_env }} + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - os: - - ubuntu-22.04 - - windows-2022 tox_env: - - dev - type - - readme - exclude: - - { os: windows-latest, tox_env: readme } + - dev + - pkg_check steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup Python "3.11" + - name: setup Python 3.11 uses: actions/setup-python@v4 with: python-version: "3.11" - - name: Install tox + - name: install tox run: python -m pip install tox - - name: Setup test suite - run: tox -vv --notest -e ${{ matrix.tox_env }} - - name: Run test suite - run: tox --skip-pkg-install -e ${{ matrix.tox_env }} - - publish: - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - needs: [check, test] - runs-on: ubuntu-22.04 - steps: - - name: Setup python to build package - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - name: Install build - run: python -m pip install build - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Build sdist and wheel - run: python -m build -s -w . -o dist - - name: Publish to PyPi - uses: pypa/gh-action-pypi-publish@v1.8.6 - with: - skip_existing: true - user: __token__ - password: ${{ secrets.pypi_password }} + - name: run check for ${{ matrix.tox_env }} + run: python -m tox -e ${{ matrix.tox_env }} + env: + UPGRADE_ADVISORY: "yes" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..8046620 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,27 @@ +name: Release to PyPI +on: + push: + tags: ["*"] + +jobs: + release: + runs-on: ubuntu-latest + environment: + name: release + url: https://pypi.org/p/sphinx-argparse-cli + permissions: + id-token: write + steps: + - name: Setup python to build package + uses: actions/setup-python@v4 + with: + python-version: "3.11" + - name: Install build + run: python -m pip install build + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Build package + run: pyproject-build -s -w . -o dist + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@v1.8.6 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 002914e..1732483 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,65 +2,32 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - - id: check-ast - - id: check-builtin-literals - - id: check-docstring-first - - id: check-merge-conflict - - id: check-yaml - - id: check-toml - - id: debug-statements - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/asottile/pyupgrade - rev: v3.3.2 - hooks: - - id: pyupgrade - args: ["--py37-plus"] - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort - repo: https://github.com/psf/black rev: 23.3.0 hooks: - id: black - args: [--safe] - - repo: https://github.com/asottile/blacken-docs - rev: 1.13.0 - hooks: - - id: blacken-docs - additional_dependencies: [black==23.3] - - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.11.1" - hooks: - - id: pyproject-fmt - additional_dependencies: [tox>=4.5.1] - repo: https://github.com/tox-dev/tox-ini-fmt rev: "1.3.0" hooks: - id: tox-ini-fmt args: ["-p", "fix"] - - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + - repo: https://github.com/tox-dev/pyproject-fmt + rev: "0.12.0" hooks: - - id: flake8 - additional_dependencies: - - flake8-bugbear==23.3.23 - - flake8-comprehensions==3.12 - - flake8-pytest-style==1.7.2 - - flake8-spellcheck==0.28 - - flake8-unused-arguments==0.0.13 - - flake8-noqa==1.3.1 - - pep8-naming==0.13.3 - - flake8-pyproject==1.2.3 + - id: pyproject-fmt + additional_dependencies: ["tox>=4.6.1"] - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v2.7.1" + rev: "v3.0.0-alpha.9-for-vscode" hooks: - id: prettier - additional_dependencies: - - prettier@2.7.1 - - "@prettier/plugin-xml@2.2" args: ["--print-width=120", "--prose-wrap=always"] + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.0.272" + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix] - repo: meta hooks: - id: check-hooks-apply diff --git a/pyproject.toml b/pyproject.toml index 17139e2..c0f3456 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ build-backend = "hatchling.build" requires = [ "hatch-vcs>=0.3", - "hatchling>=1.14", + "hatchling>=1.18", ] [project] @@ -36,11 +36,12 @@ dynamic = [ "version", ] dependencies = [ - "pytest>=7.3.1", + "pytest>=7.3.2", ] optional-dependencies.test = [ - "coverage>=7.2.3", - "pytest-mock>=3.10", + "covdefaults>=2.3", + "coverage>=7.2.7", + "pytest-mock>=3.11.1", ] urls.Homepage = "https://github.com/pytest-dev/pytest-print" urls.Source = "https://github.com/pytest-dev/pytest-print" @@ -55,17 +56,27 @@ version.source = "vcs" [tool.black] line-length = 120 -[tool.isort] -profile = "black" -known_first_party = ["pytest_print"] - -[tool.flake8] -ignore = ["E203"] -max-complexity = 22 -max-line-length = 120 -unused-arguments-ignore-abstract-functions = true -noqa-require-code = true -dictionaries = ["en_US", "python", "technical", "django"] +[tool.ruff] +select = ["ALL"] +line-length = 120 +target-version = "py37" +isort = {known-first-party = ["pytest_print"], required-imports = ["from __future__ import annotations"]} +ignore = [ + "ANN101", # no typoe annotation for self + "ANN401", # allow Any as type annotation + "D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible + "D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible + "S104", # Possible binding to all interface +] +[tool.ruff.per-file-ignores] +"tests/**/*.py" = [ + "S101", # asserts allowed in tests... + "FBT", # don"t care about booleans as positional arguments in tests + "INP001", # no implicit namespace + "D", # don"t care about documentation in tests + "S603", # `subprocess` call: check for execution of untrusted input + "PLR2004", # Magic value used in comparison, consider replacing with a constant variable +] [tool.coverage] run.source = ["pytest_print", "tests"] @@ -85,6 +96,7 @@ paths.source = [ "*/src", "*\\src", ] +run.plugins = ["covdefaults"] [tool.mypy] python_version = "3.11" diff --git a/src/pytest_print/__init__.py b/src/pytest_print/__init__.py index d90388b..296a102 100644 --- a/src/pytest_print/__init__.py +++ b/src/pytest_print/__init__.py @@ -1,13 +1,18 @@ -from datetime import datetime -from typing import Callable, Optional +"""Pytest print functionality.""" +from __future__ import annotations + +from timeit import default_timer +from typing import TYPE_CHECKING, Callable import pytest -from _pytest.config.argparsing import Parser -from _pytest.fixtures import SubRequest -from _pytest.terminal import TerminalReporter from ._version import __version__ +if TYPE_CHECKING: + from _pytest.config.argparsing import Parser + from _pytest.fixtures import SubRequest + from _pytest.terminal import TerminalReporter + def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("general") @@ -29,7 +34,7 @@ def pytest_addoption(parser: Parser) -> None: @pytest.fixture(name="printer") def printer(request: SubRequest) -> Callable[[str], None]: - """pytest plugin to print test progress steps in verbose mode""" + """Pytest plugin to print test progress steps in verbose mode.""" return create_printer(request) @@ -48,21 +53,21 @@ def create_printer(request: SubRequest) -> Callable[[str], None]: return no_op -def no_op(msg: str) -> None: # noqa: U100 - """Do nothing""" +def no_op(msg: str) -> None: # noqa: ARG001 + """Do nothing.""" class State: - def __init__(self, print_relative: bool, reporter: TerminalReporter) -> None: + def __init__(self, print_relative: bool, reporter: TerminalReporter) -> None: # noqa: FBT001 self._reporter = reporter - self._start = datetime.now() if print_relative else None + self._start = default_timer() if print_relative else None self._print_relative = print_relative @property - def elapsed(self) -> Optional[float]: + def elapsed(self) -> float | None: if self._start is None: return None # pragma: no cover - return (datetime.now() - self._start).total_seconds() + return default_timer() - self._start def printer(self, msg: str) -> None: msg = "\t{}{}".format(f"{self.elapsed}\t" if self._print_relative else "", msg) diff --git a/tests/conftest.py b/tests/conftest.py index c6481d5..fd9d35f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1 +1,3 @@ +from __future__ import annotations + pytest_plugins = ["pytester"] diff --git a/tests/example.py b/tests/example.py index 174c506..05f1dfd 100644 --- a/tests/example.py +++ b/tests/example.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from time import sleep from typing import Callable, Iterator diff --git a/tests/test_print.py b/tests/test_print.py index de14046..4dea9f9 100644 --- a/tests/test_print.py +++ b/tests/test_print.py @@ -1,8 +1,13 @@ +from __future__ import annotations + from pathlib import Path from shutil import copy2 +from typing import TYPE_CHECKING import pytest -from _pytest.monkeypatch import MonkeyPatch + +if TYPE_CHECKING: + from _pytest.monkeypatch import MonkeyPatch _EXAMPLE = Path(__file__).parent / "example.py" @@ -16,7 +21,6 @@ def test_version() -> None: @pytest.fixture() def example(testdir: pytest.Testdir) -> pytest.Testdir: dest = Path(str(testdir.tmpdir)) / "test_example.py" - # dest.symlink_to(_EXAMPLE) # for local debugging use this copy2(str(_EXAMPLE), str(dest)) return testdir @@ -55,7 +59,11 @@ def test_progress_v_no_relative(example: pytest.Testdir, monkeypatch: MonkeyPatc def test_progress_v_relative(example: pytest.Testdir) -> None: result_verbose_relative = example.runpytest( - "--print", "-v", "--print-relative-time", "-k", "test_server_parallel_requests" + "--print", + "-v", + "--print-relative-time", + "-k", + "test_server_parallel_requests", ) out = "\n".join(result_verbose_relative.outlines) result_verbose_relative.assert_outcomes(passed=1) diff --git a/tox.ini b/tox.ini index db934ab..0071041 100644 --- a/tox.ini +++ b/tox.ini @@ -34,7 +34,7 @@ commands = description = run static analysis and style check using flake8 skip_install = true deps = - pre-commit>=3.2.2 + pre-commit>=3.3.3 pass_env = HOMEPATH PROGRAMDATA @@ -44,7 +44,7 @@ commands = [testenv:type] description = run type check on code base deps = - mypy==1.2 + mypy==1.3 set_env = {tty:MYPY_FORCE_COLOR = 1} commands = diff --git a/whitelist.txt b/whitelist.txt deleted file mode 100644 index 8b6fea3..0000000 --- a/whitelist.txt +++ /dev/null @@ -1,18 +0,0 @@ -Runtime -Testdir -addoption -argparsing -copy2 -dest -getgroup -getoption -getplugin -pathlib -pluginmanager -pytester -runpytest -setenv -testdir -tmpdir -unittest -usefixtures