Skip to content

Commit b376306

Browse files
committed
add async tests
1 parent b12eb13 commit b376306

7 files changed

Lines changed: 596 additions & 43 deletions

File tree

poetry.lock

Lines changed: 14 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
name = "qbreader"
33
version = "1.0.0-beta.1"
44
description = "The official qbreader API python wrapper"
5-
authors = ["Sky \"g3ner1c\" Hong <g3ner1c-sky@pm.me>", "Rohan Arni", "Geoffrey Wu <geoffreywu1000@gmail.com>"]
5+
authors = [
6+
"Sky \"g3ner1c\" Hong <g3ner1c-sky@pm.me>",
7+
"Rohan Arni",
8+
"Geoffrey Wu <geoffreywu1000@gmail.com>",
9+
]
610
license = "MIT"
711
readme = "README.md"
812
homepage = "https://github.com/qbreader/python-module"
913
repository = "https://github.com/qbreader/python-module"
1014
documentation = "https://github.com/qbreader/python-module#readme"
1115
keywords = ["quizbowl", "quiz bowl"]
12-
classifiers=[
16+
classifiers = [
1317
"Development Status :: 4 - Beta",
1418
"Intended Audience :: Developers",
1519
"Programming Language :: Python :: 3",
@@ -34,7 +38,7 @@ types-requests = "^2.31.0.1"
3438
tox = "^4.6.4"
3539
pytest = "^7.4.0"
3640
pytest-cov = "^4.1.0"
37-
pytest-async = "^0.1.1"
41+
pytest-asyncio = "^0.21.1"
3842

3943
[tool.black]
4044
line-length = 88
@@ -49,6 +53,7 @@ convention = "numpy"
4953
[tool.pytest.ini_options]
5054
addopts = "-v --cov=qbreader --cov-report=term-missing --cov-report=xml --cov-report=html"
5155
testpaths = "tests"
56+
asyncio_mode = "strict"
5257

5358
[build-system]
5459
requires = ["poetry-core>=1.0.0"]

qbreader/asynchronous.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Directly access the qbreader API asynchronously."""
22

3-
from typing import Optional, Self
3+
from typing import Optional, Self, Type
44

55
import aiohttp
66

@@ -23,24 +23,40 @@
2323
class Async:
2424
"""The asynchronous qbreader API wrapper."""
2525

26-
def __init__(self, session: Optional[aiohttp.ClientSession] = None):
27-
"""Initialize a new Async instance.
26+
session: aiohttp.ClientSession
27+
28+
@classmethod
29+
async def create(
30+
cls: Type[Self], session: Optional[aiohttp.ClientSession] = None
31+
) -> Self:
32+
"""Create a new Async instance. `__init__()` is not async, so this is necessary.
2833
2934
Parameters
3035
----------
3136
session : aiohttp.ClientSession, optional
3237
The aiohttp session to use for requests. If none is provided, a new session
3338
will be created.
39+
40+
Returns
41+
-------
42+
Async
43+
The new Async instance.
3444
"""
45+
self = cls()
3546
self.session = session or aiohttp.ClientSession()
47+
return self
48+
49+
async def close(self: Self) -> None:
50+
"""Close the aiohttp session."""
51+
await self.session.close()
3652

3753
async def __aenter__(self: Self) -> Self:
3854
"""Enter an async context."""
3955
return self
4056

4157
async def __aexit__(self: Self) -> None:
4258
"""Exit an async context."""
43-
await self.session.close()
59+
await self.close()
4460

4561
async def query(
4662
self: Self,
@@ -323,7 +339,7 @@ async def random_bonus(
323339
raise Exception(str(response.status) + " bad request")
324340

325341
json = await response.json()
326-
return tuple(Bonus.from_json(b) for b in await json["bonuses"])
342+
return tuple(Bonus.from_json(b) for b in json["bonuses"])
327343

328344
async def random_name(self: Self) -> str:
329345
"""Get a random adjective-noun pair that can be used as a name.

qbreader/types.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ async def check_answer_async(
168168
cls: Type[Self],
169169
answerline: str,
170170
givenAnswer: str,
171-
session: aiohttp.ClientSession,
171+
session: aiohttp.ClientSession | None = None,
172172
) -> Self:
173173
"""Asynchronously create an AnswerJudgement given an answerline and an answer.
174174
@@ -199,6 +199,15 @@ async def check_answer_async(
199199

200200
data = {"answerline": answerline, "givenAnswer": givenAnswer}
201201

202+
if session is None:
203+
async with aiohttp.ClientSession() as session:
204+
async with session.get(url, params=data) as response:
205+
if response.status != 200:
206+
raise Exception(str(response.status) + " bad request")
207+
208+
json = await response.json()
209+
return cls.from_json(json)
210+
202211
async with session.get(url, params=data) as response:
203212
if response.status != 200:
204213
raise Exception(str(response.status) + " bad request")
@@ -258,7 +267,7 @@ def check_answer_sync(self, givenAnswer: str) -> AnswerJudgement:
258267
return AnswerJudgement.check_answer_sync(self.formatted_answer, givenAnswer)
259268

260269
async def check_answer_async(
261-
self, givenAnswer: str, session: aiohttp.ClientSession
270+
self, givenAnswer: str, session: aiohttp.ClientSession | None = None
262271
) -> AnswerJudgement:
263272
"""Asynchronously check whether an answer is correct."""
264273
return await AnswerJudgement.check_answer_async(

tests/__init__.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ def assert_exception(
2828
func(*args, **kwargs)
2929

3030

31+
async def async_assert_exception(
32+
func: Callable,
33+
exception,
34+
*args,
35+
**kwargs,
36+
):
37+
"""Assert that an async function raises an exception."""
38+
with pytest.raises(exception):
39+
await func(*args, **kwargs)
40+
41+
3142
def assert_warning(
3243
func: Callable,
3344
warning,
@@ -37,3 +48,14 @@ def assert_warning(
3748
"""Assert that a function raises a warning."""
3849
with pytest.warns(warning):
3950
return func(*args, **kwargs)
51+
52+
53+
async def async_assert_warning(
54+
func: Callable,
55+
warning,
56+
*args,
57+
**kwargs,
58+
):
59+
"""Assert that an async function raises a warning."""
60+
with pytest.warns(warning):
61+
return await func(*args, **kwargs)

0 commit comments

Comments
 (0)