Skip to content

Commit 39ea21e

Browse files
authored
ci: merge main to release (ietf-tools#8152)
2 parents 6dec579 + 211fed3 commit 39ea21e

5 files changed

Lines changed: 72 additions & 29 deletions

File tree

ietf/meeting/tasks.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright The IETF Trust 2024, All Rights Reserved
2+
#
3+
# Celery task definitions
4+
#
5+
from celery import shared_task
6+
7+
from .views import generate_agenda_data
8+
9+
10+
@shared_task
11+
def agenda_data_refresh():
12+
generate_agenda_data(force_refresh=True)

ietf/meeting/tests_views.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from django.urls import reverse as urlreverse
2727
from django.conf import settings
2828
from django.contrib.auth.models import User
29+
from django.core.serializers.json import DjangoJSONEncoder
2930
from django.test import Client, override_settings
3031
from django.db.models import F, Max
3132
from django.http import QueryDict, FileResponse
@@ -49,7 +50,7 @@
4950
from ietf.meeting.utils import add_event_info_to_session_qs, participants_for_meeting
5051
from ietf.meeting.utils import create_recording, get_next_sequence, bluesheet_data
5152
from ietf.meeting.views import session_draft_list, parse_agenda_filter_params, sessions_post_save, agenda_extract_schedule
52-
from ietf.meeting.views import get_summary_by_area, get_summary_by_type, get_summary_by_purpose
53+
from ietf.meeting.views import get_summary_by_area, get_summary_by_type, get_summary_by_purpose, generate_agenda_data
5354
from ietf.name.models import SessionStatusName, ImportantDateName, RoleName, ProceedingsMaterialTypeName
5455
from ietf.utils.decorators import skip_coverage
5556
from ietf.utils.mail import outbox, empty_outbox, get_payload_text
@@ -245,30 +246,34 @@ def test_meeting_agenda(self):
245246

246247
# Agenda API tests
247248
# -> Meeting data
248-
r = self.client.get(urlreverse("ietf.meeting.views.api_get_agenda_data", kwargs=dict(num=meeting.number)))
249-
self.assertEqual(r.status_code, 200)
250-
rjson = json.loads(r.content.decode("utf8"))
251-
self.assertJSONEqual(
252-
r.content.decode("utf8"),
249+
# First, check that the generation function does the right thing
250+
generated_data = generate_agenda_data(meeting.number)
251+
self.assertEqual(
252+
generated_data,
253253
{
254254
"meeting": {
255255
"number": meeting.number,
256256
"city": meeting.city,
257257
"startDate": meeting.date.isoformat(),
258258
"endDate": meeting.end_date().isoformat(),
259-
"updated": rjson.get("meeting").get("updated"), # Just expect the value to exist
259+
"updated": generated_data.get("meeting").get("updated"), # Just expect the value to exist
260260
"timezone": meeting.time_zone,
261261
"infoNote": meeting.agenda_info_note,
262262
"warningNote": meeting.agenda_warning_note
263263
},
264-
"categories": rjson.get("categories"), # Just expect the value to exist
264+
"categories": generated_data.get("categories"), # Just expect the value to exist
265265
"isCurrentMeeting": True,
266-
"usesNotes": False, # make_meeting_test_data sets number=72
267-
"schedule": rjson.get("schedule"), # Just expect the value to exist
266+
"usesNotes": False, # make_meeting_test_data sets number=72
267+
"schedule": generated_data.get("schedule"), # Just expect the value to exist
268268
"floors": []
269269
}
270270
)
271-
# -> Session Materials
271+
with patch("ietf.meeting.views.generate_agenda_data", return_value=generated_data):
272+
r = self.client.get(urlreverse("ietf.meeting.views.api_get_agenda_data", kwargs=dict(num=meeting.number)))
273+
self.assertEqual(r.status_code, 200)
274+
# json.dumps using the DjangoJSONEncoder to handle timestamps consistently
275+
self.assertJSONEqual(r.content.decode("utf8"), json.dumps(generated_data, cls=DjangoJSONEncoder))
276+
# -> Session MaterialM
272277
r = self.client.get(urlreverse("ietf.meeting.views.api_get_session_materials", kwargs=dict(session_id=session.id)))
273278
self.assertEqual(r.status_code, 200)
274279
rjson = json.loads(r.content.decode("utf8"))

ietf/meeting/views.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from wsgiref.handlers import format_date_time
2626

2727
from django import forms
28+
from django.core.cache import caches
2829
from django.shortcuts import render, redirect, get_object_or_404
2930
from django.http import (HttpResponse, HttpResponseRedirect, HttpResponseForbidden,
3031
HttpResponseNotFound, Http404, HttpResponseBadRequest,
@@ -1657,8 +1658,16 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
16571658
}
16581659
})
16591660

1660-
@cache_page(5 * 60)
1661-
def api_get_agenda_data (request, num=None):
1661+
1662+
def generate_agenda_data(num=None, force_refresh=False):
1663+
"""Generate data for the api_get_agenda_data endpoint
1664+
1665+
:num: meeting number
1666+
:force_refresh: True to force a refresh of the cache
1667+
"""
1668+
cache = caches["default"]
1669+
cache_timeout = 6 * 60
1670+
16621671
meeting = get_ietf_meeting(num)
16631672
if meeting is None:
16641673
raise Http404("No such full IETF meeting")
@@ -1667,6 +1676,12 @@ def api_get_agenda_data (request, num=None):
16671676
else:
16681677
pass
16691678

1679+
cache_key = f"generate_agenda_data_{meeting.number}"
1680+
if not force_refresh:
1681+
cached_value = cache.get(cache_key)
1682+
if cached_value is not None:
1683+
return cached_value
1684+
16701685
# Select the schedule to show
16711686
schedule = get_schedule(meeting, None)
16721687

@@ -1685,10 +1700,8 @@ def api_get_agenda_data (request, num=None):
16851700

16861701
# Get Floor Plans
16871702
floors = FloorPlan.objects.filter(meeting=meeting).order_by('order')
1688-
1689-
#debug.show('all([(item.acronym,item.session.order_number,item.session.order_in_meeting()) for item in filtered_assignments])')
1690-
1691-
return JsonResponse({
1703+
1704+
result = {
16921705
"meeting": {
16931706
"number": schedule.meeting.number,
16941707
"city": schedule.meeting.city,
@@ -1704,7 +1717,13 @@ def api_get_agenda_data (request, num=None):
17041717
"usesNotes": meeting.uses_notes(),
17051718
"schedule": list(map(agenda_extract_schedule, filtered_assignments)),
17061719
"floors": list(map(agenda_extract_floorplan, floors))
1707-
})
1720+
}
1721+
cache.set(cache_key, result, timeout=cache_timeout)
1722+
return result
1723+
1724+
1725+
def api_get_agenda_data(request, num=None):
1726+
return JsonResponse(generate_agenda_data(num, force_refresh=False))
17081727

17091728

17101729
def api_get_session_materials(request, session_id=None):

ietf/stats/views.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -596,14 +596,17 @@ def build_document_stats_url(stats_type_override=Ellipsis, get_overrides=None):
596596

597597
elif any(stats_type == t[0] for t in possible_yearly_stats_types):
598598

599-
person_filters = Q(documentauthor__document__type="draft")
600-
601599
# filter persons
602600
rfc_state = State.objects.get(type="rfc", slug="published")
603601
if document_type == "rfc":
602+
person_filters = Q(documentauthor__document__type="rfc")
604603
person_filters &= Q(documentauthor__document__states=rfc_state)
605604
elif document_type == "draft":
605+
person_filters = Q(documentauthor__document__type="draft")
606606
person_filters &= ~Q(documentauthor__document__states=rfc_state)
607+
else:
608+
person_filters = Q(documentauthor__document__type="rfc")
609+
person_filters |= Q(documentauthor__document__type="draft")
607610

608611
doc_years = defaultdict(set)
609612

@@ -625,8 +628,8 @@ def build_document_stats_url(stats_type_override=Ellipsis, get_overrides=None):
625628
).values_list("source", flat=True)[:1]
626629
)
627630
)
628-
.values_list("draft", "time")
629-
.order_by("draft")
631+
.values_list("doc", "time")
632+
.order_by("doc")
630633
)
631634

632635
for doc_id, time in rfcevent_qs.iterator():
@@ -663,9 +666,11 @@ def build_document_stats_url(stats_type_override=Ellipsis, get_overrides=None):
663666
for name, affiliation, doc in name_affiliation_doc_set:
664667
a = aliases.get(affiliation, affiliation)
665668
if a:
666-
for year in doc_years.get(doc):
667-
if years_from <= year <= years_to:
668-
bins[(year, a)].add(name)
669+
years = doc_years.get(doc)
670+
if years:
671+
for year in years:
672+
if years_from <= year <= years_to:
673+
bins[(year, a)].add(name)
669674

670675
add_labeled_top_series_from_bins(chart_data, bins, limit=8)
671676

@@ -724,9 +729,11 @@ def build_document_stats_url(stats_type_override=Ellipsis, get_overrides=None):
724729
continent_name = country_to_continent.get(country_name, "")
725730

726731
if continent_name:
727-
for year in doc_years.get(doc):
728-
if years_from <= year <= years_to:
729-
bins[(year, continent_name)].add(name)
732+
years = doc_years.get(doc)
733+
if years:
734+
for year in years:
735+
if years_from <= year <= years_to:
736+
bins[(year, continent_name)].add(name)
730737

731738
add_labeled_top_series_from_bins(chart_data, bins, limit=8)
732739

ietf/templates/base.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
{% endif %}
4747
</a>
4848
<div class="collapse navbar-collapse" id="navbar-collapse">
49-
<ul class="nav navbar-nav">
49+
<ul class="nav navbar-nav flex-nowrap">
5050
{% include "base/menu.html" with flavor="top" %}
5151
</ul>
5252
</div>

0 commit comments

Comments
 (0)