1
0
Fork 0
sito-hackit-17/plugins/talks.py

165 lines
4.4 KiB
Python
Raw Normal View History

2017-05-03 01:43:18 +02:00
'''
Manage talks scheduling in a semantic way
'''
from __future__ import print_function
import os
import io
from functools import wraps
import logging
import re
import datetime
import shutil
2017-05-03 01:43:18 +02:00
from docutils import nodes
from docutils.parsers.rst import directives, Directive
from pelican import signals, generators
import jinja2
TALKS_PATH = 'talks'
def memoize(function):
'''decorators to cache'''
memo = {}
@wraps(function)
def wrapper(*args):
if args in memo:
return memo[args]
else:
rv = function(*args)
memo[args] = rv
return rv
return wrapper
@memoize
def get_talk_names():
return [name for name in os.listdir(TALKS_PATH)
if not name.startswith('_') and
get_talk_data(name) is not None
]
@memoize
def get_talk_data(talkname):
fname = os.path.join(TALKS_PATH, talkname, 'meta.yaml')
if not os.path.isfile(fname):
return None
with io.open(fname, encoding='utf8') as buf:
data = yaml.load(buf)
if data is None:
return None
if 'title' not in data:
logging.warn("Talk <{}> has no `title` field".format(talkname))
data['title'] = talkname
if 'text' not in data:
logging.warn("Talk <{}> has no `text` field".format(talkname))
data['text'] = ''
if 'duration' not in data:
logging.info("Talk <{}> has no `duration` field".format(talkname))
2017-05-03 01:43:18 +02:00
data['duration'] = 50
data['duration'] = int(data['duration'])
if 'room' not in data:
logging.warn("Talk <{}> has no `room` field".format(talkname))
if 'time' not in data or 'day' not in data:
logging.error("Talk <{}> has no `time` or `day`".format(talkname))
if 'time' in data:
timeparts = re.findall(r'\d+', str(data['time']))
if 4 > len(timeparts) > 0:
timeparts = [int(p) for p in timeparts]
data['time'] = datetime.time(*timeparts)
else:
logging.error("Talk <{}> has malformed `time`".format(talkname))
data['id'] = talkname
resdir = os.path.join(TALKS_PATH, talkname, 'res')
if os.path.isdir(resdir) and os.listdir(resdir):
data['resources'] = resdir
2017-05-03 01:43:18 +02:00
return data
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.join(TALKS_PATH, '_templates')),
autoescape=True,
)
class TalkListDirective(Directive):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
has_content = True
def run(self):
tmpl = jinja_env.get_template('talk.html')
return [
nodes.raw('', tmpl.render(**get_talk_data(n)),
format='html')
for n in get_talk_names()
]
2017-05-03 02:23:56 +02:00
class TalkDirective(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
has_content = True
def run(self):
tmpl = jinja_env.get_template('talk.html')
data = get_talk_data(self.arguments[0])
if data is None:
return []
return [
nodes.raw('', tmpl.render(**data),
format='html')
]
# TODO: TalkGridDirective (griglia completa)
2017-05-03 01:43:18 +02:00
class TalksGenerator(generators.Generator):
def __init__(self, *args, **kwargs):
self.talks = []
super(TalksGenerator, self).__init__(*args, **kwargs)
def generate_context(self):
self.talks = {n: get_talk_data(n) for n in get_talk_names()}
self._update_context(('talks',))
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', talkname,
'res')
if os.path.isdir(outdir):
shutil.rmtree(outdir)
shutil.copytree(self.talks[talkname]['resources'], outdir)
2017-05-03 01:43:18 +02:00
def add_talks_option_defaults(pelican):
pelican.settings.setdefault('TALKS_PATH', TALKS_PATH)
def get_generators(gen):
return TalksGenerator
try:
import yaml
except ImportError:
print('ERROR: yaml not found. Talks plugins will be disabled')
def register():
pass
else:
def register():
signals.get_generators.connect(get_generators)
2017-05-03 01:43:18 +02:00
signals.initialized.connect(add_talks_option_defaults)
directives.register_directive('talklist', TalkListDirective)
2017-05-03 02:23:56 +02:00
directives.register_directive('talk', TalkDirective)