vws-python-mock 2026.2.22.3__tar.gz → 2026.8.4__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 (155) hide show
  1. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.github/workflows/dependabot-merge.yml +1 -6
  2. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.github/workflows/docker-build.yml +5 -5
  3. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.github/workflows/lint.yml +6 -3
  4. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.github/workflows/publish-site.yml +1 -1
  5. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.github/workflows/release.yml +38 -38
  6. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.github/workflows/test.yml +54 -27
  7. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.gitignore +2 -0
  8. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.pre-commit-config.yaml +80 -34
  9. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/CHANGELOG.rst +26 -2
  10. {vws_python_mock-2026.2.22.3/src/vws_python_mock.egg-info → vws_python_mock-2026.8.4}/PKG-INFO +41 -37
  11. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/README.rst +2 -2
  12. vws_python_mock-2026.8.4/admin/create_secrets_files.py +335 -0
  13. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/ci/test_custom_linters.py +49 -31
  14. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/conftest.py +2 -11
  15. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docker-bake.hcl +6 -6
  16. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/conf.py +13 -1
  17. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/contributing.rst +1 -4
  18. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/differences-to-vws.rst +38 -4
  19. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/docker.rst +6 -6
  20. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/index.rst +1 -0
  21. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/mock-api-reference.rst +2 -2
  22. vws_python_mock-2026.8.4/docs/source/unreleased.rst +8 -0
  23. vws_python_mock-2026.8.4/docs/towncrier_template.rst.jinja +14 -0
  24. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/pyproject.toml +269 -205
  25. vws_python_mock-2026.8.4/secrets.tar.gpg +0 -0
  26. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/spelling_private_dict.txt +4 -0
  27. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_constants.py +6 -2
  28. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/Dockerfile +1 -1
  29. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/healthcheck.py +1 -1
  30. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/target_manager.py +37 -9
  31. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/vwq.py +6 -5
  32. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/vws.py +200 -6
  33. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_mock_common.py +2 -2
  34. vws_python_mock-2026.8.4/src/mock_vws/_model_target_web_api.py +486 -0
  35. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/exceptions.py +3 -5
  36. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/image_validators.py +10 -10
  37. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/decorators.py +23 -14
  38. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/mock_web_services_api.py +162 -0
  39. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_respx_mock_server/decorators.py +4 -1
  40. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/__init__.py +16 -0
  41. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/exceptions.py +134 -0
  42. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/image_validators.py +14 -16
  43. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/key_validators.py +1 -1
  44. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/project_state_validators.py +21 -5
  45. vws_python_mock-2026.8.4/src/mock_vws/_services_validators/request_quota_validators.py +42 -0
  46. vws_python_mock-2026.8.4/src/mock_vws/_services_validators/target_quota_validators.py +41 -0
  47. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/database.py +17 -3
  48. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/image_matchers.py +9 -7
  49. vws_python_mock-2026.8.4/src/mock_vws/model_target.py +79 -0
  50. vws_python_mock-2026.8.4/src/mock_vws/py.typed +0 -0
  51. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/states.py +4 -0
  52. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/target.py +5 -6
  53. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/target_manager.py +20 -0
  54. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/target_raters.py +9 -9
  55. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4/src/vws_python_mock.egg-info}/PKG-INFO +41 -37
  56. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/SOURCES.txt +10 -0
  57. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/requires.txt +36 -32
  58. vws_python_mock-2026.8.4/src/vws_python_mock.egg-info/scm_file_list.json +146 -0
  59. vws_python_mock-2026.8.4/src/vws_python_mock.egg-info/scm_version.json +8 -0
  60. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/conftest.py +19 -11
  61. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/credentials.py +76 -2
  62. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/prepared_requests.py +12 -4
  63. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/vuforia_backends.py +140 -27
  64. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_authorization_header.py +1 -1
  65. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_date_header.py +1 -1
  66. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_docker.py +36 -11
  67. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_flask_app_usage.py +130 -2
  68. vws_python_mock-2026.8.4/tests/mock_vws/test_model_target_web_api.py +657 -0
  69. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_query.py +8 -12
  70. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_requests_mock_usage.py +299 -1
  71. vws_python_mock-2026.8.4/tests/mock_vws/test_respx_mock_usage.py +209 -0
  72. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_vumark_generation_api.py +82 -72
  73. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/__init__.py +1 -1
  74. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/retries.py +7 -3
  75. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/vuforia_secrets.env.example +9 -0
  76. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/zizmor.yml +1 -3
  77. vws_python_mock-2026.2.22.3/admin/create_secrets_files.py +0 -253
  78. vws_python_mock-2026.2.22.3/secrets.tar.gpg +0 -0
  79. vws_python_mock-2026.2.22.3/tests/mock_vws/test_respx_mock_usage.py +0 -346
  80. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.git_archival.txt +0 -0
  81. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.gitattributes +0 -0
  82. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.github/dependabot.yml +0 -0
  83. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.prettierrc +0 -0
  84. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.vscode/extensions.json +0 -0
  85. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/.vscode/settings.json +0 -0
  86. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/CODE_OF_CONDUCT.rst +0 -0
  87. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/LICENSE +0 -0
  88. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/MANIFEST.in +0 -0
  89. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/admin/__init__.py +0 -0
  90. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/admin/vumark_template.svg +0 -0
  91. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/ci/__init__.py +0 -0
  92. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/ci/decrypt_secret.sh +0 -0
  93. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/__init__.py +0 -0
  94. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/basic-example.rst +0 -0
  95. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/changelog.rst +0 -0
  96. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/ci-setup.rst +0 -0
  97. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/getting-started.rst +0 -0
  98. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/httpx-example.rst +0 -0
  99. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/installation.rst +0 -0
  100. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/release-process.rst +0 -0
  101. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/docs/source/versioning-and-api-stability.rst +0 -0
  102. /vws_python_mock-2026.2.22.3/src/mock_vws/py.typed → /vws_python_mock-2026.8.4/newsfragments/.gitkeep +0 -0
  103. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/setup.cfg +0 -0
  104. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/__init__.py +0 -0
  105. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_base64_decoding.py +0 -0
  106. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_database_matchers.py +0 -0
  107. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/__init__.py +0 -0
  108. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_tools.py +0 -0
  109. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/__init__.py +0 -0
  110. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/accept_header_validators.py +0 -0
  111. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/auth_validators.py +0 -0
  112. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/content_length_validators.py +0 -0
  113. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/content_type_validators.py +0 -0
  114. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/date_validators.py +0 -0
  115. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/fields_validators.py +0 -0
  116. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/include_target_data_validators.py +0 -0
  117. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/num_results_validators.py +0 -0
  118. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/project_state_validators.py +0 -0
  119. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/__init__.py +0 -0
  120. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/mock_web_query_api.py +0 -0
  121. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_respx_mock_server/__init__.py +0 -0
  122. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/active_flag_validators.py +0 -0
  123. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/auth_validators.py +0 -0
  124. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/content_length_validators.py +0 -0
  125. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/content_type_validators.py +0 -0
  126. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/date_validators.py +0 -0
  127. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/json_validators.py +0 -0
  128. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/metadata_validators.py +0 -0
  129. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/name_validators.py +0 -0
  130. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/target_validators.py +0 -0
  131. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/width_validators.py +0 -0
  132. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/mock_vws/database_type.py +0 -0
  133. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/dependency_links.txt +0 -0
  134. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/not-zip-safe +0 -0
  135. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/top_level.txt +0 -0
  136. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/__init__.py +0 -0
  137. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/__init__.py +0 -0
  138. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/__init__.py +0 -0
  139. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_add_target.py +0 -0
  140. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_content_length.py +0 -0
  141. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_database_summary.py +0 -0
  142. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_delete_target.py +0 -0
  143. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_get_duplicates.py +0 -0
  144. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_get_target.py +0 -0
  145. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_invalid_given_id.py +0 -0
  146. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_invalid_json.py +0 -0
  147. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_list.py +0 -0
  148. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_raters.py +0 -0
  149. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_summary.py +0 -0
  150. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_validators.py +0 -0
  151. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_unexpected_json.py +0 -0
  152. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/test_update_target.py +0 -0
  153. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/assertions.py +0 -0
  154. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/too_many_requests.py +0 -0
  155. {vws_python_mock-2026.2.22.3 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/usage_test_helpers.py +0 -0
@@ -10,13 +10,8 @@ permissions:
10
10
  jobs:
11
11
  dependabot:
12
12
  runs-on: ubuntu-latest
13
- if: github.actor == 'dependabot[bot]'
13
+ if: github.event.pull_request.user.login == 'dependabot[bot]'
14
14
  steps:
15
- - name: Dependabot metadata
16
- id: metadata
17
- uses: dependabot/fetch-metadata@v2
18
- with:
19
- github-token: ${{ secrets.GITHUB_TOKEN }}
20
15
  - name: Enable auto-merge for Dependabot PRs
21
16
  run: gh pr merge --auto --merge "$PR_URL"
22
17
  env:
@@ -24,22 +24,22 @@ jobs:
24
24
  runs-on: ubuntu-latest
25
25
 
26
26
  steps:
27
- - uses: actions/checkout@v6
27
+ - uses: actions/checkout@v7
28
28
  with:
29
29
  persist-credentials: false
30
30
 
31
31
  - name: Set up QEMU
32
- uses: docker/setup-qemu-action@v3
32
+ uses: docker/setup-qemu-action@v4
33
33
 
34
34
  - name: Set up Docker Buildx
35
- uses: docker/setup-buildx-action@v3
35
+ uses: docker/setup-buildx-action@v4
36
36
 
37
37
  - name: Check Docker bake definition
38
- uses: docker/bake-action@v6.10.0
38
+ uses: docker/bake-action@v7.3.0
39
39
  with:
40
40
  call: check
41
41
 
42
42
  - name: Build Docker images
43
- uses: docker/bake-action@v6.10.0
43
+ uses: docker/bake-action@v7.3.0
44
44
  with:
45
45
  push: false
@@ -18,19 +18,19 @@ jobs:
18
18
  build:
19
19
  strategy:
20
20
  matrix:
21
- python-version: ['3.13']
21
+ python-version: ['3.14']
22
22
  platform: [ubuntu-latest, windows-latest]
23
23
  hook-stage: [pre-commit, pre-push, manual]
24
24
 
25
25
  runs-on: ${{ matrix.platform }}
26
26
 
27
27
  steps:
28
- - uses: actions/checkout@v6
28
+ - uses: actions/checkout@v7
29
29
  with:
30
30
  persist-credentials: false
31
31
 
32
32
  - name: Install uv
33
- uses: astral-sh/setup-uv@v7
33
+ uses: astral-sh/setup-uv@v9.0.0
34
34
  with:
35
35
  enable-cache: true
36
36
  cache-dependency-glob: '**/pyproject.toml'
@@ -42,6 +42,9 @@ jobs:
42
42
  run: uv run --extra=dev prek run --all-files --hook-stage ${{ matrix.hook-stage }}
43
43
  --verbose
44
44
  env:
45
+ # Avoid intermittent uv distribution cache rename failures while
46
+ # prek installs hook environments on Windows.
47
+ UV_NO_CACHE: '1'
45
48
  UV_PYTHON: ${{ matrix.python-version }}
46
49
 
47
50
  - uses: pre-commit-ci/lite-action@v1.1.0
@@ -22,6 +22,6 @@ jobs:
22
22
  with:
23
23
  documentation_path: docs/source
24
24
  pyproject_extras: dev
25
- python_version: '3.13'
25
+ python_version: '3.14'
26
26
  sphinx_build_options: -W
27
27
  publish: ${{ github.ref_name == 'main' }}
@@ -7,6 +7,7 @@ jobs:
7
7
  release:
8
8
  name: Create release
9
9
  runs-on: ubuntu-latest
10
+ environment: release
10
11
 
11
12
  permissions:
12
13
  # This is needed for https://github.com/stefanzweifel/git-auto-commit-action.
@@ -17,7 +18,7 @@ jobs:
17
18
  tag: ${{ steps.tag_version.outputs.new_tag }}
18
19
 
19
20
  steps:
20
- - uses: actions/checkout@v6
21
+ - uses: actions/checkout@v7
21
22
  with:
22
23
  # Fetch all history including tags.
23
24
  # Needed to find the latest tag.
@@ -33,6 +34,12 @@ jobs:
33
34
  # The default GITHUB_TOKEN cannot bypass rulesets.
34
35
  token: ${{ secrets.RELEASE_PAT }}
35
36
 
37
+ - name: Install uv
38
+ uses: astral-sh/setup-uv@v9.0.0
39
+ with:
40
+ enable-cache: true
41
+ cache-dependency-glob: '**/pyproject.toml'
42
+
36
43
  - name: Calver calculate version
37
44
  uses: StephaneBour/actions-calver@master
38
45
  id: calver
@@ -42,37 +49,27 @@ jobs:
42
49
  env:
43
50
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44
51
 
45
- - name: Get the changelog underline
46
- id: changelog_underline
47
- run: |
48
- underline="$(echo "${{ steps.calver.outputs.release }}" | tr -c '\n' '-')"
49
- echo "underline=${underline}" >> "$GITHUB_OUTPUT"
50
-
51
- - name: Update changelog
52
- id: update_changelog
53
- uses: jacobtomlinson/gha-find-replace@v3
54
- with:
55
- find: "Next\n----"
56
- replace: |
57
- Next
58
- ----
52
+ # towncrier writes the rendered notes to stdout (informational
53
+ # chatter goes to stderr), so this is the curated release body for
54
+ # this version, not github-tag-action's commit-derived changelog.
55
+ - name: Generate the GitHub release notes
56
+ env:
57
+ RELEASE: ${{ steps.calver.outputs.release }}
58
+ run: uv run --extra=release towncrier build --draft --version "$RELEASE" >
59
+ release-notes.md
59
60
 
60
- ${{ steps.calver.outputs.release }}
61
- ${{ steps.changelog_underline.outputs.underline }}
62
- include: CHANGELOG.rst
63
- regex: false
61
+ # Assemble the same fragments into CHANGELOG.rst under a new
62
+ # ``$RELEASE`` section and delete the consumed fragment files.
63
+ - name: Update the changelog
64
+ env:
65
+ RELEASE: ${{ steps.calver.outputs.release }}
66
+ run: uv run --extra=release towncrier build --yes --version "$RELEASE"
64
67
 
65
- - name: Check Update changelog was modified
66
- run: |
67
- if [ "${{ steps.update_changelog.outputs.modifiedFiles }}" = "0" ]; then
68
- echo "Error: No files were modified when updating changelog"
69
- exit 1
70
- fi
71
68
  - uses: stefanzweifel/git-auto-commit-action@v7
72
69
  id: commit
73
70
  with:
74
71
  commit_message: Bump CHANGELOG
75
- file_pattern: CHANGELOG.rst
72
+ file_pattern: CHANGELOG.rst newsfragments
76
73
  # Error if there are no changes.
77
74
  skip_dirty_check: true
78
75
 
@@ -91,7 +88,7 @@ jobs:
91
88
  tag: ${{ steps.tag_version.outputs.new_tag }}
92
89
  makeLatest: true
93
90
  name: Release ${{ steps.tag_version.outputs.new_tag }}
94
- body: ${{ steps.tag_version.outputs.changelog }}
91
+ bodyFile: release-notes.md
95
92
 
96
93
  pypi:
97
94
  name: Publish to PyPI
@@ -108,7 +105,7 @@ jobs:
108
105
  id-token: write
109
106
 
110
107
  steps:
111
- - uses: actions/checkout@v6
108
+ - uses: actions/checkout@v7
112
109
  with:
113
110
  ref: ${{ needs.release.outputs.tag }}
114
111
  # Fetch all history including tags.
@@ -117,7 +114,7 @@ jobs:
117
114
  persist-credentials: false
118
115
 
119
116
  - name: Install uv
120
- uses: astral-sh/setup-uv@v7
117
+ uses: astral-sh/setup-uv@v9.0.0
121
118
  with:
122
119
  enable-cache: true
123
120
  cache-dependency-glob: '**/pyproject.toml'
@@ -138,29 +135,32 @@ jobs:
138
135
  name: Publish Docker images
139
136
  needs: release
140
137
  runs-on: ubuntu-latest
138
+ environment: dockerhub
141
139
 
142
- permissions: {}
140
+ permissions:
141
+ packages: write
143
142
 
144
143
  steps:
145
- - uses: actions/checkout@v6
144
+ - uses: actions/checkout@v7
146
145
  with:
147
146
  ref: ${{ needs.release.outputs.tag }}
148
147
  persist-credentials: false
149
148
 
150
- - name: Login to DockerHub
151
- uses: docker/login-action@v3
149
+ - name: Login to GHCR
150
+ uses: docker/login-action@v4.6.0
152
151
  with:
153
- username: ${{ secrets.DOCKERHUB_USERNAME }}
154
- password: ${{ secrets.DOCKERHUB_TOKEN }}
152
+ registry: ghcr.io
153
+ username: ${{ github.actor }}
154
+ password: ${{ secrets.GITHUB_TOKEN }}
155
155
 
156
156
  - name: Set up Docker Buildx
157
- uses: docker/setup-buildx-action@v3
157
+ uses: docker/setup-buildx-action@v4
158
158
 
159
159
  - name: Set up QEMU
160
- uses: docker/setup-qemu-action@v3
160
+ uses: docker/setup-qemu-action@v4
161
161
 
162
162
  - name: Build and push Docker images
163
- uses: docker/bake-action@v6.10.0
163
+ uses: docker/bake-action@v7.3.0
164
164
  with:
165
165
  push: true
166
166
  env:
@@ -22,10 +22,11 @@ jobs:
22
22
  # CI tests with matrix
23
23
  ci-tests:
24
24
  runs-on: ubuntu-latest
25
+ environment: vuforia
25
26
  strategy:
26
27
  fail-fast: false
27
28
  matrix:
28
- python-version: ['3.13']
29
+ python-version: ['3.14']
29
30
  ci_pattern:
30
31
  - tests/mock_vws/test_query.py::TestContentType
31
32
  - tests/mock_vws/test_query.py::TestSuccess
@@ -112,33 +113,38 @@ jobs:
112
113
  - tests/mock_vws/test_update_target.py::TestWidth
113
114
  - tests/mock_vws/test_update_target.py::TestInactiveProject
114
115
  - tests/mock_vws/test_requests_mock_usage.py
116
+ - tests/mock_vws/test_respx_mock_usage.py
115
117
  - tests/mock_vws/test_flask_app_usage.py
118
+ - tests/mock_vws/test_model_target_web_api.py
116
119
  - tests/mock_vws/test_vumark_generation_api.py
120
+ - tests/mock_vws/test_target_validators.py
117
121
  - tests/mock_vws/test_docker.py
122
+ - ci/test_custom_linters.py
118
123
  - README.rst
119
- - docs/source/basic-example.rst
124
+ - docs/
120
125
 
121
126
  steps:
122
- - uses: actions/checkout@v6
127
+ - uses: actions/checkout@v7
123
128
  with:
124
129
  persist-credentials: false
125
130
 
126
131
  - name: Install uv
127
- uses: astral-sh/setup-uv@v7
132
+ uses: astral-sh/setup-uv@v9.0.0
128
133
  with:
129
134
  enable-cache: true
130
135
  cache-dependency-glob: '**/pyproject.toml'
131
136
 
132
137
  - name: Set secrets file
133
- run: |
134
- # See the "CI Setup" document for details of how this was set up.
135
- ci/decrypt_secret.sh
136
- tar xvf "${HOME}"/secrets/secrets.tar
137
- cp ./ci_secrets/vuforia_secrets_${{ strategy.job-index }}.env ./vuforia_secrets.env
138
138
  env:
139
139
  CI_PATTERN: ${{ matrix.ci_pattern }}
140
140
  ENCRYPTED_FILE: secrets.tar.gpg
141
141
  LARGE_SECRET_PASSPHRASE: ${{ secrets.PASSPHRASE_FOR_VUFORIA_SECRETS }}
142
+ JOB_INDEX: ${{ strategy.job-index }}
143
+ run: |
144
+ # See the "CI Setup" document for details of how this was set up.
145
+ ci/decrypt_secret.sh
146
+ tar xvf "${HOME}"/secrets/secrets.tar
147
+ cp "./ci_secrets/vuforia_secrets_${JOB_INDEX}.env" ./vuforia_secrets.env
142
148
 
143
149
  # We have seen issues with running out of disk space on test_docker
144
150
  - name: Free Disk Space (Ubuntu)
@@ -174,7 +180,7 @@ jobs:
174
180
  echo "name=coverage-data-ci-${{ matrix.python-version }}-${SANITIZED_PATTERN}" >> "$GITHUB_OUTPUT"
175
181
 
176
182
  - name: Upload coverage data
177
- uses: actions/upload-artifact@v6
183
+ uses: actions/upload-artifact@v7
178
184
  with:
179
185
  name: ${{ steps.sanitize.outputs.name }}
180
186
  path: .coverage.*
@@ -186,16 +192,16 @@ jobs:
186
192
  runs-on: ubuntu-latest
187
193
  strategy:
188
194
  matrix:
189
- python-version: ['3.13']
195
+ python-version: ['3.14']
190
196
  platform: [ubuntu-latest]
191
197
 
192
198
  steps:
193
- - uses: actions/checkout@v6
199
+ - uses: actions/checkout@v7
194
200
  with:
195
201
  persist-credentials: false
196
202
 
197
203
  - name: Install uv
198
- uses: astral-sh/setup-uv@v7
204
+ uses: astral-sh/setup-uv@v9.0.0
199
205
  with:
200
206
  enable-cache: true
201
207
  cache-dependency-glob: '**/pyproject.toml'
@@ -220,7 +226,7 @@ jobs:
220
226
  UV_PYTHON: ${{ matrix.python-version }}
221
227
 
222
228
  - name: Upload coverage data
223
- uses: actions/upload-artifact@v6
229
+ uses: actions/upload-artifact@v7
224
230
  with:
225
231
  name: coverage-data-skip-tests-${{ matrix.python-version }}
226
232
  path: .coverage.*
@@ -232,15 +238,15 @@ jobs:
232
238
  runs-on: windows-latest
233
239
  strategy:
234
240
  matrix:
235
- python-version: ['3.13']
241
+ python-version: ['3.14']
236
242
 
237
243
  steps:
238
- - uses: actions/checkout@v6
244
+ - uses: actions/checkout@v7
239
245
  with:
240
246
  persist-credentials: false
241
247
 
242
248
  - name: Install uv
243
- uses: astral-sh/setup-uv@v7
249
+ uses: astral-sh/setup-uv@v9.0.0
244
250
  with:
245
251
  enable-cache: true
246
252
  cache-dependency-glob: '**/pyproject.toml'
@@ -249,17 +255,29 @@ jobs:
249
255
  run: |
250
256
  cp ./vuforia_secrets.env.example ./vuforia_secrets.env
251
257
 
258
+ - name: Start Docker
259
+ shell: pwsh
260
+ run: |
261
+ $service = Get-Service docker -ErrorAction Stop
262
+ if ($service.Status -ne "Running") {
263
+ Start-Service docker
264
+ }
265
+ $deadline = (Get-Date).AddMinutes(2)
266
+ do {
267
+ docker info
268
+ if ($LASTEXITCODE -eq 0) {
269
+ exit 0
270
+ }
271
+ Start-Sleep -Seconds 5
272
+ } while ((Get-Date) -lt $deadline)
273
+ docker info
274
+
252
275
  - name: Run tests
253
276
  shell: bash
254
277
  run: |
255
278
  # We use pytest-xdist to make this run much faster.
256
279
  # The downside is that we cannot use -s / --capture=no.
257
280
  #
258
- # We use coverage to collect coverage data but we currently
259
- # do not upload / use it because combining Windows and Linux
260
- # coverage is challenging.
261
- #
262
- # We therefore have a few ``# pragma: no cover`` statements.
263
281
  uv run --extra=dev \
264
282
  coverage run -m pytest \
265
283
  --skip-real \
@@ -270,6 +288,14 @@ jobs:
270
288
  env:
271
289
  UV_PYTHON: ${{ matrix.python-version }}
272
290
 
291
+ - name: Upload coverage data
292
+ uses: actions/upload-artifact@v7
293
+ with:
294
+ name: coverage-data-windows-${{ matrix.python-version }}
295
+ path: .coverage.*
296
+ include-hidden-files: true
297
+ if-no-files-found: error
298
+
273
299
  coverage:
274
300
  name: Combine & check coverage
275
301
  needs: [ci-tests, skip-tests, windows-tests]
@@ -277,17 +303,18 @@ jobs:
277
303
  runs-on: ubuntu-latest
278
304
 
279
305
  steps:
280
- - uses: actions/checkout@v6
306
+ - uses: actions/checkout@v7
281
307
  with:
282
308
  persist-credentials: false
283
309
 
284
310
  - name: Install uv
285
- uses: astral-sh/setup-uv@v7
311
+ uses: astral-sh/setup-uv@v9.0.0
286
312
  with:
287
313
  enable-cache: true
288
314
  cache-dependency-glob: '**/pyproject.toml'
315
+ python-version: '3.14'
289
316
 
290
- - uses: actions/download-artifact@v7
317
+ - uses: actions/download-artifact@v8
291
318
  with:
292
319
  pattern: coverage-data-*
293
320
  merge-multiple: true
@@ -307,14 +334,14 @@ jobs:
307
334
  coverage report
308
335
 
309
336
  - name: Upload HTML report if check failed
310
- uses: actions/upload-artifact@v6
337
+ uses: actions/upload-artifact@v7
311
338
  with:
312
339
  name: html-report
313
340
  path: htmlcov
314
341
  if: ${{ failure() }}
315
342
 
316
343
  # Final completion check
317
- completion:
344
+ completion-ci:
318
345
  needs: [ci-tests, skip-tests, windows-tests, coverage]
319
346
  runs-on: ubuntu-latest
320
347
  if: always()
@@ -112,3 +112,5 @@ secrets.tar
112
112
  src/*/_setuptools_scm_version.txt
113
113
 
114
114
  uv.lock
115
+
116
+ .claude/scheduled_tasks.lock