Skip to content

Commit 6b5cf10

Browse files
committed
add basic sessions test and example
1 parent fc44122 commit 6b5cf10

File tree

7 files changed

+317
-27
lines changed

7 files changed

+317
-27
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ transform:
1818

1919

2020
all: download transform
21+
22+
test:
23+
PYTHONPATH="src" pytest

data/examples/output/sessions.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"A8CD3F": {
3+
"code": "A8CD3F",
4+
"title": "This is a test talk from a test speaker about a test topic.",
5+
"speakers": [
6+
"F3DC8A", "ZXCVBN"
7+
],
8+
"submission_type": "Talk (long session)",
9+
"slug": "this-is-a-test-talk-from-a-test-speaker-about-a-test-topic",
10+
"track": "Software Engineering & Architecture",
11+
"state": "confirmed",
12+
"abstract": "This is the abstract of the talk, it should be about Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec condimentum viverra ante in dignissim. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec molestie lorem enim, id dignissim mi faucibus a. Suspendisse mollis lobortis mollis. Praesent eu lorem id velit maximus blandit eget at nisl. Quisque fringilla pharetra euismod. Morbi id ante vitae tortor volutpat interdum fermentum id tortor. Vivamus ligula nisl, mattis molestie purus vel, interdum venenatis nulla. Nam suscipit scelerisque ornare. Ut consequat sem vel sapien porta pretium. Nullam non lacinia nulla, a tincidunt dui. Sed consequat nibh in nibh ornare, rhoncus sollicitudin sem lobortis. Etiam molestie est et felis sollicitudin, commodo facilisis mi vehicula. Quisque pharetra consectetur ligula, sit amet tincidunt nibh consectetur fringilla. Suspendisse eu libero sed magna malesuada bibendum sed et enim. Phasellus convallis tortor nec lectus venenatis, id tristique quam finibus.",
13+
"tweet": "This is a short version of this talk, as a tweet.",
14+
"duration": "45",
15+
"level": "intermediate",
16+
"delivery": "in-person",
17+
"room": null,
18+
"start": null,
19+
"end": null,
20+
"talks_in_parallel": null,
21+
"talks_after": null,
22+
"next_talk_code": null,
23+
"prev_talk_code": null,
24+
"website_url": "https://ep2024.europython.eu/session/this-is-a-test-talk-from-a-test-speaker-about-a-test-topic"
25+
},
26+
"B8CD4F": {
27+
"code": "B8CD4F",
28+
"title": "A talk with shorter title",
29+
"speakers": [
30+
"G3DC8A"
31+
],
32+
"submission_type": "Talk",
33+
"slug": "a-talk-with-shorter-title",
34+
"track": "PyData: LLMs",
35+
"state": "confirmed",
36+
"abstract": "This is the abstract of the shoerter talk, it should be about Lorem ipsum dolor sit amet",
37+
"tweet": "Hey, short tweet",
38+
"duration": "30",
39+
"level": "beginner",
40+
"delivery": "in-person",
41+
"room": null,
42+
"start": null,
43+
"end": null,
44+
"talks_in_parallel": null,
45+
"talks_after": null,
46+
"next_talk_code": null,
47+
"prev_talk_code": null,
48+
"website_url": "https://ep2024.europython.eu/session/a-talk-with-shorter-title"
49+
}
50+
}

data/examples/output/speakers.json

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
[
2+
{
3+
"code": "A8CD3F",
4+
"speakers": [
5+
{
6+
"code": "F3DC8A",
7+
"name": "A Speaker",
8+
"biography": "This is a biography of F3D speaker",
9+
"avatar": "https://pretalx.com/media/avatars/picture.jpg",
10+
"email": "f3dc8a@example.com"
11+
},
12+
{
13+
"code": "ZXCVBN",
14+
"name": "ZXC Speaker",
15+
"biography": "This is a biography of ZXC speaker",
16+
"avatar": "https://pretalx.com/media/avatars/picture.jpg",
17+
"email": "zxcvbn@example.com"
18+
}
19+
],
20+
"title": "This is a test talk from a test speaker about a test topic.",
21+
"submission_type": "Talk (long session)",
22+
"submission_type_id": 3961,
23+
"track": {
24+
"en": "Software Engineering & Architecture"
25+
},
26+
"track_id": 4493,
27+
"state": "confirmed",
28+
"abstract": "This is the abstract of the talk, it should be about Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec condimentum viverra ante in dignissim. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec molestie lorem enim, id dignissim mi faucibus a. Suspendisse mollis lobortis mollis. Praesent eu lorem id velit maximus blandit eget at nisl. Quisque fringilla pharetra euismod. Morbi id ante vitae tortor volutpat interdum fermentum id tortor. Vivamus ligula nisl, mattis molestie purus vel, interdum venenatis nulla. Nam suscipit scelerisque ornare. Ut consequat sem vel sapien porta pretium. Nullam non lacinia nulla, a tincidunt dui. Sed consequat nibh in nibh ornare, rhoncus sollicitudin sem lobortis. Etiam molestie est et felis sollicitudin, commodo facilisis mi vehicula. Quisque pharetra consectetur ligula, sit amet tincidunt nibh consectetur fringilla. Suspendisse eu libero sed magna malesuada bibendum sed et enim. Phasellus convallis tortor nec lectus venenatis, id tristique quam finibus.",
29+
"description": null,
30+
"duration": 45,
31+
"slot_count": 1,
32+
"do_not_record": false,
33+
"is_featured": false,
34+
"content_locale": "en",
35+
"slot": null,
36+
"image": null,
37+
"resources": [],
38+
"answers": [
39+
{
40+
"question": {
41+
"id": 3406,
42+
"question": {
43+
"en": "Outline"
44+
}
45+
},
46+
"answer": "This is an outline",
47+
"answer_file": null,
48+
"submission": "A8CD3F",
49+
"review": null,
50+
"person": null,
51+
"options": []
52+
},
53+
{
54+
"question": {
55+
"id": 3412,
56+
"question": {
57+
"en": "Abstract as a tweet / toot"
58+
}
59+
},
60+
"answer": "This is a short version of this talk, as a tweet.",
61+
"answer_file": null,
62+
"submission": "A8CD3F",
63+
"review": null,
64+
"person": null
65+
},
66+
{
67+
"question": {
68+
"id": 3412,
69+
"question": {
70+
"en": "Expected audience expertise"
71+
}
72+
},
73+
"answer": "Intermediate",
74+
"answer_file": null,
75+
"submission": "A8CD3F",
76+
"review": null,
77+
"person": null,
78+
"options": [
79+
{
80+
"id": 4495,
81+
"answer": {
82+
"en": "Intermediate"
83+
}
84+
}
85+
]
86+
},
87+
{
88+
"question": {
89+
"id": 3420,
90+
"question": {
91+
"en": "My presentation can be delivered"
92+
}
93+
},
94+
"answer": "in-person at the conference venue",
95+
"answer_file": null,
96+
"submission": "A8CD3F",
97+
"review": null,
98+
"person": null,
99+
"options": [
100+
{
101+
"id": 4500,
102+
"answer": {
103+
"en": "in-person at the conference venue"
104+
}
105+
}
106+
]
107+
}
108+
],
109+
"created": "2024-03-05T00:00:10.354629+01:00",
110+
"pending_state": null,
111+
"notes": "",
112+
"internal_notes": null,
113+
"tags": [],
114+
"tag_ids": []
115+
},
116+
{
117+
"code": "B8CD4F",
118+
"speakers": [
119+
{
120+
"code": "G3DC8A",
121+
"name": "Another Speaker",
122+
"biography": "This is a biography of F3D speaker",
123+
"avatar": "https://pretalx.com/media/avatars/picture.jpg",
124+
"email": "g3dc8a@example.com"
125+
}
126+
],
127+
"title": "A talk with shorter title",
128+
"submission_type": "Talk",
129+
"submission_type_id": 3961,
130+
"track": {
131+
"en": "PyData: LLMs"
132+
},
133+
"track_id": 4493,
134+
"state": "confirmed",
135+
"abstract": "This is the abstract of the talk, it should be about Lorem ipsum dolor sit amet",
136+
"description": null,
137+
"duration": 30,
138+
"slot_count": 1,
139+
"do_not_record": false,
140+
"is_featured": false,
141+
"content_locale": "en",
142+
"slot": null,
143+
"image": null,
144+
"resources": [],
145+
"answers": [
146+
{
147+
"question": {
148+
"id": 3406,
149+
"question": {
150+
"en": "Outline"
151+
}
152+
},
153+
"answer": "This is an outline",
154+
"answer_file": null,
155+
"submission": "B8CD4F",
156+
"review": null,
157+
"person": null,
158+
"options": []
159+
},
160+
{
161+
"question": {
162+
"id": 3412,
163+
"question": {
164+
"en": "Expected audience expertise"
165+
}
166+
},
167+
"answer": "beginner",
168+
"answer_file": null,
169+
"submission": "B8CD4F",
170+
"review": null,
171+
"person": null,
172+
"options": [
173+
{
174+
"id": 4495,
175+
"answer": {
176+
"en": "Beginner"
177+
}
178+
}
179+
]
180+
},
181+
{
182+
"question": {
183+
"id": 3420,
184+
"question": {
185+
"en": "My presentation can be delivered"
186+
}
187+
},
188+
"answer": "in-person at the conference venue",
189+
"answer_file": null,
190+
"submission": "B8CD4F",
191+
"review": null,
192+
"person": null,
193+
"options": [
194+
{
195+
"id": 4500,
196+
"answer": {
197+
"en": "in-person at the conference venue"
198+
}
199+
}
200+
]
201+
}
202+
],
203+
"created": "2024-03-09T00:00:10.354629+01:00",
204+
"pending_state": null,
205+
"notes": "",
206+
"internal_notes": null,
207+
"tags": [],
208+
"tag_ids": []
209+
}
210+
]

src/transform.py

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from collections import defaultdict
44
from datetime import date, datetime, time, timedelta
55

6-
from pydantic import BaseModel
6+
from pydantic import BaseModel, Field
77
from pydantic.class_validators import root_validator
88
from slugify import slugify
99

@@ -18,6 +18,8 @@ class SpeakerQuestion:
1818
class SubmissionQuestion:
1919
outline = "Outline"
2020
tweet = "Abstract as a tweet / toot"
21+
delivery = "My presentation can be delivered"
22+
level = "Expected audience expertise"
2123

2224

2325
class SubmissionState:
@@ -49,7 +51,7 @@ class PretalxSpeaker(BaseModel):
4951
biography: str | None
5052
avatar: str | None
5153
slug: str
52-
answers: list[PretalxAnswer]
54+
answers: list[PretalxAnswer] = Field(..., exclude=True)
5355
submissions: list[str]
5456

5557
# Extracted
@@ -81,11 +83,6 @@ def extract(cls, values):
8183
if answer.question_text == SpeakerQuestion.mastodon:
8284
values["mastodon"] = answer.answer_text
8385

84-
# Remove all the other answers
85-
# This is important, because some answers might contain non-public
86-
# information
87-
values["answers"] = []
88-
8986
return values
9087

9188

@@ -98,9 +95,8 @@ class PretalxSubmission(BaseModel):
9895
track: str | None
9996
state: str
10097
abstract: str
101-
answers: list[PretalxAnswer]
98+
answers: list[PretalxAnswer] = Field(..., exclude=True)
10299
tweet: str = ""
103-
outline: str
104100
duration: str
105101

106102
level: str = ""
@@ -134,27 +130,29 @@ def extract(cls, values):
134130
if isinstance(values[field], dict):
135131
values[field] = values[field]["en"]
136132

137-
values["speakers"] = {s["code"] for s in values["speakers"]}
133+
values["speakers"] = sorted([s["code"] for s in values["speakers"]])
138134

139135
answers = [PretalxAnswer.parse_obj(ans) for ans in values["answers"]]
140136

141137
for answer in answers:
142-
if answer.question_text == SubmissionQuestion.outline:
143-
values["outline"] = answer.answer_text
138+
# TODO if we need any other questions
144139
if answer.question_text == SubmissionQuestion.tweet:
145140
values["tweet"] = answer.answer_text
146141

147-
# TODO if we need any other questions
142+
if answer.question_text == SubmissionQuestion.delivery:
143+
if "in-person" in answer.answer_text:
144+
values["delivery"] = "in-person"
145+
else:
146+
values["delivery"] = "remote"
147+
148+
if answer.question_text == SubmissionQuestion.level:
149+
values["level"] = answer.answer_text.lower()
150+
148151

149152
slug = slugify(values["title"])
150153
values["slug"] = slug
151154
values["website_url"] = f"https://ep2024.europython.eu/session/{slug}"
152155

153-
# Remove all the other answers
154-
# This is important, because some answers might contain non-public
155-
# information
156-
values["answers"] = []
157-
158156
return values
159157

160158
@property
@@ -215,18 +213,26 @@ def publishable_speakers(accepted_proposals: set[str]) -> dict[str, PretalxSpeak
215213
return output
216214

217215

218-
print(len(parse_submissions()))
219-
print(len(accepted := publishable_submissions()))
216+
# print(len(parse_submissions()))
217+
# print(len(accepted := publishable_submissions()))
220218

221-
print(len(parse_speakers()))
222-
print(len(publishable_speakers(accepted.keys())))
219+
# print(len(parse_speakers()))
220+
# print(len(publishable_speakers(accepted.keys())))
223221

224-
print(publishable_speakers(accepted.keys()))
222+
# # print(
223+
# # json.dumps(
224+
# # [p.dict() for p in publishable_speakers(accepted.keys()).values()],
225+
# # indent=2
226+
# # )
227+
# # )
228+
# print(
229+
# json.dumps([a.dict() for a in accepted.values()], indent=2)
230+
# )
225231

226232

227-
from pprint import pprint
233+
# # from pprint import pprint
228234

229-
pprint(accepted)
235+
# # pprint(accepted)
230236

231-
# Check if all the slugs are unique
232-
assert len(set(s.slug for s in accepted.values())) == len(accepted)
237+
# # Check if all the slugs are unique
238+
# assert len(set(s.slug for s in accepted.values())) == len(accepted)

0 commit comments

Comments
 (0)