Skip to content

Commit 6969f87

Browse files
Fix target_id when base_vws_url has a path prefix.
Parse the target ID from the path segment after targets, summary, or duplicates so prefixed base URLs work. Closes #3091. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent f257c27 commit 6969f87

3 files changed

Lines changed: 75 additions & 15 deletions

File tree

newsfragments/3091.change.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix ``target_id`` on target exceptions when ``base_vws_url`` includes a path prefix.

src/vws/exceptions/vws_exceptions.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@
1414
from vws.exceptions.base_exceptions import VWSError
1515

1616

17+
def _target_id_from_url(*, url: str) -> str:
18+
"""Return the target ID from a VWS response URL.
19+
20+
Paths may include a custom base URL prefix. The target ID is the
21+
path segment after ``targets``, ``summary``, or ``duplicates``.
22+
"""
23+
path = urlparse(url=url).path
24+
parts = [part for part in path.split(sep="/") if part]
25+
for marker in ("targets", "summary", "duplicates"):
26+
try:
27+
marker_index = parts.index(marker)
28+
except ValueError:
29+
continue
30+
return parts[marker_index + 1]
31+
message = f"Could not find a target ID in URL path {path!r}"
32+
raise ValueError(message) # pragma: no cover
33+
34+
1735
@beartype
1836
class UnknownTargetError(VWSError):
1937
"""Exception raised when Vuforia returns a response with a result code
@@ -23,11 +41,7 @@ class UnknownTargetError(VWSError):
2341
@property
2442
def target_id(self) -> str:
2543
"""The unknown target ID."""
26-
path = urlparse(url=self.response.url).path
27-
# Every HTTP path which can raise this error has the target ID as the
28-
# second path segment, e.g. `/something/{target_id}` or
29-
# `/something/{target_id}/more`.
30-
return path.split(sep="/")[2]
44+
return _target_id_from_url(url=self.response.url)
3145

3246

3347
@beartype
@@ -68,11 +82,7 @@ class TargetStatusProcessingError(VWSError):
6882
@property
6983
def target_id(self) -> str:
7084
"""The processing target ID."""
71-
path = urlparse(url=self.response.url).path
72-
# Every HTTP path which can raise this error has the target ID as the
73-
# second path segment, e.g. `/something/{target_id}` or
74-
# `/something/{target_id}/more`.
75-
return path.split(sep="/")[2]
85+
return _target_id_from_url(url=self.response.url)
7686

7787

7888
# This is not simulated by the mock.
@@ -158,11 +168,7 @@ class TargetStatusNotSuccessError(VWSError):
158168
@property
159169
def target_id(self) -> str:
160170
"""The unknown target ID."""
161-
path = urlparse(url=self.response.url).path
162-
# Every HTTP path which can raise this error has the target ID as the
163-
# second path segment, e.g. `/something/{target_id}` or
164-
# `/something/{target_id}/more`.
165-
return path.split(sep="/")[2]
171+
return _target_id_from_url(url=self.response.url)
166172

167173

168174
@beartype

tests/test_vws_exceptions.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,3 +473,56 @@ def test_vwserror_from_result_code() -> None:
473473

474474
assert isinstance(exception, UnknownTargetError)
475475
assert exception.response is response
476+
477+
478+
@pytest.mark.parametrize(
479+
argnames=("exception_type", "url"),
480+
argvalues=[
481+
(UnknownTargetError, "https://vws.vuforia.com/targets/abc"),
482+
(UnknownTargetError, "https://example.com/prefix/targets/abc"),
483+
(UnknownTargetError, "https://example.com/prefix/summary/abc"),
484+
(UnknownTargetError, "https://example.com/prefix/duplicates/abc"),
485+
(
486+
TargetStatusProcessingError,
487+
"https://vws.vuforia.com/targets/abc",
488+
),
489+
(
490+
TargetStatusProcessingError,
491+
"https://example.com/prefix/targets/abc",
492+
),
493+
(
494+
TargetStatusNotSuccessError,
495+
"https://vws.vuforia.com/targets/abc",
496+
),
497+
(
498+
TargetStatusNotSuccessError,
499+
"https://example.com/prefix/targets/abc",
500+
),
501+
(
502+
TargetStatusNotSuccessError,
503+
"https://example.com/prefix/targets/abc/instances",
504+
),
505+
],
506+
)
507+
def test_target_id_with_base_url_prefixes(
508+
*,
509+
exception_type: type[
510+
UnknownTargetError
511+
| TargetStatusProcessingError
512+
| TargetStatusNotSuccessError
513+
],
514+
url: str,
515+
) -> None:
516+
"""``target_id`` is correct even when ``base_vws_url`` has a path
517+
prefix.
518+
"""
519+
response = Response(
520+
text="{}",
521+
url=url,
522+
status_code=HTTPStatus.NOT_FOUND,
523+
headers={},
524+
request_body=None,
525+
tell_position=0,
526+
content=b"",
527+
)
528+
assert exception_type(response=response).target_id == "abc"

0 commit comments

Comments
 (0)