Skip to content

Commit 7bd76cb

Browse files
committed
Add command line options
1 parent b01e5b8 commit 7bd76cb

File tree

3 files changed

+129
-73
lines changed

3 files changed

+129
-73
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,26 @@ The fields for speakers are the following:
4949
* Title: Title of the proposal
5050
* Level: If provided by the schedule. If two levels are displayed, pick the
5151
most general one
52+
53+
## Scripts
54+
55+
> [!NOTE]
56+
> Make sure to install the dependencies in `scripts/requirements.txt`
57+
58+
In case the event you are trying to contribute is using Pretalx, you can get
59+
the speaker list by running the command:
60+
61+
```
62+
python scripts/get_speakers.py --url https://pretalx.com/api/events/pyladiescon-2025
63+
```
64+
To write the output directly into a file, you can use the `--output` option,
65+
and execute the script like this:
66+
67+
```
68+
python scripts/get_speakers.py \
69+
--url https://pretalx.com/api/events/pyladiescon-2024 \
70+
--output data/speakers/PyLadiesCon/2024.json
71+
```
72+
73+
> [!IMPORTANT]
74+
> Make sure that the URL needs to the the one pointing to the API.

scripts/get_speakers.py

Lines changed: 104 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,141 @@
11
import json
2+
import sys
3+
import argparse
4+
from typing import Any
5+
from datetime import datetime
6+
27
import requests
38

4-
# Configuration variables:
5-
# This URL can be a custom URL or pretalx.com/ one depending on the event configuration
6-
CONFERENCE_URL = ""
7-
TOKEN = "" # Not necessary, but in case of private events it's required
8-
YEAR = 2025 # Some events will not have it in the URL so we do it manually
99

10+
def get_response_data_from_url(url: str) -> dict[str, Any]:
11+
try:
12+
response = requests.get(url, headers={"Authorization": TOKEN})
13+
data = response.json()
14+
except requests.exceptions.RequestException as e:
15+
print(f"Error fetching data: {e}")
16+
sys.exit(1)
1017

11-
def get_pretalx_submission_types():
12-
url = f"{CONFERENCE_URL}/submission-types"
13-
submission_types = {}
18+
return data
1419

15-
while url:
16-
try:
17-
response = requests.get(url, headers={"Authorization": TOKEN})
18-
data = response.json()
1920

20-
for stype in data["results"]:
21-
if stype["id"] not in submission_types:
22-
submission_types[stype["id"]] = stype["name"]
21+
def get_pretalx_submission_types(conference_url: str) -> dict[str, str]:
22+
url: str | None = f"{conference_url}/submission-types"
23+
submission_types: dict[str, str] = {}
24+
25+
while url:
26+
data: dict[str, Any] = get_response_data_from_url(url)
2327

24-
url = data.get("next")
28+
for stype in data["results"]:
29+
if stype["id"] not in submission_types:
30+
submission_types[stype["id"]] = stype["name"]
2531

26-
except requests.exceptions.RequestException as e:
27-
print(f"Error fetching submission types: {e}")
28-
return None
32+
url = data.get("next")
2933

3034
return submission_types
3135

3236

33-
def get_pretalx_submissions(all_speakers):
34-
url = f"{CONFERENCE_URL}/submissions"
37+
def get_pretalx_submissions(conference_url: str, all_speakers: dict[str, str]) -> dict[str, dict]:
38+
url: str | None = f"{conference_url}/submissions"
3539
confirmed_submissions = {}
3640

37-
submissions_types = get_pretalx_submission_types()
41+
submissions_types = get_pretalx_submission_types(conference_url)
3842

3943
while url:
40-
try:
41-
response = requests.get(url, headers={"Authorization": TOKEN})
42-
43-
data = response.json()
44-
45-
for submission in data["results"]:
44+
data: dict[str, Any] = get_response_data_from_url(url)
4645

47-
if submission["state"] == "confirmed":
46+
for submission in data["results"]:
4847

49-
submission_code = submission["code"]
50-
submission_speakers = submission["speakers"]
51-
submission_type = submissions_types[submission["submission_type"]]
52-
if isinstance(submission_type, dict):
53-
try:
54-
# Search for 'en' default language
55-
# otherwise, the first one
56-
submission_type = submission_type["en"]
57-
except KeyError:
58-
for k, v in submission_type.items():
59-
submission_type = v
60-
break
48+
if submission["state"] == "confirmed":
6149

62-
for speaker_code in submission["speakers"]:
50+
submission_code = submission["code"]
51+
submission_speakers = submission["speakers"]
52+
submission_type = submissions_types[submission["submission_type"]]
53+
if isinstance(submission_type, dict):
54+
try:
55+
# Search for 'en' default language
56+
# otherwise, the first one
57+
submission_type = submission_type["en"]
58+
except KeyError:
59+
for k, v in submission_type.items():
60+
submission_type = v
61+
break
6362

64-
speaker_name = all_speakers[speaker_code]
65-
confirmed_submissions[f"{submission_code}-{speaker_code}"] = {
66-
"fullname": speaker_name,
67-
"title": submission["title"],
68-
"type": submission_type,
69-
}
63+
for speaker_code in submission_speakers:
7064

71-
url = data.get("next")
65+
speaker_name = all_speakers[speaker_code]
66+
confirmed_submissions[f"{submission_code}-{speaker_code}"] = {
67+
"fullname": speaker_name,
68+
"title": submission["title"],
69+
"type": submission_type,
70+
}
7271

73-
except requests.exceptions.RequestException as e:
74-
print(f"Error fetching submissions: {e}")
75-
return None
72+
url = data.get("next")
7673

7774
return confirmed_submissions
7875

7976

80-
def get_pretalx_speakers():
81-
url = f"{CONFERENCE_URL}/speakers"
77+
def get_pretalx_speakers(conference_url: str) -> dict[str, str]:
78+
url: str | None = f"{conference_url}/speakers"
8279
speakers = {}
8380

8481
while url:
85-
try:
86-
response = requests.get(url, headers={"Authorization": TOKEN})
87-
data = response.json()
82+
data: dict[str, Any] = get_response_data_from_url(url)
8883

89-
for speaker in data["results"]:
90-
code = speaker["code"]
91-
if code not in speakers:
92-
speakers[code] = speaker["name"]
84+
for speaker in data["results"]:
85+
code = speaker["code"]
86+
if code not in speakers:
87+
speakers[code] = speaker["name"]
9388

94-
url = data.get("next")
95-
96-
except requests.exceptions.RequestException as e:
97-
print(f"Error fetching speakers: {e}")
98-
return None
89+
url = data.get("next")
9990

10091
return speakers
10192

10293

103-
if __name__ == "__main__":
104-
speakers = get_pretalx_speakers()
94+
def get_event_year(conference_url: str) -> int:
95+
data: dict[str, Any] = get_response_data_from_url(conference_url)
96+
date = data["date_from"]
97+
year: int = 2025
98+
try:
99+
date_from = datetime.strptime(date, "%Y-%m-%d")
100+
except ValueError:
101+
print(f"Error: couldn't parse date '{date}'. Falling back to 2025")
102+
return year
103+
104+
return date_from.year
105105

106-
submission_data = get_pretalx_submissions(speakers)
107-
data = {}
106+
107+
if __name__ == "__main__":
108+
# This URL can be a custom URL or pretalx.com/ one depending on the event configuration
109+
CONFERENCE_URL = ""
110+
TOKEN = "" # Not necessary, but in case of private events it's required
111+
112+
parser = argparse.ArgumentParser()
113+
parser.add_argument('--url')
114+
parser.add_argument('--output')
115+
args = parser.parse_args()
116+
117+
# Check command-line arguments
118+
if args.url is not None:
119+
if CONFERENCE_URL:
120+
print(f"-- WARNING: Overriding url '{CONFERENCE_URL}' "
121+
f"with command line value '{args.url}'")
122+
print(f"-- Using event url: '{args.url}'")
123+
CONFERENCE_URL = args.url
124+
125+
if args.output is not None:
126+
if not args.output.endswith(".json"):
127+
print(f"ERROR: file '{args.output}' is not a JSON file")
128+
sys.exit(1)
129+
130+
year = get_event_year(CONFERENCE_URL)
131+
speakers = get_pretalx_speakers(CONFERENCE_URL)
132+
submission_data = get_pretalx_submissions(CONFERENCE_URL, speakers)
133+
134+
data: dict[str, Any] = {}
108135

109136
if submission_data:
110137

111-
data["year"] = YEAR
138+
data["year"] = year
112139
data["speakers"] = []
113140
for _, entry in submission_data.items():
114141
data["speakers"].append(
@@ -119,7 +146,11 @@ def get_pretalx_speakers():
119146
}
120147
)
121148

122-
print(json.dumps(data, indent=4))
123-
149+
if args.output is not None:
150+
with open(args.output, "w") as f:
151+
json.dump(data, f, ensure_ascii=False, indent=4)
152+
print(f"-- Written file: '{args.output}'")
153+
else:
154+
print(json.dumps(data, indent=4))
124155
else:
125156
print("Failed to fetch speakers data")

scripts/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
requests
2+
types-requests

0 commit comments

Comments
 (0)