Skip to content

Commit e6c52dc

Browse files
adamtheturtleclaude
andcommitted
Take the reco counts report year and month as ints
The month was a ``YYYY-mm`` string, which let callers pass a value that could not be a month at all. Taking two ints makes a malformed month unrepresentable, and reads better next to ``datetime`` attributes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent b1c34db commit e6c52dc

7 files changed

Lines changed: 89 additions & 51 deletions

File tree

docs/source/index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@ The report is generated in the background, and the URL it is served from expires
9292
)
9393
9494
now = datetime.datetime.now(tz=datetime.UTC)
95-
this_month = now.strftime(format="%Y-%m")
9695
9796
report_request = vws_client.request_database_reco_counts_report(
98-
month=this_month,
97+
year=now.year,
98+
month=now.month,
9999
)
100100
101101
report = vws_client.wait_for_reco_counts_report(

src/vws/_reco_counts.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,18 @@ def reco_counts_report_path(*, database_id: str | None) -> str:
3939

4040

4141
@beartype(conf=BeartypeConf(is_pep484_tower=True))
42-
def reco_counts_report_body(*, month: str) -> bytes:
42+
def reco_counts_report_body(*, year: int, month: int) -> bytes:
4343
"""Get the request body for requesting a reco counts report.
4444
4545
Args:
46-
month: The month to request the report for, in ``YYYY-mm`` form.
46+
year: The year to request the report for.
47+
month: The month of the year to request the report for.
4748
4849
Returns:
4950
The body of the request.
5051
"""
51-
return json.dumps(obj={"month": month}).encode(encoding="utf-8")
52+
month_string = f"{year:04d}-{month:02d}"
53+
return json.dumps(obj={"month": month_string}).encode(encoding="utf-8")
5254

5355

5456
@beartype(conf=BeartypeConf(is_pep484_tower=True))

src/vws/async_vws.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,8 @@ async def get_database_summary_report(
458458
async def request_database_reco_counts_report(
459459
self,
460460
*,
461-
month: str,
461+
year: int,
462+
month: int,
462463
) -> RecoCountsReportRequest:
463464
"""Request a per-target recognition count report for the database.
464465
@@ -467,8 +468,9 @@ async def request_database_reco_counts_report(
467468
:meth:`wait_for_reco_counts_report` to wait for it.
468469
469470
Args:
470-
month: The month to get recognition counts for, in ``YYYY-mm``
471-
form. Vuforia accepts only the current month and the previous
471+
year: The year to get recognition counts for.
472+
month: The month of the year to get recognition counts for.
473+
Vuforia accepts only the current month and the previous
472474
month.
473475
474476
Returns:
@@ -482,8 +484,8 @@ async def request_database_reco_counts_report(
482484
secret key is not correct, or the client's ``database_id`` is
483485
not the ID of the database which the client's keys belong to.
484486
~vws.exceptions.vws_exceptions.FailError: There was an error with
485-
the request. For example, the given month is not the current
486-
month or the previous month.
487+
the request. For example, the given year and month are not
488+
the current month or the previous month.
487489
~vws.exceptions.vws_exceptions.RequestTimeTooSkewedError: There is
488490
an error with the time sent to Vuforia.
489491
~vws.exceptions.custom_exceptions.ServerError: There is an error
@@ -493,7 +495,7 @@ async def request_database_reco_counts_report(
493495
"""
494496
response = await self.make_request(
495497
method=HTTPMethod.POST,
496-
data=reco_counts_report_body(month=month),
498+
data=reco_counts_report_body(year=year, month=month),
497499
request_path=reco_counts_report_path(
498500
database_id=self._database_id,
499501
),

src/vws/vws.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,8 @@ def get_database_summary_report(self) -> DatabaseSummaryReport:
431431
def request_database_reco_counts_report(
432432
self,
433433
*,
434-
month: str,
434+
year: int,
435+
month: int,
435436
) -> RecoCountsReportRequest:
436437
"""Request a per-target recognition count report for the database.
437438
@@ -440,8 +441,9 @@ def request_database_reco_counts_report(
440441
:meth:`wait_for_reco_counts_report` to wait for it.
441442
442443
Args:
443-
month: The month to get recognition counts for, in ``YYYY-mm``
444-
form. Vuforia accepts only the current month and the previous
444+
year: The year to get recognition counts for.
445+
month: The month of the year to get recognition counts for.
446+
Vuforia accepts only the current month and the previous
445447
month.
446448
447449
Returns:
@@ -455,8 +457,8 @@ def request_database_reco_counts_report(
455457
secret key is not correct, or the client's ``database_id`` is
456458
not the ID of the database which the client's keys belong to.
457459
~vws.exceptions.vws_exceptions.FailError: There was an error with
458-
the request. For example, the given month is not the current
459-
month or the previous month.
460+
the request. For example, the given year and month are not
461+
the current month or the previous month.
460462
~vws.exceptions.vws_exceptions.RequestTimeTooSkewedError: There is
461463
an error with the time sent to Vuforia.
462464
~vws.exceptions.custom_exceptions.ServerError: There is an error
@@ -466,7 +468,7 @@ def request_database_reco_counts_report(
466468
"""
467469
response = self.make_request(
468470
method=HTTPMethod.POST,
469-
data=reco_counts_report_body(month=month),
471+
data=reco_counts_report_body(year=year, month=month),
470472
request_path=reco_counts_report_path(
471473
database_id=self._database_id,
472474
),

tests/conftest.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,24 +125,24 @@ async def async_vumark_service_client(
125125

126126

127127
@pytest.fixture(name="current_month")
128-
def fixture_current_month() -> str:
129-
"""The current month, in the form which reco counts reports use."""
128+
def fixture_current_month() -> datetime.date:
129+
"""The current month, as the first day of that month."""
130130
now = datetime.datetime.now(tz=datetime.UTC)
131-
return now.strftime(format="%Y-%m")
131+
return now.date().replace(day=1)
132132

133133

134134
@pytest.fixture(name="report_month", params=["current", "previous"])
135-
def fixture_report_month(*, request: pytest.FixtureRequest) -> str:
135+
def fixture_report_month(*, request: pytest.FixtureRequest) -> datetime.date:
136136
"""A month which a reco counts report can be requested for.
137137
138138
Vuforia accepts only the current month and the previous month.
139139
"""
140140
now = datetime.datetime.now(tz=datetime.UTC)
141+
first_of_month = now.date().replace(day=1)
141142
if request.param == "current":
142-
return now.strftime(format="%Y-%m")
143+
return first_of_month
143144

144-
last_of_previous_month = now.replace(day=1) - datetime.timedelta(days=1)
145-
return last_of_previous_month.strftime(format="%Y-%m")
145+
return first_of_month - datetime.timedelta(days=1)
146146

147147

148148
@pytest.fixture(name="image_file", params=["r+b", "rb"])

tests/test_async_vws.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Tests for async helper functions for managing a Vuforia database."""
22

33
import base64
4+
import datetime # noqa: TC003
45
import io # noqa: TC003
56
import time
67
import uuid
@@ -509,12 +510,13 @@ class TestRecoCountsReport:
509510
async def test_reco_counts_report(
510511
*,
511512
async_vws_client: AsyncVWS,
512-
report_month: str,
513+
report_month: datetime.date,
513514
) -> None:
514515
"""A report can be requested, waited for and downloaded."""
515516
client = async_vws_client
516517
report_request = await client.request_database_reco_counts_report(
517-
month=report_month,
518+
year=report_month.year,
519+
month=report_month.month,
518520
)
519521
assert report_request.transaction_id
520522
assert report_request.presigned_url
@@ -529,7 +531,7 @@ async def test_reco_counts_report(
529531

530532
@staticmethod
531533
@pytest.mark.asyncio
532-
async def test_not_ready(*, current_month: str) -> None:
534+
async def test_not_ready(*, current_month: datetime.date) -> None:
533535
"""Downloading a report before Vuforia has generated it raises an
534536
error.
535537
"""
@@ -543,7 +545,8 @@ async def test_not_ready(*, current_month: str) -> None:
543545
) as client:
544546
report_request = (
545547
await client.request_database_reco_counts_report(
546-
month=current_month,
548+
year=current_month.year,
549+
month=current_month.month,
547550
)
548551
)
549552

@@ -558,7 +561,7 @@ async def test_not_ready(*, current_month: str) -> None:
558561

559562
@staticmethod
560563
@pytest.mark.asyncio
561-
async def test_wait_timeout(*, current_month: str) -> None:
564+
async def test_wait_timeout(*, current_month: datetime.date) -> None:
562565
"""Waiting for a report which is not generated in time raises an
563566
error.
564567
"""
@@ -572,7 +575,8 @@ async def test_wait_timeout(*, current_month: str) -> None:
572575
) as client:
573576
report_request = (
574577
await client.request_database_reco_counts_report(
575-
month=current_month,
578+
year=current_month.year,
579+
month=current_month.month,
576580
)
577581
)
578582

@@ -594,19 +598,24 @@ async def test_wait_timeout(*, current_month: str) -> None:
594598
@staticmethod
595599
@pytest.mark.asyncio
596600
@pytest.mark.parametrize(
597-
argnames="month",
598-
argvalues=["1999-01", "not-a-month"],
601+
argnames=("year", "month"),
602+
argvalues=[
603+
pytest.param(1999, 1, id="month-in-the-past"),
604+
pytest.param(1999, 13, id="month-out-of-range"),
605+
],
599606
)
600607
async def test_month_not_accepted(
601608
*,
602609
async_vws_client: AsyncVWS,
603-
month: str,
610+
year: int,
611+
month: int,
604612
) -> None:
605613
"""Months other than the current and previous month are
606614
rejected.
607615
"""
608616
with pytest.raises(expected_exception=FailError) as exc:
609617
await async_vws_client.request_database_reco_counts_report(
618+
year=year,
610619
month=month,
611620
)
612621

@@ -616,7 +625,7 @@ async def test_month_not_accepted(
616625
@pytest.mark.asyncio
617626
async def test_database_id_does_not_match_keys(
618627
*,
619-
current_month: str,
628+
current_month: datetime.date,
620629
) -> None:
621630
"""A database ID which does not match the given keys is
622631
rejected.
@@ -633,7 +642,8 @@ async def test_database_id_does_not_match_keys(
633642
expected_exception=AuthenticationFailureError,
634643
) as exc:
635644
await client.request_database_reco_counts_report(
636-
month=current_month,
645+
year=current_month.year,
646+
month=current_month.month,
637647
)
638648

639649
assert (
@@ -660,7 +670,7 @@ async def test_download_error() -> None:
660670

661671
@staticmethod
662672
@pytest.mark.asyncio
663-
async def test_no_database_id(*, current_month: str) -> None:
673+
async def test_no_database_id(*, current_month: datetime.date) -> None:
664674
"""A client which was given no database ID cannot request a
665675
report.
666676
"""
@@ -670,7 +680,8 @@ async def test_no_database_id(*, current_month: str) -> None:
670680
) as client:
671681
with pytest.raises(expected_exception=DatabaseIdNotSetError):
672682
await client.request_database_reco_counts_report(
673-
month=current_month,
683+
year=current_month.year,
684+
month=current_month.month,
674685
)
675686

676687

0 commit comments

Comments
 (0)