Skip to content

Commit 5c3f9c1

Browse files
committed
Refactor top-level logic into testable functions
1 parent 56c95fc commit 5c3f9c1

File tree

1 file changed

+94
-65
lines changed

1 file changed

+94
-65
lines changed

_conferences/__main__.py

Lines changed: 94 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import yaml
88
from github import Auth, Github
9+
from github.Issue import Issue
10+
from github.PaginatedList import PaginatedList
911

1012
TOKEN = os.getenv("GITHUB_TOKEN", "")
1113
ROOT = Path(__file__).parent.parent
@@ -14,68 +16,95 @@
1416
auth = Auth.Token(TOKEN)
1517
g = Github(auth=auth)
1618

17-
repo = g.get_repo("BlackPythonDevs/blackpythondevs.github.io")
18-
open_issues = repo.get_issues(state="open", labels=["conference"])
19-
conferences = []
20-
today = datetime.combine(datetime.now(), time())
21-
22-
for issue in open_issues:
23-
if "conference" in [label.name for label in issue.labels]:
24-
# Extract fields from issue body
25-
name_match = re.search(
26-
r"Conference Name(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue.body
27-
)
28-
url_match = re.search(r"URL(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue.body)
29-
dates_match = re.search(
30-
r"Conference Dates(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue.body
31-
)
32-
type_match = re.search(
33-
r"Conference Type(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue.body
34-
)
35-
location_match = re.search(
36-
r"Conference Location(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue.body
37-
)
38-
summary_match = re.search(
39-
r"Summary(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}",
40-
issue.body,
41-
re.DOTALL,
42-
)
43-
speaking_match = re.search(
44-
r"Speaking(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}### Code of Conduct(?:\r\n|\n){2}",
45-
issue.body,
46-
re.DOTALL,
47-
)
48-
49-
# Set a default value of None for when the url field isn't as expected
50-
valid_url = None
51-
52-
# Ensure the url field is not blank and the url matches the regex
53-
if url_match is not None and url_match[1].strip() != "":
54-
# Parse the url and see if a scheme (`https`) is included in it
55-
# If not, then prepend `https` to the url from the issue body
56-
# This guards against the website thinking the passed in url is another page on https://blackpythondevs.com/
57-
parsed_url = urlparse(url_match[1])
58-
if "http" not in parsed_url.scheme.casefold():
59-
valid_url = f"https://{url_match[1]}"
60-
61-
if dates_match:
62-
conferenceDates = dates_match[1]
63-
# Parse the end date of the conference
64-
endDateStr = conferenceDates.split("-")[1].strip()
65-
endDate = datetime.strptime(endDateStr, "%d %b %Y")
66-
# Check if the conference end date is greater than today
67-
if endDate >= today:
68-
conference = {
69-
"name": name_match[1],
70-
"url": valid_url,
71-
"dates": dates_match[1],
72-
"type": type_match[1],
73-
"location": location_match[1],
74-
"summary": summary_match[1],
75-
"speaking": speaking_match[1] if speaking_match else "",
76-
}
77-
conferences.append(conference)
78-
79-
# Write the conferences to the _data/conferences.yml file
80-
with conferences_path.open("w") as f:
81-
yaml.dump(conferences, f)
19+
20+
def get_open_issues() -> PaginatedList[Issue]:
21+
repo = g.get_repo("BlackPythonDevs/blackpythondevs.github.io")
22+
issues = repo.get_issues(state="open", labels=["conference"])
23+
return issues
24+
25+
26+
def parse_conference_details(issue_body: str) -> dict | None:
27+
# Extract fields from issue body
28+
name_match = re.search(
29+
r"Conference Name(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue_body
30+
)
31+
url_match = re.search(r"URL(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue_body)
32+
dates_match = re.search(
33+
r"Conference Dates(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue_body
34+
)
35+
type_match = re.search(
36+
r"Conference Type(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue_body
37+
)
38+
location_match = re.search(
39+
r"Conference Location(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}", issue_body
40+
)
41+
summary_match = re.search(
42+
r"Summary(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}",
43+
issue_body,
44+
re.DOTALL,
45+
)
46+
speaking_match = re.search(
47+
r"Speaking(?:\r\n|\n){2}(.*?)(?:\r\n|\n){2}### Code of Conduct(?:\r\n|\n){2}",
48+
issue_body,
49+
re.DOTALL,
50+
)
51+
52+
# Set a default value of None for when the url field isn't as expected
53+
valid_url = normalize_url() if not url_match else normalize_url(url_match[1])
54+
55+
if dates_match:
56+
conferenceDates = dates_match[1]
57+
# Parse the end date of the conference
58+
endDateStr = conferenceDates.split("-")[1].strip()
59+
endDate = datetime.strptime(endDateStr, "%d %b %Y")
60+
# Check if the conference end date is greater than today
61+
today = datetime.combine(datetime.now(), time())
62+
63+
if endDate >= today:
64+
conference = {
65+
"name": name_match[1],
66+
"url": valid_url,
67+
"dates": dates_match[1],
68+
"type": type_match[1],
69+
"location": location_match[1],
70+
"summary": summary_match[1],
71+
"speaking": speaking_match[1] if speaking_match else "",
72+
}
73+
return conference
74+
return None
75+
76+
77+
def normalize_url(url_match: str = None):
78+
valid_url = None
79+
# Ensure the url field is not blank and the url matches the regex
80+
if url_match is not None and url_match.strip() != "":
81+
# Parse the url and see if a scheme (`https`) is included in it
82+
# If not, then prepend `https` to the url from the issue body
83+
# This guards against the website thinking the passed in url is another page on https://blackpythondevs.com/
84+
parsed_url = urlparse(url_match)
85+
if "http" not in parsed_url.scheme.casefold():
86+
valid_url = f"https://{url_match}"
87+
else:
88+
valid_url = url_match
89+
return valid_url
90+
91+
92+
def write_conferences_to_file(confs: list[dict]):
93+
# Write the conferences to the _data/conferences.yml file
94+
with conferences_path.open("w") as f:
95+
yaml.dump(confs, f)
96+
97+
98+
if __name__ == '__main__':
99+
conferences = []
100+
101+
# Get open issues from repo
102+
open_issues: PaginatedList[Issue] = get_open_issues()
103+
104+
# Parse each conference issue so long as it has the "conference" label
105+
for issue in open_issues:
106+
if "conference" in [label.name for label in issue.labels]:
107+
parsed_conf = parse_conference_details(issue_body=issue.body)
108+
conferences.append(parsed_conf)
109+
110+
write_conferences_to_file(conferences)

0 commit comments

Comments
 (0)