From 39e195c861d54cfe072c09a3145eb9f37e658d99 Mon Sep 17 00:00:00 2001 From: Bryant Finney Date: Sun, 8 Sep 2024 19:01:35 -0400 Subject: [PATCH] ci: fix caching and documentation builds the documentation job wasn't setting up dynamic versioning, and sdist was using a shallow clone at some point, I'll want to replace the shell tasks with Python ones Signed-off-by: Bryant Finney --- .github/workflows/push-poetry.yaml | 22 ++++++++++++++---- pyproject.toml | 36 ++++++++++++------------------ src/dicom_echo/__init__.py | 25 +++++++++++---------- tests/test_pycli.py | 6 +++++ 4 files changed, 51 insertions(+), 38 deletions(-) diff --git a/.github/workflows/push-poetry.yaml b/.github/workflows/push-poetry.yaml index 9d1283e..1cb9543 100644 --- a/.github/workflows/push-poetry.yaml +++ b/.github/workflows/push-poetry.yaml @@ -105,9 +105,10 @@ jobs: path: docs - uses: ./.github/actions/poetry - with: - artifacts: "" - command: setup-versioning + with: { artifacts: "", command: setup-versioning } + + - uses: ./.github/actions/poetry + with: { artifacts: "", command: dynamic-versioning } - uses: ./.github/actions/poetry with: @@ -192,7 +193,6 @@ jobs: - uses: actions/setup-python@v5 with: - architecture: ${{ matrix.python-architecture || 'x64' }} python-version: 3.x - uses: ./.github/actions/poetry @@ -218,6 +218,20 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - uses: actions/setup-python@v5 + with: + python-version: 3.x + + - uses: ./.github/actions/poetry + with: { artifacts: "", command: setup-versioning, groups: build } + + - uses: ./.github/actions/poetry + with: { artifacts: "", command: dynamic-versioning, groups: build } + - uses: PyO3/maturin-action@v1 with: command: sdist diff --git a/pyproject.toml b/pyproject.toml index 2441254..dad9e46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,9 +7,7 @@ name = "dicom-echo" description = "A lightweight, cross-platform, blazingly fast implementation of the C-ECHO DICOM procedure. 🔥" readme = "README.md" license = { file = "LICENSE.md" } -authors = [ - { name = "Bryant Finney", email = "bryant.finney@outlook.com" }, -] +authors = [ { name = "Bryant Finney", email = "bryant.finney@outlook.com" } ] requires-python = ">=3.8.1,<4" classifiers = [ "Development Status :: 2 - Pre-Alpha", @@ -83,9 +81,7 @@ mdformat-frontmatter = "^2.0.8" mdformat-footnote = "^0.1.1" [tool.poetry.group.test.dependencies] -coverage = { extras = [ - "toml", -], version = ">=6.4,<8.0" } +coverage = { extras = [ "toml" ], version = ">=6.4,<8.0" } pytest = ">=7.4.4,<9.0.0" pytest-clarity = "^1.0.1" pytest-cov = ">=3,<6" @@ -119,15 +115,8 @@ python-source = "src" [tool.ruff] line-length = 120 -src = [ - "echoscu", - "src", - "tests", -] - -extend-include = [ - "*.ipynb", -] +src = [ "echoscu", "src", "tests" ] +extend-include = [ "*.ipynb" ] fix = true show-fixes = true output-format = "full" @@ -679,13 +668,16 @@ post_publish = "maturin-upload" [tool.poe.tasks] _version.cmd = "poetry version --short" -_missing_cargo.shell = "command -v cargo >/dev/null || echo cargo not found" + +[tool.poe.tasks.which-cargo] +expr = "shutil.which('cargo') or ''" +imports = [ "shutil" ] [tool.poe.tasks.cargo] help = "Invoke cargo commands after applying `poetry-dynamic-versioning` substitutions" -shell = """test -n "$CARGO_MISSING" || cargo $cmd""" -args = [ { name = "cmd", positional = true } ] -uses = { CARGO_MISSING = "_missing_cargo" } +expr = "subprocess.check_output([${CARGO}, *sys.argv[1:]], encoding='utf-8') if ${CARGO} else ''" +imports = [ "subprocess", "sys" ] +uses = { CARGO = "which-cargo" } [tool.poe.tasks.check-for-prerelease] capture_stdout = "check-for-prerelease.out" @@ -700,7 +692,7 @@ help = "Generate this package's docs" uses = { PACKAGE_VERSION = "_version" } [[tool.poe.tasks.docs.sequence]] -ref = "cargo doc -- --target-dir ./docs" +ref = "cargo doc --target-dir docs" [[tool.poe.tasks.docs.sequence]] ref = "docs-serve --output-directory ./docs" @@ -807,13 +799,13 @@ cmd = "maturin build --out dist --sdist" [tool.poe.tasks.maturin-develop] help = "Install the crate as a module in the poetry-managed virtualenv" shell = """ - if [ -n "$CARGO_MISSING" ]; then + if [ -z "${CARGO}" ]; then poetry pth else maturin develop fi """ -uses = { CARGO_MISSING = "_missing_cargo" } +uses = { CARGO = "which-cargo" } [tool.poe.tasks.maturin-upload] help = "Invoke maturin upload to publish this package to a PyPI registry" diff --git a/src/dicom_echo/__init__.py b/src/dicom_echo/__init__.py index 41e8297..94ad849 100644 --- a/src/dicom_echo/__init__.py +++ b/src/dicom_echo/__init__.py @@ -16,6 +16,7 @@ from __future__ import annotations import sys +from typing import Literal if not sys.argv[0].endswith('pdoc'): from dicom_echo.backend import ( # pylint: disable=no-name-in-module @@ -23,9 +24,14 @@ DEFAULT_CALLING_AE_TITLE, ) from dicom_echo.backend import send as __send # pylint: disable=no-name-in-module -else: - DEFAULT_CALLED_AE_TITLE = 'ANY-SCP' # pyright: ignore[reportConstantRedefinition] - DEFAULT_CALLING_AE_TITLE = 'ECHOSCU' # pyright: ignore[reportConstantRedefinition] +else: # pragma: no cover + # copy `backend.pyi` contents so the documentation can be built without cargo + + DEFAULT_CALLED_AE_TITLE: Literal['ANY-SCP'] = 'ANY-SCP' # type: ignore[no-redef] + """By default, specify this AE title for the target SCP.""" + + DEFAULT_CALLING_AE_TITLE: Literal['ECHOSCU'] = 'ECHOSCU' # type: ignore[no-redef] + """By default, specify this AE title for the SCU sending the `C-ECHO` message.""" def __send( address: str, @@ -41,7 +47,7 @@ def __send( return 0 -__all__ = ['DEFAULT_CALLED_AE_TITLE', 'DEFAULT_CALLING_AE_TITLE', 'send'] +__all__ = ['DEFAULT_CALLED_AE_TITLE', 'DEFAULT_CALLING_AE_TITLE', 'Counter', 'send'] __version__ = '0.0.0' __version_tuple__ = (0, 0, 0) @@ -58,12 +64,7 @@ def increment(self) -> int: return self.count -class Sentinel: - """Explicitly define a class for the sentinel object for type annotations.""" - - counter = Counter() -sentinel = Sentinel() def send( @@ -71,14 +72,14 @@ def send( /, called_ae_title: str = DEFAULT_CALLED_AE_TITLE, calling_ae_title: str = DEFAULT_CALLING_AE_TITLE, - message_id: int | Sentinel = sentinel, + message_id: int | Counter = counter, ) -> int: """Send a `C-ECHO` message to the given address. - If `message_id` is not overwritten, a global counter will be incremented and passed. + If `message_id` is not provided, a global counter will be incremented and passed. Reference: [DICOM Standard Part 7, Section 9.1.5](https://www.dicomstandard.org/standards/view/message-exchange#sect_9.1.5) """ - if isinstance(message_id, Sentinel): + if isinstance(message_id, Counter): message_id = counter.increment() return __send(address, called_ae_title=called_ae_title, calling_ae_title=calling_ae_title, message_id=message_id) diff --git a/tests/test_pycli.py b/tests/test_pycli.py index f06f379..34df5d8 100644 --- a/tests/test_pycli.py +++ b/tests/test_pycli.py @@ -2,6 +2,8 @@ from __future__ import annotations +import subprocess +import sys from typing import TYPE_CHECKING import rich.emoji @@ -54,6 +56,10 @@ def test_version() -> None: def test_version_called_as_module() -> None: """Test the CLI output when the utility is invoked as a Python module.""" + out = subprocess.check_output([sys.executable, '-m', 'dicom_echo', '--version'], text=True) + + assert 'dicom_echo' in out + assert echo.__version__ in out def test_host_aetitle(mock_send_rc0: MagicMock) -> None: