[foundation-web] Prepare the field for 2018 elections
- From: Andrea Veri <av src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [foundation-web] Prepare the field for 2018 elections
- Date: Thu, 3 May 2018 13:45:00 +0000 (UTC)
commit 784904feb48f921d0871b00d0f457dc4fb377131
Author: Andrea Veri <averi redhat com>
Date: Thu May 3 15:44:41 2018 +0200
Prepare the field for 2018 elections
foundation.gnome.org/vote/2018/Makefile.am | 14 ++
foundation.gnome.org/vote/2018/index.wml | 63 +++++++
foundation.gnome.org/vote/2018/mkical.py | 256 +++++++++++++++++++++++++++
foundation.gnome.org/vote/2018/rules.wml | 137 ++++++++++++++
foundation.gnome.org/vote/2018/timeline.ics | 76 ++++++++
foundation.gnome.org/vote/Makefile.am | 2 +-
6 files changed, 547 insertions(+), 1 deletions(-)
---
diff --git a/foundation.gnome.org/vote/2018/Makefile.am b/foundation.gnome.org/vote/2018/Makefile.am
new file mode 100644
index 0000000..4d1dd91
--- /dev/null
+++ b/foundation.gnome.org/vote/2018/Makefile.am
@@ -0,0 +1,14 @@
+SUBDIRS =
+
+urlpath = /vote/2018
+
+page_SCRIPTS = \
+ index.html \
+ candidates.html \
+ rules.html
+
+page_DATA = \
+ timeline.ics \
+ electorate.txt
+
+include $(top_srcdir)/rules.common
diff --git a/foundation.gnome.org/vote/2018/index.wml b/foundation.gnome.org/vote/2018/index.wml
new file mode 100644
index 0000000..9d3e09f
--- /dev/null
+++ b/foundation.gnome.org/vote/2018/index.wml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+
+ <head>
+ <title>GNOME Foundation 2018 Elections</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta name="author" content="Andrea Veri" />
+ </head>
+
+ <body>
+
+ <div id="content">
+ <h1>GNOME Foundation 2018 Elections</h1>
+
+ <p>
+ The GNOME Foundation Membership currently elects the Board of
+ Directors each year for July, 1st. Any member can nominate
+ themself to run in the elections. The overall elections process
+ is overseen by the Membership and Elections Committee, which can
+ be reached at <a
+ href="mailto:membership-committee@gnome.org">membership-committee@gnome.org</a>.
+ </p>
+
+ <p>
+ The elections results from the 2018 Board of Directors elections
+ will be archived here for public access.
+ </p>
+
+ <h2>2018 Elections Materials:</h2>
+ <ul>
+<!--
+ <li>
+ <a href="https://mail.gnome.org/archives/foundation-announce/2018-June/msg00003.html">Election
results announcement</a>
+ </li>
+ <li>
+ <a href="../../results.php?election_id=25">Detailed election results</a>
+ </li>
+ <li>
+ <a href="../../votes.php?election_id=25">List of all votes</a>
+ </li>
+ <li>
+ <a href="../../vote.php?election_id=25">Interface to vote</a>
+ </li>
+ <li>
+ <a href="electorate.txt">List of registered voters</a>
+ </li>
+ <li>
+ <a href="candidates.html">List of candidates for Board of Directors</a>
+ </li>
+-->
+ <li>
+ <a href="rules.html">Elections Rules and Timeline</a> (webcal <a
+ href="webcal://vote.gnome.org/2018/timeline.ics">timeline</a>)
+ </li>
+
+ <li>
+ <a href="../overview.html">Overview of the Board of Directors role</a>
+ </li>
+ </ul>
+
+ </body>
+</html>
diff --git a/foundation.gnome.org/vote/2018/mkical.py b/foundation.gnome.org/vote/2018/mkical.py
new file mode 100755
index 0000000..ec34526
--- /dev/null
+++ b/foundation.gnome.org/vote/2018/mkical.py
@@ -0,0 +1,256 @@
+#!/usr/bin/env python
+'''
+This Python script creates a simple iCal file based on hardcoded events
+in this file.
+'''
+
+import calendar
+import datetime
+import logging
+import math
+import os
+import vobject
+
+
+#### Configure these variables
+YEAR = 2018
+CANDIDATES_OPENED_DATE = (YEAR, 5, 12)
+CANDIDATES_CLOSED_DATE = (YEAR, 5, 24)
+CANDIDATES_ANNOUNCED_DATE = (YEAR, 5, 25)
+VOTING_OPENED_DATE = (YEAR, 5, 26)
+VOTING_CLOSED_DATE = (YEAR, 6, 9)
+PRELIMINARY_RESULTS_DATE = (YEAR, 6, 12)
+CHALLENGE_CLOSED_DATE = (YEAR, 6, 19)
+
+
+
+### I'm sorry that these functions clutter your calendar-creating experience
+### Please scroll down a bit to edit the description texts
+
+#### Application Data
+def c(multilinestring):
+ '''
+ A helper functions which cleans up a multiline string, so that
+ it doesn't contain any newlines or multiple whitespaces
+ '''
+ stripped = [l.strip() for l in multilinestring.splitlines()]
+ ret = " ".join (stripped)
+ return ret
+
+def d(year, month, day):
+ '''
+ Just a tiny wrapper around datetime.datetime to create a datetime object
+ '''
+ return datetime.date(year, month, day)
+
+
+
+CANDIDATES_OPENED = (
+ d(*CANDIDATES_OPENED_DATE),
+ 'Announcements and list of candidates opens',
+ c("""If you are a member of the GNOME Foundation and are interested
+ in running for election, you may nominate yourself by sending an
+ e-mail to foundation-announce gnome org with your name, e-mail
+ address, corporate affiliation (if any), and a description of why
+ you'd like to serve, before
+ %s (23:59 UTC).""" % d(*CANDIDATES_CLOSED_DATE)) + '''
+ ''' + c("""
+ If you are not yet a GNOME Foundation member and would like to stand
+ for election, you must first apply for membership and be accepted to be
+ eligible to run. (You may, however, announce your candidacy prior to formal
+ acceptance of your application;
+ should your application not be accepted, you will not be included in
+ the list of candidates.)""") + '''
+ '''
+)
+
+CANDIDATES_CLOSED = (
+ d(*CANDIDATES_CLOSED_DATE),
+ 'List of candidates closed',
+ CANDIDATES_OPENED[2] # Get the same text again
+)
+
+CANDIDATES_ANNOUNCED = (
+ d(*CANDIDATES_ANNOUNCED_DATE),
+ 'List of candidates announced',
+ 'You may now start to send your questions to the candidates'
+)
+
+VOTING_OPENED = (
+ d(*VOTING_OPENED_DATE),
+ 'Instructions to vote are sent',
+ 'Please read your email and follow these instructions and submit your vote by %s' %
d(*VOTING_CLOSED_DATE)
+)
+VOTING_CLOSED = (
+ d(*VOTING_CLOSED_DATE),
+ 'Votes must be returned',
+ 'Preliminary results are announced on %s' % d(*PRELIMINARY_RESULTS_DATE)
+)
+
+
+PRELIMINARY_RESULTS = (
+ d(*PRELIMINARY_RESULTS_DATE),
+ 'Preliminary results are announced',
+ 'The preliminary results can be challenged until %s' % d(*CHALLENGE_CLOSED_DATE)
+)
+
+CHALLENGE_CLOSED = (
+ d(*CHALLENGE_CLOSED_DATE),
+ 'Challenges to the results closed',
+ "If there weren't any challenges, preliminary results are valid"
+)
+
+
+
+
+def create_ical(eventlist):
+ '''Generates an ical stream based on the list given as eventlist.
+ The list shall contain elements with a tuple with a
+ (date, string, string) object, serving as date when the event takes place,
+ summary and description respectively.
+ '''
+ log = logging.getLogger('create_ical')
+
+ cal = vobject.iCalendar()
+ cal.add('method').value = 'PUBLISH'
+ cal.add('calscale').value = 'GREGORIAN'
+ cal.add('x-wr-timezone').value = 'UTC'
+
+ for (timestamp, summary, description) in eventlist:
+ log.debug('creating %s, %s', timestamp, description)
+ vevent = cal.add('vevent')
+ vevent.add('dtstart').value = timestamp
+ vevent.add('dtend').value = timestamp + datetime.timedelta(1)
+ vevent.add('summary').value = summary
+ vevent.add('description').value = description
+
+ stream = cal.serialize()
+ return stream
+
+
+def wraptext(s, width):
+ '''Wraps a string @s at @width characters.
+
+ >>> wraptext('fooo', 2)
+ ['fo','oo']
+ '''
+ l = len(s)
+ nr_frames = int(math.ceil(float(l)/width))
+ print nr_frames
+ frames = []
+ for i in xrange(nr_frames):
+ start, end = i*width, (i+1) * width
+ frames.append(s[start:end])
+ # One could (and prolly should) yield that
+ return frames
+
+def ordinal(n):
+ n = int(n)
+ if 10 <= n % 100 < 20:
+ return str(n) + 'th'
+ else:
+ return str(n) + {1 : 'st', 2 : 'nd', 3 : 'rd'}.get(n % 10, "th")
+
+
+def cal_for_month(month, events, width=80, year=datetime.datetime.now().year):
+ '''Generates a textual calendar for the @month in @year.
+ It will return a string with the calendar on the left hand side and the
+ events on the right hand side.
+ @events shall be a list with tuples: timestamp, summary, description.
+
+ Returns a string with the calendar
+ '''
+ log = logging.getLogger('cal_for_month')
+
+ cal = calendar.TextCalendar()
+ calstrings = cal.formatmonth(year, month, 3).splitlines()
+
+ for (timestamp, summary, description) in events:
+ log.debug('creating %s, %s', timestamp, summary)
+ year, month, day = timestamp.year, timestamp.month, timestamp.day
+ maxwidth = max([len(cs) for cs in calstrings])
+ rightwidth = 80 - maxwidth
+ for i, line in enumerate(calstrings):
+ needles = (" %d " % day,
+ " %d\n" % day)
+ replacement = "(%d)" % day
+ # Find the day so that we can highlight it and add a comment
+ day_in_week = False
+ for needle in needles:
+ if needle in line+"\n":
+ # k, this looks a bit weird but we have that corner
+ # case with the day being at the end of the line
+ # which in turn will have been split off
+ day_in_week = True
+ break # Set the needle to the found one
+ if day_in_week == False: # Nothing found, try next week
+ log.debug('Day (%d) not found in %s', day, line)
+ continue
+ else:
+ log.debug('Day (%d) found in %s', day, line)
+ new_line = (line+"\n").replace(needle, replacement).rstrip()
+ new_line += " %s (%s)" % (summary, ordinal(day))
+ # Replace in-place for two events in the same week
+ # FIXME: This has bugs :-(
+ calstrings[i] = new_line
+
+ return os.linesep.join(calstrings)
+
+def create_textcal(eventlist):
+ '''Generates a multiline string containing a calendar with the
+ events written on the side
+ The list shall contain elements with a tuple with a
+ (date, string, string) object, serving as date when the event takes place,
+ summary and description respectively.
+ '''
+ log = logging.getLogger('textcal')
+ log.debug('Generating from %s', eventlist)
+ months = set(map(lambda x: x[0].month, eventlist))
+ year = set(map(lambda x: x[0].year, eventlist)).pop()
+
+ final_cal = []
+ for month in months:
+ events = filter(lambda x: x[0].month == month, eventlist)
+ log.debug('Events for %d: %s', month, events)
+ month_cal = cal_for_month(month, events, year=year)
+ final_cal.append(month_cal)
+
+ return os.linesep.join(final_cal)
+
+if __name__ == "__main__":
+ from optparse import OptionParser
+ parser = OptionParser("usage: %prog [options]")
+ parser.add_option("-l", "--loglevel", dest="loglevel", help="Sets the loglevel to one of debug, info,
warn, error, critical",
+ default=None)
+ parser.add_option("-i", "--ical",
+ action="store_true", dest="ical", default=False,
+ help="print iCal file to stdout")
+ parser.add_option("-t", "--textcal",
+ action="store_true", dest="tcal", default=False,
+ help="print textual calendar to stdout")
+ (options, args) = parser.parse_args()
+
+ loglevel = {'debug': logging.DEBUG, 'info': logging.INFO,
+ 'warn': logging.WARN, 'error': logging.ERROR,
+ 'critical': logging.CRITICAL}.get(options.loglevel, logging.WARN)
+ logging.basicConfig( level=loglevel )
+ log = logging.getLogger()
+
+ eventlist = [
+ CANDIDATES_OPENED,
+ CANDIDATES_CLOSED,
+ CANDIDATES_ANNOUNCED,
+ VOTING_OPENED,
+ VOTING_CLOSED,
+ PRELIMINARY_RESULTS,
+ CHALLENGE_CLOSED,
+ ]
+
+ if not any([options.ical, options.tcal]):
+ parser.error("You want to select either ical or textcal output. See --help for details")
+ if options.ical:
+ ical = create_ical( eventlist )
+ print ical
+ if options.tcal:
+ tcal = create_textcal( eventlist )
+ print tcal
diff --git a/foundation.gnome.org/vote/2018/rules.wml b/foundation.gnome.org/vote/2018/rules.wml
new file mode 100644
index 0000000..4bdd38b
--- /dev/null
+++ b/foundation.gnome.org/vote/2018/rules.wml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+
+ <head>
+ <title>GNOME Foundation 2018 Elections Rules</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+
+ <body>
+
+ <div id="content">
+ <h1>Rules & Timeline for the GNOME Foundation 2018 Elections</h1>
+
+ <h2>Elections Rules</h2>
+
+ <ol>
+ <li>
+ See the <a
href="https://git.gnome.org/browse/foundation-web/tree/foundation.gnome.org/about/bylaws.rst">GNOME
Foundation Bylaws</a> (<a href="https://www.gnome.org/foundation/governance/attachment/bylaws-2/">PDF</a>) for
+ general rules.
+ </li>
+ <li>
+ There are 7 board slots that are to be filled during these elections.
+ </li>
+ <li>
+ Members of the GNOME Foundation as of
+ <!-- CANDIDATES_ANNOUNCED_DATE -->2018-05-25
+
+ are eligible to vote in the elections. Members without voting rights
+ such as <a
href="https://mail.gnome.org/archives/foundation-announce/2012-May/msg00015.html">Emeritus members</a>
+ are not eligible to vote.
+ Anyone who has made a
+ contribution to GNOME can apply for membership by completing the
+ <a href="https://foundation.gnome.org/membership/apply/">application</a>.
+ </li>
+ <li>
+ Any eligible voter is eligible to be elected to the Board of Directors.
+ To announce your candidacy, send a message to
+ <a
href="https://mail.gnome.org/archives/foundation-announce/">foundation-announce@gnome.org</a>
+ with your full name, e-mail, corporate affiliation (if any), and a
+ description of your reasons for wanting to serve as a director.
+ Candidacies must be announced prior to
+ <!-- CANDIDATES_CLOSED_DATE -->2018-05-24, 23:59 UTC.
+
+ </li>
+ <li>
+ All discussion related to the elections should be held on
+ <a href="https://mail.gnome.org/archives/foundation-list/">foundation-list@gnome.org</a>.
+ Members are invited to ask questions to one or all candidates on that
+ list.
+ </li>
+ <li>
+ Instructions explaining how to vote will be sent via e-mail to all
+ eligible voters on
+ <!-- VOTING_OPENED_DATE -->2018-05-26,
+
+ and votes must be returned by
+ <!-- VOTING_CLOSED_DATE -->2018-06-09, 23:59 UTC.
+ </li>
+ <li>
+ Votes will be held confidential during the elections, but an
+ anonymized archive of all submitted votes will be made publicly
+ accessible at its conclusion.
+ </li>
+ <li>
+ The GNOME Foundation Membership and Elections Committee is
+ responsible for counting the votes.
+ The committee serves at the pleasure of the GNOME Board of Directors
+ as per Section 9.1 of the bylaws.
+ </li>
+ <li>
+ The 7 candidates voted for most as counted by a <a
href="http://mail.gnome.org/archives/foundation-list/2009-March/msg00012.html">single transferable
+ vote system</a> will be elected, except that no more than two
+ individuals affiliated with any one corporation may be elected. Should
+ more than two of the top seven vote-getters be affiliated with the
+ same company, only the two with the most votes will be considered
+ elected. For a full definition of corporate affiliation, see the
+ <a href="https://wiki.gnome.org/Foundation/Charter">GNOME Foundation charter</a>.
+ </li>
+ <li>
+ In the event of a tie for the final slot on the board, the Elections
+ Committee will schedule run-off elections as soon as possible.
+ </li>
+ <li>
+ The Elections Committee will announce preliminary results as soon as
+ possible after the elections close, along with instructions on how to
+ access the votes archive and how to independently verify the vote
+ count.
+ </li>
+ <li>
+ Any eligible voter may challenge the preliminary results by e-mailing
+ <a
+ href="mailto:membership-committee gnome org">membership-committee gnome org</a>
+ prior to
+ <!-- PRELIMINARY_RESULTS_DATE -->2018-06-12.
+
+ The decision of the Elections Committee as
+ to any challenge shall be final. Once any challenges have been
+ resolved, the Elections Committee shall announce the final results.
+ </li>
+ <li>
+ Any questions regarding these procedures should be directed to the
+ Elections Committee by e-mail to <a
+ href="mailto:membership-committee gnome org">membership-committee gnome org</a>.
+ The committee shall have the power to make any necessary changes or
+ clarifications to these rules at any point during the elections.
+ </li>
+ </ol>
+
+ <h2>Timeline</h2>
+ <p><small>(all deadlines are 23:59 UTC)</small></p>
+ <ul>
+ <li>
+ <!-- CANDIDATES_OPENED_DATE -->2018-05-12: Announcements and list of candidates opens.
+ </li>
+ <li>
+ <!-- CANDIDATES_CLOSED_DATE -->2018-05-24: Last day to announce candidacies, submit summary
statements.
+ </li>
+ <li>
+ <!-- CANDIDATES_ANNOUNCED_DATE -->2018-05-25: Final list of candidates.
+ </li>
+ <li>
+ <!-- VOTING_OPENED_DATE -->2018-05-26: Instructions mailed to eligible voters, voting begins.
+ </li>
+ <li>
+ <!-- VOTING_CLOSED_DATE -->2018-06-09: Voting closes.
+ </li>
+ <li>
+ <!-- PRELIMINARY_RESULTS_DATE -->2018-06-12: Preliminary results are announced.
+ </li>
+ <li>
+ <!-- CHALLENGE_CLOSED_DATE -->2018-06-19: Last day to challenge preliminary results.
+ </li>
+ </ul>
+
+ </body>
+</html>
diff --git a/foundation.gnome.org/vote/2018/timeline.ics b/foundation.gnome.org/vote/2018/timeline.ics
new file mode 100644
index 0000000..4bfaa74
--- /dev/null
+++ b/foundation.gnome.org/vote/2018/timeline.ics
@@ -0,0 +1,76 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+METHOD:PUBLISH
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:20180503T130112Z - 55775@honneamise
+DTSTART;VALUE=DATE:20180512
+DTEND;VALUE=DATE:20180513
+DESCRIPTION:If you are a member of the GNOME Foundation and are interested
+ in running for election\, you may nominate yourself by sending an e-mail t
+ o foundation-announce gnome org with your name\, e-mail address\, corporat
+ e affiliation (if any)\, and a description of why you'd like to serve\, be
+ fore 2018-05-24 (23:59 UTC).\n If you are not yet a GNOME Foundation m
+ ember and would like to stand for election\, you must first apply for memb
+ ership and be accepted to be eligible to run. (You may\, however\, announc
+ e your candidacy prior to formal acceptance of your application\; should y
+ our application not be accepted\, you will not be included in the list of
+ candidates.)\n
+SUMMARY:Announcements and list of candidates opens
+END:VEVENT
+BEGIN:VEVENT
+UID:20180503T130112Z - 47675@honneamise
+DTSTART;VALUE=DATE:20180524
+DTEND;VALUE=DATE:20180525
+DESCRIPTION:If you are a member of the GNOME Foundation and are interested
+ in running for election\, you may nominate yourself by sending an e-mail t
+ o foundation-announce gnome org with your name\, e-mail address\, corporat
+ e affiliation (if any)\, and a description of why you'd like to serve\, be
+ fore 2018-05-24 (23:59 UTC).\n If you are not yet a GNOME Foundation m
+ ember and would like to stand for election\, you must first apply for memb
+ ership and be accepted to be eligible to run. (You may\, however\, announc
+ e your candidacy prior to formal acceptance of your application\; should y
+ our application not be accepted\, you will not be included in the list of
+ candidates.)\n
+SUMMARY:List of candidates closed
+END:VEVENT
+BEGIN:VEVENT
+UID:20180503T130112Z - 75481@honneamise
+DTSTART;VALUE=DATE:20180525
+DTEND;VALUE=DATE:20180526
+DESCRIPTION:You may now start to send your questions to the candidates
+SUMMARY:List of candidates announced
+END:VEVENT
+BEGIN:VEVENT
+UID:20180503T130112Z - 40802@honneamise
+DTSTART;VALUE=DATE:20180526
+DTEND;VALUE=DATE:20180527
+DESCRIPTION:Please read your email and follow these instructions and submit
+ your vote by 2018-06-09
+SUMMARY:Instructions to vote are sent
+END:VEVENT
+BEGIN:VEVENT
+UID:20180503T130112Z - 20856@honneamise
+DTSTART;VALUE=DATE:20180609
+DTEND;VALUE=DATE:20180610
+DESCRIPTION:Preliminary results are announced on 2018-06-12
+SUMMARY:Votes must be returned
+END:VEVENT
+BEGIN:VEVENT
+UID:20180503T130112Z - 98277@honneamise
+DTSTART;VALUE=DATE:20180612
+DTEND;VALUE=DATE:20180613
+DESCRIPTION:The preliminary results can be challenged until 2018-06-19
+SUMMARY:Preliminary results are announced
+END:VEVENT
+BEGIN:VEVENT
+UID:20180503T130112Z - 97055@honneamise
+DTSTART;VALUE=DATE:20180619
+DTEND;VALUE=DATE:20180620
+DESCRIPTION:If there weren't any challenges\, preliminary results are valid
+SUMMARY:Challenges to the results closed
+END:VEVENT
+X-WR-TIMEZONE:UTC
+END:VCALENDAR
+
diff --git a/foundation.gnome.org/vote/Makefile.am b/foundation.gnome.org/vote/Makefile.am
index 6c9e7c5..46caaee 100644
--- a/foundation.gnome.org/vote/Makefile.am
+++ b/foundation.gnome.org/vote/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = include 2004-10 2005-10 2000 2001 2002 2003 2004 2005 2006 2007 2007-10 2009 2010 2011 2012 2013
2014 2015 2016 2017
+SUBDIRS = include 2004-10 2005-10 2000 2001 2002 2003 2004 2005 2006 2007 2007-10 2009 2010 2011 2012 2013
2014 2015 2016 2017 2018
urlpath = /vote
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]