From 8b0b0805139ea57887bae1bb3cdeda1907367fa4 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Fri, 22 May 2026 07:04:50 +0100 Subject: [PATCH 1/2] Support requesting the advanced Model Target Web API scope Adds a ``scopes`` argument to ``get_model_target_web_api_details`` and exposes ``MODEL_TARGET_WEB_API_STANDARD_SCOPES`` / ``MODEL_TARGET_WEB_API_ADVANCED_SCOPES`` so Enterprise callers can request the advanced Model Target scope. Closes #1393. Co-Authored-By: Claude Opus 4.7 (1M context) --- newsfragments/1393.change.rst | 4 ++++ pyproject.toml | 3 +++ src/vws_web_tools/__init__.py | 29 ++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 newsfragments/1393.change.rst diff --git a/newsfragments/1393.change.rst b/newsfragments/1393.change.rst new file mode 100644 index 00000000..79237106 --- /dev/null +++ b/newsfragments/1393.change.rst @@ -0,0 +1,4 @@ +Add a ``scopes`` argument to ``get_model_target_web_api_details`` so callers +on Vuforia Enterprise accounts can request the advanced Model Target Web API +scope alongside the standard scope, via the new +``MODEL_TARGET_WEB_API_ADVANCED_SCOPES`` constant. diff --git a/pyproject.toml b/pyproject.toml index b6afea9a..03d8d502 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -386,6 +386,9 @@ ignore_names = [ # public API used by downstream secret generation "cad_data_url", "get_model_target_web_api_details", + "MODEL_TARGET_WEB_API_ADVANCED_SCOPE", + "MODEL_TARGET_WEB_API_ADVANCED_SCOPES", + "MODEL_TARGET_WEB_API_STANDARD_SCOPES", # pytest fixtures - we name fixtures like this for this purpose "fixture_*", # Sphinx diff --git a/src/vws_web_tools/__init__.py b/src/vws_web_tools/__init__.py index 9fda8e05..b3fd4349 100644 --- a/src/vws_web_tools/__init__.py +++ b/src/vws_web_tools/__init__.py @@ -3,6 +3,7 @@ import contextlib import datetime import logging +from collections.abc import Sequence from dataclasses import dataclass from pathlib import Path from typing import Any, TypedDict, TypeGuard @@ -40,7 +41,15 @@ "d7a3cc8e51d7c573771ae77a57f16b0662a905c6/" "2.0/Duck/glTF-Binary/Duck.glb" ) -_MODEL_TARGET_WEB_API_SCOPES = ("modeltargets.standardmodeltarget.all",) +MODEL_TARGET_WEB_API_STANDARD_SCOPE = "modeltargets.standardmodeltarget.all" +MODEL_TARGET_WEB_API_ADVANCED_SCOPE = "modeltargets.advancedmodeltarget.all" +MODEL_TARGET_WEB_API_STANDARD_SCOPES: tuple[str, ...] = ( + MODEL_TARGET_WEB_API_STANDARD_SCOPE, +) +MODEL_TARGET_WEB_API_ADVANCED_SCOPES: tuple[str, ...] = ( + MODEL_TARGET_WEB_API_STANDARD_SCOPE, + MODEL_TARGET_WEB_API_ADVANCED_SCOPE, +) _OAUTH2_CLIENT_CREDENTIALS_SCOPE = "oauth2.clientcredentials.all" _REQUEST_TIMEOUT_SECONDS = 30 @@ -1056,6 +1065,7 @@ def _create_model_target_web_api_client_credentials( *, driver: WebDriver, credential_name: str, + scopes: Sequence[str], ) -> _ModelTargetWebAPIClientCredentials: """Create OAuth2 client credentials for the Model Target Web API.""" session = _requests_session_from_driver(driver=driver) @@ -1096,7 +1106,7 @@ def _create_model_target_web_api_client_credentials( url="https://vws.vuforia.com/oauth2/clientcredentials", data={ "name": credential_name, - "scopes": list(_MODEL_TARGET_WEB_API_SCOPES), + "scopes": list(scopes), }, access_token=access_token, ) @@ -1243,8 +1253,20 @@ def _json_request( def get_model_target_web_api_details( *, driver: WebDriver, + scopes: Sequence[str] = MODEL_TARGET_WEB_API_STANDARD_SCOPES, ) -> ModelTargetWebAPIDict: - """Get Model Target Web API credentials and a CAD data URL.""" + """Get Model Target Web API credentials and a CAD data URL. + + The ``scopes`` argument selects which OAuth2 scopes are requested for + the created credential. It defaults to + :data:`MODEL_TARGET_WEB_API_STANDARD_SCOPES`, which is the only set + of scopes available on non-Enterprise developer accounts. Pass + :data:`MODEL_TARGET_WEB_API_ADVANCED_SCOPES` to additionally request + the advanced Model Target scope; this requires a Vuforia Enterprise + developer account, and credential creation raises a + :exc:`RuntimeError` if the account is not entitled to a requested + scope. + """ driver.get(url="https://developer.vuforia.com/develop/credentials") wait_for_logged_in(driver=driver) @@ -1255,6 +1277,7 @@ def get_model_target_web_api_details( credentials = _create_model_target_web_api_client_credentials( driver=driver, credential_name=credential_name, + scopes=scopes, ) return { From 30a12e7ef2d90571bd531645d24b4252aa731023 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Fri, 22 May 2026 07:10:39 +0100 Subject: [PATCH 2/2] Use inline literals for scope constant references in docstring Sphinx (nitpicky mode) could not resolve ``:data:`` cross-references to the module-level ``MODEL_TARGET_WEB_API_*_SCOPES`` constants, failing the docs build. Switch to plain literal backticks. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/vws_web_tools/__init__.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/vws_web_tools/__init__.py b/src/vws_web_tools/__init__.py index b3fd4349..2abe57d7 100644 --- a/src/vws_web_tools/__init__.py +++ b/src/vws_web_tools/__init__.py @@ -1259,13 +1259,12 @@ def get_model_target_web_api_details( The ``scopes`` argument selects which OAuth2 scopes are requested for the created credential. It defaults to - :data:`MODEL_TARGET_WEB_API_STANDARD_SCOPES`, which is the only set - of scopes available on non-Enterprise developer accounts. Pass - :data:`MODEL_TARGET_WEB_API_ADVANCED_SCOPES` to additionally request - the advanced Model Target scope; this requires a Vuforia Enterprise - developer account, and credential creation raises a - :exc:`RuntimeError` if the account is not entitled to a requested - scope. + ``MODEL_TARGET_WEB_API_STANDARD_SCOPES``, which is the only set of + scopes available on non-Enterprise developer accounts. Pass + ``MODEL_TARGET_WEB_API_ADVANCED_SCOPES`` to additionally request the + advanced Model Target scope; this requires a Vuforia Enterprise + developer account, and credential creation raises a ``RuntimeError`` + if the account is not entitled to a requested scope. """ driver.get(url="https://developer.vuforia.com/develop/credentials") wait_for_logged_in(driver=driver)