Add VuMark Generation API endpoint (#473)#2878
Conversation
Implement POST /targets/<target_id>/instances endpoint for generating VuMark instance images in SVG, PNG, or PDF format. Includes validators, exception classes, image generators, and comprehensive test coverage for both requests-mock and Flask implementations. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Address mypy type checking issues in vumark implementation: - Use keyword arguments for PIL Image/ImageDraw methods - Add proper type annotation for accept_header variable - Use str(object=...) syntax for strict type checking Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add 'svg' to spelling dictionary and fix 'pdf' to 'PDF' in comments to pass pylint spell checking. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Use the standard test pattern with the verify_mock_vuforia fixture so tests run against all backends (real, mock, docker). Add test classes to the CI matrix in test.yml. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- PNG: Use white background (was black, making text invisible) - SVG: Escape instance_id with xml.sax.saxutils.escape to prevent malformed XML from special characters - PDF: Compute stream length, xref offsets, and startxref dynamically instead of hardcoding them. Escape PDF string literal characters. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Return exc.response_text as str (consistent with all other endpoints) instead of encoding to bytes on error paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Real Vuforia returns 422 InvalidTargetType because the test targets are regular image targets, not VuMark targets. Use mock_only_vuforia to skip real Vuforia backend. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| return requests.post(url=url, data=content, headers=headers, timeout=30) | ||
|
|
||
|
|
||
| @pytest.mark.usefixtures("mock_only_vuforia") |
There was a problem hiding this comment.
This needs to not be mock-only
| """Tests for successful VuMark instance generation.""" | ||
|
|
||
| @pytest.fixture | ||
| def vuforia_database( # pylint: disable=no-self-use |
There was a problem hiding this comment.
Instead, let's have a conftest.py fixture for a vucloud dataabse
pyproject.toml
Outdated
| "@*APP.route", | ||
| "@*APP.before_request", | ||
| "@*APP.errorhandler", | ||
| # requests-mock server |
There was a problem hiding this comment.
Not sure why we need this
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| vucloud_database: VuforiaDatabase, | ||
| ) -> VuforiaDatabase: | ||
| """Use a VuCloud database for VuMark generation tests.""" | ||
| return vucloud_database |
There was a problem hiding this comment.
Circular fixture dependency in TestSuccessfulGeneration class
High Severity
The class-level vuforia_database fixture depends on vucloud_database (from conftest), which in turn depends on vuforia_database. Pytest resolves all fixture dependencies from the test's scope, so vucloud_database's vuforia_database parameter resolves to the class-level override — creating a circular dependency. The other test classes (TestTargetStatusNotSuccess, TestResponseHeaders) avoid this by using the self-referencing pattern def vuforia_database(self, vuforia_database), which pytest special-cases to resolve to the outer scope.
Additional Locations (1)
| _ROUTES: set[Route] = set() | ||
|
|
||
| _ResponseType = tuple[int, Mapping[str, str], str] | ||
| _ResponseType = tuple[int, Mapping[str, str], str | bytes] |
There was a problem hiding this comment.
_ResponseType in decorators not updated for bytes
Medium Severity
The _ResponseType in mock_web_services_api.py was updated to str | bytes to support the vumark endpoint returning binary content, but the corresponding _ResponseType in decorators.py still uses str. The _Callback type and wrapped function's return annotation in _wrap_callback incorrectly claim only str bodies are supported. This type mismatch could cause static type checker failures and is misleading.


Implements POST /targets/<target_id>/instances endpoint for generating VuMark instance images in SVG, PNG, or PDF format. Includes validators, exception classes, image generators, and comprehensive test coverage for both requests-mock and Flask implementations.
Closes #473
🤖 Generated with Claude Code
Note
Medium Risk
Adds a new API endpoint returning binary payloads (SVG/PNG/PDF) and introduces new validation/error paths plus new
target_type/default_target_typefields that affect target/database serialization and test fixtures.Overview
Implements
POST /targets/{target_id}/instances(VuMark Generation API) across both the Flask app and theresponses/requests-mock backend, returning placeholderimage/svg+xml,image/png, orapplication/pdfcontent based on theAcceptheader and validatinginstance_id, target type, and target success status.Extends the data model to support VuMark targets by adding
default_target_typetoVuforiaDatabaseandtarget_typetoTarget(propagated through target/database creation/serialization), adds new validator exceptions/result codes for invalid Accept/header/instance/target type, updates target-id parsing to handle/targets/{id}/instances, and adds comprehensive tests + CI matrix entries (plus minor vulture/spellcheck updates).Written by Cursor Bugbot for commit fc1e301. This will update automatically on new commits. Configure here.