From b5a1c3583bb18fc53c24e102c88b81f1c95e7245 Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Mon, 17 Aug 2026 18:05:05 -0600 Subject: [PATCH] Prepare for publication: CalVer bump, LICENSE, classifiers, repository URL - version 2026.08.17 in pyproject and __init__, kept in sync by a test - add the MIT LICENSE file the metadata already claimed; it ships in both the sdist and the wheel - classifiers and Repository URL following the convention used by the other MCP servers (git.supported.systems/MCP/) - tests/test_packaging.py guards the invariants that only bite after upload: version drift, an unimportable console-script target, a declared license with no file, and a Python floor that moves ahead of what we test --- LICENSE | 21 ++++++++++++++++++++ pyproject.toml | 21 ++++++++++++++++++-- src/mcqemu/__init__.py | 2 +- tests/test_packaging.py | 43 +++++++++++++++++++++++++++++++++++++++++ uv.lock | 2 +- 5 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 LICENSE create mode 100644 tests/test_packaging.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3edc958 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ryan Malloy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/pyproject.toml b/pyproject.toml index 41ffff0..887f854 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,34 @@ [project] name = "mcqemu" -version = "2026.8.16" +version = "2026.08.17" description = "MCP server for managing QEMU virtual machines" readme = "README.md" requires-python = ">=3.11" authors = [{ name = "Ryan Malloy", email = "ryan@supported.systems" }] license = "MIT" -keywords = ["mcp", "qemu", "qmp", "virtualization", "kvm"] +keywords = ["mcp", "qemu", "qmp", "virtualization", "kvm", "sandbox"] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: MIT License", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: System :: Emulators", + "Topic :: System :: Systems Administration", +] + dependencies = [ "fastmcp>=3.4.7,<4", "qemu.qmp>=0.0.6", ] +[project.urls] +Repository = "https://git.supported.systems/MCP/mcqemu" + [project.scripts] mcqemu = "mcqemu.server:main" diff --git a/src/mcqemu/__init__.py b/src/mcqemu/__init__.py index 49efe4a..424775f 100644 --- a/src/mcqemu/__init__.py +++ b/src/mcqemu/__init__.py @@ -1,3 +1,3 @@ """mcqemu — MCP server for managing QEMU virtual machines.""" -__version__ = "2026.8.16" +__version__ = "2026.08.17" diff --git a/tests/test_packaging.py b/tests/test_packaging.py new file mode 100644 index 0000000..56df82d --- /dev/null +++ b/tests/test_packaging.py @@ -0,0 +1,43 @@ +"""Packaging invariants — cheap guards against publishing something wrong. + +PyPI is immutable per version, so these are worth catching before upload +rather than after. +""" + +import tomllib +from pathlib import Path + +import mcqemu + +PYPROJECT = Path(__file__).resolve().parent.parent / "pyproject.toml" + + +def project_metadata() -> dict: + return tomllib.loads(PYPROJECT.read_text())["project"] + + +def test_version_matches_pyproject(): + """__version__ is what the startup banner prints; drift is confusing.""" + assert mcqemu.__version__ == project_metadata()["version"] + + +def test_console_script_target_is_importable(): + """A typo here only shows up after install, when `mcqemu` fails to start.""" + module, _, attr = project_metadata()["scripts"]["mcqemu"].partition(":") + imported = __import__(module, fromlist=[attr]) + assert callable(getattr(imported, attr)) + + +def test_license_file_ships_with_the_declared_license(): + metadata = project_metadata() + assert metadata["license"] == "MIT" + license_text = (PYPROJECT.parent / "LICENSE").read_text() + assert "MIT License" in license_text + assert "Ryan Malloy" in license_text + + +def test_declared_python_floor_is_honest(): + """We test against this floor; it must not silently move ahead of us.""" + assert project_metadata()["requires-python"] == ">=3.11" + classifiers = project_metadata()["classifiers"] + assert "Programming Language :: Python :: 3.11" in classifiers diff --git a/uv.lock b/uv.lock index 4143652..bdafce1 100644 --- a/uv.lock +++ b/uv.lock @@ -681,7 +681,7 @@ wheels = [ [[package]] name = "mcqemu" -version = "2026.8.16" +version = "2026.8.17" source = { editable = "." } dependencies = [ { name = "fastmcp" },