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

View file

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