From 5450dc6c61ad7c631556d9458b0d8d625c1adc33 Mon Sep 17 00:00:00 2001 From: David Jiang Date: Tue, 18 Nov 2025 00:39:35 -0500 Subject: [PATCH 1/3] add min date for query --- qbreader/synchronous.py | 18 +++++++++++++++++- tests/test_sync.py | 27 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/qbreader/synchronous.py b/qbreader/synchronous.py index 31c1bb0..72b8cf0 100644 --- a/qbreader/synchronous.py +++ b/qbreader/synchronous.py @@ -45,6 +45,8 @@ def query( maxReturnLength: Optional[int] = 25, tossupPagination: Optional[int] = 1, bonusPagination: Optional[int] = 1, + min_year: int = Year.MIN_YEAR, + max_year: int = Year.CURRENT_YEAR, ) -> QueryResponse: """Query the qbreader database for questions. @@ -92,7 +94,10 @@ class type. The page of tossups to return. bonusPagination : int, default = 1 The page of bonuses to return. - + min_year : int, default = Year.MIN_YEAR + The earliest year to search. + max_year : int, default = Year.CURRENT_YEAR + The latest year to search. Returns ------- QueryResponse @@ -149,6 +154,15 @@ class type. elif param < 1: raise ValueError(f"{name} must be at least 1.") + for name, year in { + "minYear": min_year, + "maxYear": max_year, + }.items(): + if not isinstance(year, int): + raise TypeError( + f"{name} must be an integer, not {type(param).__name__}." + ) + url = BASE_URL + "/query" ( @@ -174,6 +188,8 @@ class type. "maxReturnLength": maxReturnLength, "tossupPagination": tossupPagination, "bonusPagination": bonusPagination, + "minYear": min_year, + "maxYear": max_year, } data = api_utils.prune_none(data) diff --git a/tests/test_sync.py b/tests/test_sync.py index 5a485c0..d61f331 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -88,6 +88,21 @@ def test_query(self, params: dict[str, Any], expected_answer: str): elif params["questionType"] == "bonus": assert query.bonuses[0].check_answer_sync(0, expected_answer).correct() + def test_query_min_max_year_range(self): + min_year = 2010 + max_year = 2015 + + query = qbr.query( + questionType="tossup", + searchType="question", + min_year=min_year, + max_year=max_year, + maxReturnLength=10, + ) + + for tossup in query.tossups: + assert min_year <= tossup.set.year <= max_year + @pytest.mark.parametrize( "params, exception", [ @@ -133,6 +148,18 @@ def test_query(self, params: dict[str, Any], expected_answer: str): }, ValueError, ), + ( + { + "min_year": "not an int", + }, + TypeError, + ), + ( + { + "max_year": "not an int", + }, + TypeError, + ), ], ) def test_query_exception(self, params: dict[str, Any], exception: Exception): From dcd7193cc02f9d294c18475367e2a041e51bde93 Mon Sep 17 00:00:00 2001 From: Geoffrey Wu Date: Fri, 28 Nov 2025 23:29:40 -0600 Subject: [PATCH 2/3] fix linting --- qbreader/synchronous.py | 2 +- tests/test_sync.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qbreader/synchronous.py b/qbreader/synchronous.py index 72b8cf0..bec6e9f 100644 --- a/qbreader/synchronous.py +++ b/qbreader/synchronous.py @@ -46,7 +46,7 @@ def query( tossupPagination: Optional[int] = 1, bonusPagination: Optional[int] = 1, min_year: int = Year.MIN_YEAR, - max_year: int = Year.CURRENT_YEAR, + max_year: int = Year.CURRENT_YEAR, ) -> QueryResponse: """Query the qbreader database for questions. diff --git a/tests/test_sync.py b/tests/test_sync.py index d61f331..4dd64fd 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -102,7 +102,7 @@ def test_query_min_max_year_range(self): for tossup in query.tossups: assert min_year <= tossup.set.year <= max_year - + @pytest.mark.parametrize( "params, exception", [ From ba9cb9c5783fe61df57ec78e23a500ead16c01f5 Mon Sep 17 00:00:00 2001 From: Geoffrey Wu Date: Fri, 28 Nov 2025 23:37:14 -0600 Subject: [PATCH 3/3] copy over to async --- qbreader/asynchronous.py | 18 +++++++++++++++++- tests/test_async.py | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/qbreader/asynchronous.py b/qbreader/asynchronous.py index 97265fb..5907514 100644 --- a/qbreader/asynchronous.py +++ b/qbreader/asynchronous.py @@ -80,6 +80,8 @@ async def query( maxReturnLength: Optional[int] = 25, tossupPagination: Optional[int] = 1, bonusPagination: Optional[int] = 1, + min_year: int = Year.MIN_YEAR, + max_year: int = Year.CURRENT_YEAR, ) -> QueryResponse: """Query the qbreader database for questions. @@ -127,7 +129,10 @@ class type. The page of tossups to return. bonusPagination : int, default = 1 The page of bonuses to return. - + min_year : int, default = Year.MIN_YEAR + The earliest year to search. + max_year : int, default = Year.CURRENT_YEAR + The latest year to search. Returns ------- QueryResponse @@ -184,6 +189,15 @@ class type. elif param < 1: raise ValueError(f"{name} must be at least 1.") + for name, year in { + "minYear": min_year, + "maxYear": max_year, + }.items(): + if not isinstance(year, int): + raise TypeError( + f"{name} must be an integer, not {type(param).__name__}." + ) + url = BASE_URL + "/query" ( @@ -209,6 +223,8 @@ class type. "maxReturnLength": maxReturnLength, "tossupPagination": tossupPagination, "bonusPagination": bonusPagination, + "minYear": min_year, + "maxYear": max_year, } data = api_utils.prune_none(data) diff --git a/tests/test_async.py b/tests/test_async.py index 15180ef..0151dc5 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -116,6 +116,22 @@ async def test_query(self, qbr, params: dict[str, Any], expected_answer: str): ) assert judgement.correct() + @pytest.mark.asyncio + async def test_query_min_max_year_range(self, qbr): + min_year = 2010 + max_year = 2015 + + query = await qbr.query( + questionType="tossup", + searchType="question", + min_year=min_year, + max_year=max_year, + maxReturnLength=10, + ) + + for tossup in query.tossups: + assert min_year <= tossup.set.year <= max_year + @pytest.mark.asyncio @pytest.mark.parametrize( "params, exception",