diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..e43fc3a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include LICENSE +include README.md +include RELEASING.md +include requirements.txt diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..d6c5e57 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,24 @@ +# Releasing RT-Utils + +The package version has a single source of truth in +`rt_utils/_version.py`. `setup.py` reads that value without importing the +package. + +## Release checklist + +1. Update `rt_utils/_version.py` and merge the change into `main`. +2. Run the complete test suite. +3. Build and validate both distributions: + + ```bash + python -m build + python -m twine check dist/* + ``` + +4. Install the wheel in a clean environment and confirm `rt_utils.__version__`. +5. Upload only the artifacts for the intended version to PyPI. +6. Tag the exact published commit as `v`. +7. Create the matching GitHub release from that tag. + +PyPI distributions cannot be replaced. Never tag or upload from an uncommitted +or untested working tree. diff --git a/rt_utils/__init__.py b/rt_utils/__init__.py index a17580d..4ad8032 100644 --- a/rt_utils/__init__.py +++ b/rt_utils/__init__.py @@ -1,3 +1,6 @@ +from ._version import __version__ from .rtstruct import RTStruct from .rtstruct_builder import RTStructBuilder from .rtstruct_merger import RTStructMerger + +__all__ = ["RTStruct", "RTStructBuilder", "RTStructMerger", "__version__"] diff --git a/rt_utils/_version.py b/rt_utils/_version.py new file mode 100644 index 0000000..ee3a0ac --- /dev/null +++ b/rt_utils/_version.py @@ -0,0 +1,3 @@ +"""RT-Utils package version.""" + +__version__ = "1.3.1" diff --git a/setup.py b/setup.py index 5d525ed..8c9e13a 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,10 @@ +from pathlib import Path + import setuptools -VERSION = "1.2.6" +version_namespace = {} +exec(Path("rt_utils/_version.py").read_text(encoding="utf-8"), version_namespace) +VERSION = version_namespace["__version__"] with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() with open("requirements.txt") as f: @@ -14,16 +18,14 @@ description="A small library for handling masks and RT-Structs", long_description=long_description, long_description_content_type="text/markdown", - url="https://github.com/qurit/rtutils", - package_dir={'':"rt_utils"}, - packages=setuptools.find_packages("rt_utils", exclude="tests"), + url="https://github.com/qurit/rt-utils", + packages=setuptools.find_packages(exclude=["tests"]), keywords=["RTStruct", "Dicom", "Pydicom"], classifiers=[ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", @@ -39,6 +41,6 @@ "Intended Audience :: Science/Research", "Intended Audience :: Developers", ], - python_requires=">=3.7", + python_requires=">=3.8", install_requires=required, ) diff --git a/tests/test_utils.py b/tests/test_utils.py index bac9d69..5ed6969 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,11 +1,16 @@ import numpy as np import pytest +from rt_utils import __version__ from rt_utils.image_helper import mask_to_edge_polygons from rt_utils.utils import COLOR_PALETTE from tests.test_rtstruct_builder import get_empty_mask +def test_package_version(): + assert __version__ == "1.3.1" + + def test_single_voxel_edge_polygon(): mask = np.zeros((3, 4), dtype=bool) mask[1, 2] = True