Fix iCalendar format violations

After observing errors from importing our iCal into Outlook, I found
there were a few issues with our generated output according to [0].

This adds an overall VERSION to the iCal and sets per event timestamps
and UIDs.

This also updates YAML loading to use safe_load to get rid of a
deprecation warning noticed while testing.

[0] https://icalendar.org/validator.html?url=https://releases.openstack.org/schedule.ics

Change-Id: I3803a432da2538af4de163b77c192130366ddadf
Signed-off-by: Sean McGinnis <sean.mcginnis@gmail.com>
This commit is contained in:
Sean McGinnis
2019-06-26 12:22:01 -05:00
parent bde1ee9204
commit 1506d94374

View File

@@ -1,7 +1,20 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import json
import os
import os.path
import subprocess
from docutils.io import FileOutput
from docutils import nodes
@@ -15,11 +28,12 @@ LOG = logging.getLogger(__name__)
class PendingICS(nodes.Element):
def __init__(self, data_source, series_name, data):
def __init__(self, data_source, series_name, data, last_update):
super(PendingICS, self).__init__()
self._data_source = data_source
self._series_name = series_name
self._data = data
self.last_update = last_update
class ICS(rst.Directive):
@@ -29,12 +43,30 @@ class ICS(rst.Directive):
'name': rst.directives.unchanged,
}
has_content = False
last_update = ''
def _load_data(self, env, data_source):
rel_filename, filename = env.relfn2path(data_source)
# Attempt to get the last update time for our timestamp
try:
last_update = subprocess.check_output(
[
'git', 'log', '-n1', '--format=%ad',
'--date=format:%Y-%m-%d %H:%M:%S',
'--', filename,
]
).decode('utf-8').strip()
self.last_update = datetime.datetime.strptime(
last_update, '%Y-%m-%d %H:%M:%S')
LOG.info('[ics] Last update of %s was %s',
rel_filename, last_update)
except subprocess.CalledProcessError:
self.last_update = datetime.datetime.utcnow()
if data_source.endswith('.yaml'):
with open(filename, 'r') as f:
return yaml.load(f)
return yaml.safe_load(f)
elif data_source.endswith('.json'):
with open(filename, 'r') as f:
return json.load(f)
@@ -65,13 +97,14 @@ class ICS(rst.Directive):
data = self._load_data(env, data_source)
node = PendingICS(data_source, series_name, data)
node = PendingICS(data_source, series_name, data, self.last_update)
node.document = self.state.document
return [node]
_global_calendar = icalendar.Calendar()
_global_calendar.add('prodid', '-//releases.openstack.org//EN')
_global_calendar.add('version', '2.0')
_global_calendar.add('X-WR-CALNAME', 'OpenStack Release Schedule')
@@ -128,6 +161,9 @@ def doctree_resolved(app, doctree, docname):
summary_text),
)
event.add('dtstamp', node.last_update)
event.add('uid', '%s-%s' % (series_name, week.get('name')))
start = datetime.datetime.strptime(week['start'], '%Y-%m-%d')
event.add('dtstart', icalendar.vDate(start.date()))