plugin talks configurabile

This commit is contained in:
boyska 2017-05-24 11:17:23 +02:00
parent 3b80ed79b0
commit 3d172beb73
2 changed files with 50 additions and 35 deletions

View file

@ -2,6 +2,7 @@
Manage talks scheduling in a semantic way Manage talks scheduling in a semantic way
''' '''
from __future__ import print_function from __future__ import print_function
import os import os
import io import io
@ -23,11 +24,9 @@ from docutils.parsers.rst import directives, Directive
from pelican import signals, generators from pelican import signals, generators
import jinja2 import jinja2
pelican = None # This will be set during register()
TALKS_PATH = 'talks'
TALK_ATTACHMENT_PATH = 'res'
TALK_ICS = 'schedule.ics'
GRID_STEP = 30
def memoize(function): def memoize(function):
@ -56,7 +55,7 @@ def setlocale(name):
@memoize @memoize
def get_talk_names(): def get_talk_names():
return [name for name in os.listdir(TALKS_PATH) return [name for name in os.listdir(pelican.settings['TALKS_PATH'])
if not name.startswith('_') and if not name.startswith('_') and
get_talk_data(name) is not None get_talk_data(name) is not None
] ]
@ -73,7 +72,7 @@ def unique_attr(iterable, attr):
@memoize @memoize
def get_global_data(): def get_global_data():
fname = os.path.join(TALKS_PATH, 'meta.yaml') fname = os.path.join(pelican.settings['TALKS_PATH'], 'meta.yaml')
if not os.path.isfile(fname): if not os.path.isfile(fname):
return None return None
with io.open(fname, encoding='utf8') as buf: with io.open(fname, encoding='utf8') as buf:
@ -92,7 +91,7 @@ def get_global_data():
@memoize @memoize
def get_talk_data(talkname): def get_talk_data(talkname):
fname = os.path.join(TALKS_PATH, talkname, 'meta.yaml') fname = os.path.join(pelican.settings['TALKS_PATH'], talkname, 'meta.yaml')
if not os.path.isfile(fname): if not os.path.isfile(fname):
return None return None
with io.open(fname, encoding='utf8') as buf: with io.open(fname, encoding='utf8') as buf:
@ -104,6 +103,7 @@ def get_talk_data(talkname):
if data is None: if data is None:
return None return None
try: try:
gridstep = pelican.settings['TALKS_GRID_STEP']
if 'title' not in data: if 'title' not in data:
logging.warn("Talk <{}> has no `title` field".format(talkname)) logging.warn("Talk <{}> has no `title` field".format(talkname))
data['title'] = talkname data['title'] = talkname
@ -115,10 +115,10 @@ def get_talk_data(talkname):
.format(talkname)) .format(talkname))
data['duration'] = 50 data['duration'] = 50
data['duration'] = int(data['duration']) data['duration'] = int(data['duration'])
if data['duration'] < GRID_STEP: if data['duration'] < gridstep:
logging.info("Talk <{}> lasts only {} minutes; changing to {}" logging.info("Talk <{}> lasts only {} minutes; changing to {}"
.format(talkname, data['duration'], GRID_STEP)) .format(talkname, data['duration'], gridstep))
data['duration'] = GRID_STEP data['duration'] = gridstep
if 'links' not in data or not data['links']: if 'links' not in data or not data['links']:
data['links'] = [] data['links'] = []
if 'contacts' not in data or not data['contacts']: if 'contacts' not in data or not data['contacts']:
@ -145,7 +145,8 @@ def get_talk_data(talkname):
else: else:
logging.error("Talk <%s> has malformed `time`", talkname) logging.error("Talk <%s> has malformed `time`", talkname)
data['id'] = talkname data['id'] = talkname
resdir = os.path.join(TALKS_PATH, talkname, TALK_ATTACHMENT_PATH) resdir = os.path.join(pelican.settings['TALKS_PATH'], talkname,
pelican.settings['TALKS_ATTACHMENT_PATH'])
if os.path.isdir(resdir) and os.listdir(resdir): if os.path.isdir(resdir) and os.listdir(resdir):
data['resources'] = resdir data['resources'] = resdir
return data return data
@ -154,16 +155,19 @@ def get_talk_data(talkname):
raise raise
jinja_env = jinja2.Environment( @memoize
loader=jinja2.FileSystemLoader(os.path.join(TALKS_PATH, '_templates')), def jinja_env():
autoescape=True, env = jinja2.Environment(
) loader=jinja2.FileSystemLoader(os.path.join(pelican.settings['TALKS_PATH'], '_templates')),
jinja_env.filters['markdown'] = lambda text: \ autoescape=True,
jinja2.Markup(markdown.Markdown(extensions=['meta']). )
convert(text)) env.filters['markdown'] = lambda text: \
jinja_env.filters['dateformat'] = format_date jinja2.Markup(markdown.Markdown(extensions=['meta']).
jinja_env.filters['datetimeformat'] = format_datetime convert(text))
jinja_env.filters['timeformat'] = format_time env.filters['dateformat'] = format_date
env.filters['datetimeformat'] = format_datetime
env.filters['timeformat'] = format_time
return env
class TalkListDirective(Directive): class TalkListDirective(Directive):
@ -175,7 +179,7 @@ class TalkListDirective(Directive):
def run(self): def run(self):
lang = self.options.get('lang', 'C') lang = self.options.get('lang', 'C')
tmpl = jinja_env.get_template('talk.html') tmpl = jinja_env().get_template('talk.html')
return [ return [
nodes.raw('', tmpl.render(lang=lang, **get_talk_data(n)), nodes.raw('', tmpl.render(lang=lang, **get_talk_data(n)),
format='html') format='html')
@ -193,7 +197,7 @@ class TalkDirective(Directive):
def run(self): def run(self):
lang = self.options.get('lang', 'C') lang = self.options.get('lang', 'C')
tmpl = jinja_env.get_template('talk.html') tmpl = jinja_env().get_template('talk.html')
data = get_talk_data(self.arguments[0]) data = get_talk_data(self.arguments[0])
if data is None: if data is None:
return [] return []
@ -213,9 +217,10 @@ class TalkGridDirective(Directive):
def run(self): def run(self):
lang = self.options.get('lang', 'C') lang = self.options.get('lang', 'C')
tmpl = jinja_env.get_template('grid.html') tmpl = jinja_env().get_template('grid.html')
output = [] output = []
days = unique_attr(all_talks(), 'day') days = unique_attr(all_talks(), 'day')
gridstep = pelican.settings['TALKS_GRID_STEP']
for day in sorted(days): for day in sorted(days):
talks = {talk['id'] for talk in all_talks() talks = {talk['id'] for talk in all_talks()
if talk.get('day', None) == day if talk.get('day', None) == day
@ -231,18 +236,18 @@ class TalkGridDirective(Directive):
del rooms[rooms.index('*')] del rooms[rooms.index('*')]
mintime = min({talk['time'].hour * 60 + mintime = min({talk['time'].hour * 60 +
talk['time'].minute talk['time'].minute
for talk in talks}) // GRID_STEP * GRID_STEP for talk in talks}) // gridstep * gridstep
maxtime = max({talk['time'].hour * 60 + maxtime = max({talk['time'].hour * 60 +
talk['time'].minute + talk['time'].minute +
talk['duration'] talk['duration']
for talk in talks}) for talk in talks})
times = {} times = {}
for t in range(mintime, maxtime, GRID_STEP): for t in range(mintime, maxtime, gridstep):
times[t] = [None] * len(rooms) times[t] = [None] * len(rooms)
for talk in sorted(talks, key=lambda x: x['time']): for talk in sorted(talks, key=lambda x: x['time']):
talktime = talk['time'].hour * 60 + talk['time'].minute talktime = talk['time'].hour * 60 + talk['time'].minute
position = talktime // GRID_STEP * GRID_STEP # round position = talktime // gridstep * gridstep # round
assert position in times assert position in times
if talk['room'] == '*': if talk['room'] == '*':
roomnums = range(len(rooms)) roomnums = range(len(rooms))
@ -258,14 +263,14 @@ class TalkGridDirective(Directive):
continue continue
times[position][roomnum] = copy(talk) times[position][roomnum] = copy(talk)
times[position][roomnum]['skip'] = False times[position][roomnum]['skip'] = False
for i in range(1, talk['duration'] // GRID_STEP): for i in range(1, talk['duration'] // gridstep):
times[position + i*GRID_STEP][roomnum] = copy(talk) times[position + i*gridstep][roomnum] = copy(talk)
times[position + i*GRID_STEP][roomnum]['skip'] = True times[position + i*gridstep][roomnum]['skip'] = True
render = tmpl.render(times=times, render = tmpl.render(times=times,
rooms=rooms, rooms=rooms,
mintime=mintime, maxtime=maxtime, mintime=mintime, maxtime=maxtime,
timestep=GRID_STEP, timestep=gridstep,
lang=lang, lang=lang,
) )
output.append(nodes.raw( output.append(nodes.raw(
@ -321,25 +326,33 @@ class TalksGenerator(generators.Generator):
def generate_output(self, writer=None): def generate_output(self, writer=None):
for talkname in self.talks: for talkname in self.talks:
if 'resources' in self.talks[talkname]: if 'resources' in self.talks[talkname]:
outdir = os.path.join(self.output_path, TALKS_PATH, talkname, outdir = os.path.join(self.output_path,
TALK_ATTACHMENT_PATH) pelican.settings['TALKS_PATH'], talkname,
pelican.settings['TALKS_ATTACHMENT_PATH'])
if os.path.isdir(outdir): if os.path.isdir(outdir):
shutil.rmtree(outdir) shutil.rmtree(outdir)
shutil.copytree(self.talks[talkname]['resources'], outdir) shutil.copytree(self.talks[talkname]['resources'], outdir)
with io.open(os.path.join(self.output_path, TALK_ICS), with io.open(os.path.join(self.output_path, pelican.settings.get('TALKS_ICS')),
'w', 'w',
encoding='utf8') as buf: encoding='utf8') as buf:
buf.write(talks_to_ics()) buf.write(talks_to_ics())
def add_talks_option_defaults(pelican): def add_talks_option_defaults(pelican):
pelican.settings.setdefault('TALKS_PATH', TALKS_PATH) pelican.settings.setdefault('TALKS_PATH', 'talks')
pelican.settings.setdefault('TALKS_ATTACHMENT_PATH', 'res')
pelican.settings.setdefault('TALKS_ICS', 'schedule.ics')
pelican.settings.setdefault('TALKS_GRID_STEP', 30)
def get_generators(gen): def get_generators(gen):
return TalksGenerator return TalksGenerator
def pelican_init(pelicanobj):
global pelican
pelican = pelicanobj
try: try:
import yaml import yaml
except ImportError: except ImportError:
@ -350,6 +363,7 @@ except ImportError:
else: else:
def register(): def register():
signals.initialized.connect(pelican_init)
signals.get_generators.connect(get_generators) signals.get_generators.connect(get_generators)
signals.initialized.connect(add_talks_option_defaults) signals.initialized.connect(add_talks_option_defaults)
directives.register_directive('talklist', TalkListDirective) directives.register_directive('talklist', TalkListDirective)

View file

@ -12,6 +12,7 @@ from pelicanconf import *
SITEURL = '/hackit17' SITEURL = '/hackit17'
RELATIVE_URLS = True RELATIVE_URLS = True
TALKS_GRID_STEP = 30
# DELETE_OUTPUT_DIRECTORY = True # DELETE_OUTPUT_DIRECTORY = True