From a832675bd67355065966009e41d44d7a5e6209eb Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Mon, 26 Oct 2026 11:20:22 +0000 Subject: [PATCH] Expose the supported core API used by Flask servers --- docs/source/mock-api-reference.rst | 35 ++++++++++++ newsfragments/3740.change.md | 1 + src/mock_vws/_flask_server/vwq.py | 14 ++--- src/mock_vws/_flask_server/vws.py | 82 +++++++++++++--------------- src/mock_vws/server_api.py | 88 ++++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 51 deletions(-) create mode 100644 newsfragments/3740.change.md create mode 100644 src/mock_vws/server_api.py diff --git a/docs/source/mock-api-reference.rst b/docs/source/mock-api-reference.rst index 70afa2ac4..f863da766 100644 --- a/docs/source/mock-api-reference.rst +++ b/docs/source/mock-api-reference.rst @@ -100,3 +100,38 @@ Target raters .. autoclass:: mock_vws.target_raters.HardcodedTargetTrackingRater .. autoclass:: mock_vws.target_raters.BrisqueTargetTrackingRater + +Server integration +------------------ + +``mock_vws.server_api`` is the supported interface for the core operations used by VWS and VWQ HTTP servers. +The bundled Flask applications use these same imports. +Adapters provide request data and database state, call core operations, and translate their results into HTTP responses. +Validation order, matching and response construction remain owned by core. + +The interface exports the following operations and supporting types: + +* Request handling: ``RequestData``, ``json_dump``, ``sorted_targets``, ``matching_targets`` and ``get_database_matching_server_keys``. +* Services validation: ``run_services_validators``, ``RequestRateLimiter``, ``ServicesValidatorError``, ``FailError``, ``InvalidAcceptHeaderError``, ``InvalidTargetTypeError``, ``TargetStatusNotSuccessError`` and ``TargetStatusProcessingError``. +* Query handling: ``run_query_validators``, ``ValidatedQuery``, ``get_query_match_response_text`` and ``QueryValidatorError``. +* Model Target datasets: ``create_model_target_dataset``, ``delete_model_target_dataset``, ``download_model_target_dataset`` and ``get_model_target_dataset_status``. +* OAuth2: ``create_oauth2_client_credential``, ``delete_oauth2_client_credential``, ``list_oauth2_client_credentials``, ``oauth2_token`` and ``update_oauth2_client_credential_scopes``. +* Recognition reports: ``create_reco_counts_report`` and ``download_reco_counts_report``. +* Response constants: ``ResultCodes``, ``TargetStatuses``, ``VUMARK_PDF``, ``VUMARK_PNG`` and ``VUMARK_SVG``. + +For example, a query adapter passes the result of ``run_query_validators`` to ``get_query_match_response_text``. +If validation raises ``QueryValidatorError``, its ``status_code``, ``headers`` and ``response_text`` describe the HTTP response to send. +``ServicesValidatorError`` provides the same response attributes for VWS. +Use the distinct error types to keep each API's error handling scoped to its own validators. + +Servers also use the public modules ``mock_vws.database``, ``mock_vws.database_type``, ``mock_vws.image_matchers``, ``mock_vws.model_target``, ``mock_vws.reco_counts``, ``mock_vws.request_rate_limits``, ``mock_vws.states``, ``mock_vws.target``, ``mock_vws.target_manager`` and ``mock_vws.target_raters``. +Database and target ``to_dict`` and ``from_dict`` methods support the target-manager transport. +These public imports and their typed signatures form the server interface. +Underscore-prefixed modules remain implementation details. + +Server consumers should pin a compatible core revision or release. +The :doc:`versioning-and-api-stability` policy applies to this interface, including documenting incompatible changes in the changelog. + +Core operations do not require Flask. +The package still installs Flask while the bundled server lives here. +``Werkzeug`` remains a core dependency because query validation uses its multipart parser. diff --git a/newsfragments/3740.change.md b/newsfragments/3740.change.md new file mode 100644 index 000000000..aa82bb6c1 --- /dev/null +++ b/newsfragments/3740.change.md @@ -0,0 +1 @@ +Expose `mock_vws.server_api` as the supported core interface for HTTP server adapters, and use it in the bundled Flask applications. diff --git a/src/mock_vws/_flask_server/vwq.py b/src/mock_vws/_flask_server/vwq.py index d533e731c..fa2e94961 100644 --- a/src/mock_vws/_flask_server/vwq.py +++ b/src/mock_vws/_flask_server/vwq.py @@ -16,19 +16,19 @@ from pydantic import TypeAdapter from pydantic_settings import BaseSettings -from mock_vws._query_tools import ( - get_query_match_response_text, -) -from mock_vws._query_validators import run_query_validators -from mock_vws._query_validators.exceptions import ( - ValidatorError, -) from mock_vws.database import CloudDatabase from mock_vws.image_matchers import ( ExactMatcher, ImageMatcher, StructuralSimilarityMatcher, ) +from mock_vws.server_api import ( + QueryValidatorError as ValidatorError, +) +from mock_vws.server_api import ( + get_query_match_response_text, + run_query_validators, +) CLOUDRECO_FLASK_APP = Flask(import_name=__name__, static_folder=None) CLOUDRECO_FLASK_APP.config["PROPAGATE_EXCEPTIONS"] = True diff --git a/src/mock_vws/_flask_server/vws.py b/src/mock_vws/_flask_server/vws.py index 20444baf8..375852500 100644 --- a/src/mock_vws/_flask_server/vws.py +++ b/src/mock_vws/_flask_server/vws.py @@ -23,70 +23,64 @@ from pydantic_settings import BaseSettings from werkzeug.exceptions import MethodNotAllowed, NotFound -from mock_vws._constants import ( +from mock_vws.database import CloudDatabase, VuMarkDatabase +from mock_vws.image_matchers import ( + ExactMatcher, + ImageMatcher, + StructuralSimilarityMatcher, +) +from mock_vws.model_target import ( + JSONValue, + ModelTargetDataset, + ModelTargetDatasetType, + OAuth2ClientCredential, +) +from mock_vws.reco_counts import RecoCountsReport +from mock_vws.server_api import ( VUMARK_PDF, VUMARK_PNG, VUMARK_SVG, + FailError, + InvalidAcceptHeaderError, + InvalidTargetTypeError, + RequestData, + RequestRateLimiter, ResultCodes, TargetStatuses, -) -from mock_vws._database_matchers import get_database_matching_server_keys -from mock_vws._matching import matching_targets -from mock_vws._mock_common import ( - RequestData, - json_dump, - sorted_targets, -) -from mock_vws._model_target_web_api import ( + TargetStatusNotSuccessError, + TargetStatusProcessingError, create_model_target_dataset, + create_reco_counts_report, delete_model_target_dataset, download_model_target_dataset, + get_database_matching_server_keys, get_model_target_dataset_status, + json_dump, + matching_targets, + run_services_validators, + sorted_targets, ) -from mock_vws._model_target_web_api import ( +from mock_vws.server_api import ( + ServicesValidatorError as ValidatorError, +) +from mock_vws.server_api import ( create_oauth2_client_credential as model_target_create_oauth2_credential, ) -from mock_vws._model_target_web_api import ( +from mock_vws.server_api import ( delete_oauth2_client_credential as model_target_delete_oauth2_credential, ) -from mock_vws._model_target_web_api import ( +from mock_vws.server_api import ( + download_reco_counts_report as download_report, +) +from mock_vws.server_api import ( list_oauth2_client_credentials as model_target_list_oauth2_credentials, ) -from mock_vws._model_target_web_api import ( +from mock_vws.server_api import ( oauth2_token as model_target_oauth2_token, ) -from mock_vws._model_target_web_api import ( +from mock_vws.server_api import ( update_oauth2_client_credential_scopes as update_oauth2_scopes, ) -from mock_vws._reco_counts_web_api import create_reco_counts_report -from mock_vws._reco_counts_web_api import ( - download_reco_counts_report as download_report, -) -from mock_vws._services_validators import run_services_validators -from mock_vws._services_validators.exceptions import ( - FailError, - InvalidAcceptHeaderError, - InvalidTargetTypeError, - TargetStatusNotSuccessError, - TargetStatusProcessingError, - ValidatorError, -) -from mock_vws._services_validators.request_rate_limiter import ( - RequestRateLimiter, -) -from mock_vws.database import CloudDatabase, VuMarkDatabase -from mock_vws.image_matchers import ( - ExactMatcher, - ImageMatcher, - StructuralSimilarityMatcher, -) -from mock_vws.model_target import ( - JSONValue, - ModelTargetDataset, - ModelTargetDatasetType, - OAuth2ClientCredential, -) -from mock_vws.reco_counts import RecoCountsReport from mock_vws.target import ImageTarget from mock_vws.target_raters import ( HardcodedTargetTrackingRater, diff --git a/src/mock_vws/server_api.py b/src/mock_vws/server_api.py new file mode 100644 index 000000000..878bb8cb2 --- /dev/null +++ b/src/mock_vws/server_api.py @@ -0,0 +1,88 @@ +"""Supported core operations for VWS and VWQ server implementations. + +Server adapters supply HTTP request data and database state to these +operations, then translate their results or validation errors into HTTP +responses. Core owns validation order, matching and response construction. +The operations have no dependency on Flask or a running server. +""" + +from mock_vws._constants import ( + VUMARK_PDF, + VUMARK_PNG, + VUMARK_SVG, + ResultCodes, + TargetStatuses, +) +from mock_vws._database_matchers import get_database_matching_server_keys +from mock_vws._matching import matching_targets +from mock_vws._mock_common import RequestData, json_dump, sorted_targets +from mock_vws._model_target_web_api import ( + create_model_target_dataset, + create_oauth2_client_credential, + delete_model_target_dataset, + delete_oauth2_client_credential, + download_model_target_dataset, + get_model_target_dataset_status, + list_oauth2_client_credentials, + oauth2_token, + update_oauth2_client_credential_scopes, +) +from mock_vws._query_tools import get_query_match_response_text +from mock_vws._query_validators import ValidatedQuery, run_query_validators +from mock_vws._query_validators.exceptions import ( + ValidatorError as QueryValidatorError, +) +from mock_vws._reco_counts_web_api import ( + create_reco_counts_report, + download_reco_counts_report, +) +from mock_vws._services_validators import run_services_validators +from mock_vws._services_validators.exceptions import ( + FailError, + InvalidAcceptHeaderError, + InvalidTargetTypeError, + TargetStatusNotSuccessError, + TargetStatusProcessingError, +) +from mock_vws._services_validators.exceptions import ( + ValidatorError as ServicesValidatorError, +) +from mock_vws._services_validators.request_rate_limiter import ( + RequestRateLimiter, +) + +__all__ = [ + "VUMARK_PDF", + "VUMARK_PNG", + "VUMARK_SVG", + "FailError", + "InvalidAcceptHeaderError", + "InvalidTargetTypeError", + "QueryValidatorError", + "RequestData", + "RequestRateLimiter", + "ResultCodes", + "ServicesValidatorError", + "TargetStatusNotSuccessError", + "TargetStatusProcessingError", + "TargetStatuses", + "ValidatedQuery", + "create_model_target_dataset", + "create_oauth2_client_credential", + "create_reco_counts_report", + "delete_model_target_dataset", + "delete_oauth2_client_credential", + "download_model_target_dataset", + "download_reco_counts_report", + "get_database_matching_server_keys", + "get_model_target_dataset_status", + "get_query_match_response_text", + "json_dump", + "list_oauth2_client_credentials", + "matching_targets", + "oauth2_token", + "run_query_validators", + "run_services_validators", + "sorted_targets", + "update_oauth2_client_credential_scopes", +]