Skip to content

Commit 1094f2c

Browse files
feat: add support for the /read-event-type endpoint (#110)
* feat: add support for the `/read-event-type` endpoint * chore: fix typo * Update README.md --------- Co-authored-by: Golo Roden <[email protected]>
1 parent 14f4c4a commit 1094f2c

File tree

4 files changed

+110
-1
lines changed

4 files changed

+110
-1
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,14 @@ async for event_type in event_types:
498498
await event_types.aclose()
499499
```
500500

501+
### Listing a Specific Event Type
502+
503+
To list a specific event type, call the `read_event_type` function with the event type as an argument. The function returns the detailed event type, which includes the schema:
504+
505+
```python
506+
event_type = await client.read_event_type("io.eventsourcingdb.library.book-acquired")
507+
```
508+
501509
### Using Testcontainers
502510

503511
Import the `Container` class, create an instance, call the `start` function to run a test container, get a client, run your test code, and finally call the `stop` function to stop the test container:

eventsourcingdb/client.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,38 @@ async def read_subjects(
294294
f'was received \'{message}\'.'
295295
)
296296

297+
async def read_event_type(self, event_type: str) -> EventType:
298+
request_body = json.dumps({
299+
'eventType': event_type
300+
})
301+
302+
response: Response = await self.http_client.post(
303+
path='/api/v1/read-event-type',
304+
request_body=request_body,
305+
)
306+
307+
async with response:
308+
if response.status_code != HTTPStatus.OK:
309+
raise ServerError(
310+
f'Unexpected response status: {response}'
311+
)
312+
313+
response_data = await response.body.read()
314+
response_data = bytes.decode(response_data, encoding='utf-8')
315+
response_json = json.loads(response_data)
316+
317+
if not isinstance(response_json, dict):
318+
raise ServerError(
319+
f'Failed to parse response \'{response_json}\' to dict.')
320+
321+
try:
322+
return EventType.parse(response_json)
323+
except ValidationError as validation_error:
324+
raise ServerError(str(validation_error)) from validation_error
325+
except Exception as other_error:
326+
raise InternalError(str(other_error)) from other_error
327+
328+
297329
async def read_event_types(self) -> AsyncGenerator[EventType]:
298330
response: Response
299331
try:

tests/test_read_event_type.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import re
2+
import pytest
3+
4+
from eventsourcingdb import EventCandidate, EventType
5+
from eventsourcingdb.errors.server_error import ServerError
6+
7+
from .conftest import TestData
8+
from .shared.database import Database
9+
10+
11+
class TestReadEventType:
12+
@staticmethod
13+
@pytest.mark.asyncio
14+
async def test_fails_if_the_event_type_does_not_exist(
15+
database: Database,
16+
) -> None:
17+
with pytest.raises(ServerError, match=re.compile("^Server error occurred: Unexpected response status: status_code=404 Not Found")):
18+
await database.get_client().read_event_type("non.existent.event.type")
19+
20+
@staticmethod
21+
@pytest.mark.asyncio
22+
async def test_fails_if_the_event_type_is_malformed(
23+
database: Database,
24+
) -> None:
25+
with pytest.raises(ServerError, match=re.compile("^Server error occurred: Unexpected response status: status_code=400 Bad Request")):
26+
await database.get_client().read_event_type("malformed.event.type.")
27+
28+
@staticmethod
29+
@pytest.mark.asyncio
30+
async def test_read_an_existing_event_type(
31+
database: Database,
32+
test_data: TestData,
33+
) -> None:
34+
client = database.get_client("with_authorization")
35+
await client.write_events(
36+
[
37+
EventCandidate(
38+
source=test_data.TEST_SOURCE_STRING,
39+
subject="/account",
40+
type="com.foo.bar",
41+
data={},
42+
),
43+
EventCandidate(
44+
source=test_data.TEST_SOURCE_STRING,
45+
subject="/account/user",
46+
type="com.bar.baz",
47+
data={},
48+
),
49+
EventCandidate(
50+
source=test_data.TEST_SOURCE_STRING,
51+
subject="/account/user",
52+
type="com.baz.leml",
53+
data={},
54+
),
55+
EventCandidate(
56+
source=test_data.TEST_SOURCE_STRING,
57+
subject="/",
58+
type="com.quux.knax",
59+
data={},
60+
),
61+
]
62+
)
63+
64+
event_type = await client.read_event_type("com.foo.bar")
65+
66+
assert isinstance(event_type, EventType)
67+
assert event_type.event_type == "com.foo.bar"
68+
assert event_type.is_phantom is False
69+
assert event_type.schema is None

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)