vws-python-mock 2026.2.22.1__tar.gz → 2026.2.22.3__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.2.22.1 → vws_python_mock-2026.2.22.3}/CHANGELOG.rst +11 -0
- {vws_python_mock-2026.2.22.1/src/vws_python_mock.egg-info → vws_python_mock-2026.2.22.3}/PKG-INFO +10 -17
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/README.rst +8 -14
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/admin/create_secrets_files.py +30 -17
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/basic-example.rst +2 -1
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/contributing.rst +1 -1
- vws_python_mock-2026.2.22.3/docs/source/getting-started.rst +9 -0
- vws_python_mock-2026.2.22.3/docs/source/httpx-example.rst +18 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/index.rst +2 -5
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/mock-api-reference.rst +0 -4
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/pyproject.toml +2 -2
- vws_python_mock-2026.2.22.3/src/mock_vws/__init__.py +9 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_mock_common.py +23 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_requests_mock_server/decorators.py +32 -27
- vws_python_mock-2026.2.22.3/src/mock_vws/_respx_mock_server/decorators.py +183 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3/src/vws_python_mock.egg-info}/PKG-INFO +10 -17
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/vws_python_mock.egg-info/requires.txt +1 -2
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_requests_mock_usage.py +86 -1
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_respx_mock_usage.py +45 -130
- vws_python_mock-2026.2.22.1/docs/source/getting-started.rst +0 -12
- vws_python_mock-2026.2.22.1/docs/source/httpx-example.rst +0 -22
- vws_python_mock-2026.2.22.1/src/mock_vws/__init__.py +0 -13
- vws_python_mock-2026.2.22.1/src/mock_vws/_respx_mock_server/decorators.py +0 -272
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.git_archival.txt +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.gitattributes +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.github/dependabot.yml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.github/workflows/dependabot-merge.yml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.github/workflows/docker-build.yml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.github/workflows/lint.yml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.github/workflows/publish-site.yml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.github/workflows/release.yml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.github/workflows/test.yml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.gitignore +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.pre-commit-config.yaml +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.prettierrc +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.vscode/extensions.json +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/.vscode/settings.json +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/CODE_OF_CONDUCT.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/LICENSE +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/MANIFEST.in +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/admin/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/admin/vumark_template.svg +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/ci/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/ci/decrypt_secret.sh +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/ci/test_custom_linters.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/conftest.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docker-bake.hcl +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/changelog.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/ci-setup.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/conf.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/differences-to-vws.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/docker.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/installation.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/release-process.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/docs/source/versioning-and-api-stability.rst +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/secrets.tar.gpg +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/setup.cfg +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/spelling_private_dict.txt +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_base64_decoding.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_constants.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_database_matchers.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_flask_server/Dockerfile +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_flask_server/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_flask_server/healthcheck.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_flask_server/target_manager.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_flask_server/vwq.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_flask_server/vws.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_tools.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/accept_header_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/auth_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/content_length_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/content_type_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/date_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/exceptions.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/fields_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/image_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/include_target_data_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/num_results_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_query_validators/project_state_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_requests_mock_server/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_requests_mock_server/mock_web_query_api.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_requests_mock_server/mock_web_services_api.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_respx_mock_server/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/active_flag_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/auth_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/content_length_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/content_type_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/date_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/exceptions.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/image_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/json_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/key_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/metadata_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/name_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/project_state_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/target_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/_services_validators/width_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/database.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/database_type.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/image_matchers.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/py.typed +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/states.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/target.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/target_manager.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/mock_vws/target_raters.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/vws_python_mock.egg-info/SOURCES.txt +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/vws_python_mock.egg-info/dependency_links.txt +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/vws_python_mock.egg-info/not-zip-safe +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/src/vws_python_mock.egg-info/top_level.txt +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/conftest.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/fixtures/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/fixtures/credentials.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/fixtures/prepared_requests.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/fixtures/vuforia_backends.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_add_target.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_authorization_header.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_content_length.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_database_summary.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_date_header.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_delete_target.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_docker.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_flask_app_usage.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_get_duplicates.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_get_target.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_invalid_given_id.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_invalid_json.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_query.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_target_list.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_target_raters.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_target_summary.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_target_validators.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_unexpected_json.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_update_target.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/test_vumark_generation_api.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/utils/__init__.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/utils/assertions.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/utils/retries.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/utils/too_many_requests.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/tests/mock_vws/utils/usage_test_helpers.py +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/vuforia_secrets.env.example +0 -0
- {vws_python_mock-2026.2.22.1 → vws_python_mock-2026.2.22.3}/zizmor.yml +0 -0
|
@@ -4,6 +4,17 @@ Changelog
|
|
|
4
4
|
Next
|
|
5
5
|
----
|
|
6
6
|
|
|
7
|
+
2026.02.22.3
|
|
8
|
+
------------
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
- ``MockVWS`` now intercepts both ``requests`` (via ``responses``) and ``httpx`` (via ``respx``) simultaneously.
|
|
12
|
+
``MockVWSForHttpx`` has been removed — ``MockVWS`` handles both HTTP libraries.
|
|
13
|
+
|
|
14
|
+
2026.02.22.2
|
|
15
|
+
------------
|
|
16
|
+
|
|
17
|
+
|
|
7
18
|
2026.02.22.1
|
|
8
19
|
------------
|
|
9
20
|
|
{vws_python_mock-2026.2.22.1/src/vws_python_mock.egg-info → vws_python_mock-2026.2.22.3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vws-python-mock
|
|
3
|
-
Version: 2026.2.22.
|
|
3
|
+
Version: 2026.2.22.3
|
|
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
|
|
@@ -61,7 +61,6 @@ Requires-Dist: pyroma==5.0.1; extra == "dev"
|
|
|
61
61
|
Requires-Dist: pytest==9.0.2; 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
|
-
Requires-Dist: python-dotenv==1.2.1; extra == "dev"
|
|
65
64
|
Requires-Dist: pyyaml==6.0.3; extra == "dev"
|
|
66
65
|
Requires-Dist: requests-mock-flask==2026.2.16; extra == "dev"
|
|
67
66
|
Requires-Dist: ruff==0.15.1; extra == "dev"
|
|
@@ -86,7 +85,7 @@ Requires-Dist: urllib3==2.6.3; extra == "dev"
|
|
|
86
85
|
Requires-Dist: vulture==2.14; extra == "dev"
|
|
87
86
|
Requires-Dist: vws-python==2026.2.21; extra == "dev"
|
|
88
87
|
Requires-Dist: vws-test-fixtures==2023.3.5; extra == "dev"
|
|
89
|
-
Requires-Dist: vws-web-tools==2026.2.
|
|
88
|
+
Requires-Dist: vws-web-tools==2026.2.22; extra == "dev"
|
|
90
89
|
Requires-Dist: yamlfix==1.19.1; extra == "dev"
|
|
91
90
|
Requires-Dist: zizmor==1.22.0; extra == "dev"
|
|
92
91
|
Provides-Extra: release
|
|
@@ -103,10 +102,10 @@ VWS Mock
|
|
|
103
102
|
|
|
104
103
|
Mock for the Vuforia Web Services (VWS) API and the Vuforia Web Query API.
|
|
105
104
|
|
|
106
|
-
Mocking calls made to Vuforia
|
|
107
|
-
|
|
105
|
+
Mocking calls made to Vuforia
|
|
106
|
+
------------------------------
|
|
108
107
|
|
|
109
|
-
|
|
108
|
+
``MockVWS`` intercepts requests made with `requests`_ or `httpx`_.
|
|
110
109
|
|
|
111
110
|
.. code-block:: shell
|
|
112
111
|
|
|
@@ -129,25 +128,18 @@ This requires Python |minimum-python-version|\+.
|
|
|
129
128
|
# This will use the Vuforia mock.
|
|
130
129
|
requests.get(url="https://vws.vuforia.com/summary", timeout=30)
|
|
131
130
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
.. _requests: https://pypi.org/project/requests/
|
|
135
|
-
|
|
136
|
-
Mocking calls made to Vuforia with Python ``httpx``
|
|
137
|
-
----------------------------------------------------
|
|
138
|
-
|
|
139
|
-
Using the mock redirects requests to Vuforia made with `httpx`_ to an in-memory implementation.
|
|
131
|
+
``MockVWS`` also intercepts `httpx`_ requests:
|
|
140
132
|
|
|
141
133
|
.. code-block:: python
|
|
142
134
|
|
|
143
|
-
"""Make a request to the Vuforia Web Services API mock."""
|
|
135
|
+
"""Make a request to the Vuforia Web Services API mock using httpx."""
|
|
144
136
|
|
|
145
137
|
import httpx
|
|
146
138
|
|
|
147
|
-
from mock_vws import
|
|
139
|
+
from mock_vws import MockVWS
|
|
148
140
|
from mock_vws.database import CloudDatabase
|
|
149
141
|
|
|
150
|
-
with
|
|
142
|
+
with MockVWS() as mock:
|
|
151
143
|
database = CloudDatabase()
|
|
152
144
|
mock.add_cloud_database(cloud_database=database)
|
|
153
145
|
# This will use the Vuforia mock.
|
|
@@ -155,6 +147,7 @@ Using the mock redirects requests to Vuforia made with `httpx`_ to an in-memory
|
|
|
155
147
|
|
|
156
148
|
By default, an exception will be raised if any requests to unmocked addresses are made.
|
|
157
149
|
|
|
150
|
+
.. _requests: https://pypi.org/project/requests/
|
|
158
151
|
.. _httpx: https://pypi.org/project/httpx/
|
|
159
152
|
|
|
160
153
|
Using Docker to mock calls to Vuforia from any language
|
|
@@ -8,10 +8,10 @@ VWS Mock
|
|
|
8
8
|
|
|
9
9
|
Mock for the Vuforia Web Services (VWS) API and the Vuforia Web Query API.
|
|
10
10
|
|
|
11
|
-
Mocking calls made to Vuforia
|
|
12
|
-
|
|
11
|
+
Mocking calls made to Vuforia
|
|
12
|
+
------------------------------
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
``MockVWS`` intercepts requests made with `requests`_ or `httpx`_.
|
|
15
15
|
|
|
16
16
|
.. code-block:: shell
|
|
17
17
|
|
|
@@ -34,25 +34,18 @@ This requires Python |minimum-python-version|\+.
|
|
|
34
34
|
# This will use the Vuforia mock.
|
|
35
35
|
requests.get(url="https://vws.vuforia.com/summary", timeout=30)
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.. _requests: https://pypi.org/project/requests/
|
|
40
|
-
|
|
41
|
-
Mocking calls made to Vuforia with Python ``httpx``
|
|
42
|
-
----------------------------------------------------
|
|
43
|
-
|
|
44
|
-
Using the mock redirects requests to Vuforia made with `httpx`_ to an in-memory implementation.
|
|
37
|
+
``MockVWS`` also intercepts `httpx`_ requests:
|
|
45
38
|
|
|
46
39
|
.. code-block:: python
|
|
47
40
|
|
|
48
|
-
"""Make a request to the Vuforia Web Services API mock."""
|
|
41
|
+
"""Make a request to the Vuforia Web Services API mock using httpx."""
|
|
49
42
|
|
|
50
43
|
import httpx
|
|
51
44
|
|
|
52
|
-
from mock_vws import
|
|
45
|
+
from mock_vws import MockVWS
|
|
53
46
|
from mock_vws.database import CloudDatabase
|
|
54
47
|
|
|
55
|
-
with
|
|
48
|
+
with MockVWS() as mock:
|
|
56
49
|
database = CloudDatabase()
|
|
57
50
|
mock.add_cloud_database(cloud_database=database)
|
|
58
51
|
# This will use the Vuforia mock.
|
|
@@ -60,6 +53,7 @@ Using the mock redirects requests to Vuforia made with `httpx`_ to an in-memory
|
|
|
60
53
|
|
|
61
54
|
By default, an exception will be raised if any requests to unmocked addresses are made.
|
|
62
55
|
|
|
56
|
+
.. _requests: https://pypi.org/project/requests/
|
|
63
57
|
.. _httpx: https://pypi.org/project/httpx/
|
|
64
58
|
|
|
65
59
|
Using Docker to mock calls to Vuforia from any language
|
|
@@ -11,7 +11,6 @@ from pathlib import Path
|
|
|
11
11
|
from typing import TYPE_CHECKING
|
|
12
12
|
|
|
13
13
|
import vws_web_tools
|
|
14
|
-
from dotenv import load_dotenv
|
|
15
14
|
from selenium.common.exceptions import TimeoutException
|
|
16
15
|
|
|
17
16
|
if TYPE_CHECKING:
|
|
@@ -123,6 +122,25 @@ def _create_and_get_vumark_target_id(
|
|
|
123
122
|
)
|
|
124
123
|
|
|
125
124
|
|
|
125
|
+
def _fetch_inactive_database_details(
|
|
126
|
+
driver: "WebDriver",
|
|
127
|
+
email_address: str,
|
|
128
|
+
password: str,
|
|
129
|
+
database_name: str,
|
|
130
|
+
) -> "DatabaseDict":
|
|
131
|
+
"""Fetch details for an existing inactive database."""
|
|
132
|
+
vws_web_tools.log_in(
|
|
133
|
+
driver=driver,
|
|
134
|
+
email_address=email_address,
|
|
135
|
+
password=password,
|
|
136
|
+
)
|
|
137
|
+
vws_web_tools.wait_for_logged_in(driver=driver)
|
|
138
|
+
return vws_web_tools.get_database_details(
|
|
139
|
+
driver=driver,
|
|
140
|
+
database_name=database_name,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
126
144
|
def _create_vuforia_resource_names() -> tuple[str, str, str, str]:
|
|
127
145
|
"""Create names for Vuforia resources."""
|
|
128
146
|
time = datetime.datetime.now(tz=datetime.UTC).strftime(
|
|
@@ -141,23 +159,18 @@ def main() -> None:
|
|
|
141
159
|
email_address = os.environ["VWS_EMAIL_ADDRESS"]
|
|
142
160
|
password = os.environ["VWS_PASSWORD"]
|
|
143
161
|
new_secrets_dir = Path(os.environ["NEW_SECRETS_DIR"]).expanduser()
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if not existing_secrets_file.exists():
|
|
148
|
-
msg = f"Existing secrets file does not exist: {existing_secrets_file}"
|
|
149
|
-
raise FileNotFoundError(msg)
|
|
150
|
-
load_dotenv(dotenv_path=existing_secrets_file)
|
|
151
|
-
inactive_database_details: DatabaseDict = {
|
|
152
|
-
"database_name": os.environ[
|
|
153
|
-
"INACTIVE_VUFORIA_TARGET_MANAGER_DATABASE_NAME"
|
|
154
|
-
],
|
|
155
|
-
"server_access_key": os.environ["INACTIVE_VUFORIA_SERVER_ACCESS_KEY"],
|
|
156
|
-
"server_secret_key": os.environ["INACTIVE_VUFORIA_SERVER_SECRET_KEY"],
|
|
157
|
-
"client_access_key": os.environ["INACTIVE_VUFORIA_CLIENT_ACCESS_KEY"],
|
|
158
|
-
"client_secret_key": os.environ["INACTIVE_VUFORIA_CLIENT_SECRET_KEY"],
|
|
159
|
-
}
|
|
162
|
+
inactive_database_name = os.environ[
|
|
163
|
+
"INACTIVE_VUFORIA_TARGET_MANAGER_DATABASE_NAME"
|
|
164
|
+
]
|
|
160
165
|
new_secrets_dir.mkdir(exist_ok=True)
|
|
166
|
+
inactive_driver = vws_web_tools.create_chrome_driver()
|
|
167
|
+
inactive_database_details = _fetch_inactive_database_details(
|
|
168
|
+
driver=inactive_driver,
|
|
169
|
+
email_address=email_address,
|
|
170
|
+
password=password,
|
|
171
|
+
database_name=inactive_database_name,
|
|
172
|
+
)
|
|
173
|
+
inactive_driver.quit()
|
|
161
174
|
|
|
162
175
|
num_databases = 100
|
|
163
176
|
required_files = [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
``MockVWS`` intercepts requests to Vuforia made with `requests`_ or `httpx`_.
|
|
2
2
|
|
|
3
3
|
.. code-block:: python
|
|
4
4
|
|
|
@@ -20,3 +20,4 @@ By default, an exception will be raised if any requests to unmocked addresses ar
|
|
|
20
20
|
See :ref:`mock-api-reference` for details of what can be changed and how.
|
|
21
21
|
|
|
22
22
|
.. _requests: https://pypi.org/project/requests/
|
|
23
|
+
.. _httpx: https://pypi.org/project/httpx/
|
|
@@ -102,7 +102,7 @@ To create databases without using the browser, use :file:`admin/create_secrets_f
|
|
|
102
102
|
$ export VWS_EMAIL_ADDRESS=...
|
|
103
103
|
$ export VWS_PASSWORD=...
|
|
104
104
|
$ export NEW_SECRETS_DIR=...
|
|
105
|
-
$ export
|
|
105
|
+
$ export INACTIVE_VUFORIA_TARGET_MANAGER_DATABASE_NAME=...
|
|
106
106
|
# You may have to run this a few times, but it is idempotent.
|
|
107
107
|
$ python admin/create_secrets_files.py
|
|
108
108
|
# Each generated file gets its own Cloud database credentials and shares
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
``MockVWS`` also intercepts requests made with `httpx`_.
|
|
2
|
+
|
|
3
|
+
.. code-block:: python
|
|
4
|
+
|
|
5
|
+
"""Make a request to the Vuforia Web Services API mock using httpx."""
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from mock_vws import MockVWS
|
|
10
|
+
from mock_vws.database import CloudDatabase
|
|
11
|
+
|
|
12
|
+
with MockVWS() as mock:
|
|
13
|
+
database = CloudDatabase()
|
|
14
|
+
mock.add_cloud_database(cloud_database=database)
|
|
15
|
+
# This will use the Vuforia mock.
|
|
16
|
+
httpx.get(url="https://vws.vuforia.com/summary", timeout=30)
|
|
17
|
+
|
|
18
|
+
.. _httpx: https://pypi.org/project/httpx/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|project|
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
Mocking calls made to Vuforia
|
|
5
|
-
|
|
4
|
+
Mocking calls made to Vuforia
|
|
5
|
+
------------------------------
|
|
6
6
|
|
|
7
7
|
.. code-block:: console
|
|
8
8
|
|
|
@@ -12,9 +12,6 @@ This requires Python |minimum-python-version|\+.
|
|
|
12
12
|
|
|
13
13
|
.. include:: basic-example.rst
|
|
14
14
|
|
|
15
|
-
Mocking calls made to Vuforia with Python ``httpx``
|
|
16
|
-
----------------------------------------------------
|
|
17
|
-
|
|
18
15
|
.. include:: httpx-example.rst
|
|
19
16
|
|
|
20
17
|
Using Docker to mock calls to Vuforia from any language
|
|
@@ -79,7 +79,6 @@ optional-dependencies.dev = [
|
|
|
79
79
|
"pytest==9.0.2",
|
|
80
80
|
"pytest-retry==1.7.0",
|
|
81
81
|
"pytest-xdist==3.8.0",
|
|
82
|
-
"python-dotenv==1.2.1",
|
|
83
82
|
"pyyaml==6.0.3",
|
|
84
83
|
"requests-mock-flask==2026.2.16",
|
|
85
84
|
"ruff==0.15.1",
|
|
@@ -107,7 +106,7 @@ optional-dependencies.dev = [
|
|
|
107
106
|
"vulture==2.14",
|
|
108
107
|
"vws-python==2026.2.21",
|
|
109
108
|
"vws-test-fixtures==2023.3.5",
|
|
110
|
-
"vws-web-tools==2026.2.
|
|
109
|
+
"vws-web-tools==2026.2.22",
|
|
111
110
|
"yamlfix==1.19.1",
|
|
112
111
|
"zizmor==1.22.0",
|
|
113
112
|
]
|
|
@@ -453,6 +452,7 @@ ignore_names = [
|
|
|
453
452
|
"model_config",
|
|
454
453
|
# Used in TYPE_CHECKING for type hints
|
|
455
454
|
"CloudDatabaseDict",
|
|
455
|
+
"DatabaseDict",
|
|
456
456
|
"VuMarkDatabaseDict",
|
|
457
457
|
"VuMarkTargetDict",
|
|
458
458
|
]
|
|
@@ -8,6 +8,29 @@ from typing import Any
|
|
|
8
8
|
from beartype import beartype
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
@beartype
|
|
12
|
+
class MissingSchemeError(Exception):
|
|
13
|
+
"""Raised when a URL is missing a schema."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, url: str) -> None:
|
|
16
|
+
"""
|
|
17
|
+
Args:
|
|
18
|
+
url: The URL which is missing a scheme.
|
|
19
|
+
"""
|
|
20
|
+
super().__init__()
|
|
21
|
+
self.url = url
|
|
22
|
+
|
|
23
|
+
def __str__(self) -> str:
|
|
24
|
+
"""
|
|
25
|
+
Give a string representation of this error with a
|
|
26
|
+
suggestion.
|
|
27
|
+
"""
|
|
28
|
+
return (
|
|
29
|
+
f'Invalid URL "{self.url}": No scheme supplied. '
|
|
30
|
+
f'Perhaps you meant "https://{self.url}".'
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
11
34
|
@beartype
|
|
12
35
|
@dataclass(frozen=True)
|
|
13
36
|
class RequestData:
|
|
@@ -4,7 +4,7 @@ import re
|
|
|
4
4
|
import time
|
|
5
5
|
from collections.abc import Callable, Mapping
|
|
6
6
|
from contextlib import ContextDecorator
|
|
7
|
-
from typing import Any, Literal, Self
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Literal, Self
|
|
8
8
|
from urllib.parse import urlparse
|
|
9
9
|
|
|
10
10
|
import requests
|
|
@@ -12,7 +12,8 @@ from beartype import BeartypeConf, beartype
|
|
|
12
12
|
from requests import PreparedRequest
|
|
13
13
|
from responses import RequestsMock
|
|
14
14
|
|
|
15
|
-
from mock_vws._mock_common import RequestData
|
|
15
|
+
from mock_vws._mock_common import MissingSchemeError, RequestData
|
|
16
|
+
from mock_vws._respx_mock_server.decorators import start_respx_router
|
|
16
17
|
from mock_vws.database import CloudDatabase, VuMarkDatabase
|
|
17
18
|
from mock_vws.image_matchers import (
|
|
18
19
|
ImageMatcher,
|
|
@@ -27,6 +28,9 @@ from mock_vws.target_raters import (
|
|
|
27
28
|
from .mock_web_query_api import MockVuforiaWebQueryAPI
|
|
28
29
|
from .mock_web_services_api import MockVuforiaWebServicesAPI
|
|
29
30
|
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
import respx
|
|
33
|
+
|
|
30
34
|
_ResponseType = tuple[int, Mapping[str, str], str | bytes]
|
|
31
35
|
_MockCallback = Callable[[RequestData], _ResponseType]
|
|
32
36
|
_ResponsesCallback = Callable[[PreparedRequest], _ResponseType]
|
|
@@ -35,32 +39,12 @@ _STRUCTURAL_SIMILARITY_MATCHER = StructuralSimilarityMatcher()
|
|
|
35
39
|
_BRISQUE_TRACKING_RATER = BrisqueTargetTrackingRater()
|
|
36
40
|
|
|
37
41
|
|
|
38
|
-
@beartype
|
|
39
|
-
class MissingSchemeError(Exception):
|
|
40
|
-
"""Raised when a URL is missing a schema."""
|
|
41
|
-
|
|
42
|
-
def __init__(self, url: str) -> None:
|
|
43
|
-
"""
|
|
44
|
-
Args:
|
|
45
|
-
url: The URL which is missing a scheme.
|
|
46
|
-
"""
|
|
47
|
-
super().__init__()
|
|
48
|
-
self.url = url
|
|
49
|
-
|
|
50
|
-
def __str__(self) -> str:
|
|
51
|
-
"""
|
|
52
|
-
Give a string representation of this error with a
|
|
53
|
-
suggestion.
|
|
54
|
-
"""
|
|
55
|
-
return (
|
|
56
|
-
f'Invalid URL "{self.url}": No scheme supplied. '
|
|
57
|
-
f'Perhaps you meant "https://{self.url}".'
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
|
|
61
42
|
@beartype(conf=BeartypeConf(is_pep484_tower=True))
|
|
62
43
|
class MockVWS(ContextDecorator):
|
|
63
|
-
"""Route requests to Vuforia's Web Service APIs to fakes of those APIs.
|
|
44
|
+
"""Route requests to Vuforia's Web Service APIs to fakes of those APIs.
|
|
45
|
+
|
|
46
|
+
Works with both ``requests`` and ``httpx``.
|
|
47
|
+
"""
|
|
64
48
|
|
|
65
49
|
def __init__(
|
|
66
50
|
self,
|
|
@@ -78,6 +62,8 @@ class MockVWS(ContextDecorator):
|
|
|
78
62
|
"""Route requests to Vuforia's Web Service APIs to fakes of those
|
|
79
63
|
APIs.
|
|
80
64
|
|
|
65
|
+
Works with both ``requests`` and ``httpx``.
|
|
66
|
+
|
|
81
67
|
Args:
|
|
82
68
|
real_http: Whether or not to forward requests to the real
|
|
83
69
|
server if they are not handled by the mock.
|
|
@@ -108,6 +94,7 @@ class MockVWS(ContextDecorator):
|
|
|
108
94
|
self._response_delay_seconds = response_delay_seconds
|
|
109
95
|
self._sleep_fn = sleep_fn
|
|
110
96
|
self._mock: RequestsMock
|
|
97
|
+
self._router: respx.MockRouter
|
|
111
98
|
self._target_manager = TargetManager()
|
|
112
99
|
|
|
113
100
|
self._base_vws_url = base_vws_url
|
|
@@ -162,6 +149,7 @@ class MockVWS(ContextDecorator):
|
|
|
162
149
|
callback: _MockCallback,
|
|
163
150
|
delay_seconds: float,
|
|
164
151
|
sleep_fn: Callable[[float], None],
|
|
152
|
+
base_path: str,
|
|
165
153
|
) -> _ResponsesCallback:
|
|
166
154
|
"""Wrap a callback to add a response delay."""
|
|
167
155
|
|
|
@@ -197,9 +185,13 @@ class MockVWS(ContextDecorator):
|
|
|
197
185
|
else:
|
|
198
186
|
body_bytes = raw_body
|
|
199
187
|
|
|
188
|
+
path = request.path_url
|
|
189
|
+
if base_path and path.startswith(base_path):
|
|
190
|
+
path = path[len(base_path) :]
|
|
191
|
+
|
|
200
192
|
request_data = RequestData(
|
|
201
193
|
method=request.method or "",
|
|
202
|
-
path=
|
|
194
|
+
path=path,
|
|
203
195
|
headers=dict(request.headers),
|
|
204
196
|
body=body_bytes,
|
|
205
197
|
)
|
|
@@ -221,6 +213,7 @@ class MockVWS(ContextDecorator):
|
|
|
221
213
|
(self._mock_vws_api, self._base_vws_url),
|
|
222
214
|
(self._mock_vwq_api, self._base_vwq_url),
|
|
223
215
|
):
|
|
216
|
+
base_path = urlparse(url=base_url).path.rstrip("/")
|
|
224
217
|
for route in api.routes:
|
|
225
218
|
url_pattern = base_url.rstrip("/") + route.path_pattern + "$"
|
|
226
219
|
compiled_url_pattern = re.compile(pattern=url_pattern)
|
|
@@ -234,6 +227,7 @@ class MockVWS(ContextDecorator):
|
|
|
234
227
|
callback=original_callback,
|
|
235
228
|
delay_seconds=self._response_delay_seconds,
|
|
236
229
|
sleep_fn=self._sleep_fn,
|
|
230
|
+
base_path=base_path,
|
|
237
231
|
),
|
|
238
232
|
content_type=None,
|
|
239
233
|
)
|
|
@@ -245,6 +239,16 @@ class MockVWS(ContextDecorator):
|
|
|
245
239
|
self._mock = mock
|
|
246
240
|
self._mock.start()
|
|
247
241
|
|
|
242
|
+
self._router = start_respx_router(
|
|
243
|
+
mock_vws_api=self._mock_vws_api,
|
|
244
|
+
mock_vwq_api=self._mock_vwq_api,
|
|
245
|
+
base_vws_url=self._base_vws_url,
|
|
246
|
+
base_vwq_url=self._base_vwq_url,
|
|
247
|
+
response_delay_seconds=self._response_delay_seconds,
|
|
248
|
+
sleep_fn=self._sleep_fn,
|
|
249
|
+
real_http=self._real_http,
|
|
250
|
+
)
|
|
251
|
+
|
|
248
252
|
return self
|
|
249
253
|
|
|
250
254
|
def __exit__(self, *exc: object) -> Literal[False]:
|
|
@@ -258,4 +262,5 @@ class MockVWS(ContextDecorator):
|
|
|
258
262
|
del exc
|
|
259
263
|
|
|
260
264
|
self._mock.stop()
|
|
265
|
+
self._router.stop()
|
|
261
266
|
return False
|