
Previously, there were two load_meetings() methods. One was in util.py and one was a member of the Meeting object. This commit combines the two and makes it general enough for both cases. Update tox.ini as well as .testr.conf so that we can run some basic unit tests. An initial test has been added so there is something to run. Change-Id: I44fd693f1a4c0a0efcf99d935123108f22afea36
201 lines
6.4 KiB
Python
201 lines
6.4 KiB
Python
#! /usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright 2014 OpenStack Foundation
|
|
#
|
|
# 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 logging
|
|
import os
|
|
|
|
import yaml
|
|
|
|
from arbiter import const
|
|
from arbiter import meeting
|
|
|
|
"""Utility functions for check and gate jobs."""
|
|
|
|
|
|
def publish(meeting, ical):
|
|
"""Publish meeting information and ical file to wiki."""
|
|
|
|
pass
|
|
|
|
|
|
def convert_yaml_to_ical(yaml_dir, ical_dir, meeting_list_file=None):
|
|
"""Convert meeting YAML files to the iCal format and place
|
|
in ical_dir. If meeting_list is specified, only those meetings
|
|
in yaml_dir with filenames contained in meeting_list are
|
|
converted; otherwise, all meeting in yaml_dir are converted.
|
|
|
|
"""
|
|
meetings = meeting.load_meetings(yaml_dir)
|
|
|
|
# convert meetings to a list of ical
|
|
for m in meetings:
|
|
m.write_ical(ical_dir)
|
|
|
|
# TODO(jotan): verify converted ical is valid
|
|
|
|
logging.info('Wrote %d meetings to iCal' % (len(meetings)))
|
|
|
|
|
|
def check_uniqueness():
|
|
"""Check for uniqueness in meeting room and time combination. During gate
|
|
job, we do not care about the meeting name.
|
|
|
|
"""
|
|
|
|
# reads the current changes and verifies
|
|
change_list = _read_yaml_files(const.DEFAULT_YAML_DIR)
|
|
change_dict = _counting_dict_with(_make_schedule_key, change_list)
|
|
|
|
# fails if duplicates exist
|
|
if len(change_dict) == sum(change_dict.values()):
|
|
return 0
|
|
else:
|
|
change_dict = _make_schedule_dict(_make_schedule_key,
|
|
change_list,
|
|
False)
|
|
for key in change_dict:
|
|
if len(change_dict[key]) > 1:
|
|
meeting_quote = ['\'' + m + '\'' for m in change_dict[key]]
|
|
meeting_str = ', '.join(meeting_quote)
|
|
logging.error('Meetings %s are in conflict.' % (meeting_str))
|
|
return 1
|
|
|
|
|
|
def check_conflicts():
|
|
"""Return whether the meeting would create scheduling conflicts. At this
|
|
point, we are comparing the changes against the origin, while the meeting
|
|
do matter. If a meeting from the changes and a different meeting from the
|
|
origin shares the same time, then we have a conflict.
|
|
|
|
"""
|
|
|
|
# reads the current changes and verifies
|
|
change_list = _read_yaml_files(const.DEFAULT_YAML_DIR)
|
|
change_dict = _make_schedule_dict(_make_schedule_key, change_list, True)
|
|
|
|
# FIXME(lbragstad): Removed the clonerepo script since Jenkins takes care
|
|
# of that. The path resolution needs to be fix here too.
|
|
origin_dict = _make_schedule_dict(_make_schedule_key,
|
|
_read_yaml_files(const.DEFAULT_YAML_DIR),
|
|
True)
|
|
|
|
# make a set with all the meeting time
|
|
meeting_time_set = set(list(change_dict.keys()) +
|
|
list(origin_dict.keys()))
|
|
|
|
# compares the two, keep track of a conflict flag
|
|
conflict = False # doing this way so we can log all the conflicts
|
|
for key in meeting_time_set:
|
|
# both the changes and the original have this meeting time
|
|
if key in change_dict and key in origin_dict:
|
|
# and they are actually different meetings
|
|
if change_dict[key] != origin_dict[key]:
|
|
logging.error('Meetings \'%s\' and \'%s\' are in conflict.'
|
|
% (change_dict[key], origin_dict[key]))
|
|
conflict = True
|
|
|
|
if conflict:
|
|
return 1
|
|
return 0
|
|
|
|
|
|
def _read_yaml_files(directory):
|
|
"""Reads all the yaml in the given directory and returns a list of
|
|
schedules times.
|
|
|
|
:param directory: location of the yaml files
|
|
:returns: list of schedules
|
|
|
|
"""
|
|
|
|
yaml_files = []
|
|
for file in os.listdir('.'):
|
|
if os.path.isfile(file) and file.endswith(const.YAML_FILE_EXT):
|
|
yaml_files.append(file)
|
|
|
|
meetings = []
|
|
for file in yaml_files:
|
|
meetings.append(meeting.Meeting(yaml.load(open(file, 'r')), file))
|
|
logging.info('Loaded %d meetings form YAML' % len(meetings))
|
|
|
|
schedules = []
|
|
for m in meetings:
|
|
for schedule in m.get_schedule_tuple():
|
|
schedules.append(schedule)
|
|
|
|
return schedules
|
|
|
|
|
|
def _counting_dict_with(key_maker, list):
|
|
"""Make a counting dictionary. The key is obtained by a function applied to
|
|
the element; the value counts the occurrence of the item in the list.
|
|
|
|
:param key_maker: converts list items to strings
|
|
:returns: counting dictionary
|
|
|
|
"""
|
|
|
|
item_dict = {}
|
|
for item in list:
|
|
# just join the elements in the tuple together as key
|
|
key = key_maker(item)
|
|
if key in item_dict:
|
|
item_dict[key] += 1
|
|
else:
|
|
item_dict[key] = 1
|
|
return item_dict
|
|
|
|
|
|
def _make_schedule_dict(key_maker, list, replace_flag):
|
|
"""Make a schedule dictionary. The key is the time of the meeting. If
|
|
replace_flag is true, then the value is the meeting name; otherwise, if
|
|
replace_flag is false, the value is a list of meeting names.
|
|
|
|
:param key_maker: converts list items to strings
|
|
:param list: the list of schedules
|
|
:param replace_flag: determines the value of the dictionary
|
|
:returns: schedule dictionary
|
|
|
|
"""
|
|
|
|
item_dict = {}
|
|
for item in list:
|
|
key = key_maker(item)
|
|
if replace_flag:
|
|
item_dict[key] = item[0]
|
|
else:
|
|
if key in item_dict:
|
|
item_dict[key] += [item[0]]
|
|
else:
|
|
item_dict[key] = [item[0]]
|
|
return item_dict
|
|
|
|
|
|
def _make_schedule_key(schedule):
|
|
"""A key making function for a schedule item. The first item in the
|
|
schedule is meeting name, followed by a tuple of time, day, and room.
|
|
|
|
:param schedule: a schedule tuple
|
|
:returns: string representation of the schedule tuple
|
|
|
|
"""
|
|
|
|
schedule_time = schedule[1]
|
|
schedules_str = [str(schedule_time[0]), schedule_time[1], schedule_time[2]]
|
|
key = ''.join(schedules_str)
|
|
return key
|