Consolidate to single dlp_io module and publish release artifacts via Gitea Actions
publish-dlp-io / publish (push) Successful in 1m27s

This commit is contained in:
2026-07-31 16:42:59 +08:00
parent 3b0c81fd9d
commit fe1a6ed749
20 changed files with 1191 additions and 1245 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ from pathlib import Path
import pytest
import dlp_io
import dlp_io._api as api_module
import dlp_io as api_module
class _FakeSession:
+44 -15
View File
@@ -11,6 +11,7 @@ from enum import Enum
from pathlib import Path, PurePosixPath
import pytest
import yaml
from packaging.specifiers import SpecifierSet
from packaging.utils import canonicalize_name, parse_wheel_filename
from packaging.version import Version
@@ -19,11 +20,12 @@ import dlp_io
try:
import tomllib
except ModuleNotFoundError: # Python 3.9-3.10
except ModuleNotFoundError: # Python 3.10
import tomli as tomllib
PROJECT_ROOT = Path(__file__).resolve().parents[1]
WORKFLOW_PATH = PROJECT_ROOT / ".gitea" / "workflows" / "publish-dlp-io.yaml"
class DynamicField(Enum):
@@ -38,6 +40,14 @@ class PackageClassifier(Enum):
WINDOWS = "Operating System :: Microsoft :: Windows"
class WorkflowStep(Enum):
CLONE_TAG = "Clone immutable package tag"
TEST_MATRIX = "Test Python 3.10-3.14"
BUILD = "Build and check distribution"
SMOKE = "Smoke test release artifacts"
RELEASE = "Create Gitea release with wheels"
@dataclass(frozen=True)
class BuiltDistributions:
wheel: Path
@@ -49,15 +59,25 @@ def _load_pyproject() -> dict:
return tomllib.load(file)
def _load_workflow() -> dict:
with WORKFLOW_PATH.open(encoding="utf-8") as file:
return yaml.safe_load(file)
def _copy_source_tree(source: Path) -> None:
source.mkdir()
shutil.copy2(PROJECT_ROOT / "pyproject.toml", source)
shutil.copy2(PROJECT_ROOT / "MANIFEST.in", source)
shutil.copy2(PROJECT_ROOT / "setup.py", source)
shutil.copy2(PROJECT_ROOT / "dlp_io.py", source)
shutil.copytree(PROJECT_ROOT / "docs", source / "docs")
@pytest.fixture(scope="module")
def built_distributions(tmp_path_factory: pytest.TempPathFactory) -> BuiltDistributions:
root = tmp_path_factory.mktemp("dlp-io-build")
source = root / "source"
source.mkdir()
shutil.copy2(PROJECT_ROOT / "pyproject.toml", source)
shutil.copy2(PROJECT_ROOT / "MANIFEST.in", source)
shutil.copytree(PROJECT_ROOT / "dlp_io", source / "dlp_io")
shutil.copytree(PROJECT_ROOT / "docs", source / "docs")
_copy_source_tree(source)
dist = root / "dist"
completed = subprocess.run(
@@ -85,10 +105,9 @@ def built_distributions(tmp_path_factory: pytest.TempPathFactory) -> BuiltDistri
def test_pyproject_declares_structured_public_package_contract() -> None:
config = _load_pyproject()
project = config["project"]
setuptools = config["tool"]["setuptools"]
assert PackageName(canonicalize_name(project["name"])) is PackageName.DLP_IO
assert SpecifierSet(project["requires-python"]) == SpecifierSet(">=3.9")
assert SpecifierSet(project["requires-python"]) == SpecifierSet(">=3.10")
assert {DynamicField(item) for item in project["dynamic"]} == {
DynamicField.VERSION
}
@@ -99,10 +118,6 @@ def test_pyproject_declares_structured_public_package_contract() -> None:
if item in known_classifier_values
}
assert PackageClassifier.WINDOWS in known_classifiers
assert {Path(item) for item in setuptools["packages"]} == {Path("dlp_io")}
assert {Path(item) for item in setuptools["package-data"]["dlp_io"]} == {
Path("py.typed")
}
version_ref = config["tool"]["setuptools"]["dynamic"]["version"]["attr"]
module_name, attribute_name = version_ref.rsplit(".", 1)
@@ -121,8 +136,8 @@ def test_wheel_contains_only_installable_dlp_io_runtime(
assert version == Version(dlp_io.__version__)
assert build == ()
assert tags
assert PurePosixPath("dlp_io/__init__.py") in members
assert PurePosixPath("dlp_io/py.typed") in members
assert PurePosixPath("dlp_io.py") in members
assert not [item for item in members if item.suffix == ".pyd"]
member_roots = {Path(item.parts[0]) for item in members}
assert member_roots.isdisjoint({Path("tests"), Path("Lib")})
assert PurePosixPath(".env") not in members
@@ -139,9 +154,23 @@ def test_sdist_contains_package_sources_and_public_readme_only(
}
assert PurePosixPath("pyproject.toml") in members
assert PurePosixPath("setup.py") in members
assert PurePosixPath("docs/DLP_IO_LIBRARY.md") in members
assert PurePosixPath("dlp_io/__init__.py") in members
assert PurePosixPath("dlp_io.py") in members
member_roots = {Path(item.parts[0]) for item in members}
assert Path("tests") not in member_roots
assert PurePosixPath("README.md") not in members
assert PurePosixPath(".env") not in members
def test_publish_workflow_tests_builds_and_releases_tagged_distributions() -> None:
document = _load_workflow()
trigger = document.get("on", document.get(True))
assert set(trigger["push"]["tags"]) == {"dlp-io-v*.*.*"}
assert "workflow_dispatch" in trigger
job = document["jobs"]["publish"]
assert job["runs-on"] == "windows-latest"
assert Path(job["defaults"]["run"]["working-directory"]) == Path("repo")
step_names = [step["name"] for step in job["steps"]]
assert step_names == [step.value for step in WorkflowStep]
+3 -3
View File
@@ -18,14 +18,14 @@ from dlp_io import (
DlpSessionBusyError,
DlpTransportError,
)
import dlp_io._session as session_module
from dlp_io._helper import (
import dlp_io as session_module
from dlp_io import (
CHUNK_SIZE,
HelperErrorCode,
HelperSourceConfig,
render_helper_source,
)
from dlp_io._raw import _PipeRawIO
from dlp_io import _PipeRawIO
pytestmark = pytest.mark.skipif(os.name != "nt", reason="AF_PIPE requires Windows")