lpschedule-generator

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

commit 6b294c6c4d891a48c25c078980da285067d22cb9
parent e4f8416dc963ea550d204e8c61400a3e7d17a3ee
Author: rsiddharth <rsd@gnu.org>
Date:   Sat,  6 Feb 2016 22:54:45 -0500

Initial version LP Speakers Renderer ready.

- New classes:
    - LPSpeakersRenderer
    - LPSpeakersMarkdown
+ tests for them

- New package dependency
    - unidecode

Address issue #1.

Diffstat:
lps_gen.py | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
setup.py | 2+-
tests/files/lp-speakers.md | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/test_lps_gen.py | 246++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 524 insertions(+), 3 deletions(-)

diff --git a/lps_gen.py b/lps_gen.py @@ -29,6 +29,7 @@ from bs4 import BeautifulSoup from jinja2 import Environment, FileSystemLoader from jinja2.exceptions import TemplateNotFound from mistune import Renderer, Markdown +from unidecode import unidecode __version__ = '0.1.1' @@ -40,6 +41,8 @@ sys.setdefaultencoding('utf-8') # Python dictionary that will contain the lp schedule. lps_dict = OrderedDict() +# Python dictionary that will contain the lp speakers. +lpspeakers_dict = OrderedDict() def read_file(filename): """Read file and return it as a string. @@ -122,6 +125,90 @@ class LPSRenderer(Renderer): return p +class LPSpeakersRenderer(Renderer): + """Helps in converting Markdown version of LP speakers to a dictionary. + """ + + def __init__(self, **kwargs): + super(LPSpeakersRenderer, self).__init__(**kwargs) + global lpspeakers_dict + + lpspeakers_dict = OrderedDict() + lpspeakers_dict['keynote-speakers'] = [] + lpspeakers_dict['speakers'] = [] + + # Type of present speaker being processed; can either be + # 'keynote-speakers' or 'speakers'.' + self.speaker_type = None + + # Maintain a list of used IDs + self.used_ids = [] + + + def mk_uid(self, text): + """Returns a unique id. + """ + # 'John HÖcker, Onion Project' -> 'John HÖcker' + text = text.split(', ')[0] + + # 'John HÖcker' -> 'John Hacker' + ascii_text = unidecode(unicode(text)) + + # 'John Hacker' -> 'hacker' + id_ = ascii_text.split()[-1].lower() + + if id_ not in self.used_ids: + self.used_ids.append(id_) + return id_ + else: + # 'John Hacker' -> 'john_hacker' + id_ = '_'.join([s.lower() for s in ascii_text.split()]) + self.used_ids.append(id_) + return id_ + + + def header(self, text, level, raw=None): + global lpspeakers_dict + + if level == 1: + self.speaker_type = 'keynote-speakers' + lpspeakers_dict[self.speaker_type].append(OrderedDict()) + + lpspeakers_dict[self.speaker_type][-1]['speaker'] = text + lpspeakers_dict[self.speaker_type][-1]['id'] = self.mk_uid(text) + elif level == 2: + self.speaker_type = 'speakers' + lpspeakers_dict[self.speaker_type].append(OrderedDict()) + + lpspeakers_dict[self.speaker_type][-1]['speaker'] = text.split(', ')[0] + lpspeakers_dict[self.speaker_type][-1]['id'] = self.mk_uid(text) + + return super(LPSpeakersRenderer, self).header(text, level, raw) + + + def image(self, src, title, text): + global lpspeakers_dict + + lpspeakers_dict[self.speaker_type][-1]['img_url'] = src + lpspeakers_dict[self.speaker_type][-1]['img_alt'] = text + + return super(LPSpeakersRenderer, self).image(src, title, text) + + + def paragraph(self, text): + global lpspeakers_dict + + p = super(LPSpeakersRenderer, self).paragraph(text) + + if not lpspeakers_dict[self.speaker_type][-1].has_key('bio'): + lpspeakers_dict[self.speaker_type][-1]['bio'] = [] + return p + + lpspeakers_dict[self.speaker_type][-1]['bio'].append(p) + + return p + + class LPSMarkdown(Markdown): """Converts MD LP schedule to a dictionary. @@ -144,6 +231,28 @@ class LPSMarkdown(Markdown): return lps_dict +class LPSpeakersMarkdown(Markdown): + """Converts MD LP speakers to a dictionary. + + Returns the Markdown version of LP speakers as a dictionary. + """ + + def __init__(self, inline=None, block=None, **kwargs): + """ + Initialize with LPSpeakersRenderer as the renderer. + """ + super(LPSpeakersMarkdown, self).__init__(renderer=LPSpeakersRenderer(), + inline=None, block=None, + **kwargs) + + + def parse(self, text): + global lpspeakers_dict + + html = super(LPSpeakersMarkdown, self).parse(text) + return lpspeakers_dict + + def RenderHTML(lps_dict, template): """Renders LP schedule in HTML from a python dictionary. diff --git a/setup.py b/setup.py @@ -34,7 +34,7 @@ config = { 'url': 'https://notabug.org/rsd/lpschedule-generator/', 'author': 'rsiddharth', 'author_email': 'rsd@gnu.org', - 'install_requires': ['mistune', 'Jinja2', 'beautifulsoup4'], + 'install_requires': ['mistune', 'Jinja2', 'beautifulsoup4', 'unidecode'], 'tests_require': ['nose', 'mock'], 'test_suite': 'nose.collector', 'py_modules': ['lps_gen'], diff --git a/tests/files/lp-speakers.md b/tests/files/lp-speakers.md @@ -0,0 +1,170 @@ +# Daniel Kahn Gillmor + +![Daniel Kahn Gillmor - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/dkg.jpg) + +Daniel Kahn Gillmor is a technologist with the ACLU's Speech, Privacy +and Technology Project, and a free software developer. He's a Free +Software Foundation member, a member of Debian, a contributor to a +wide range of free software projects, and a participant in protocol +development standards organizations like the IETF, with an eye toward +preserving and improving civil liberties and civil rights through our +shared infrastructure. <span class="text-muted">Photo license: This +work by <span xmlns:cc="http://creativecommons.org/ns#" +property="cc:attributionName">Daniel Kahn Gillmor</span> is licensed +under a <a rel="license" +href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons +Attribution ShareAlike 4.0 International License</a>.</span> + +# Edward Snowden + +![Edward Snowden - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/snowden.jpg) + +Edward Snowden is a former intelligence officer who served the CIA, +NSA, and DIA for nearly a decade as a subject matter expert on +technology and cybersecurity. In 2013, he revealed the NSA was +unconstitutionally seizing the private records of billions of +individuals who had not been suspected of any wrongdoing, resulting in +the largest debate about reforms to US surveillance policy +since 1978. Today, he works on methods of enforcing human rights +through the application and development of new technologies. He joined +the board of Freedom of the Press Foundation in February 2014. <span +class="text-muted">Photo license: <span +xmlns:dct="http://purl.org/dc/terms/" +href="http://purl.org/dc/dcmitype/StillImage" property="dct:title" +rel="dct:type">Screenshot of a Citizen Four by Praxis Films.</span> by +<span xmlns:cc="http://creativecommons.org/ns#" +property="cc:attributionName">Laura Poitras</span> is licensed under a +<a rel="license" +href="http://creativecommons.org/licenses/by/3.0/">Creative Commons +Attribution 3.0</a></span>.) + +# Richard Stallman + +![Richard Stallman - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/stallman.jpg) + +Richard is a software developer and software freedom activist. In 1983 +he announced the project to develop the <a href="https://gnu.org">GNU +operating system</a>, a Unix-like operating system meant to be +entirely free software, and has been the project's leader ever +since. With that announcement Richard also launched the Free Software +Movement. In October 1985 he started the Free Software Foundation. + +Since the mid-1990s, Richard has spent most of his time in political +advocacy for free software, and spreading the ethical ideas of the +movement, as well as campaigning against both software patents and +dangerous extension of copyright laws. Before that, Richard developed +a number of widely used software components of GNU, including the +original Emacs, the GNU Compiler Collection, the GNU symbolic debugger +(gdb), GNU Emacs, and various other programs for the GNU operating +system. + +# Clara Snowden + +![Clara Snowden - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/c_snowden.jpg) + +# Ludovic Courtès + +NO_IMAGE + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam +lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +viverra nec consectetur ante hendrerit. Donec et mollis +dolor. Praesent et diam eget libero egestas mattis sit amet vitae +augue. Nam tincidunt congue enim, ut porta lorem lacinia +consectetur. Donec ut libero sed arcu vehicula ultricies a non +tortor. Lorem ipsum dolor sit amet, consectetur adipiscing +elit. Aenean ut gravida lorem. + +Ut turpis felis, pulvinar a semper sed, adipiscing id +dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur +dapibus enim sit amet elit pharetra tincidunt feugiat nisl +imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed +odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu +rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, +nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae +nisi at sem facilisis semper ac in est. + +## Emmanuel, Hampshire College + +Emmanuel is a Division III student at Hampshire College, studying how +technology (especially restrictive technology, like DRM) can affect +how individuals share information, learn, remix content, and organize, +among other things. Born and raised in western Massachusetts, they are +committed to building a free society, improving the lives of others +with technology. + +## George Chriss, OpenMeetings.org + +## Marianne Corvellec, April + +![Marianne Corvellec - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/corvellec.jpg) + +Marianne Corvellec has been a Free Software activist with April +since 2011. April is an advocacy association which has been promoting +and defending Free Software in France and Europe +since 1996. Marianne's focus has been on legal and institutional +issues. + +## Richard Fontana, Red Hat + +NO_IMAGE + +Richard Fontana is a lawyer at Red Hat. He leads support for Red Hat's +engineering and research and development units and is Red Hat's lead +counsel for legal issues relating to free software. Richard is also a +board director of the Open Source Initiative. + +## Mike Gerwitz + +## Bassam Kurdali, Urchin + +![Bassam Kurdali - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/kurdali.png) + +Bassam is a 3D animator/filmmaker whose 2006 short, Elephants Dream, +was the first "open movie." It established the viability of libre +tools in a production environment and set precedent by offering its +source data under a permissive license for learning, remixing and +re-use. His character, ManCandy, began as an easily animatable test +bed for rigging experiments. Multiple iterations have been released to +the public, and Bassam demonstrates him in the animated tutorial +video + short, The ManCandy FAQ. Under the sign of the urchin, Bassam +is continuing to pursue a model of production that invests in +commonwealth. He teaches, writes and lectures around the world on free +production and free software technique. Raised in Damascus, Bassam +trained in the United States as an electrical and software engineer. + +## Jonathan Le Lous, April + +![Jonathan Le Lous - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/lelous.jpg) + +Jonathan has been involved with the Free Software Movement for ten +years, in France and now in Canada. + +## M. C. McGrath + +NO_IMAGE + +M. C. is the founder of Transparency Toolkit, a free software project +that helps people use open data to expose surveillance and human +rights abuses. He is also a Thiel Fellow and an Echoing Green +Fellow. Previously, M. C. graduated from Boston University with a +degree in civic technology and did research at the MIT Media Lab. + +## Deb Nicholson, Open Invention Network + +![Deb Nicholson - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/nicholson.jpg) + +## Stefano Zacchiroli, Debian, IRILL + +![Stefano Zacchiroli - Photo](//static.fsf.org/nosvn/libreplanet/speaker-pics/zacchiroli.jpg) + +Stefano Zacchiroli is Associate Professor of Computer Science at +University Paris Diderot. His research interests span formal methods +and their applications to improve software quality and user experience +in the context of Free Software distributions. He has been an official +member of the Debian Project since 2001, taking care of many tasks +from package maintenance to distribution-wide Quality Assurance. He +has been elected to serve as Debian Project Leader for 3 terms in a +row, over the period 2010-2013. He is a Board Director of the Open +Source Initiative (OSI). He is a recipient of the 2015 O'Reilly Open +Source Award. diff --git a/tests/test_lps_gen.py b/tests/test_lps_gen.py @@ -31,9 +31,9 @@ from nose.tools import * from lps_gen import * -class TestLpsGen(object): +class TestLPS(object): """ - Class that tests the lps_gen.py module. + Class that tests everything related LP Schedule. """ @classmethod def setup_class(self): @@ -198,3 +198,245 @@ class TestLpsGen(object): def teardown_class(self): """Purge the mess created by this test.""" pass + + +class TestLPSpeakers(object): + """ + Class that tests everything related LP Speakers + """ + + @classmethod + def setup_class(self): + """Runs before running any tests in this class.""" + + self.MD_FILE = path.join('tests', 'files', 'lp-speakers.md') + self.MD_FILE_CONTENT = read_file(self.MD_FILE) + + self.markdown = LPSpeakersMarkdown() + self.lpspeakers_dict = self.markdown(self.MD_FILE_CONTENT) + + + def setup(self): + """Runs before each test in this class.""" + pass + + + def test_LPSpeakersMarkdown_keynotespeakers_name(self): + """Testing LPSpeakersMarkdown keynote speakers' names. + + """ + keynote_speakers = ['Daniel Kahn Gillmor', + 'Edward Snowden', + 'Richard Stallman', + 'Clara Snowden', + 'Ludovic Courtès'] + + i = 0 + for kspeaker in self.lpspeakers_dict['keynote-speakers']: + assert_equal(kspeaker['speaker'], keynote_speakers[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_keynotespeakers_id(self): + """Testing LPSpeakersMarkdown keynote speakers' id. + + """ + keynote_speaker_ids = ['gillmor', + 'snowden', + 'stallman', + 'clara_snowden', + 'courtes'] + + + i = 0 + for kspeaker in self.lpspeakers_dict['keynote-speakers']: + assert_equal(kspeaker['id'], keynote_speaker_ids[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_keynotespeakers_imgurl(self): + """Testing LPSpeakersMarkdown keynote speakers' image url. + + """ + keynote_speaker_img_urls = ['//static.fsf.org/nosvn/libreplanet/speaker-pics/dkg.jpg', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/snowden.jpg', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/stallman.jpg', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/c_snowden.jpg'] + + + + i = 0 + for kspeaker in self.lpspeakers_dict['keynote-speakers']: + if kspeaker.has_key('img_url'): + assert_equal(kspeaker['img_url'], + keynote_speaker_img_urls[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_keynotespeakers_imgalt(self): + """Testing LPSpeakersMarkdown keynote speakers' image alt text. + + """ + + keynote_speaker_img_alts = ['Daniel Kahn Gillmor - Photo', + 'Edward Snowden - Photo', + 'Richard Stallman - Photo', + 'Clara Snowden - Photo'] + + + + i = 0 + for kspeaker in self.lpspeakers_dict['keynote-speakers']: + if kspeaker.has_key('img_alt'): + assert_equal(kspeaker['img_alt'], + keynote_speaker_img_alts[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_keynotespeakers_bio(self): + """Testing LPSpeakersMarkdown keynote speakers' bio. + + """ + + keynote_speaker_bios = [['<p>Daniel Kahn Gillmor is a technologist with the ACLU\'s Speech, Privacy'], + ['<p>Edward Snowden is a former intelligence officer who served the CIA,'], + ['<p>Richard is a software developer and software freedom activist. In 1983', + '<p>Since the mid-1990s, Richard has spent most of his time in political',], + [], + + ['<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam', + '<p>Ut turpis felis, pulvinar a semper sed, adipiscing id']] + + + i = 0 + for kspeaker in self.lpspeakers_dict['keynote-speakers']: + if kspeaker.has_key('bio'): + j = 0 + for p in kspeaker['bio']: + p.startswith(keynote_speaker_bios[i][j]) + j = j + 1 + + i = i + 1 + + + def test_LPSpeakersMarkdown_speakers_name(self): + """Testing LPSpeakersMarkdown speakers' names. + + """ + speakers = ['Emmanuel', + 'George Chriss', + 'Marianne Corvellec', + 'Richard Fontana', + 'Mike Gerwitz', + 'Bassam Kurdali', + 'Jonathan Le Lous', + 'M. C. McGrath', + 'Deb Nicholson', + 'Stefano Zacchiroli'] + + i = 0 + for kspeaker in self.lpspeakers_dict['speakers']: + assert_equal(kspeaker['speaker'], speakers[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_speakers_id(self): + """Testing LPSpeakersMarkdown speakers' id. + + """ + speaker_ids = ['emmanuel', + 'chriss', + 'corvellec', + 'fontana', + 'gerwitz', + 'kurdali', + 'lous', + 'mcgrath', + 'nicholson', + 'zacchiroli'] + + i = 0 + for kspeaker in self.lpspeakers_dict['speakers']: + assert_equal(kspeaker['id'], speaker_ids[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_speakers_imgurl(self): + """Testing LPSpeakersMarkdown speakers' image url. + + """ + speaker_img_urls = ['', '', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/corvellec.jpg', + '', '', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/kurdali.png', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/lelous.jpg', + '', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/nicholson.jpg', + '//static.fsf.org/nosvn/libreplanet/speaker-pics/zacchiroli.jpg'] + + i = 0 + for kspeaker in self.lpspeakers_dict['speakers']: + if kspeaker.has_key('img_url'): + assert_equal(kspeaker['img_url'], + speaker_img_urls[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_speakers_imgalt(self): + """Testing LPSpeakersMarkdown speakers' image alt text. + + """ + speaker_img_alts = ['', '', + 'Marianne Corvellec - Photo', + '', '', + 'Bassam Kurdali - Photo', + 'Jonathan Le Lous - Photo', + '', + 'Deb Nicholson - Photo', + 'Stefano Zacchiroli - Photo'] + + + + i = 0 + for kspeaker in self.lpspeakers_dict['speakers']: + if kspeaker.has_key('img_alt'): + assert_equal(kspeaker['img_alt'], + speaker_img_alts[i]) + i = i + 1 + + + def test_LPSpeakersMarkdown_speakers_bio(self): + """Testing LPSpeakersMarkdown speakers' bio. + + """ + speaker_bios = [['<p>Emmanuel is a Division III student at Hampshire College, studying how'], + [], + ['<p>Marianne Corvellec has been a Free Software activist with April'], + ['<p>Richard Fontana is a lawyer at Red Hat. He leads support for Red Hat\'s'], + [], + ['<p>Bassam is a 3D animator/filmmaker whose 2006 short, Elephants Dream,'], + ['<p>Jonathan has been involved with the Free Software Movement for ten'], + ['<p>M. C. is the founder of Transparency Toolkit, a free software project'], + [], + ['<p>Stefano Zacchiroli is Associate Professor of Computer Science at']] + + i = 0 + for kspeaker in self.lpspeakers_dict['speakers']: + if kspeaker.has_key('bio'): + j = 0 + for p in kspeaker['bio']: + p.startswith(speaker_bios[i][j]) + j = j + 1 + + 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