vws-python-mock 2026.4.26__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.
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.github/workflows/docker-build.yml +3 -3
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.github/workflows/lint.yml +5 -2
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.github/workflows/release.yml +26 -34
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.github/workflows/test.yml +34 -13
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.pre-commit-config.yaml +14 -2
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/CHANGELOG.rst +22 -2
- {vws_python_mock-2026.4.26/src/vws_python_mock.egg-info → vws_python_mock-2026.8.4}/PKG-INFO +30 -26
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/README.rst +1 -1
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/admin/create_secrets_files.py +35 -1
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/conftest.py +2 -2
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/conf.py +9 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/differences-to-vws.rst +38 -4
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/index.rst +1 -0
- vws_python_mock-2026.8.4/docs/source/unreleased.rst +8 -0
- vws_python_mock-2026.8.4/docs/towncrier_template.rst.jinja +14 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/pyproject.toml +224 -171
- vws_python_mock-2026.8.4/secrets.tar.gpg +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/spelling_private_dict.txt +1 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_constants.py +6 -2
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/target_manager.py +32 -9
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/vwq.py +6 -5
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/vws.py +200 -6
- vws_python_mock-2026.8.4/src/mock_vws/_model_target_web_api.py +486 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/decorators.py +9 -2
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/mock_web_services_api.py +162 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_respx_mock_server/decorators.py +4 -1
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/__init__.py +16 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/exceptions.py +134 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/project_state_validators.py +13 -1
- vws_python_mock-2026.8.4/src/mock_vws/_services_validators/request_quota_validators.py +42 -0
- vws_python_mock-2026.8.4/src/mock_vws/_services_validators/target_quota_validators.py +41 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/database.py +11 -1
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/image_matchers.py +2 -12
- vws_python_mock-2026.8.4/src/mock_vws/model_target.py +79 -0
- vws_python_mock-2026.8.4/src/mock_vws/py.typed +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/states.py +4 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/target_manager.py +20 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/target_raters.py +1 -6
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4/src/vws_python_mock.egg-info}/PKG-INFO +30 -26
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/SOURCES.txt +10 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/requires.txt +28 -24
- vws_python_mock-2026.8.4/src/vws_python_mock.egg-info/scm_file_list.json +146 -0
- vws_python_mock-2026.8.4/src/vws_python_mock.egg-info/scm_version.json +8 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/credentials.py +35 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/prepared_requests.py +2 -2
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/vuforia_backends.py +79 -2
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_authorization_header.py +1 -1
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_date_header.py +1 -1
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_docker.py +36 -11
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_flask_app_usage.py +129 -1
- vws_python_mock-2026.8.4/tests/mock_vws/test_model_target_web_api.py +657 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_requests_mock_usage.py +299 -1
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_respx_mock_usage.py +48 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/retries.py +7 -3
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/vuforia_secrets.env.example +4 -0
- vws_python_mock-2026.4.26/secrets.tar.gpg +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.git_archival.txt +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.gitattributes +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.github/dependabot.yml +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.github/workflows/dependabot-merge.yml +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.github/workflows/publish-site.yml +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.gitignore +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.prettierrc +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.vscode/extensions.json +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/.vscode/settings.json +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/CODE_OF_CONDUCT.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/LICENSE +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/MANIFEST.in +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/admin/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/admin/vumark_template.svg +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/ci/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/ci/decrypt_secret.sh +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/ci/test_custom_linters.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docker-bake.hcl +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/basic-example.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/changelog.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/ci-setup.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/contributing.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/docker.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/getting-started.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/httpx-example.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/installation.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/mock-api-reference.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/release-process.rst +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/docs/source/versioning-and-api-stability.rst +0 -0
- /vws_python_mock-2026.4.26/src/mock_vws/py.typed → /vws_python_mock-2026.8.4/newsfragments/.gitkeep +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/setup.cfg +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_base64_decoding.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_database_matchers.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/Dockerfile +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_flask_server/healthcheck.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_mock_common.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_tools.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/accept_header_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/auth_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/content_length_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/content_type_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/date_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/exceptions.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/fields_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/image_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/include_target_data_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/num_results_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_query_validators/project_state_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_requests_mock_server/mock_web_query_api.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_respx_mock_server/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/active_flag_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/auth_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/content_length_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/content_type_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/date_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/image_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/json_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/key_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/metadata_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/name_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/target_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/_services_validators/width_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/database_type.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/mock_vws/target.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/dependency_links.txt +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/not-zip-safe +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/src/vws_python_mock.egg-info/top_level.txt +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/conftest.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/fixtures/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_add_target.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_content_length.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_database_summary.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_delete_target.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_get_duplicates.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_get_target.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_invalid_given_id.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_invalid_json.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_query.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_list.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_raters.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_summary.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_target_validators.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_unexpected_json.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_update_target.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/test_vumark_generation_api.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/__init__.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/assertions.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/too_many_requests.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/tests/mock_vws/utils/usage_test_helpers.py +0 -0
- {vws_python_mock-2026.4.26 → vws_python_mock-2026.8.4}/zizmor.yml +0 -0
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
runs-on: ubuntu-latest
|
|
25
25
|
|
|
26
26
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@v7
|
|
28
28
|
with:
|
|
29
29
|
persist-credentials: false
|
|
30
30
|
|
|
@@ -35,11 +35,11 @@ jobs:
|
|
|
35
35
|
uses: docker/setup-buildx-action@v4
|
|
36
36
|
|
|
37
37
|
- name: Check Docker bake definition
|
|
38
|
-
uses: docker/bake-action@v7.
|
|
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@v7.
|
|
43
|
+
uses: docker/bake-action@v7.3.0
|
|
44
44
|
with:
|
|
45
45
|
push: false
|
|
@@ -25,12 +25,12 @@ jobs:
|
|
|
25
25
|
runs-on: ${{ matrix.platform }}
|
|
26
26
|
|
|
27
27
|
steps:
|
|
28
|
-
- uses: actions/checkout@
|
|
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@
|
|
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
|
|
@@ -18,7 +18,7 @@ jobs:
|
|
|
18
18
|
tag: ${{ steps.tag_version.outputs.new_tag }}
|
|
19
19
|
|
|
20
20
|
steps:
|
|
21
|
-
- uses: actions/checkout@
|
|
21
|
+
- uses: actions/checkout@v7
|
|
22
22
|
with:
|
|
23
23
|
# Fetch all history including tags.
|
|
24
24
|
# Needed to find the latest tag.
|
|
@@ -34,6 +34,12 @@ jobs:
|
|
|
34
34
|
# The default GITHUB_TOKEN cannot bypass rulesets.
|
|
35
35
|
token: ${{ secrets.RELEASE_PAT }}
|
|
36
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
|
+
|
|
37
43
|
- name: Calver calculate version
|
|
38
44
|
uses: StephaneBour/actions-calver@master
|
|
39
45
|
id: calver
|
|
@@ -43,41 +49,27 @@ jobs:
|
|
|
43
49
|
env:
|
|
44
50
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
48
56
|
env:
|
|
49
57
|
RELEASE: ${{ steps.calver.outputs.release }}
|
|
50
|
-
run:
|
|
51
|
-
|
|
52
|
-
echo "underline=${underline}" >> "$GITHUB_OUTPUT"
|
|
58
|
+
run: uv run --extra=release towncrier build --draft --version "$RELEASE" >
|
|
59
|
+
release-notes.md
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
with:
|
|
58
|
-
find: "Next\n----"
|
|
59
|
-
replace: |
|
|
60
|
-
Next
|
|
61
|
-
----
|
|
62
|
-
|
|
63
|
-
${{ steps.calver.outputs.release }}
|
|
64
|
-
${{ steps.changelog_underline.outputs.underline }}
|
|
65
|
-
include: CHANGELOG.rst
|
|
66
|
-
regex: false
|
|
67
|
-
|
|
68
|
-
- name: Check Update changelog was modified
|
|
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
|
|
69
64
|
env:
|
|
70
|
-
|
|
71
|
-
run:
|
|
72
|
-
|
|
73
|
-
echo "Error: No files were modified when updating changelog"
|
|
74
|
-
exit 1
|
|
75
|
-
fi
|
|
65
|
+
RELEASE: ${{ steps.calver.outputs.release }}
|
|
66
|
+
run: uv run --extra=release towncrier build --yes --version "$RELEASE"
|
|
67
|
+
|
|
76
68
|
- uses: stefanzweifel/git-auto-commit-action@v7
|
|
77
69
|
id: commit
|
|
78
70
|
with:
|
|
79
71
|
commit_message: Bump CHANGELOG
|
|
80
|
-
file_pattern: CHANGELOG.rst
|
|
72
|
+
file_pattern: CHANGELOG.rst newsfragments
|
|
81
73
|
# Error if there are no changes.
|
|
82
74
|
skip_dirty_check: true
|
|
83
75
|
|
|
@@ -96,7 +88,7 @@ jobs:
|
|
|
96
88
|
tag: ${{ steps.tag_version.outputs.new_tag }}
|
|
97
89
|
makeLatest: true
|
|
98
90
|
name: Release ${{ steps.tag_version.outputs.new_tag }}
|
|
99
|
-
|
|
91
|
+
bodyFile: release-notes.md
|
|
100
92
|
|
|
101
93
|
pypi:
|
|
102
94
|
name: Publish to PyPI
|
|
@@ -113,7 +105,7 @@ jobs:
|
|
|
113
105
|
id-token: write
|
|
114
106
|
|
|
115
107
|
steps:
|
|
116
|
-
- uses: actions/checkout@
|
|
108
|
+
- uses: actions/checkout@v7
|
|
117
109
|
with:
|
|
118
110
|
ref: ${{ needs.release.outputs.tag }}
|
|
119
111
|
# Fetch all history including tags.
|
|
@@ -122,7 +114,7 @@ jobs:
|
|
|
122
114
|
persist-credentials: false
|
|
123
115
|
|
|
124
116
|
- name: Install uv
|
|
125
|
-
uses: astral-sh/setup-uv@
|
|
117
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
126
118
|
with:
|
|
127
119
|
enable-cache: true
|
|
128
120
|
cache-dependency-glob: '**/pyproject.toml'
|
|
@@ -149,13 +141,13 @@ jobs:
|
|
|
149
141
|
packages: write
|
|
150
142
|
|
|
151
143
|
steps:
|
|
152
|
-
- uses: actions/checkout@
|
|
144
|
+
- uses: actions/checkout@v7
|
|
153
145
|
with:
|
|
154
146
|
ref: ${{ needs.release.outputs.tag }}
|
|
155
147
|
persist-credentials: false
|
|
156
148
|
|
|
157
149
|
- name: Login to GHCR
|
|
158
|
-
uses: docker/login-action@v4
|
|
150
|
+
uses: docker/login-action@v4.6.0
|
|
159
151
|
with:
|
|
160
152
|
registry: ghcr.io
|
|
161
153
|
username: ${{ github.actor }}
|
|
@@ -168,7 +160,7 @@ jobs:
|
|
|
168
160
|
uses: docker/setup-qemu-action@v4
|
|
169
161
|
|
|
170
162
|
- name: Build and push Docker images
|
|
171
|
-
uses: docker/bake-action@v7.
|
|
163
|
+
uses: docker/bake-action@v7.3.0
|
|
172
164
|
with:
|
|
173
165
|
push: true
|
|
174
166
|
env:
|
|
@@ -115,6 +115,7 @@ jobs:
|
|
|
115
115
|
- tests/mock_vws/test_requests_mock_usage.py
|
|
116
116
|
- tests/mock_vws/test_respx_mock_usage.py
|
|
117
117
|
- tests/mock_vws/test_flask_app_usage.py
|
|
118
|
+
- tests/mock_vws/test_model_target_web_api.py
|
|
118
119
|
- tests/mock_vws/test_vumark_generation_api.py
|
|
119
120
|
- tests/mock_vws/test_target_validators.py
|
|
120
121
|
- tests/mock_vws/test_docker.py
|
|
@@ -123,12 +124,12 @@ jobs:
|
|
|
123
124
|
- docs/
|
|
124
125
|
|
|
125
126
|
steps:
|
|
126
|
-
- uses: actions/checkout@
|
|
127
|
+
- uses: actions/checkout@v7
|
|
127
128
|
with:
|
|
128
129
|
persist-credentials: false
|
|
129
130
|
|
|
130
131
|
- name: Install uv
|
|
131
|
-
uses: astral-sh/setup-uv@
|
|
132
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
132
133
|
with:
|
|
133
134
|
enable-cache: true
|
|
134
135
|
cache-dependency-glob: '**/pyproject.toml'
|
|
@@ -195,12 +196,12 @@ jobs:
|
|
|
195
196
|
platform: [ubuntu-latest]
|
|
196
197
|
|
|
197
198
|
steps:
|
|
198
|
-
- uses: actions/checkout@
|
|
199
|
+
- uses: actions/checkout@v7
|
|
199
200
|
with:
|
|
200
201
|
persist-credentials: false
|
|
201
202
|
|
|
202
203
|
- name: Install uv
|
|
203
|
-
uses: astral-sh/setup-uv@
|
|
204
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
204
205
|
with:
|
|
205
206
|
enable-cache: true
|
|
206
207
|
cache-dependency-glob: '**/pyproject.toml'
|
|
@@ -240,12 +241,12 @@ jobs:
|
|
|
240
241
|
python-version: ['3.14']
|
|
241
242
|
|
|
242
243
|
steps:
|
|
243
|
-
- uses: actions/checkout@
|
|
244
|
+
- uses: actions/checkout@v7
|
|
244
245
|
with:
|
|
245
246
|
persist-credentials: false
|
|
246
247
|
|
|
247
248
|
- name: Install uv
|
|
248
|
-
uses: astral-sh/setup-uv@
|
|
249
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
249
250
|
with:
|
|
250
251
|
enable-cache: true
|
|
251
252
|
cache-dependency-glob: '**/pyproject.toml'
|
|
@@ -254,17 +255,29 @@ jobs:
|
|
|
254
255
|
run: |
|
|
255
256
|
cp ./vuforia_secrets.env.example ./vuforia_secrets.env
|
|
256
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
|
+
|
|
257
275
|
- name: Run tests
|
|
258
276
|
shell: bash
|
|
259
277
|
run: |
|
|
260
278
|
# We use pytest-xdist to make this run much faster.
|
|
261
279
|
# The downside is that we cannot use -s / --capture=no.
|
|
262
280
|
#
|
|
263
|
-
# We use coverage to collect coverage data but we currently
|
|
264
|
-
# do not upload / use it because combining Windows and Linux
|
|
265
|
-
# coverage is challenging.
|
|
266
|
-
#
|
|
267
|
-
# We therefore have a few ``# pragma: no cover`` statements.
|
|
268
281
|
uv run --extra=dev \
|
|
269
282
|
coverage run -m pytest \
|
|
270
283
|
--skip-real \
|
|
@@ -275,6 +288,14 @@ jobs:
|
|
|
275
288
|
env:
|
|
276
289
|
UV_PYTHON: ${{ matrix.python-version }}
|
|
277
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
|
+
|
|
278
299
|
coverage:
|
|
279
300
|
name: Combine & check coverage
|
|
280
301
|
needs: [ci-tests, skip-tests, windows-tests]
|
|
@@ -282,12 +303,12 @@ jobs:
|
|
|
282
303
|
runs-on: ubuntu-latest
|
|
283
304
|
|
|
284
305
|
steps:
|
|
285
|
-
- uses: actions/checkout@
|
|
306
|
+
- uses: actions/checkout@v7
|
|
286
307
|
with:
|
|
287
308
|
persist-credentials: false
|
|
288
309
|
|
|
289
310
|
- name: Install uv
|
|
290
|
-
uses: astral-sh/setup-uv@
|
|
311
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
291
312
|
with:
|
|
292
313
|
enable-cache: true
|
|
293
314
|
cache-dependency-glob: '**/pyproject.toml'
|
|
@@ -9,6 +9,7 @@ ci:
|
|
|
9
9
|
skip:
|
|
10
10
|
- actionlint
|
|
11
11
|
- sphinx-lint
|
|
12
|
+
- strict-kwargs-fix
|
|
12
13
|
- check-manifest
|
|
13
14
|
- custom-linters
|
|
14
15
|
- deptry
|
|
@@ -174,7 +175,7 @@ repos:
|
|
|
174
175
|
- id: mypy
|
|
175
176
|
name: mypy
|
|
176
177
|
stages: [pre-push]
|
|
177
|
-
entry: uv run --extra=dev -m mypy
|
|
178
|
+
entry: uv run --extra=dev -m mypy --num-workers=4
|
|
178
179
|
language: python
|
|
179
180
|
types_or: [python, toml]
|
|
180
181
|
pass_filenames: false
|
|
@@ -185,7 +186,8 @@ repos:
|
|
|
185
186
|
- id: mypy-docs
|
|
186
187
|
name: mypy-docs
|
|
187
188
|
stages: [pre-push]
|
|
188
|
-
entry: uv run --extra=dev doccmd --no-write-to-file --language=python --command="mypy
|
|
189
|
+
entry: uv run --extra=dev doccmd --no-write-to-file --language=python --command="mypy
|
|
190
|
+
--num-workers=4"
|
|
189
191
|
language: python
|
|
190
192
|
types_or: [markdown, rst]
|
|
191
193
|
|
|
@@ -337,6 +339,16 @@ repos:
|
|
|
337
339
|
- *uv_version
|
|
338
340
|
stages: [pre-commit]
|
|
339
341
|
|
|
342
|
+
- id: strict-kwargs-fix
|
|
343
|
+
name: strict-kwargs
|
|
344
|
+
entry: uv run --extra=dev strict-kwargs check --fix
|
|
345
|
+
language: python
|
|
346
|
+
types_or: [python]
|
|
347
|
+
additional_dependencies:
|
|
348
|
+
- *uv_version
|
|
349
|
+
stages: [pre-commit]
|
|
350
|
+
require_serial: true
|
|
351
|
+
|
|
340
352
|
- id: doc8
|
|
341
353
|
name: doc8
|
|
342
354
|
entry: uv run --extra=dev -m doc8
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
.. towncrier release notes start
|
|
5
|
+
|
|
6
|
+
2026.08.04
|
|
7
|
+
----------
|
|
8
|
+
|
|
9
|
+
- Cloud databases with ``request_quota=0`` now return a
|
|
10
|
+
``RequestQuotaReached`` response from VWS endpoints.
|
|
11
|
+
|
|
12
|
+
- Add a mock implementation of the Model Target Web API, including OAuth2 token creation, standard and advanced dataset creation, status polling, dataset download, and deletion.
|
|
13
|
+
|
|
14
|
+
- Improve Model Target Web API mock authentication failure responses.
|
|
15
|
+
|
|
16
|
+
- Match real Vuforia Model Target dataset creation validation error shape, including per-request UUID, details list, and status codes (415 for unsupported media type, 400 with ``BAD_REQUEST`` validation details).
|
|
17
|
+
|
|
18
|
+
- Match real Vuforia Model Target unknown-dataset response shape (``NOT_FOUND`` code, ``Could not find a model-view database with uuid <uuid>`` message, ``userId:`` target).
|
|
19
|
+
|
|
20
|
+
- Make synthetic Model Target dataset zip downloads byte-for-byte reproducible.
|
|
21
|
+
|
|
22
|
+
- Match real Vuforia Model Target Web API error responses for invalid request bodies, invalid dataset creation payloads, unknown datasets, and downloads of still-processing datasets.
|
|
23
|
+
|
|
24
|
+
- Add configurable ``TargetQuotaReached``, ``ProjectSuspended``, and
|
|
25
|
+
``ProjectHasNoAPIAccess`` responses from VWS endpoints.
|
|
6
26
|
|
|
7
27
|
2026.04.26
|
|
8
28
|
----------
|
{vws_python_mock-2026.4.26/src/vws_python_mock.egg-info → vws_python_mock-2026.8.4}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vws-python-mock
|
|
3
|
-
Version: 2026.4
|
|
3
|
+
Version: 2026.8.4
|
|
4
4
|
Summary: A mock for the Vuforia Web Services (VWS) API.
|
|
5
5
|
Author-email: Adam Dangoor <adamdangoor@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -37,59 +37,63 @@ Provides-Extra: dev
|
|
|
37
37
|
Requires-Dist: actionlint-py==1.7.12.24; extra == "dev"
|
|
38
38
|
Requires-Dist: check-manifest==0.51; extra == "dev"
|
|
39
39
|
Requires-Dist: check-wheel-contents==0.6.3; extra == "dev"
|
|
40
|
-
Requires-Dist: coverage==7.
|
|
40
|
+
Requires-Dist: coverage==7.15.2; extra == "dev"
|
|
41
41
|
Requires-Dist: deptry==0.25.1; extra == "dev"
|
|
42
42
|
Requires-Dist: dirty-equals==0.11; extra == "dev"
|
|
43
43
|
Requires-Dist: doc8==2.0.0; extra == "dev"
|
|
44
|
-
Requires-Dist: doccmd==2026.
|
|
45
|
-
Requires-Dist: docker==7.
|
|
44
|
+
Requires-Dist: doccmd==2026.7.19; extra == "dev"
|
|
45
|
+
Requires-Dist: docker==7.2.0; extra == "dev"
|
|
46
46
|
Requires-Dist: freezegun==1.5.5; extra == "dev"
|
|
47
47
|
Requires-Dist: furo==2025.12.19; extra == "dev"
|
|
48
48
|
Requires-Dist: interrogate==1.7.0; extra == "dev"
|
|
49
|
-
Requires-Dist: mypy[faster-cache]==
|
|
50
|
-
Requires-Dist: mypy-strict-kwargs==2026.1
|
|
51
|
-
Requires-Dist: prek==0.
|
|
52
|
-
Requires-Dist: pydocstringformatter==0.
|
|
49
|
+
Requires-Dist: mypy[faster-cache]==2.3.0; extra == "dev"
|
|
50
|
+
Requires-Dist: mypy-strict-kwargs==2026.7.19.1; extra == "dev"
|
|
51
|
+
Requires-Dist: prek==0.4.11; extra == "dev"
|
|
52
|
+
Requires-Dist: pydocstringformatter==1.0.0; extra == "dev"
|
|
53
53
|
Requires-Dist: pydocstyle==6.3; extra == "dev"
|
|
54
|
-
Requires-Dist: pylint[spelling]==4.0.
|
|
54
|
+
Requires-Dist: pylint[spelling]==4.0.6; extra == "dev"
|
|
55
55
|
Requires-Dist: pylint-per-file-ignores==3.2.1; extra == "dev"
|
|
56
|
-
Requires-Dist: pyproject-fmt==2.
|
|
57
|
-
Requires-Dist: pyrefly==
|
|
58
|
-
Requires-Dist: pyright==1.1.
|
|
56
|
+
Requires-Dist: pyproject-fmt==2.26.0; extra == "dev"
|
|
57
|
+
Requires-Dist: pyrefly==1.1.1; extra == "dev"
|
|
58
|
+
Requires-Dist: pyright==1.1.411; extra == "dev"
|
|
59
59
|
Requires-Dist: pyroma==5.0.1; extra == "dev"
|
|
60
|
-
Requires-Dist: pytest==9.
|
|
60
|
+
Requires-Dist: pytest==9.1.1; extra == "dev"
|
|
61
61
|
Requires-Dist: pytest-beartype-tests==2026.4.26; extra == "dev"
|
|
62
62
|
Requires-Dist: pytest-retry==1.7.0; extra == "dev"
|
|
63
63
|
Requires-Dist: pytest-xdist==3.8.0; extra == "dev"
|
|
64
64
|
Requires-Dist: pyyaml==6.0.3; extra == "dev"
|
|
65
65
|
Requires-Dist: requests-mock-flask==2026.4.2; extra == "dev"
|
|
66
|
-
Requires-Dist: ruff==0.
|
|
66
|
+
Requires-Dist: ruff==0.16.1; extra == "dev"
|
|
67
67
|
Requires-Dist: shellcheck-py==0.11.0.1; extra == "dev"
|
|
68
|
-
Requires-Dist: shfmt-py==
|
|
68
|
+
Requires-Dist: shfmt-py==4.0.0; extra == "dev"
|
|
69
69
|
Requires-Dist: sphinx==9.1.0; extra == "dev"
|
|
70
70
|
Requires-Dist: sphinx-copybutton==0.5.2; extra == "dev"
|
|
71
71
|
Requires-Dist: sphinx-lint==1.0.2; extra == "dev"
|
|
72
72
|
Requires-Dist: sphinx-paramlinks==0.6; extra == "dev"
|
|
73
73
|
Requires-Dist: sphinx-pyproject==0.3.0; extra == "dev"
|
|
74
|
-
Requires-Dist: sphinx-substitution-extensions==2026.
|
|
75
|
-
Requires-Dist: sphinx-toolbox==4.
|
|
74
|
+
Requires-Dist: sphinx-substitution-extensions==2026.6.17; extra == "dev"
|
|
75
|
+
Requires-Dist: sphinx-toolbox==4.3.0; extra == "dev"
|
|
76
76
|
Requires-Dist: sphinxcontrib-httpdomain==2.0.0; extra == "dev"
|
|
77
77
|
Requires-Dist: sphinxcontrib-spelling==8.0.2; extra == "dev"
|
|
78
|
-
Requires-Dist:
|
|
78
|
+
Requires-Dist: sphinxcontrib-towncrier==0.5.0a0; extra == "dev"
|
|
79
|
+
Requires-Dist: strict-kwargs==2026.7.24; extra == "dev"
|
|
80
|
+
Requires-Dist: sybil==10.1.0; extra == "dev"
|
|
79
81
|
Requires-Dist: tenacity==9.1.4; extra == "dev"
|
|
80
|
-
Requires-Dist:
|
|
81
|
-
Requires-Dist:
|
|
82
|
-
Requires-Dist: types-
|
|
83
|
-
Requires-Dist: types-
|
|
84
|
-
Requires-Dist:
|
|
82
|
+
Requires-Dist: towncrier==25.8.0; extra == "dev"
|
|
83
|
+
Requires-Dist: ty==0.0.65; extra == "dev"
|
|
84
|
+
Requires-Dist: types-docker==7.2.0.20260728; extra == "dev"
|
|
85
|
+
Requires-Dist: types-pyyaml==6.0.12.20260724; extra == "dev"
|
|
86
|
+
Requires-Dist: types-requests==2.33.0.20260712; extra == "dev"
|
|
87
|
+
Requires-Dist: urllib3==2.7.0; extra == "dev"
|
|
85
88
|
Requires-Dist: vulture==2.16; extra == "dev"
|
|
86
89
|
Requires-Dist: vws-python==2026.2.25.1; extra == "dev"
|
|
87
90
|
Requires-Dist: vws-test-fixtures==2023.3.5; extra == "dev"
|
|
88
|
-
Requires-Dist: vws-web-tools==2026.
|
|
91
|
+
Requires-Dist: vws-web-tools==2026.5.21; extra == "dev"
|
|
89
92
|
Requires-Dist: yamlfix==1.19.1; extra == "dev"
|
|
90
|
-
Requires-Dist: zizmor==1.
|
|
93
|
+
Requires-Dist: zizmor==1.28.0; extra == "dev"
|
|
91
94
|
Provides-Extra: release
|
|
92
95
|
Requires-Dist: check-wheel-contents==0.6.3; extra == "release"
|
|
96
|
+
Requires-Dist: towncrier==25.8.0; extra == "release"
|
|
93
97
|
Dynamic: license-file
|
|
94
98
|
|
|
95
99
|
|Build Status| |PyPI|
|
|
@@ -100,7 +104,7 @@ VWS Mock
|
|
|
100
104
|
.. contents::
|
|
101
105
|
:local:
|
|
102
106
|
|
|
103
|
-
Mock for the Vuforia Web Services (VWS) API
|
|
107
|
+
Mock for the Vuforia Web Services (VWS) API, the Vuforia Web Query API, and the Model Target Web API.
|
|
104
108
|
|
|
105
109
|
Mocking calls made to Vuforia
|
|
106
110
|
------------------------------
|
|
@@ -6,7 +6,7 @@ VWS Mock
|
|
|
6
6
|
.. contents::
|
|
7
7
|
:local:
|
|
8
8
|
|
|
9
|
-
Mock for the Vuforia Web Services (VWS) API
|
|
9
|
+
Mock for the Vuforia Web Services (VWS) API, the Vuforia Web Query API, and the Model Target Web API.
|
|
10
10
|
|
|
11
11
|
Mocking calls made to Vuforia
|
|
12
12
|
------------------------------
|
|
@@ -12,7 +12,11 @@ from pathlib import Path
|
|
|
12
12
|
import vws_web_tools
|
|
13
13
|
from selenium.common.exceptions import TimeoutException
|
|
14
14
|
from selenium.webdriver.remote.webdriver import WebDriver
|
|
15
|
-
from vws_web_tools import
|
|
15
|
+
from vws_web_tools import (
|
|
16
|
+
DatabaseDict,
|
|
17
|
+
ModelTargetWebAPIDict,
|
|
18
|
+
VuMarkDatabaseDict,
|
|
19
|
+
)
|
|
16
20
|
|
|
17
21
|
VUMARK_TEMPLATE_SVG_FILE_PATH = Path(__file__).with_name(
|
|
18
22
|
name="vumark_template.svg",
|
|
@@ -72,11 +76,13 @@ def _create_and_get_vumark_details(
|
|
|
72
76
|
|
|
73
77
|
|
|
74
78
|
def _generate_secrets_file_content(
|
|
79
|
+
*,
|
|
75
80
|
cloud_database_details: DatabaseDict,
|
|
76
81
|
vumark_details: VuMarkDatabaseDict,
|
|
77
82
|
inactive_database_details: DatabaseDict,
|
|
78
83
|
inactive_vumark_details: VuMarkDatabaseDict,
|
|
79
84
|
vumark_target_id: str,
|
|
85
|
+
model_target_web_api_details: ModelTargetWebAPIDict,
|
|
80
86
|
) -> str:
|
|
81
87
|
"""Generate the content of a secrets file."""
|
|
82
88
|
return textwrap.dedent(
|
|
@@ -101,6 +107,10 @@ def _generate_secrets_file_content(
|
|
|
101
107
|
INACTIVE_VUMARK_VUFORIA_TARGET_MANAGER_DATABASE_NAME={inactive_vumark_details["database_name"]}
|
|
102
108
|
INACTIVE_VUMARK_VUFORIA_SERVER_ACCESS_KEY={inactive_vumark_details["server_access_key"]}
|
|
103
109
|
INACTIVE_VUMARK_VUFORIA_SERVER_SECRET_KEY={inactive_vumark_details["server_secret_key"]}
|
|
110
|
+
|
|
111
|
+
MODEL_TARGET_VUFORIA_CLIENT_ID={model_target_web_api_details["client_id"]}
|
|
112
|
+
MODEL_TARGET_VUFORIA_CLIENT_SECRET={model_target_web_api_details["client_secret"]}
|
|
113
|
+
MODEL_TARGET_VUFORIA_CAD_DATA_URL={model_target_web_api_details["cad_data_url"]}
|
|
104
114
|
""",
|
|
105
115
|
)
|
|
106
116
|
|
|
@@ -193,6 +203,21 @@ def _create_and_get_inactive_vumark_details(
|
|
|
193
203
|
return vumark_database_details
|
|
194
204
|
|
|
195
205
|
|
|
206
|
+
def _get_model_target_web_api_details(
|
|
207
|
+
driver: WebDriver,
|
|
208
|
+
email_address: str,
|
|
209
|
+
password: str,
|
|
210
|
+
) -> ModelTargetWebAPIDict:
|
|
211
|
+
"""Get credentials and input data for the Model Target Web API."""
|
|
212
|
+
vws_web_tools.log_in(
|
|
213
|
+
driver=driver,
|
|
214
|
+
email_address=email_address,
|
|
215
|
+
password=password,
|
|
216
|
+
)
|
|
217
|
+
vws_web_tools.wait_for_logged_in(driver=driver)
|
|
218
|
+
return vws_web_tools.get_model_target_web_api_details(driver=driver)
|
|
219
|
+
|
|
220
|
+
|
|
196
221
|
def _create_vuforia_resource_names() -> tuple[str, str, str, str]:
|
|
197
222
|
"""Create names for Vuforia resources."""
|
|
198
223
|
time = datetime.datetime.now(tz=datetime.UTC).strftime(
|
|
@@ -236,6 +261,14 @@ def main() -> None:
|
|
|
236
261
|
)
|
|
237
262
|
inactive_vumark_driver.quit()
|
|
238
263
|
|
|
264
|
+
model_target_driver = vws_web_tools.create_chrome_driver()
|
|
265
|
+
model_target_web_api_details = _get_model_target_web_api_details(
|
|
266
|
+
driver=model_target_driver,
|
|
267
|
+
email_address=email_address,
|
|
268
|
+
password=password,
|
|
269
|
+
)
|
|
270
|
+
model_target_driver.quit()
|
|
271
|
+
|
|
239
272
|
num_databases = 100
|
|
240
273
|
required_files = [
|
|
241
274
|
(new_secrets_dir / f"vuforia_secrets_{i}.env")
|
|
@@ -291,6 +324,7 @@ def main() -> None:
|
|
|
291
324
|
inactive_database_details=inactive_database_details,
|
|
292
325
|
inactive_vumark_details=inactive_vumark_details,
|
|
293
326
|
vumark_target_id=vumark_target_id,
|
|
327
|
+
model_target_web_api_details=model_target_web_api_details,
|
|
294
328
|
)
|
|
295
329
|
file.write_text(data=file_contents)
|
|
296
330
|
sys.stdout.write(f"Created database {file.name}\n")
|
|
@@ -10,7 +10,7 @@ from sybil.parsers.rest import (
|
|
|
10
10
|
PythonCodeBlockParser,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
-
from tests.mock_vws.utils.retries import
|
|
13
|
+
from tests.mock_vws.utils.retries import TRANSIENT_VWS_EXCEPTIONS
|
|
14
14
|
|
|
15
15
|
pytest_collect_file = Sybil(
|
|
16
16
|
parsers=[
|
|
@@ -29,4 +29,4 @@ def pytest_set_filtered_exceptions() -> tuple[type[Exception], ...]:
|
|
|
29
29
|
This is for ``pytest-retry``.
|
|
30
30
|
The configuration for retries is in ``pyproject.toml``.
|
|
31
31
|
"""
|
|
32
|
-
return
|
|
32
|
+
return TRANSIENT_VWS_EXCEPTIONS
|
|
@@ -24,10 +24,19 @@ extensions = [
|
|
|
24
24
|
"sphinx_paramlinks",
|
|
25
25
|
"sphinx_substitution_extensions",
|
|
26
26
|
"sphinxcontrib.spelling",
|
|
27
|
+
"sphinxcontrib.towncrier.ext",
|
|
27
28
|
"sphinxcontrib.autohttp.flask",
|
|
28
29
|
"sphinx_toolbox.more_autodoc.autoprotocol",
|
|
29
30
|
]
|
|
30
31
|
|
|
32
|
+
# Render the unreleased ``newsfragments/`` entries into
|
|
33
|
+
# ``docs/source/unreleased.rst`` so the Sphinx spelling, doc-build and
|
|
34
|
+
# link-checking gates cover the prose before it is assembled into
|
|
35
|
+
# CHANGELOG.rst at release time.
|
|
36
|
+
towncrier_draft_autoversion_mode = "draft"
|
|
37
|
+
towncrier_draft_include_empty = True
|
|
38
|
+
towncrier_draft_working_directory = f"{_pyproject_file.parent}"
|
|
39
|
+
|
|
31
40
|
# Required by sphinx-toolbox 4.2.0rc1 for compatibility with Sphinx 9.
|
|
32
41
|
# See https://github.com/sphinx-toolbox/sphinx-toolbox/issues/201#issuecomment-4313483053.
|
|
33
42
|
autodoc_use_legacy_class_based = True
|
|
@@ -92,12 +92,31 @@ There are some result codes which the mock cannot return.
|
|
|
92
92
|
These are:
|
|
93
93
|
|
|
94
94
|
* ``DateRangeError``
|
|
95
|
-
* ``ProjectHasNoAPIAccess``
|
|
96
|
-
* ``ProjectSuspended``
|
|
97
|
-
* ``RequestQuotaReached``
|
|
98
|
-
* ``TargetQuotaReached``
|
|
99
95
|
* ``TooManyRequests``
|
|
100
96
|
|
|
97
|
+
Request quota exhaustion
|
|
98
|
+
------------------------
|
|
99
|
+
|
|
100
|
+
The mock returns ``RequestQuotaReached`` when a
|
|
101
|
+
:class:`mock_vws.database.CloudDatabase` is created with
|
|
102
|
+
``request_quota=0``. This behavior follows the public Vuforia documentation,
|
|
103
|
+
but the response has not been verified against a real database with an
|
|
104
|
+
exhausted quota.
|
|
105
|
+
|
|
106
|
+
Other configurable result codes
|
|
107
|
+
-------------------------------
|
|
108
|
+
|
|
109
|
+
The mock also supports three other result codes which have not been verified
|
|
110
|
+
against real databases in the corresponding states:
|
|
111
|
+
|
|
112
|
+
* ``TargetQuotaReached`` is returned when adding a target to a
|
|
113
|
+
:class:`mock_vws.database.CloudDatabase` which already contains
|
|
114
|
+
``target_quota`` targets.
|
|
115
|
+
* ``ProjectSuspended`` is returned by VWS endpoints when a database uses the
|
|
116
|
+
:attr:`mock_vws.states.States.PROJECT_SUSPENDED` state.
|
|
117
|
+
* ``ProjectHasNoAPIAccess`` is returned by VWS endpoints when a database uses
|
|
118
|
+
the :attr:`mock_vws.states.States.PROJECT_HAS_NO_API_ACCESS` state.
|
|
119
|
+
|
|
101
120
|
``Content-Length`` headers
|
|
102
121
|
--------------------------
|
|
103
122
|
|
|
@@ -110,6 +129,21 @@ The mock returns a fixed minimal image in the requested format.
|
|
|
110
129
|
The ``instance_id`` value is not encoded into the response image.
|
|
111
130
|
Real Vuforia encodes the instance ID into the VuMark pattern.
|
|
112
131
|
|
|
132
|
+
Model Target datasets
|
|
133
|
+
---------------------
|
|
134
|
+
|
|
135
|
+
The Model Target Web API mock supports OAuth2 token requests, standard and advanced dataset creation, status polling, dataset downloads, and deletion.
|
|
136
|
+
The generated dataset download is a small valid zip file containing request metadata, not a real Vuforia Engine Model Target dataset.
|
|
137
|
+
Model Target API routes require a syntactically JSON Web Token-shaped bearer token, such as the token returned by the mock OAuth2 route.
|
|
138
|
+
The mock does not verify token signatures, claims, expiry, or revocation.
|
|
139
|
+
|
|
140
|
+
For unknown Model Target datasets, the mock returns an error whose ``target`` is ``userId:mock``.
|
|
141
|
+
Real Vuforia uses ``userId:<numeric-user-id>`` where the numeric portion is per-account.
|
|
142
|
+
|
|
143
|
+
Two Model Target Web API error paths remain mock-only in ``tests/mock_vws/test_model_target_web_api.py::TestMockOnlyErrors``.
|
|
144
|
+
Downloads of still-processing datasets are mock-only because exercising the path against real Vuforia would require creating a dataset on every test run; the mock drives the processing window deterministically.
|
|
145
|
+
Advanced-dataset creation with more than 20 models is mock-only because the available test account lacks the advanced-dataset scope and real Vuforia rejects the request with a 403 before validating model counts.
|
|
146
|
+
|
|
113
147
|
Header cases
|
|
114
148
|
------------
|
|
115
149
|
|