Skip to content

Commit 31a2332

Browse files
adamtheturtleclaude
andcommitted
Add database type and target type support with VuMark validation; refresh Vuforia secrets
## Summary - Add `DatabaseType` and `TargetType` enums to support cloud and VuMark databases - Implement VuMark target validation, generation, and database operations - Optimize secrets creation script to reuse VuMark/inactive credentials - Bump vws-web-tools to 2026.2.20 for improved stability - Refresh encrypted secrets archive with 100 new cloud database credentials ## Key Changes - New `database_type.py` and enhanced `target.py` with TargetType support - VuMark endpoint implementation in Flask and requests-mock servers - Target type validation in endpoints and database - Simplified admin script: creates only new cloud databases, reuses VuMark/inactive databases - Updated secrets.tar.gpg with fresh 2026-02-20 licenses Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 0bebbbe commit 31a2332

15 files changed

Lines changed: 349 additions & 264 deletions

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Changelog
44
Next
55
----
66

7+
- Add ``VuMarkTarget`` class for VuMark template targets, alongside the renamed ``ImageTarget`` class (previously ``Target``).
8+
``ImageTarget`` is for image-based targets and ``VuMarkTarget`` is for VuMark template targets.
9+
Both can be stored in a ``VuforiaDatabase``.
10+
711
2026.02.18.2
812
------------
913

admin/create_secrets_files.py

Lines changed: 13 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@
1919
from vws_web_tools import DatabaseDict, VuMarkDatabaseDict
2020

2121

22-
VUMARK_TEMPLATE_SVG_FILE_PATH = Path(__file__).with_name(
23-
name="vumark_template.svg",
24-
)
25-
26-
2722
def _create_and_get_database_details(
2823
driver: "WebDriver",
2924
email_address: str,
@@ -55,25 +50,6 @@ def _create_and_get_database_details(
5550
)
5651

5752

58-
def _create_and_get_vumark_details(
59-
driver: "WebDriver",
60-
vumark_database_name: str,
61-
) -> "VuMarkDatabaseDict":
62-
"""Create a VuMark database and get its details.
63-
64-
Returns VuMark database details.
65-
"""
66-
vws_web_tools.create_vumark_database(
67-
driver=driver,
68-
database_name=vumark_database_name,
69-
)
70-
71-
return vws_web_tools.get_vumark_database_details(
72-
driver=driver,
73-
database_name=vumark_database_name,
74-
)
75-
76-
7753
def _generate_secrets_file_content(
7854
database_details: "DatabaseDict",
7955
vumark_details: "VuMarkDatabaseDict",
@@ -103,36 +79,14 @@ def _generate_secrets_file_content(
10379
)
10480

10581

106-
def _create_and_get_vumark_target_id(
107-
driver: "WebDriver",
108-
vumark_database_name: str,
109-
vumark_template_name: str,
110-
) -> str:
111-
"""Upload a VuMark template and get its target ID."""
112-
vws_web_tools.upload_vumark_template(
113-
driver=driver,
114-
database_name=vumark_database_name,
115-
svg_file_path=VUMARK_TEMPLATE_SVG_FILE_PATH,
116-
template_name=vumark_template_name,
117-
width=100.0,
118-
)
119-
return vws_web_tools.get_vumark_target_id(
120-
driver=driver,
121-
database_name=vumark_database_name,
122-
target_name=vumark_template_name,
123-
)
124-
125-
126-
def _create_vuforia_resource_names() -> tuple[str, str, str, str]:
82+
def _create_vuforia_resource_names() -> tuple[str, str]:
12783
"""Create names for Vuforia resources."""
12884
time = datetime.datetime.now(tz=datetime.UTC).strftime(
12985
format="%Y-%m-%d-%H-%M-%S",
13086
)
13187
return (
13288
f"my-license-{time}",
13389
f"my-database-{time}",
134-
f"my-vumark-database-{time}",
135-
f"my-vumark-template-{time}",
13690
)
13791

13892

@@ -157,6 +111,18 @@ def main() -> None:
157111
"client_access_key": os.environ["INACTIVE_VUFORIA_CLIENT_ACCESS_KEY"],
158112
"client_secret_key": os.environ["INACTIVE_VUFORIA_CLIENT_SECRET_KEY"],
159113
}
114+
vumark_details: VuMarkDatabaseDict = {
115+
"database_name": os.environ[
116+
"VUMARK_VUFORIA_TARGET_MANAGER_DATABASE_NAME"
117+
],
118+
"server_access_key": os.environ[
119+
"VUMARK_VUFORIA_SERVER_ACCESS_KEY"
120+
],
121+
"server_secret_key": os.environ[
122+
"VUMARK_VUFORIA_SERVER_SECRET_KEY"
123+
],
124+
}
125+
vumark_target_id = os.environ["VUMARK_VUFORIA_TARGET_ID"]
160126
new_secrets_dir.mkdir(exist_ok=True)
161127

162128
num_databases = 100
@@ -175,8 +141,6 @@ def main() -> None:
175141
(
176142
license_name,
177143
database_name,
178-
vumark_database_name,
179-
vumark_template_name,
180144
) = _create_vuforia_resource_names()
181145

182146
try:
@@ -195,33 +159,6 @@ def main() -> None:
195159
driver = None
196160
continue
197161

198-
try:
199-
vumark_details = _create_and_get_vumark_details(
200-
driver=driver,
201-
vumark_database_name=vumark_database_name,
202-
)
203-
except TimeoutException:
204-
sys.stderr.write(
205-
"Timed out waiting for VuMark setup/details after retries\n"
206-
)
207-
driver.quit()
208-
driver = None
209-
continue
210-
211-
try:
212-
vumark_target_id = _create_and_get_vumark_target_id(
213-
driver=driver,
214-
vumark_database_name=vumark_database_name,
215-
vumark_template_name=vumark_template_name,
216-
)
217-
except TimeoutException:
218-
sys.stderr.write(
219-
"Timed out waiting for VuMark template upload after retries\n"
220-
)
221-
driver.quit()
222-
driver = None
223-
continue
224-
225162
driver.quit()
226163
driver = None
227164

docs/source/mock-api-reference.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@ API Reference
2828
:members:
2929
:undoc-members:
3030

31-
.. autoclass:: mock_vws.target.Target
31+
.. autoclass:: mock_vws.target.ImageTarget
3232

33-
.. autoenum:: mock_vws.target_type.TargetType
34-
:members:
35-
:undoc-members:
33+
.. autoclass:: mock_vws.target.VuMarkTarget
3634

3735
Image matchers
3836
--------------

pyproject.toml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ optional-dependencies.dev = [
105105
"vulture==2.14",
106106
"vws-python==2026.2.15",
107107
"vws-test-fixtures==2023.3.5",
108-
"vws-web-tools==2026.2.17.1",
108+
"vws-web-tools==2026.2.20",
109109
"yamlfix==1.19.1",
110110
"zizmor==1.22.0",
111111
]
@@ -452,10 +452,7 @@ ignore_names = [
452452
# Used in TYPE_CHECKING for type hints
453453
"DatabaseDict",
454454
"VuMarkDatabaseDict",
455-
# TypedDict field names accessed via dict subscript
456-
"target_type_name",
457-
# Public enum values for library consumers
458-
"VUMARK_TEMPLATE",
455+
"VuMarkTargetDict",
459456
]
460457
# Duplicate some of .gitignore
461458
exclude = [ ".venv" ]

secrets.tar.gpg

1.45 KB
Binary file not shown.

src/mock_vws/_flask_server/target_manager.py

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
from mock_vws.database import VuforiaDatabase
1616
from mock_vws.database_type import DatabaseType
1717
from mock_vws.states import States
18-
from mock_vws.target import Target
19-
from mock_vws.target_type import TargetType
18+
from mock_vws.target import ImageTarget, VuMarkTarget
2019
from mock_vws.target_manager import TargetManager
2120
from mock_vws.target_raters import (
2221
BrisqueTargetTrackingRater,
@@ -205,25 +204,29 @@ def create_target(database_name: str) -> Response:
205204
if database.database_name == database_name
206205
)
207206
request_json = json.loads(s=request.data)
208-
image_base64 = request_json["image_base64"]
209-
image_bytes = base64.b64decode(s=image_base64)
210207
settings = TargetManagerSettings.model_validate(obj={})
211-
target_tracking_rater = settings.target_rater.to_target_rater()
212-
213-
target_type = TargetType[
214-
request_json.get("target_type_name", TargetType.IMAGE.name)
215-
]
216-
target = Target(
217-
name=request_json["name"],
218-
width=request_json["width"],
219-
image_value=image_bytes,
220-
active_flag=request_json["active_flag"],
221-
processing_time_seconds=request_json["processing_time_seconds"],
222-
application_metadata=request_json["application_metadata"],
223-
target_id=request_json["target_id"],
224-
target_tracking_rater=target_tracking_rater,
225-
target_type=target_type,
226-
)
208+
209+
target_type_name = request_json.get("target_type_name", "IMAGE")
210+
if target_type_name == "VUMARK_TEMPLATE":
211+
target: ImageTarget | VuMarkTarget = VuMarkTarget(
212+
name=request_json["name"],
213+
active_flag=request_json["active_flag"],
214+
processing_time_seconds=request_json["processing_time_seconds"],
215+
target_id=request_json["target_id"],
216+
)
217+
else:
218+
image_bytes = base64.b64decode(s=request_json["image_base64"])
219+
target_tracking_rater = settings.target_rater.to_target_rater()
220+
target = ImageTarget(
221+
name=request_json["name"],
222+
width=request_json["width"],
223+
image_value=image_bytes,
224+
active_flag=request_json["active_flag"],
225+
processing_time_seconds=request_json["processing_time_seconds"],
226+
application_metadata=request_json["application_metadata"],
227+
target_id=request_json["target_id"],
228+
target_tracking_rater=target_tracking_rater,
229+
)
227230
database.targets.add(target)
228231

229232
return Response(
@@ -247,7 +250,7 @@ def delete_target(database_name: str, target_id: str) -> Response:
247250
target = database.get_target(target_id=target_id)
248251
now = datetime.datetime.now(tz=target.upload_date.tzinfo)
249252
# See https://github.com/facebook/pyrefly/issues/1897
250-
new_target = copy.replace(
253+
new_target: ImageTarget | VuMarkTarget = copy.replace( # type: ignore[assignment]
251254
target, # pyrefly: ignore[bad-argument-type]
252255
delete_date=now,
253256
)
@@ -273,32 +276,39 @@ def update_target(database_name: str, target_id: str) -> Response:
273276
target = database.get_target(target_id=target_id)
274277

275278
request_json = json.loads(s=request.data)
276-
width = request_json.get("width", target.width)
277279
name = request_json.get("name", target.name)
278280
active_flag = request_json.get("active_flag", target.active_flag)
279-
application_metadata = request_json.get(
280-
"application_metadata",
281-
target.application_metadata,
282-
)
283-
284-
image_value = target.image_value
285-
request_json = json.loads(s=request.data)
286-
if "image" in request_json:
287-
image_value = base64.b64decode(s=request_json["image"])
288281

289282
gmt = ZoneInfo(key="GMT")
290283
last_modified_date = datetime.datetime.now(tz=gmt)
291284

292-
# See https://github.com/facebook/pyrefly/issues/1897
293-
new_target = copy.replace(
294-
target, # pyrefly: ignore[bad-argument-type]
295-
name=name,
296-
width=width,
297-
active_flag=active_flag,
298-
application_metadata=application_metadata,
299-
image_value=image_value,
300-
last_modified_date=last_modified_date,
301-
)
285+
if isinstance(target, ImageTarget):
286+
width = request_json.get("width", target.width)
287+
application_metadata = request_json.get(
288+
"application_metadata",
289+
target.application_metadata,
290+
)
291+
image_value = target.image_value
292+
if "image" in request_json:
293+
image_value = base64.b64decode(s=request_json["image"])
294+
# See https://github.com/facebook/pyrefly/issues/1897
295+
new_target: ImageTarget | VuMarkTarget = copy.replace(
296+
target, # pyrefly: ignore[bad-argument-type]
297+
name=name,
298+
width=width,
299+
active_flag=active_flag,
300+
application_metadata=application_metadata,
301+
image_value=image_value,
302+
last_modified_date=last_modified_date,
303+
)
304+
else:
305+
# See https://github.com/facebook/pyrefly/issues/1897
306+
new_target = copy.replace(
307+
target, # pyrefly: ignore[bad-argument-type]
308+
name=name,
309+
active_flag=active_flag,
310+
last_modified_date=last_modified_date,
311+
)
302312

303313
database.targets.remove(target)
304314
database.targets.add(new_target)

0 commit comments

Comments
 (0)