pytest-xspec 0.5.0__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 (196) hide show
  1. pytest_xspec-0.5.0/.github/workflows/check.yml +49 -0
  2. pytest_xspec-0.5.0/.github/workflows/integration.yml +66 -0
  3. pytest_xspec-0.5.0/.github/workflows/publish.yml +86 -0
  4. pytest_xspec-0.5.0/.gitignore +227 -0
  5. pytest_xspec-0.5.0/.vscode/extensions.json +3 -0
  6. pytest_xspec-0.5.0/AGENTS.md +299 -0
  7. pytest_xspec-0.5.0/CONTRIBUTING.md +78 -0
  8. pytest_xspec-0.5.0/LICENSE +21 -0
  9. pytest_xspec-0.5.0/PKG-INFO +205 -0
  10. pytest_xspec-0.5.0/README.md +193 -0
  11. pytest_xspec-0.5.0/conftest.py +3 -0
  12. pytest_xspec-0.5.0/docs/acceptance-contract.md +147 -0
  13. pytest_xspec-0.5.0/docs/images/terminal-reports.png +0 -0
  14. pytest_xspec-0.5.0/docs/licenses/ferrox-agents-md-LICENSE.txt +21 -0
  15. pytest_xspec-0.5.0/docs/releasing.md +47 -0
  16. pytest_xspec-0.5.0/docs/specification-v0.1.md +213 -0
  17. pytest_xspec-0.5.0/examples/__init__.py +0 -0
  18. pytest_xspec-0.5.0/examples/acceptance_only/__init__.py +0 -0
  19. pytest_xspec-0.5.0/examples/acceptance_only/pytest.ini +4 -0
  20. pytest_xspec-0.5.0/examples/acceptance_only/test_behavior.py +18 -0
  21. pytest_xspec-0.5.0/examples/missing_requirement/__init__.py +0 -0
  22. pytest_xspec-0.5.0/examples/missing_requirement/pyproject.toml +5 -0
  23. pytest_xspec-0.5.0/examples/missing_requirement/test_behavior.py +13 -0
  24. pytest_xspec-0.5.0/examples/partial_verification/__init__.py +0 -0
  25. pytest_xspec-0.5.0/examples/partial_verification/pyproject.toml +5 -0
  26. pytest_xspec-0.5.0/examples/partial_verification/test_behavior.py +20 -0
  27. pytest_xspec-0.5.0/examples/quickstart/__init__.py +0 -0
  28. pytest_xspec-0.5.0/examples/quickstart/pyproject.toml +5 -0
  29. pytest_xspec-0.5.0/examples/quickstart/report.json +21 -0
  30. pytest_xspec-0.5.0/examples/quickstart/test_behavior.py +10 -0
  31. pytest_xspec-0.5.0/examples/test_examples.py +140 -0
  32. pytest_xspec-0.5.0/prek.toml +45 -0
  33. pytest_xspec-0.5.0/pyproject.toml +60 -0
  34. pytest_xspec-0.5.0/src/pytest_xspec/__init__.py +0 -0
  35. pytest_xspec-0.5.0/src/pytest_xspec/collector.py +23 -0
  36. pytest_xspec-0.5.0/src/pytest_xspec/config.py +60 -0
  37. pytest_xspec-0.5.0/src/pytest_xspec/outcomes.py +38 -0
  38. pytest_xspec-0.5.0/src/pytest_xspec/plugin.py +94 -0
  39. pytest_xspec-0.5.0/src/pytest_xspec/reporting.py +103 -0
  40. pytest_xspec-0.5.0/tests/__init__.py +0 -0
  41. pytest_xspec-0.5.0/tests/acceptance/__init__.py +0 -0
  42. pytest_xspec-0.5.0/tests/acceptance/conftest.py +45 -0
  43. pytest_xspec-0.5.0/tests/acceptance/expectations.py +17 -0
  44. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/acceptance_only/__init__.py +0 -0
  45. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/acceptance_only/test_behavior.py +10 -0
  46. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/all_requirements_pass/__init__.py +0 -0
  47. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/all_requirements_pass/test_behavior.py +6 -0
  48. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/collection_error/__init__.py +0 -0
  49. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/collection_error/test_behavior.py +6 -0
  50. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/collection_error/test_broken.py +1 -0
  51. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/deselected_requirement/__init__.py +0 -0
  52. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/deselected_requirement/test_behavior.py +10 -0
  53. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/missing_requirement/__init__.py +0 -0
  54. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/missing_requirement/test_behavior.py +2 -0
  55. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/plain_pytest/__init__.py +0 -0
  56. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/plain_pytest/test_behavior.py +2 -0
  57. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/expected_failure/__init__.py +0 -0
  58. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/expected_failure/test_behavior.py +7 -0
  59. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/failed_test/__init__.py +0 -0
  60. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/failed_test/test_behavior.py +6 -0
  61. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/setup_error/__init__.py +0 -0
  62. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/setup_error/conftest.py +6 -0
  63. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/setup_error/test_behavior.py +6 -0
  64. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/skipped_test/__init__.py +0 -0
  65. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/skipped_test/test_behavior.py +6 -0
  66. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/unexpected_pass/__init__.py +0 -0
  67. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/strict_unverified_outcome/unexpected_pass/test_behavior.py +7 -0
  68. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/unmarked_outcomes/failed/__init__.py +0 -0
  69. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/unmarked_outcomes/failed/test_behavior.py +10 -0
  70. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/unmarked_outcomes/skipped/__init__.py +0 -0
  71. pytest_xspec-0.5.0/tests/acceptance/scenarios/cli/unmarked_outcomes/skipped/test_behavior.py +10 -0
  72. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/conflicting_inventories/__init__.py +0 -0
  73. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/conflicting_inventories/test_behavior.py +6 -0
  74. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/duplicate_ini_ids/__init__.py +0 -0
  75. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/duplicate_ini_ids/test_behavior.py +6 -0
  76. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/pyproject_with_pytest_ini/__init__.py +0 -0
  77. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/pyproject_with_pytest_ini/test_behavior.py +6 -0
  78. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/pytest_ini_inventory/__init__.py +0 -0
  79. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/pytest_ini_inventory/test_behavior.py +6 -0
  80. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/unknown_id_without_inventory/__init__.py +0 -0
  81. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/unknown_id_without_inventory/test_behavior.py +6 -0
  82. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/unmarked_with_unsupported_inventory/__init__.py +0 -0
  83. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/unmarked_with_unsupported_inventory/test_behavior.py +2 -0
  84. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/unsupported_inventory/__init__.py +0 -0
  85. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/unsupported_inventory/test_behavior.py +6 -0
  86. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/without_requirement_configuration/__init__.py +0 -0
  87. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/without_requirement_configuration/test_behavior.py +2 -0
  88. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/zero_requirements_without_configuration/__init__.py +0 -0
  89. pytest_xspec-0.5.0/tests/acceptance/scenarios/configuration/zero_requirements_without_configuration/test_behavior.py +2 -0
  90. pytest_xspec-0.5.0/tests/acceptance/scenarios/reporting/empty_inventory/__init__.py +0 -0
  91. pytest_xspec-0.5.0/tests/acceptance/scenarios/reporting/empty_inventory/test_behavior.py +2 -0
  92. pytest_xspec-0.5.0/tests/acceptance/scenarios/reporting/summary/__init__.py +0 -0
  93. pytest_xspec-0.5.0/tests/acceptance/scenarios/reporting/summary/test_behavior.py +16 -0
  94. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/class_markers/__init__.py +0 -0
  95. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/class_markers/test_behavior.py +10 -0
  96. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_deselected_marker/__init__.py +0 -0
  97. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_deselected_marker/test_behavior.py +10 -0
  98. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_inventory/__init__.py +0 -0
  99. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_inventory/test_behavior.py +2 -0
  100. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/keyword_id/__init__.py +0 -0
  101. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/keyword_id/test_behavior.py +6 -0
  102. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/missing_id/__init__.py +0 -0
  103. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/missing_id/test_behavior.py +6 -0
  104. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/multiple_ids/__init__.py +0 -0
  105. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/multiple_ids/test_behavior.py +6 -0
  106. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/non_string_id/__init__.py +0 -0
  107. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/non_string_id/test_behavior.py +6 -0
  108. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/unknown_id/__init__.py +0 -0
  109. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/invalid_markers/unknown_id/test_behavior.py +6 -0
  110. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/multiple_requirements/__init__.py +0 -0
  111. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/multiple_requirements/test_behavior.py +7 -0
  112. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/opaque_ids/dotted/__init__.py +0 -0
  113. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/opaque_ids/dotted/test_behavior.py +6 -0
  114. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/opaque_ids/simple/__init__.py +0 -0
  115. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/opaque_ids/simple/test_behavior.py +6 -0
  116. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/opaque_ids/unicode/__init__.py +0 -0
  117. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/opaque_ids/unicode/test_behavior.py +6 -0
  118. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/parameterized_cases/__init__.py +0 -0
  119. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/parameterized_cases/test_behavior.py +7 -0
  120. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/repeated_marker/__init__.py +0 -0
  121. pytest_xspec-0.5.0/tests/acceptance/scenarios/requirements/repeated_marker/test_behavior.py +7 -0
  122. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/deselected_tests/__init__.py +0 -0
  123. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/deselected_tests/test_behavior.py +11 -0
  124. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/deselected_tests/test_excluded.py +6 -0
  125. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/missing_requirement/__init__.py +0 -0
  126. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/missing_requirement/test_behavior.py +2 -0
  127. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/outside_collected_path/__init__.py +0 -0
  128. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/outside_collected_path/test_behavior.py +2 -0
  129. pytest_xspec-0.5.0/tests/acceptance/scenarios/selection/outside_collected_path/test_not_collected.py +6 -0
  130. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/assertion_with_xpass_text/__init__.py +0 -0
  131. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/assertion_with_xpass_text/test_behavior.py +6 -0
  132. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/both_tests_pass/__init__.py +0 -0
  133. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/both_tests_pass/test_behavior.py +11 -0
  134. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/deselection_over_pass/__init__.py +0 -0
  135. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/deselection_over_pass/test_behavior.py +11 -0
  136. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/early_stop/__init__.py +0 -0
  137. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/early_stop/test_behavior.py +11 -0
  138. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/failure_over_xpass/__init__.py +0 -0
  139. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/failure_over_xpass/test_behavior.py +12 -0
  140. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/fixture_skip/__init__.py +0 -0
  141. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/fixture_skip/conftest.py +6 -0
  142. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/fixture_skip/test_behavior.py +6 -0
  143. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/partial_verification/one_failed_test/__init__.py +0 -0
  144. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/partial_verification/one_failed_test/test_behavior.py +11 -0
  145. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/partial_verification/one_skipped_test/__init__.py +0 -0
  146. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/partial_verification/one_skipped_test/test_behavior.py +11 -0
  147. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/partial_verification/one_unexecuted_test/__init__.py +0 -0
  148. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/partial_verification/one_unexecuted_test/test_behavior.py +15 -0
  149. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/expected_failure/__init__.py +0 -0
  150. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/expected_failure/test_behavior.py +7 -0
  151. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/failed_test/__init__.py +0 -0
  152. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/failed_test/test_behavior.py +6 -0
  153. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/passing_test/__init__.py +0 -0
  154. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/passing_test/test_behavior.py +6 -0
  155. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/setup_error/__init__.py +0 -0
  156. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/setup_error/conftest.py +6 -0
  157. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/setup_error/test_behavior.py +6 -0
  158. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/skipped_test/__init__.py +0 -0
  159. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/skipped_test/test_behavior.py +6 -0
  160. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/unexpected_pass/__init__.py +0 -0
  161. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/reported_outcome/unexpected_pass/test_behavior.py +7 -0
  162. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/setup_error_over_failure/__init__.py +0 -0
  163. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/setup_error_over_failure/conftest.py +6 -0
  164. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/setup_error_over_failure/test_behavior.py +11 -0
  165. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/setup_xfail/__init__.py +0 -0
  166. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/setup_xfail/conftest.py +6 -0
  167. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/setup_xfail/test_behavior.py +6 -0
  168. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/skip_over_deselection/__init__.py +0 -0
  169. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/skip_over_deselection/test_behavior.py +11 -0
  170. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/strict_xpass/__init__.py +0 -0
  171. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/strict_xpass/test_behavior.py +7 -0
  172. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_error_after_failure/__init__.py +0 -0
  173. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_error_after_failure/conftest.py +7 -0
  174. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_error_after_failure/test_behavior.py +6 -0
  175. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_error_after_pass/__init__.py +0 -0
  176. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_error_after_pass/conftest.py +7 -0
  177. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_error_after_pass/test_behavior.py +6 -0
  178. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_xfail/__init__.py +0 -0
  179. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_xfail/conftest.py +7 -0
  180. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/teardown_xfail/test_behavior.py +6 -0
  181. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/xfail_over_skip/__init__.py +0 -0
  182. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/xfail_over_skip/test_behavior.py +12 -0
  183. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/xpass_over_xfail/__init__.py +0 -0
  184. pytest_xspec-0.5.0/tests/acceptance/scenarios/statuses/xpass_over_xfail/test_behavior.py +13 -0
  185. pytest_xspec-0.5.0/tests/acceptance/test_cli.py +127 -0
  186. pytest_xspec-0.5.0/tests/acceptance/test_configuration.py +175 -0
  187. pytest_xspec-0.5.0/tests/acceptance/test_reporting.py +197 -0
  188. pytest_xspec-0.5.0/tests/acceptance/test_requirements.py +151 -0
  189. pytest_xspec-0.5.0/tests/acceptance/test_selection.py +45 -0
  190. pytest_xspec-0.5.0/tests/acceptance/test_statuses.py +402 -0
  191. pytest_xspec-0.5.0/tests/unit/__init__.py +0 -0
  192. pytest_xspec-0.5.0/tests/unit/test_config.py +33 -0
  193. pytest_xspec-0.5.0/tests/unit/test_expectations.py +154 -0
  194. pytest_xspec-0.5.0/tests/unit/test_outcomes.py +29 -0
  195. pytest_xspec-0.5.0/tests/unit/test_reporting.py +18 -0
  196. pytest_xspec-0.5.0/uv.lock +441 -0
@@ -0,0 +1,49 @@
1
+ name: check
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+
7
+ pull_request:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ check:
14
+ runs-on: ubuntu-latest
15
+ name: ${{ matrix.name }}
16
+ permissions:
17
+ contents: read
18
+ id-token: write
19
+
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ include:
24
+ - name: pre-commit
25
+ command: prek run --all-files
26
+
27
+ - name: collection
28
+ command: pytest --collect-only -q
29
+
30
+ - name: tests
31
+ command: pytest --cov --cov-report=term-missing --cov-report=xml --tb=short -q
32
+
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - uses: astral-sh/setup-uv@v6
37
+
38
+ - run: uv sync --locked --python 3.10
39
+
40
+ - run: uv run --locked ${{ matrix.command }}
41
+
42
+ - name: Upload code coverage
43
+ if: matrix.name == 'tests'
44
+ uses: codecov/codecov-action@v5
45
+ with:
46
+ use_oidc: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
47
+ files: coverage.xml
48
+ disable_search: true
49
+ fail_ci_if_error: true
@@ -0,0 +1,66 @@
1
+ name: integration
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+
7
+ pull_request:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ installed-package:
14
+ runs-on: ubuntu-latest
15
+
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ include:
20
+ - python: "3.10"
21
+ pytest: "pytest>=8,<9"
22
+
23
+ - python: "3.13"
24
+ pytest: "pytest>=8"
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+
29
+ - uses: astral-sh/setup-uv@v6
30
+
31
+ - run: uv python install '${{ matrix.python }}'
32
+
33
+ - run: uv build --python '${{ matrix.python }}'
34
+
35
+ - run: uv venv /tmp/acceptance-integration --python '${{ matrix.python }}'
36
+
37
+ - name: Install the wheel into an isolated environment
38
+ run: >-
39
+ uv pip install --python /tmp/acceptance-integration/bin/python
40
+ dist/*.whl '${{ matrix.pytest }}' 'pytest-xdist>=3.8.0'
41
+
42
+ - name: Verify installed distribution and plugin identity
43
+ working-directory: /tmp
44
+ run: |
45
+ /tmp/acceptance-integration/bin/python - <<'PY'
46
+ from importlib.metadata import distribution
47
+
48
+ import pytest_xspec
49
+
50
+ package = distribution("pytest-xspec")
51
+ assert package.metadata["Name"] == "pytest-xspec"
52
+ entry_points = [entry for entry in package.entry_points if entry.group == "pytest11"]
53
+ assert len(entry_points) == 1
54
+ assert entry_points[0].name == "xspec"
55
+ assert entry_points[0].value == "pytest_xspec.plugin"
56
+ entry_points[0].load()
57
+ print(f"Installed {package.metadata['Name']} {package.version}:")
58
+ print(pytest_xspec.__file__)
59
+ PY
60
+
61
+ - name: Verify acceptance and public examples against the installed wheel
62
+ working-directory: /tmp
63
+ run: >-
64
+ /tmp/acceptance-integration/bin/python -m pytest
65
+ "$GITHUB_WORKSPACE/tests/acceptance"
66
+ "$GITHUB_WORKSPACE/examples/test_examples.py" --import-mode=prepend --tb=short -ra
@@ -0,0 +1,86 @@
1
+ name: publish
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - .github/workflows/publish.yml
7
+ - pyproject.toml
8
+
9
+ release:
10
+ types: [published]
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ build:
17
+ runs-on: ubuntu-latest
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0
23
+
24
+ - uses: astral-sh/setup-uv@v6
25
+
26
+ - run: uv sync --locked --python 3.10
27
+
28
+ - name: Verify release tag and source
29
+ if: github.event_name == 'release'
30
+ env:
31
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
32
+ run: |
33
+ uv run --locked python - <<'PY'
34
+ import os
35
+ from importlib.metadata import version
36
+
37
+ expected_tag = f"v{version('pytest-xspec')}"
38
+ assert os.environ["RELEASE_TAG"] == expected_tag, expected_tag
39
+ PY
40
+ git merge-base --is-ancestor HEAD origin/master
41
+
42
+ - run: uv run --locked pytest --tb=short -q
43
+
44
+ - run: uv build --no-sources
45
+
46
+ - name: Check distribution metadata
47
+ run: uvx --from 'twine>=7,<8' twine check --strict dist/*
48
+
49
+ - run: uv venv /tmp/pypi-release-check --python 3.10
50
+
51
+ - name: Install the built wheel
52
+ run: >-
53
+ uv pip install --python /tmp/pypi-release-check/bin/python
54
+ dist/*.whl 'pytest-xdist>=3.8.0'
55
+
56
+ - name: Verify the installed package
57
+ working-directory: /tmp
58
+ run: >-
59
+ /tmp/pypi-release-check/bin/python -m pytest
60
+ "$GITHUB_WORKSPACE/tests/acceptance"
61
+ "$GITHUB_WORKSPACE/examples/test_examples.py" --import-mode=prepend --tb=short -q
62
+
63
+ - uses: actions/upload-artifact@v4
64
+ with:
65
+ name: distributions
66
+ path: dist/
67
+ if-no-files-found: error
68
+
69
+ publish:
70
+ if: github.event_name == 'release'
71
+ needs: build
72
+ runs-on: ubuntu-latest
73
+ environment:
74
+ name: pypi
75
+ url: https://pypi.org/project/pytest-xspec/
76
+ permissions:
77
+ id-token: write
78
+
79
+ steps:
80
+ - uses: actions/download-artifact@v4
81
+ with:
82
+ name: distributions
83
+ path: dist/
84
+
85
+ - name: Publish to PyPI
86
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,227 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ *.lcov
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ /examples/*/report.json
54
+ !/examples/quickstart/report.json
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ # Pipfile.lock
99
+
100
+ # uv
101
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ # uv.lock
105
+
106
+ # poetry
107
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
108
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
109
+ # commonly ignored for libraries.
110
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
111
+ # poetry.lock
112
+ # poetry.toml
113
+
114
+ # pdm
115
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
116
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
117
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
118
+ # pdm.lock
119
+ # pdm.toml
120
+ .pdm-python
121
+ .pdm-build/
122
+
123
+ # pixi
124
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
125
+ # pixi.lock
126
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
127
+ # in the .venv directory. It is recommended not to include this directory in version control.
128
+ .pixi/*
129
+ !.pixi/config.toml
130
+
131
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
132
+ __pypackages__/
133
+
134
+ # Celery stuff
135
+ celerybeat-schedule*
136
+ celerybeat.pid
137
+
138
+ # Redis
139
+ *.rdb
140
+ *.aof
141
+ *.pid
142
+
143
+ # RabbitMQ
144
+ mnesia/
145
+ rabbitmq/
146
+ rabbitmq-data/
147
+
148
+ # ActiveMQ
149
+ activemq-data/
150
+
151
+ # SageMath parsed files
152
+ *.sage.py
153
+
154
+ # Environments
155
+ .env
156
+ .envrc
157
+ .venv
158
+ env/
159
+ venv/
160
+ ENV/
161
+ env.bak/
162
+ venv.bak/
163
+
164
+ # Spyder project settings
165
+ .spyderproject
166
+ .spyproject
167
+
168
+ # Rope project settings
169
+ .ropeproject
170
+
171
+ # mkdocs/Zensical documentation
172
+ /site
173
+
174
+ # mypy
175
+ .mypy_cache/
176
+ .dmypy.json
177
+ dmypy.json
178
+
179
+ # Pyre type checker
180
+ .pyre/
181
+
182
+ # pytype static type analyzer
183
+ .pytype/
184
+
185
+ # Cython debug symbols
186
+ cython_debug/
187
+
188
+ # PyCharm
189
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
190
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
191
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
192
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
193
+ # .idea/
194
+
195
+ # Abstra
196
+ # Abstra is an AI-powered process automation framework.
197
+ # Ignore directories containing user credentials, local state, and settings.
198
+ # Learn more at https://abstra.io/docs
199
+ .abstra/
200
+
201
+ # Visual Studio Code
202
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
203
+ # can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
204
+ # and can be added to the global gitignore or merged into this file. However, if you prefer, you
205
+ # could uncomment the following to ignore the entire vscode folder
206
+ # .vscode/
207
+ # Temporary file for partial code execution
208
+ tempCodeRunnerFile.py
209
+
210
+ # Ruff stuff:
211
+ .ruff_cache/
212
+ .rumdl_cache/
213
+
214
+ # PyPI configuration file
215
+ .pypirc
216
+
217
+ # Marimo
218
+ marimo/_static/
219
+ marimo/_lsp/
220
+ __marimo__/
221
+
222
+ # Streamlit
223
+ .streamlit/secrets.toml
224
+
225
+ # Local Codex configuration
226
+ /.codex/
227
+ /.agents/
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["rvben.rumdl"]
3
+ }