|
@@ -0,0 +1,144 @@
|
|
|
+'''
|
|
|
+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
|
|
|
+
|
|
|
+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
|
|
|
+ ]
|
|
|
+
|
|
|
+
|
|
|
+def warn(s):
|
|
|
+ print('WARN:', s)
|
|
|
+
|
|
|
+
|
|
|
+@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.warn("Talk <{}> has no `duration` field".format(talkname))
|
|
|
+ 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
|
|
|
+ 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
|
|
|
+
|
|
|
+ # TODO: use a jinja template
|
|
|
+ tmpl = u'''<div id="talk-{t[id]}">
|
|
|
+ <h3 class="talk-title">{t[title]}</h3>
|
|
|
+ <div class="talk-description">{t[text]}</div>
|
|
|
+ </div>'''
|
|
|
+
|
|
|
+ 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()
|
|
|
+ ]
|
|
|
+
|
|
|
+
|
|
|
+class TalksGenerator(generators.Generator):
|
|
|
+ def __init__(self, *args, **kwargs):
|
|
|
+ self.talks = []
|
|
|
+ super(TalksGenerator, self).__init__(*args, **kwargs)
|
|
|
+
|
|
|
+ def generate_context(self):
|
|
|
+ self.talks.append('sblindola')
|
|
|
+ self.talks.append('tapioco')
|
|
|
+ if os.path.isdir(self.settings['TALKS_PATH']):
|
|
|
+ self.talks += os.listdir(self.settings['TALKS_PATH'])
|
|
|
+ self._update_context(('talks', ))
|
|
|
+
|
|
|
+
|
|
|
+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)
|
|
|
+ signals.initialized.connect(add_talks_option_defaults)
|
|
|
+ directives.register_directive('talklist', TalkListDirective)
|