From 7e31c136575b6a3aab62a3c696d6c3593394ef87 Mon Sep 17 00:00:00 2001 From: Andre Herbst Date: Sat, 18 Dec 2021 11:53:24 +0100 Subject: [PATCH 1/3] fixed: populate events-list template variable with the Article() objects instead of just lightweight Event()-objects. This enables the template to place links to the real page url. Pages therefore do not need to have a slug header anymore for these links to work. --- events/events.py | 50 ++++++++++++++++++++++------------------- events/events_list.html | 16 ++++++------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/events/events.py b/events/events.py index 4badf62f0..3fe31a01f 100644 --- a/events/events.py +++ b/events/events.py @@ -14,7 +14,7 @@ """ from datetime import datetime, timedelta -from pelican import signals, utils +from pelican import signals, utils, contents from collections import namedtuple, defaultdict import icalendar import logging @@ -33,30 +33,29 @@ events = [] localized_events = defaultdict(list) -Event = namedtuple("Event", "dtstart dtend metadata") -def parse_tstamp(ev, field_name): +def parse_tstamp(metadata, field_name): """Parse a timestamp string in format "YYYY-MM-DD HH:MM" :returns: datetime """ try: - return datetime.strptime(ev[field_name], '%Y-%m-%d %H:%M') + return datetime.strptime(metadata[field_name], '%Y-%m-%d %H:%M') except Exception as e: log.error("Unable to parse the '%s' field in the event named '%s': %s" \ - % (field_name, ev['title'], e)) + % (field_name, metadata['title'], e)) raise -def parse_timedelta(ev): +def parse_timedelta(metadata): """Parse a timedelta string in format [ ]* e.g. 2h 30m :returns: timedelta """ - chunks = ev['event-duration'].split() + chunks = metadata['event-duration'].split() tdargs = {} for c in chunks: try: @@ -66,41 +65,46 @@ def parse_timedelta(ev): except KeyError: log.error("""Unknown time multiplier '%s' value in the \ 'event-duration' field in the '%s' event. Supported multipliers \ -are: '%s'.""" % (c, ev['title'], ' '.join(TIME_MULTIPLIERS))) +are: '%s'.""" % (c, metadata['title'], ' '.join(TIME_MULTIPLIERS))) raise RuntimeError("Unknown time multiplier '%s'" % c) except ValueError: log.error("""Unable to parse '%s' value in the 'event-duration' \ -field in the '%s' event.""" % (c, ev['title'])) +field in the '%s' event.""" % (c, metadata['title'])) raise ValueError("Unable to parse '%s'" % c) return timedelta(**tdargs) -def parse_article(generator, metadata): +def parse_article(content): """Collect articles metadata to be used for building the event calendar :returns: None """ - if 'event-start' not in metadata: + if not isinstance(content, contents.Article): return - dtstart = parse_tstamp(metadata, 'event-start') + if 'event-start' not in content.metadata: + return + + dtstart = parse_tstamp(content.metadata, 'event-start') - if 'event-end' in metadata: - dtend = parse_tstamp(metadata, 'event-end') + if 'event-end' in content.metadata: + dtend = parse_tstamp(content.metadata, 'event-end') - elif 'event-duration' in metadata: - dtdelta = parse_timedelta(metadata) + elif 'event-duration' in content.metadata: + dtdelta = parse_timedelta(content.metadata) dtend = dtstart + dtdelta else: msg = "Either 'event-end' or 'event-duration' must be" + \ - " speciefied in the event named '%s'" % metadata['title'] + " speciefied in the event named '%s'" % content.metadata['title'] log.error(msg) raise ValueError(msg) - events.append(Event(dtstart, dtend, metadata)) + content.event_plugin_data = {"dtstart": dtstart, "dtend": dtend} + + events.append(content) def generate_ical_file(generator): @@ -127,8 +131,8 @@ def generate_ical_file(generator): for e in curr_events: ie = icalendar.Event( summary=e.metadata['summary'], - dtstart=e.dtstart, - dtend=e.dtend, + dtstart=e.event_plugin_data["dtstart"], + dtend=e.event_plugin_data["dtend"], dtstamp=e.metadata['date'], priority=5, uid=e.metadata['title'] + e.metadata['summary'], @@ -161,10 +165,10 @@ def generate_events_list(generator): if not localized_events: generator.context['events_list'] = sorted(events, reverse = True, - key=lambda ev: (ev.dtstart, ev.dtend)) + key=lambda ev: (ev.event_plugin_data["dtstart"], ev.event_plugin_data["dtend"])) else: generator.context['events_list'] = {k: sorted(v, reverse = True, - key=lambda ev: (ev.dtstart, ev.dtend)) + key=lambda ev: (ev.event_plugin_data["dtstart"], ev.event_plugin_data["dtend"])) for k, v in localized_events.items()} def initialize_events(article_generator): @@ -178,7 +182,7 @@ def initialize_events(article_generator): def register(): signals.article_generator_init.connect(initialize_events) - signals.article_generator_context.connect(parse_article) + signals.content_object_init.connect(parse_article) signals.article_generator_finalized.connect(generate_localized_events) signals.article_generator_finalized.connect(generate_ical_file) signals.article_generator_finalized.connect(generate_events_list) diff --git a/events/events_list.html b/events/events_list.html index ac0184ce6..98885c9b9 100644 --- a/events/events_list.html +++ b/events/events_list.html @@ -7,26 +7,26 @@ {% if events_list %}
    - {% for evstart, evend, event in events_list %} + {% for event in events_list %}
  • - - {{event['title']}} + + {{ event.metadata["title"] }}

    - {% if evstart.date() == evend.date() %} - From {{evstart}} to {{evend.time()}} + {% if event.event_plugin_data["dtstart"].date() == event.event_plugin_data["dtend"].date() %} + From {{ event.event_plugin_data["dtstart"] }} to {{ event.event_plugin_data["dtend"].time() }} {% else %} - From {{evstart}} to {{evend}} + From {{ event.event_plugin_data["dtstart"] }} to {{ event.event_plugin_data["dtend"] }} {% endif %}

    {% if event.location %} -

    Location: {{event.location}}

    +

    Location: {{ event.metadata["location"] }}

    {% endif %} -

    {{event['summary']}}

    +

    {{ event.metadata["summary"] }}

  • {% endfor %} From d0385c18109140df93fbea2f977edea17024be31 Mon Sep 17 00:00:00 2001 From: Andre Herbst Date: Sat, 18 Dec 2021 13:48:37 +0100 Subject: [PATCH 2/3] fix: use ISO format date strings in ical file as specified in https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.5 --- events/events.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/events/events.py b/events/events.py index 3fe31a01f..a9dedd661 100644 --- a/events/events.py +++ b/events/events.py @@ -131,9 +131,9 @@ def generate_ical_file(generator): for e in curr_events: ie = icalendar.Event( summary=e.metadata['summary'], - dtstart=e.event_plugin_data["dtstart"], - dtend=e.event_plugin_data["dtend"], - dtstamp=e.metadata['date'], + dtstart=e.event_plugin_data["dtstart"].isoformat(), + dtend=e.event_plugin_data["dtend"].isoformat(), + dtstamp=e.metadata['date'].isoformat(), priority=5, uid=e.metadata['title'] + e.metadata['summary'], ) From f03cf239712d59cf97773cad665293a68d49162a Mon Sep 17 00:00:00 2001 From: Andre Herbst Date: Sat, 18 Dec 2021 14:11:22 +0100 Subject: [PATCH 3/3] fix: use ISO format date strings without - and : separators in ical file as specified in https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.5 --- events/events.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/events/events.py b/events/events.py index a9dedd661..3f08b0985 100644 --- a/events/events.py +++ b/events/events.py @@ -76,6 +76,10 @@ def parse_timedelta(metadata): return timedelta(**tdargs) +def basic_isoformat(datetime_value): + return datetime_value.strftime("%Y%m%dT%H%M%S") + + def parse_article(content): """Collect articles metadata to be used for building the event calendar @@ -131,9 +135,9 @@ def generate_ical_file(generator): for e in curr_events: ie = icalendar.Event( summary=e.metadata['summary'], - dtstart=e.event_plugin_data["dtstart"].isoformat(), - dtend=e.event_plugin_data["dtend"].isoformat(), - dtstamp=e.metadata['date'].isoformat(), + dtstart=basic_isoformat(e.event_plugin_data["dtstart"]), + dtend=basic_isoformat(e.event_plugin_data["dtend"]), + dtstamp=basic_isoformat(e.metadata['date']), priority=5, uid=e.metadata['title'] + e.metadata['summary'], )