Josh Tan 8451dcbbc7 Make code PEP8-compliant and add PEP8 test files
In order to run PEP8-compliance tests using PBR, the setup.py, setup.cfg,
requirements.txt, and tox.ini files must exist in the base directory of
this project. These files have been created and specified accordingly.

The specific environments to be tested using tox are specified in
requirements.txt and include the py33 and pep8 environments. Package
requirements are specified in requirements.txt and include pyyaml and
icalendar. Additional package requirements for testing are specified in
test-requirements.txt and include pbr and hacking.

Existing Python source code has been modified to pass PEP8-compliance
checks. This included adding docstrings and limiting line length.

Lastly, the README file has been renamed and files have been added
for the project license and manifest.

Change-Id: I51a50d64c579212c5c7fa756bb1d34e774666be9
2014-04-03 18:50:40 -05:00

135 lines
4.6 KiB
Python

#! /usr/bin/env python
#
# Copyright 2014 North Dakota State University
#
# 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 icalendar
import logging
import os
import pytz
import yaml
import const
class Meeting:
"""An OpenStack meeting."""
def __init__(self, yaml, filename):
"""Initialize meeting from yaml file name 'filename'."""
self.filename = filename
# initialize using yaml
self.project = yaml['project']
self.chair = yaml['chair']
self.description = yaml['description']
self.agenda = yaml['agenda'] # this is a list of list of topics
# create schedule objects
self.schedules = [Schedule(schedule) for schedule in yaml['schedule']]
def write_ical(self):
"""Write this meeting to disk using the iCal format."""
cal = icalendar.Calendar()
# add properties to ensure compliance
cal.add('prodid', '-//OpenStack//Gerrit-Powered Meeting Agendas//EN')
cal.add('version', '2.0')
i = 1
for schedule in self.schedules:
# one Event per iCal file
event = icalendar.Event()
# NOTE(jotan): I think the summary field needs to be unique per
# event in an ical file (at least, for it to work with
# Google Calendar)
event.add('summary', self.project + ' ' + str(i))
# add ical description
project_descript = "Project: %s" % (self.project)
chair_descript = "Chair: %s" % (self.chair)
irc_descript = "IRC: %s" % (schedule.irc)
agenda_yaml = yaml.dump(self.agenda, default_flow_style=False)
agenda_descript = "Agenda:\n%s\n" % (agenda_yaml)
descript_descript = "Description: %s" % (self.description)
ical_descript = "\n".join((project_descript,
chair_descript,
irc_descript,
agenda_descript,
descript_descript))
event.add('description', ical_descript)
# get starting date
d = datetime.datetime.utcnow()
next_meeting = next_weekday(d, const.WEEKDAYS[schedule.day])
next_meeting_dt = datetime.datetime(next_meeting.year,
next_meeting.month,
next_meeting.day,
schedule.time.hour,
schedule.time.minute,
tzinfo=pytz.utc)
event.add('dtstart', next_meeting_dt)
# add recurrence rule
event.add('rrule', {'freq': schedule.freq})
# add meeting length
# TODO(jotan): determine duration to use for OpenStack meetings
event.add('duration', datetime.timedelta(hours=1))
# add event to calendar
cal.add_component(event)
i += 1
# write ical files to disk
ical_dir = '../icals'
ical_filename = self.filename[:-4] + 'ics'
if not os.path.exists(ical_dir):
os.makedirs(ical_dir)
os.chdir(ical_dir)
with open(ical_filename, 'wb') as ics:
ics.write(cal.to_ical())
num_events = len(cal.subcomponents)
logging.info('\'%s\' processed. [%d event(s)]' % (ical_filename,
num_events))
class Schedule:
"""A meeting schedule."""
def __init__(self, sched_yaml):
"""Initialize schedule from yaml."""
self.time = datetime.datetime.strptime(sched_yaml['time'], '%H%M')
self.day = sched_yaml['day']
self.irc = sched_yaml['irc']
self.freq = sched_yaml['frequency']
def next_weekday(ref_date, weekday):
"""Return the date of the next weekday after ref_date."""
days_ahead = weekday - ref_date.weekday()
if days_ahead <= 0: # target day already happened this week
days_ahead += 7
return ref_date + datetime.timedelta(days_ahead)