toolframe-testkit 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. toolframe_testkit-0.2.1/.github/workflows/compatibility.yml +85 -0
  2. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/.github/workflows/publish.yml +7 -11
  3. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/PKG-INFO +8 -5
  4. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/README.md +6 -3
  5. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/docs/development.md +1 -1
  6. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/docs/releasing.md +12 -11
  7. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/pyproject.toml +2 -2
  8. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/scripts/smoke_wheel.py +3 -3
  9. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/src/toolframe_testkit/__init__.py +1 -1
  10. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/assets/service-plugin/pyproject.toml +1 -1
  11. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/uv.lock +1 -1
  12. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/.github/workflows/ci.yml +0 -0
  13. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/.github/workflows/quality.yml +0 -0
  14. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/.gitignore +0 -0
  15. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/.pre-commit-config.yaml +0 -0
  16. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/CONTRIBUTING.md +0 -0
  17. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/LICENSE +0 -0
  18. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/cchk.toml +0 -0
  19. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/conftest.py +0 -0
  20. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/docs/contracts.md +0 -0
  21. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/docs/harness.md +0 -0
  22. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/examples/check_fixture.py +0 -0
  23. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/examples/installed_application.py +0 -0
  24. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/scripts/check_branch_name.py +0 -0
  25. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/scripts/validate_release.py +0 -0
  26. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/src/toolframe_testkit/contracts.py +0 -0
  27. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/src/toolframe_testkit/harness.py +0 -0
  28. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/src/toolframe_testkit/py.typed +0 -0
  29. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/src/toolframe_testkit/pytest_plugin.py +0 -0
  30. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/assets/service-plugin/LICENSE +0 -0
  31. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/assets/service-plugin/src/fixture_records/__init__.py +0 -0
  32. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/assets/service-plugin/src/fixture_records/definition.py +0 -0
  33. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/assets/service-plugin/src/fixture_records/docs/usage.md +0 -0
  34. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/assets/service-plugin/src/fixture_records/migrations/0001_init.sql +0 -0
  35. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/assets/service-plugin/src/fixture_records/service.py +0 -0
  36. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/test_contracts.py +0 -0
  37. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/test_harness_http.py +0 -0
  38. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/test_harness_process.py +0 -0
  39. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/test_installed_core.py +0 -0
  40. {toolframe_testkit-0.2.0 → toolframe_testkit-0.2.1}/tests/test_pytest_plugin.py +0 -0
@@ -0,0 +1,85 @@
1
+ name: SDK compatibility
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+ schedule:
8
+ - cron: '17 4 * * *'
9
+ workflow_dispatch:
10
+ workflow_call:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ wheel:
17
+ name: Build the shared plugin wheel
18
+ runs-on: ubuntu-24.04
19
+ timeout-minutes: 10
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+ with:
23
+ persist-credentials: false
24
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
25
+ with:
26
+ python-version: '3.14.7'
27
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
28
+ with:
29
+ version: '0.12.8'
30
+ enable-cache: false
31
+ - run: uv build --no-sources --wheel --out-dir build/compatibility-wheel
32
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
33
+ with:
34
+ name: compatibility-wheel
35
+ path: build/compatibility-wheel/*.whl
36
+ if-no-files-found: error
37
+ retention-days: 7
38
+
39
+ compatibility:
40
+ name: SDK ${{ matrix.sdk }}
41
+ needs: wheel
42
+ runs-on: ubuntu-24.04
43
+ timeout-minutes: 20
44
+ strategy:
45
+ fail-fast: false
46
+ matrix:
47
+ sdk: [minimum, latest]
48
+ steps:
49
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
50
+ with:
51
+ persist-credentials: false
52
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
53
+ with:
54
+ python-version: '3.14.7'
55
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
56
+ with:
57
+ version: '0.12.8'
58
+ enable-cache: false
59
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
60
+ with:
61
+ name: compatibility-wheel
62
+ path: build/compatibility-wheel
63
+ - name: Select the unchanged wheel
64
+ id: wheels
65
+ shell: bash
66
+ run: |
67
+ plugin=(build/compatibility-wheel/toolframe_testkit-*.whl)
68
+ test "${#plugin[@]}" = 1
69
+ echo "plugin=${plugin[0]}" >> "$GITHUB_OUTPUT"
70
+ - name: Verify installed wheel and package tests
71
+ uses: toolframe/toolframe-sdk/.github/actions/plugin-compatibility@2e2a3d79f35fbdb04249e8351fe9c75fc2164269
72
+ with:
73
+ mode: ${{ matrix.sdk }}
74
+ wheel: ${{ steps.wheels.outputs.plugin }}
75
+ output: build/compatibility-${{ matrix.sdk }}
76
+ - name: Retain compatibility evidence
77
+ if: always()
78
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
79
+ with:
80
+ name: compatibility-${{ matrix.sdk }}
81
+ path: |
82
+ build/compatibility-${{ matrix.sdk }}/report.json
83
+ build/compatibility-${{ matrix.sdk }}/pytest.xml
84
+ if-no-files-found: warn
85
+ retention-days: 14
@@ -2,19 +2,12 @@ name: Publish Python distribution
2
2
 
3
3
  on:
4
4
  workflow_dispatch:
5
- inputs:
6
- index:
7
- description: Package index; run against the matching vVERSION tag
8
- type: choice
9
- options: [testpypi, pypi]
10
- default: testpypi
11
- required: true
12
5
 
13
6
  permissions:
14
7
  contents: read
15
8
 
16
9
  concurrency:
17
- group: publish-${{ inputs.index }}
10
+ group: publish-pypi
18
11
  cancel-in-progress: false
19
12
 
20
13
  jobs:
@@ -45,12 +38,15 @@ jobs:
45
38
  uses: ./.github/workflows/ci.yml
46
39
  secrets: inherit
47
40
 
41
+ compatibility:
42
+ uses: ./.github/workflows/compatibility.yml
43
+
48
44
  publish:
49
- needs: [release-tag, validate]
45
+ needs: [release-tag, validate, compatibility]
50
46
  runs-on: ubuntu-24.04
51
47
  timeout-minutes: 10
52
48
  environment:
53
- name: ${{ inputs.index }}
49
+ name: pypi
54
50
  permissions:
55
51
  contents: read
56
52
  id-token: write
@@ -62,4 +58,4 @@ jobs:
62
58
  - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
63
59
  with:
64
60
  packages-dir: dist/
65
- repository-url: ${{ inputs.index == 'testpypi' && 'https://test.pypi.org/legacy/' || 'https://upload.pypi.org/legacy/' }}
61
+ repository-url: https://upload.pypi.org/legacy/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: toolframe-testkit
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Public contract checks and installed-application tests for Toolframe developers
5
5
  Project-URL: Homepage, https://github.com/toolframe/toolframe-testkit
6
6
  Project-URL: Repository, https://github.com/toolframe/toolframe-testkit
@@ -15,7 +15,7 @@ Requires-Dist: jsonschema<5,>=4.23
15
15
  Requires-Dist: psutil<9,>=7
16
16
  Requires-Dist: pydantic<3,>=2.12.5
17
17
  Requires-Dist: tomlkit<1,>=0.13
18
- Requires-Dist: toolframe-sdk==0.4.0
18
+ Requires-Dist: toolframe-sdk<1,>=0.4.0
19
19
  Provides-Extra: pytest
20
20
  Requires-Dist: pytest<10,>=8; extra == 'pytest'
21
21
  Description-Content-Type: text/markdown
@@ -24,8 +24,8 @@ Description-Content-Type: text/markdown
24
24
 
25
25
  Toolframe testkit is a Python library for checking a plugin's public SDK contract
26
26
  and exercising an installed Toolframe Core application through its public CLI and
27
- HTTP APIs. It is a developer test dependency, not a Core runtime plugin. Version
28
- 0.2.0 supports Python 3.14 or newer and pins `toolframe-sdk==0.4.0`.
27
+ HTTP APIs. It is a developer test dependency, not a Core runtime plugin.
28
+ Use Python 3.14 or newer and a compatible SDK satisfying `toolframe-sdk>=0.4.0,<1`.
29
29
 
30
30
  The package is Apache-2.0 licensed. It does not install Core, choose a global
31
31
  application, or load a pytest plugin automatically.
@@ -35,7 +35,7 @@ application, or load a pytest plugin automatically.
35
35
  Install the checker and opt-in pytest integration from PyPI:
36
36
 
37
37
  ```sh
38
- python -m pip install 'toolframe-testkit[pytest]==0.2.0'
38
+ python -m pip install 'toolframe-testkit[pytest]==0.2.1'
39
39
  ```
40
40
 
41
41
  The SDK is installed as a dependency. See
@@ -108,3 +108,6 @@ query forms, but cannot guarantee redaction of arbitrary plugin output.
108
108
  For release validation and Trusted Publisher setup, see [releasing](docs/releasing.md).
109
109
 
110
110
  For development hooks and contribution rules, see [Contributing](CONTRIBUTING.md).
111
+
112
+ Plugin dependencies allow compatible SDK 0.x updates from the declared minimum.
113
+ See the [SDK compatibility policy](https://github.com/toolframe/toolframe-sdk/blob/main/docs/compatibility.md) for API guarantees and minimum/latest verification.
@@ -2,8 +2,8 @@
2
2
 
3
3
  Toolframe testkit is a Python library for checking a plugin's public SDK contract
4
4
  and exercising an installed Toolframe Core application through its public CLI and
5
- HTTP APIs. It is a developer test dependency, not a Core runtime plugin. Version
6
- 0.2.0 supports Python 3.14 or newer and pins `toolframe-sdk==0.4.0`.
5
+ HTTP APIs. It is a developer test dependency, not a Core runtime plugin.
6
+ Use Python 3.14 or newer and a compatible SDK satisfying `toolframe-sdk>=0.4.0,<1`.
7
7
 
8
8
  The package is Apache-2.0 licensed. It does not install Core, choose a global
9
9
  application, or load a pytest plugin automatically.
@@ -13,7 +13,7 @@ application, or load a pytest plugin automatically.
13
13
  Install the checker and opt-in pytest integration from PyPI:
14
14
 
15
15
  ```sh
16
- python -m pip install 'toolframe-testkit[pytest]==0.2.0'
16
+ python -m pip install 'toolframe-testkit[pytest]==0.2.1'
17
17
  ```
18
18
 
19
19
  The SDK is installed as a dependency. See
@@ -86,3 +86,6 @@ query forms, but cannot guarantee redaction of arbitrary plugin output.
86
86
  For release validation and Trusted Publisher setup, see [releasing](docs/releasing.md).
87
87
 
88
88
  For development hooks and contribution rules, see [Contributing](CONTRIBUTING.md).
89
+
90
+ Plugin dependencies allow compatible SDK 0.x updates from the declared minimum.
91
+ See the [SDK compatibility policy](https://github.com/toolframe/toolframe-sdk/blob/main/docs/compatibility.md) for API guarantees and minimum/latest verification.
@@ -1,7 +1,7 @@
1
1
  # Development and verification
2
2
 
3
3
  The testkit repository is independently buildable. Runtime dependencies are
4
- `toolframe-sdk==0.4.0`, `httpx`, `tomlkit`, `psutil`, `pydantic`, and `jsonschema`;
4
+ `toolframe-sdk>=0.4.0,<1`, `httpx`, `tomlkit`, `psutil`, `pydantic`, and `jsonschema`;
5
5
  pytest is available
6
6
  through the `[pytest]` extra. Python 3.14 or newer is required. Consumer-style installation can use PyPI or an explicitly built local wheelhouse.
7
7
 
@@ -1,6 +1,6 @@
1
1
  # Releasing toolframe-testkit
2
2
 
3
- The distribution name is `toolframe-testkit`; its current version is `0.1.2`.
3
+ The distribution name is `toolframe-testkit`. The version is defined in `pyproject.toml`.
4
4
  Release tags must exactly match `v<project.version>`. Ordinary CI never uploads
5
5
  packages. The manual `publish.yml` workflow reruns validation and publishes only
6
6
  artifacts produced by that successful run.
@@ -19,13 +19,14 @@ metadata and licenses, runs Ruff and package tests against an installed wheel,
19
19
  and installs each distribution into a separate fresh consumer environment.
20
20
  Optional database/service integrations require their documented fixtures.
21
21
 
22
- Publish `toolframe-sdk==0.4.0` first. The pytest extra is installed with `toolframe-testkit[pytest]`. The coordinated order and native CLI channels are documented in
22
+ Publish any newly required SDK version before the plugin. Compatible Core or SDK
23
+ updates alone do not require a plugin release. The pytest extra is installed with `toolframe-testkit[pytest]`. The coordinated order and native CLI channels are documented in
23
24
  [Toolframe's release guide](https://github.com/toolframe/toolframe-core/blob/main/docs/releasing.md).
24
25
 
25
26
  ## Trusted Publishers
26
27
 
27
- Create GitHub environments named `testpypi` and `pypi`. On each corresponding
28
- package index, configure a normal or pending Trusted Publisher with these values:
28
+ Create a GitHub environment named `pypi`. On PyPI, configure a normal or
29
+ pending Trusted Publisher with these values:
29
30
 
30
31
  | Field | Value |
31
32
  | --- | --- |
@@ -33,7 +34,7 @@ package index, configure a normal or pending Trusted Publisher with these values
33
34
  | GitHub owner | `toolframe` |
34
35
  | GitHub repository | `toolframe-testkit` |
35
36
  | Workflow filename | `publish.yml` |
36
- | Environment | `testpypi` or `pypi`, matching the index |
37
+ | Environment | `pypi` |
37
38
 
38
39
  If publishing from another owner, use that actual owner in the publisher binding.
39
40
  Follow [PyPI's Trusted Publishing guide](https://docs.pypi.org/trusted-publishers/using-a-publisher/).
@@ -49,7 +50,7 @@ sibling owner where the workflow exposes that variable.
49
50
  ## Publish and verify
50
51
 
51
52
  After the release commit and matching tag are available remotely, manually run
52
- `publish.yml` at `v0.1.2`, selecting `testpypi` first and then `pypi`.
53
+ `publish.yml` at the matching `v<project.version>` tag to publish to PyPI.
53
54
  A branch or mismatched tag is rejected. Downloaded files are the artifacts from
54
55
  that run; the publishing job does not rebuild them. Published files cannot be
55
56
  replaced under the same version.
@@ -58,11 +59,11 @@ After PyPI publication, verify a clean installation:
58
59
 
59
60
  ```sh
60
61
  uv venv --python 3.14.7 build/consumer
61
- uv pip install --python build/consumer/bin/python 'toolframe-testkit==0.2.0'
62
+ uv pip install --python build/consumer/bin/python 'toolframe-testkit==0.2.1'
62
63
  uv pip check --python build/consumer/bin/python
63
64
  ```
64
65
 
65
- TestPyPI does not mirror dependencies. Test the specific artifact against an
66
- explicit dependency source; a local or TestPyPI check alone does not demonstrate
67
- that production PyPI resolution works. Keep logs, hashes and exact revisions in
68
- CI artifacts or ignored local evidence directories.
66
+ Test the specific artifact with dependencies from PyPI. Local artifact checks
67
+ alone do not demonstrate that the published package resolves correctly from
68
+ PyPI. Keep logs, hashes and exact revisions in CI artifacts or ignored local
69
+ evidence directories.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "toolframe-testkit"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Public contract checks and installed-application tests for Toolframe developers"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -12,7 +12,7 @@ license-files = ["LICENSE"]
12
12
  authors = [{ name = "byfb", email = "62798989+byfb@users.noreply.github.com" }]
13
13
  requires-python = ">=3.14"
14
14
  dependencies = [
15
- "toolframe-sdk==0.4.0", "httpx>=0.28,<1", "tomlkit>=0.13,<1", "psutil>=7,<9",
15
+ "toolframe-sdk>=0.4.0,<1", "httpx>=0.28,<1", "tomlkit>=0.13,<1", "psutil>=7,<9",
16
16
  "jsonschema>=4.23,<5", "pydantic>=2.12.5,<3",
17
17
  ]
18
18
 
@@ -21,7 +21,7 @@ from toolframe_sdk import load_object
21
21
  from toolframe_testkit import ResourceExample, ServiceExample, check_definition
22
22
 
23
23
  distribution = metadata.distribution("toolframe-testkit")
24
- assert distribution.version == "0.1.0"
24
+ assert distribution.version == sys.argv[1]
25
25
  assert importlib.util.find_spec("toolframe_core") is None
26
26
  assert importlib.util.find_spec("pytest") is None
27
27
  assert "pytest" not in sys.modules
@@ -66,7 +66,7 @@ def main():
66
66
  assert document["Requires-Python"] == ">=3.14"
67
67
  assert document["License-Expression"] == "Apache-2.0"
68
68
  requirements = document.get_all("Requires-Dist") or []
69
- assert any(item.startswith("toolframe-sdk==0.4.0") for item in requirements)
69
+ assert any(item.startswith("toolframe-sdk<1,>=0.4.0") for item in requirements)
70
70
  assert not any(" @ " in item or "file:" in item for item in requirements)
71
71
  assert not any(
72
72
  "fixture_records/" in name or name.startswith("tests/") for name in names
@@ -109,7 +109,7 @@ def main():
109
109
  timeout=180,
110
110
  )
111
111
  result = subprocess.run(
112
- [str(python), "-I", "-c", CHECK],
112
+ [str(python), "-I", "-c", CHECK, document["Version"]],
113
113
  cwd=output,
114
114
  env=environment,
115
115
  capture_output=True,
@@ -10,7 +10,7 @@ from .contracts import (
10
10
  )
11
11
  from .harness import ApplicationHarness, CLIResult, HarnessError, HarnessTimeout
12
12
 
13
- __version__ = "0.2.0"
13
+ __version__ = "0.2.1"
14
14
  __all__ = [
15
15
  "ApplicationHarness",
16
16
  "CLIResult",
@@ -9,7 +9,7 @@ description = "Small independently packaged Toolframe records plugin for testkit
9
9
  license = "Apache-2.0"
10
10
  license-files = ["LICENSE"]
11
11
  requires-python = ">=3.14"
12
- dependencies = ["toolframe-sdk==0.4.0"]
12
+ dependencies = ["toolframe-sdk>=0.4.0,<1"]
13
13
 
14
14
  [project.entry-points."toolframe.plugins"]
15
15
  fixture-records = "fixture_records.definition:plugin"
@@ -475,7 +475,7 @@ dev = [
475
475
 
476
476
  [[package]]
477
477
  name = "toolframe-testkit"
478
- version = "0.2.0"
478
+ version = "0.2.1"
479
479
  source = { editable = "." }
480
480
  dependencies = [
481
481
  { name = "httpx" },