-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathbuild_calendar.py
124 lines (93 loc) · 4.58 KB
/
build_calendar.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/python
import json
import sys
from datetime import datetime, UTC
import os
import time
import icalendar
import requests
import helper
import settings
from calgen.mixins import GlobalHolidays
from calgen.models.Calendar import CalendarTypes
from calgen.providers.Provider import Provider
def mixin_events(ical, locale: str):
""" Mixes in additional events that would be missed by a provider. Currently, we only account for global mixins. """
# Global mix ins
for event in GlobalHolidays.MIXINS:
ical.add_component(event.to_ics())
# Locale specific mix ins
# ...
def build_ical(provider: Provider, locale: str, language: str, years_to_generate: int):
""" Queries provider, and generates an iCalendar object which it returns. """
ical = icalendar.Calendar()
ical.add('prodid', '-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN')
ical.add('version', '2.0')
mixin_events(ical, locale)
current_year = datetime.now().year
for i in range(0, years_to_generate):
year = current_year + i
for calendar_type in [CalendarTypes.NATIONAL, CalendarTypes.LOCAL]:
try:
holidays = provider.build(locale, year, {'calendar_type': calendar_type.value, 'language': language})
for holiday in holidays:
ical.add_component(holiday.to_ics())
except requests.HTTPError as err:
response = err.response.json()
# Generic error message
error_response = "{}: {}. ".format(err.response.status_code, err.response.reason)
# If we have the error_detail key, append that.
if response['meta'].get('error_detail'):
error_response += response['meta'].get('error_detail')
# Known errors:
# Too many requests, upgrade required are API limit reached.
# Unauthorized is malformed or bad API key.
sys.exit(error_response)
return ical
def build_calendars(provider: Provider, locales: dict):
"""
Entry function for build_calendar.py script, will query the provider passed, and build the actual .ics file.
While this has been cleaned up to not specifically call out Calendarific, there are still data / assumptions made on function calls that will require a small touch up if you happen to use a different Provider.
"""
if len(locales.items()) == 0:
sys.exit("No locales specified, skipping calendar generation.")
is_free_tier = helper.is_calendarific_free_tier()
years_to_generate = settings.CALDATA_YEARS_TO_GENERATE
current_year = datetime.now().year
date_span = "{}-{}".format(current_year, current_year + years_to_generate)
calendar_metadata = []
now_utc = datetime.now(UTC)
# Check if the folders exist
if not os.path.exists(settings.CALDATA_AUTOGEN_URL):
os.mkdir(settings.CALDATA_AUTOGEN_URL)
print("Querying calendar data from {}".format(provider.name))
for locale, country_info_list in locales.items():
if not isinstance(country_info_list, list):
country_info_list = [country_info_list]
for country_name, language_code in country_info_list:
# Wait 1 second due to free api restrictions
if is_free_tier:
time.sleep(1)
ical = build_ical(provider, locale, language_code, years_to_generate)
calendar_name_parts = [country_name.replace(' ', ''), 'Holidays']
if country_name in settings.CALENDAR_REMAP:
new_name = settings.CALENDAR_REMAP[country_name]
if isinstance(new_name, tuple) and len(new_name) > 1:
calendar_name_parts = [new_name[0], 'Holidays', new_name[1]]
else:
calendar_name_parts = [new_name, 'Holidays']
calendar_name = f"{''.join(calendar_name_parts)}.ics"
calendar_metadata.append({
'country': country_name,
'locale': locale,
'language': language_code,
'filename': "autogen/{}".format(calendar_name),
'datespan': date_span,
'authors': settings.CALDATA_AUTOGEN_AUTHOR,
'updated': str(now_utc.replace(microsecond=0).isoformat())
})
with open('{}{}'.format(settings.CALDATA_AUTOGEN_URL, calendar_name), 'wb') as fh:
fh.write(ical.to_ical())
print("Re-building calendars.json")
with open('{}/calendars.json'.format(settings.CALDATA_AUTOGEN_URL), 'w') as fh:
fh.write(json.dumps(calendar_metadata, indent=2))