summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.rst7
-rw-r--r--lps_gen.py31
-rw-r--r--tests/files/lp-sch-2016.jinja2117
-rw-r--r--tests/test_lps_gen.py12
4 files changed, 140 insertions, 27 deletions
diff --git a/README.rst b/README.rst
index 3a743ba..0936add 100644
--- a/README.rst
+++ b/README.rst
@@ -47,12 +47,7 @@ Usage
::
- $ lps_gen YEAR path/to/lp-sch.md > path/to/program-schedule.html
-
-Replace ``YEAR`` with LP year; for example, for generating LP 2016
-schedule, the command will be::
-
- $ lps_gen 2016 path/to/lp-sch.md > path/to/program-schedule.html
+ $ lps_gen path/to/lp-sch.jinja2 path/to/lp-sch.md > path/to/program-schedule.html
LP schedule markdown structure
diff --git a/lps_gen.py b/lps_gen.py
index 8f04af8..8cf566c 100644
--- a/lps_gen.py
+++ b/lps_gen.py
@@ -26,7 +26,7 @@ from collections import OrderedDict
from os import path
from bs4 import BeautifulSoup
-from jinja2 import Environment, PackageLoader
+from jinja2 import Environment, FileSystemLoader
from jinja2.exceptions import TemplateNotFound
from mistune import Renderer, Markdown
@@ -144,16 +144,15 @@ class LPSMarkdown(Markdown):
return lps_dict
-def RenderHTML(lps_dict, year):
+def RenderHTML(lps_dict, template):
"""Renders LP schedule in HTML from a python dictionary.
Returns the HTML as a string.
"""
- env = Environment(loader=PackageLoader('lpschedule_generator',
- 'templates'),
+ env = Environment(loader=FileSystemLoader(path.dirname(template)),
trim_blocks=True, lstrip_blocks=True)
- template_name = 'lp-sch-%s.jinja2' % year
+ template_name = path.basename(template)
template = None
try:
@@ -172,25 +171,25 @@ def main():
parser.add_argument("--version", action="version",
version='lpschedule-generator version %s' % __version__,
help="Show version number and exit.")
- parser.add_argument("year",
- help="LP Schedule year.")
- parser.add_argument("lps_md",
- help="Path to the markdown version of LP Schedule.")
+ parser.add_argument("lp_t",
+ help="Path to the LP template.")
+ parser.add_argument("lp_md",
+ help="Path to the LP markdown.")
args = parser.parse_args()
- lps_md_content = read_file(path.abspath(args.lps_md))
- lp_year = args.year
+ lp_template = args.lp_t
+ lp_md_content = read_file(path.abspath(args.lp_md))
- if lps_md_content:
+ if path.exists(lp_template) and lp_md_content:
markdown = LPSMarkdown()
- lps_dict = markdown(lps_md_content)
- lps_html = RenderHTML(lps_dict, lp_year)
+ lp_dict = markdown(lp_md_content)
+ lp_html = RenderHTML(lp_dict, lp_template)
else:
exit(1)
- if lps_html:
+ if lp_html:
# stdout lps html
- print lps_html
+ print lp_html
else:
print 'Error generating LP HTML.'
diff --git a/tests/files/lp-sch-2016.jinja2 b/tests/files/lp-sch-2016.jinja2
new file mode 100644
index 0000000..f7cb0de
--- /dev/null
+++ b/tests/files/lp-sch-2016.jinja2
@@ -0,0 +1,117 @@
+{# -*- mode: jinja2; -*- #}
+{#
+ Copyright (C) 2015 lpschedule-generator contributors. See CONTRIBUTORS.
+
+ 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/>.
+#}
+
+{# macros start #}
+
+{# make speakers macro #}
+{% macro mk_speakers(speakers) %}
+ <span class="program-session-speaker">
+ {% for speaker in speakers %}
+ {% if loop.last %}
+ {{ speaker }}
+ {% else %}
+ {{ speaker }},
+ {% endif %}
+ {% endfor %}
+ </span>
+{% endmacro %}
+
+{# make room macro #}
+{% macro mk_room(room) %}
+ <span class="label label-default">{{ room }}</span>
+{% endmacro %}
+
+{# make day header macro #}
+{% macro mk_day_header(day, collapse_area) %}
+ <header class="program-day-header">
+ <hgroup>
+ <h2>{{ day }}</h2>
+ </hgroup>
+ </header>
+{% endmacro %}
+
+{# make timeslot header macro #}
+{% macro mk_timeslot_header(timeslot, collapse, collapse_area='') %}
+ <header class="program-timeslot-header">
+ <hgroup>
+ <h2>{{ timeslot }}</h2>
+ </hgroup>
+ </header>
+{% endmacro %}
+
+{# make session header macro #}
+{% macro mk_session_header(session) %}
+ <header class="program-session-header">
+ <hgroup>
+ <h2>{{ session }}</h2>
+ </hgroup>
+ </header>
+{% endmacro %}
+
+{# desc macro #}
+{% macro desc(disc_list) %}
+ {% for desc_p in disc_list %}
+ <p>{{ desc_p }}</p>
+ {% endfor %}
+{% endmacro %}
+
+{# populate sessions macro #}
+{% macro populate_sessions(sessions, day_index, timeslot_index) %}
+ {% for session, session_info in sessions.iteritems() %} {# session start #}
+ <section id="day-{{ day_index }}-timeslot-{{ timeslot_index }}-session-{{ loop.index }}" class="program-session">
+ {{ mk_session_header(session) }}
+ {{ mk_speakers(session_info['speakers']) }}
+ <p class="program-session-room-details">
+ {{ mk_room(session_info['room']) }}
+ <button class="btn btn-default btn-xs"
+ data-toggle="collapse" aria-expanded="false"
+ aria-controls="day-{{ day_index }}-timeslot-{{ timeslot_index }}-session-{{ loop.index }}-collapse"
+ data-target="#day-{{ day_index }}-timeslot-{{ timeslot_index }}-session-{{ loop.index }}-collapse">
+ Details
+ </button>
+ </p>
+ <div class="collapse in"
+ id="day-{{ day_index }}-timeslot-{{ timeslot_index }}-session-{{ loop.index }}-collapse">
+ {{ desc(session_info['desc']) }}
+ </div> <!-- day-{{ day_index }}-timeslot-{{ timeslot_index }}-session-{{ loop.index }}-collapse end -->
+ </section> <!-- day-{{ day_index }}-timeslot-{{ timeslot_index }}-session-{{ loop.index }} end -->
+ {% endfor %} {# session end #}
+{% endmacro %}
+
+{# populate timeslots macro #}
+{% macro populate_timeslots(timeslots, day_index) %}
+ {% for timeslot, sessions in timeslots.iteritems() %} {# timeslot start #}
+ <article id="day-{{ day_index }}-timeslot-{{ loop.index }}" class="program-timeslot">
+ {{ mk_timeslot_header(timeslot) }}
+ {% if sessions|length > 0 %}
+ {{ populate_sessions(sessions, day_index, loop.index) }}
+ {% endif %}
+ </article> <!-- day-{{ day_index }}-timeslot-{{ loop.index }} end -->
+ {% endfor %} {# timeslot start #}
+{% endmacro %}
+
+{# lp 2016 template start #}
+{% for day, timeslots in schedule.iteritems() %} {# day start #}
+ <article id="day-{{ loop.index }}-program" class="program-day">
+ {{ mk_day_header(day) }}
+ {{ populate_timeslots(timeslots, loop.index) }}
+ </article> <!-- day-{{ loop.index }} end -->
+{% endfor %} {# day loop end #}
diff --git a/tests/test_lps_gen.py b/tests/test_lps_gen.py
index e964a5a..a84ca78 100644
--- a/tests/test_lps_gen.py
+++ b/tests/test_lps_gen.py
@@ -42,6 +42,9 @@ class TestLpsGen(object):
self.MD_FILE = path.join('tests', 'files', 'lp-sch.md')
self.MD_FILE_CONTENT = read_file(self.MD_FILE)
+ self.SCH_TEMPLATE = path.join('tests', 'files',
+ 'lp-sch-2016.jinja2')
+
self.markdown = LPSMarkdown()
self.lps_dict = self.markdown(self.MD_FILE_CONTENT)
@@ -160,19 +163,18 @@ class TestLpsGen(object):
def test_RenderHTML(self):
"""Testing `RenderHTML` function
"""
- lps_html = RenderHTML(self.lps_dict, '2016')
+ lps_html = RenderHTML(self.lps_dict, self.SCH_TEMPLATE)
print lps_html
@raises(SystemExit)
def test_RenderHTML_invalid_year(self):
- """Testing `RenderHTML` function - with invalid year
+ """Testing `RenderHTML` function - with non-existent template
"""
with mock.patch('sys.stdout', new_callable=StringIO) as out:
- invalid_year = '2016_invalid'
- template_name = 'lp-sch-%s.jinja2' % invalid_year
+ nonexistent_template = 'lpsch-template.null'
- lps_html = RenderHTML(self.lps_dict, invalid_year)
+ lps_html = RenderHTML(self.lps_dict, nonexistent_template)
expected_out = 'Template %s not found.\n' % template_name
assert out.getvalue() == expected_out