lpschedule-generator

libreplanet schedule generator - ricketyspace.net/lpschedule-generator
git clone git://git.ricketyspace.net/lpschedule-generator.git
Log | Files | Refs

commit fd73b5b32895f54d026a904f8d3b60d69d32d28c
parent 866821ad8f140b0ed00314e9f92a96793a3b5df5
Author: rsiddharth <rsd@gnu.org>
Date:   Sat, 12 Dec 2015 21:01:45 -0500

Added lps_gen.py + tests for it.

Contains `LPSRenderer` and `LPSMarkdown` classes which convert a given
Markdown LP schedule text to a python dictionary (OrderedDict).

Diffstat:
lps_gen.py | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/files/lp-sch.md | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/test_lps_gen.py | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 465 insertions(+), 0 deletions(-)

diff --git a/lps_gen.py b/lps_gen.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2015 lpschedule-generator author(s). See AUTHORS. +# +# This file is part of lpschedule-generator. +# +# lpschedule-generator is free software: you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# lpschedule-generator is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with lpschedule-generator (see COPYING). If not, see +# <http://www.gnu.org/licenses/>. + +from collections import OrderedDict +from os import path + +from mistune import Renderer, Markdown + +# Python dictionary that will contain the lp schedule. +lps_dict = OrderedDict() + + +def read_file(filename): + """Read file and return it as a string. + + filename: Absolute pathname of the file. + """ + content = '' + + with open(filename, 'rb') as f: + for line in f: + content = content + line + + return content + + +class LPSRenderer(Renderer): + """Helps in converting Markdown version of LP schedule to a dictionary. + """ + def __init__(self, **kwargs): + super(LPSRenderer, self).__init__(**kwargs) + self.last_day = None + self.last_time_slot = None + self.last_session = None + + # Denotes the no. of the paragraph under a session; this + # information will be helpful in identifying the "speaker", + # "room" and session "description". + self.no_paragraph = None + + + def header(self, text, level, raw=None): + global lps_dict + + if level == 2: + # Add new day. + lps_dict[text] = OrderedDict() + self.last_day = text + elif level == 3: + # Add new timeslot + lps_dict[self.last_day][text] = OrderedDict() + self.last_time_slot = text + elif level == 4: + # Add new session + lps_dict[self.last_day][self.last_time_slot][text] = OrderedDict() + self.last_session = text + # We found a new session; set no of paragraphs processed + # to 0. + self.no_paragraph = 0 + + return super(LPSRenderer, self).header(text, level, raw) + + + def paragraph(self, text): + global lps_dict + + p = super(LPSRenderer, self).paragraph(text) + + if self.no_paragraph == 0: + # Speaker + if len(text.split(', ')) == 1: + speaker_text = text + else: + speaker_text = text.split(', ') + + lps_dict[self.last_day][self.last_time_slot][ + self.last_session]['speaker'] = speaker_text + self.no_paragraph = self.no_paragraph + 1 + elif self.no_paragraph == 1: + # Room + lps_dict[self.last_day][self.last_time_slot][ + self.last_session]['room'] = text + # Initialize description + lps_dict[self.last_day][self.last_time_slot][ + self.last_session]['desc'] = [] + self.no_paragraph = self.no_paragraph + 1 + elif self.no_paragraph > 1: + lps_dict[self.last_day][self.last_time_slot][ + self.last_session]['desc'].append(text) + + return p + + +class LPSMarkdown(Markdown): + """Converts MD LP schedule to a dictionary. + + Returns the Markdown version of LP schedule as a dictionary. + """ + def __init__(self, inline=None, block=None, **kwargs): + """ + Initialize with LPSRenderer as the renderer. + """ + super(LPSMarkdown, self).__init__(renderer=LPSRenderer(), + inline=None, block=None, + **kwargs) + + + def parse(self, text): + global lps_dict + + lps_dict = OrderedDict() + html = super(LPSMarkdown, self).parse(text) + return lps_dict diff --git a/tests/files/lp-sch.md b/tests/files/lp-sch.md @@ -0,0 +1,170 @@ +## Saturday, March 19 + +### 09:00 - 09:45: Registration and Breakfast + +### 09:45 - 10:45: Opening Keynote: Richard Stallman + +#### Free software, free hardware, and other things + +Richard Stallman + +Room 32-123 + +Preceded by a welcome address from John Sullivan, FSF executive +director. + +### 10:55 - 11:40: Session Block 1A + +#### Federation and GNU + +Christopher Webber + +Room 32-123 + +The effort to re-decentralize the web has been under way for a number +of years, but what's really happening under the hood? Various projects +like Diaspora, GNU social, [GNU MediaGoblin][gmg-home], Friendica Red, and Pump.IO +all exist, but not all these projects can talk to each other. How can +we fix that? A demo of PyPump will be given, as well as a rundown on +the progress of the W3C Social Working Group. + +[gmg-home]: http://mediagoblin.org/ + +#### Dr. Hyde and Mr. Jekyll: advocating for free software in nonfree academic contexts + +ginger coons + +Room 32-141 + +What if the classic horror trope of the good doctor who becomes a +monster at night were reversed? Instead of the good Dr. Jekyll +transforming into the rampaging Mr. Hyde, advocates of free who work +in nonfree environments can feel as if they only get to put on their +altruistic persona at night. For academics advocating free software +and free culture in particular, libre ethics are often at odds with +both administrative structures and expected teaching outcomes. This +session explores the struggles of advocating free in both research and +teaching. + +#### TAFTA, CETA, TISA: traps and threats to Free Software Everywhere + +Marianne Corvellec, Jonathan Le Lous + +Room 32-155 + +TAFTA, CETA, and TISA are far-reaching trade agreements posing major +threats to online freedom and creating legal uncertainty for all +Internet players. They set forth an ever stronger protection of +copyright and patents. They 'recycle' the most toxic parts of ACTA, +the anti-counterfeiting trade agreement which was rejected +in 2012. The presentation focuses on the software aspects of TAFTA, +CETA, TISA. We will call for action against these global treaty +projects and offer alternative proposals, which favour Free Software +Everywhere. + +### 11:40 - 11:50: Break + +### 11:50 - 12:35: Session Block 2A + +#### Let's encrypt! + +Seth Schoen + +Room 32-123 + +This year a robotic certificate authority will start issuing +publicly-trusted certificates, at no charge, by the millions. Called +Let's Encrypt, this CA is an initiative of several organizations. Our +free software and protocol will let sysadmins run a single command to +turn on HTTPS on their servers in about a minute, helping eliminate +obstacles to activating encryption for every Web server. I'll describe +how it all works and give a demo. We need lots of testing and +integration help! + +#### Attribution revolution -- turning copyright upside-down + +Jonas Öberg + +Room 32-141 + +Reusing works licensed under free licenses seems pretty simple, but it +can often be quite time consuming. One image or a few lines of source +code might be okay, but keeping track of the license and attribution +of a thousand different pieces, or when quoting from massive data sets +such as Wikipedia? Whoah! Don’t we have computers to do that for us!? +We do, but there’s no widespread support for including licensing or +author information when sharing or reusing digital works. This session +will discuss how this should work in a free knowledge environment, and +could it be that many problems regarding copyright and "piracy" in our +digital society could be solved with free software? + +In order to relate effectively to the digital works we see online, +attribution (who made or built something) matters. Proper attribution +is the start of being able to explore digital works online in their +right context. This talk will focus on the philosophical background of +why attribution matters, the benefits that free software can bring to +the way we work with pieces of art (lolcats and Shakespeare alike), +and where we're heading in the future. + +## Sunday, March 20 + +### 09:00 - 09:45: Registration and breakfast + +### 09:45 - 10:30: Keynote: Benjamin Mako Hill + +#### Access without empowerment + +Benjamin Mako Hill + +Room 32-123 + +The free software movement has twin goals: promoting access to +software through users' freedom to share, and empowering users by +giving them control over their technology. For all our movement's +success, we have been much more successful at the former. I will use +data from free software and from several related movements to explain +why promoting empowerment is systematically more difficult than +promoting access and I will explore how our movement might address the +second challenge in the future. + +### 10:30 - 10:40: Break + +### 10:40 - 11:25: Session Block 1B + +#### Fork and ignore: fighting a GPL violation by coding instead + +Bradley Kuhn + +Room 32-123 + +Typically, GPL enforcement activity involves copyright infringement +actions which compel license violators to correct errors in their GPL +compliance, defending the policy goals of the GPL: the rights of +developers and users to copy, share, modify and redistribute. + +While traditional enforcement is often undeniably necessary for +embedded electronics products, novel approaches to GPL violations are +often possible and even superior for more traditional software +distributions. + +Recently, Software Freedom Conservancy engaged in an enforcement +action whereby, rather than fight the violator in court, we instead +provided resources and assistance to a vetted GPL-compliant fork of a +violating codebase. + +This talk discusses which scenarios make this remedy optimal and the +lessons learned. The talk includes some licensing and technical +content about vetting the licensing information of codebases. + +#### Who did this? Just wait until your father gets home + +Ken Starks + +Room 32-141 + +What's going on in here? Computer parts laying all over the +place... screws and ribbon cables scattered cross heaven's half +acre. And who left this power supply in the refrigerator? Is that your +dad's new impact drive? Don't you dare let me get up in the middle of +the night and step on that motherboard in my bare feet. Just what in +the name of Michael Dell is going on here? diff --git a/tests/test_lps_gen.py b/tests/test_lps_gen.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2015 lpschedule-generator author(s). See AUTHORS. +# +# This file is part of lpschedule-generator. +# +# lpschedule-generator is free software: you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# lpschedule-generator is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with lpschedule-generator (see COPYING). If not, see +# <http://www.gnu.org/licenses/>. + +import json +import pprint + +import mistune + +from os import path + +from nose.tools import * + +from lps_gen import * + +class TestLpsGen(object): + """ + Class that tests the lps_gen.py module. + """ + @classmethod + def setup_class(self): + """Runs before running any tests in this class.""" + + self.MD_FILE = path.join('tests', 'files', 'lp-sch.md') + self.MD_FILE_CONTENT = read_file(self.MD_FILE) + + self.markdown = LPSMarkdown() + self.lps_dict = self.markdown(self.MD_FILE_CONTENT) + + def setup(self): + """Runs before each test in this class.""" + pass + + + def test_LPSMarkdown_day(self): + """ + Testing `LPSMarkdown` class - Day. + """ + days = ['Saturday, March 19', + 'Sunday, March 20'] + i = 0 + for day in self.lps_dict.keys(): + assert_equal(day, days[i]) + i = i + 1 + + + def test_LPSMarkdown_timeslot(self): + """ + Testing `LPSMarkdown` class - Timeslot. + """ + timeslots = [ + '09:00 - 09:45: Registration and Breakfast', + '09:45 - 10:45: Opening Keynote: Richard Stallman', + '10:55 - 11:40: Session Block 1A', + '11:40 - 11:50: Break', + '11:50 - 12:35: Session Block 2A', + '09:00 - 09:45: Registration and breakfast', + '09:45 - 10:30: Keynote: Benjamin Mako Hill', + '10:30 - 10:40: Break', + '10:40 - 11:25: Session Block 1B', + ] + + i = 0 + for lps_timeslots in self.lps_dict.values(): + for timeslot in lps_timeslots.keys(): + assert_equal(timeslot, timeslots[i]) + i = i + 1 + + + def test_LPSMarkdown_session(self): + """ + Testing `LPSMarkdown` class - Session. + """ + sessions = [ + 'Free software, free hardware, and other things', + 'Federation and GNU', + 'Dr. Hyde and Mr. Jekyll: advocating for free software in nonfree academic contexts', + 'TAFTA, CETA, TISA: traps and threats to Free Software Everywhere', + 'Let\'s encrypt!', + 'Attribution revolution -- turning copyright upside-down', + 'Access without empowerment', + 'Fork and ignore: fighting a GPL violation by coding instead', + 'Who did this? Just wait until your father gets home', + ] + + i = 0 + for lps_timeslots in self.lps_dict.values(): + for lps_sessions in lps_timeslots.values(): + for session in lps_sessions.keys(): + assert_equal(session, sessions[i]) + i = i + 1 + + + def test_LPSMarkdown_speaker(self): + """ + Testing `LPSMarkdown` class - Speaker + """ + speakers = [ + 'Richard Stallman', + 'Christopher Webber', + 'ginger coons', + ['Marianne Corvellec', 'Jonathan Le Lous'], + 'Seth Schoen', + 'Jonas Öberg', + 'Benjamin Mako Hill', + 'Bradley Kuhn', + 'Ken Starks', + ] + + i = 0 + for lps_timeslots in self.lps_dict.values(): + for lps_sessions in lps_timeslots.values(): + for session_info in lps_sessions.values(): + assert_equal(session_info['speaker'], speakers[i]) + i = i + 1 + + + def test_LPSMarkdown_room(self): + """ + Testing `LPSMarkdown` class - Room + """ + rooms = [ + 'Room 32-123', + 'Room 32-123', + 'Room 32-141', + 'Room 32-155', + 'Room 32-123', + 'Room 32-141', + 'Room 32-123', + 'Room 32-123', + 'Room 32-141', + ] + i = 0 + for lps_timeslots in self.lps_dict.values(): + for lps_sessions in lps_timeslots.values(): + for session_info in lps_sessions.values(): + assert_equal(session_info['room'], rooms[i]) + i = i + 1 + + + def teardown(self): + """Cleans up things after each test in this class.""" + pass + + + @classmethod + def teardown_class(self): + """Purge the mess created by this test.""" + pass