diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 39865d4..5bc75dd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,12 @@ Change Log Unreleased ********** +3.6.2 — 2023-10-12 +********************************************** + +* Handle rare blocks missing dates when calculating last updated +* Remove log of expected "not here" exception during config + 3.6.1 — 2023-10-10 ********************************************** diff --git a/ai_aside/__init__.py b/ai_aside/__init__.py index 4f4cdd8..1ccfe5a 100644 --- a/ai_aside/__init__.py +++ b/ai_aside/__init__.py @@ -2,6 +2,6 @@ A plugin containing xblocks and apps supporting GPT and other LLM use on edX. """ -__version__ = '3.6.1' +__version__ = '3.6.2' default_app_config = "ai_aside.apps.AiAsideConfig" diff --git a/ai_aside/block.py b/ai_aside/block.py index 76f50c1..e134e42 100644 --- a/ai_aside/block.py +++ b/ai_aside/block.py @@ -3,6 +3,7 @@ import logging from datetime import datetime +import pytz from django.conf import settings from django.template import Context, Template from web_fragments.fragment import Fragment @@ -135,6 +136,17 @@ def _check_summarizable(block): return False +def _latest_block_date(maybe_dates): + """ + Find the latest a set of possibly null dates sourced from blocks. + """ + latest = datetime(2012, 5, 1, 0, 0, 0, 0, pytz.UTC) # no blocks predate edx + for d in maybe_dates: + if d is not None and d > latest: + latest = d + return latest + + def _render_hook_fragment(user_role_string, handler_url, block, summary_items): """ Create hook Fragment from block and summarized children. @@ -147,18 +159,15 @@ def _render_hook_fragment(user_role_string, handler_url, block, summary_items): usage_id = block.scope_ids.usage_id course_key = usage_id.course_key + all_interesting_dates = [last_published, last_edited] for item in summary_items: published = item['published_on'] edited = item['edited_on'] - if published and published > last_published: - last_published = published - if edited and edited > last_edited: - last_edited = edited + all_interesting_dates.append(published) + all_interesting_dates.append(edited) # we only need to know when the last time was that anything happened - last_updated = last_published - if last_edited > last_published: - last_updated = last_edited + last_updated = _latest_block_date(all_interesting_dates) fragment = Fragment('') fragment.add_content( diff --git a/tests/test_block.py b/tests/test_block.py index 714cefa..0d5a428 100644 --- a/tests/test_block.py +++ b/tests/test_block.py @@ -4,6 +4,7 @@ from textwrap import dedent from unittest.mock import MagicMock, Mock, call, patch +import pytz from django.test import TestCase, override_settings from opaque_keys.edx.keys import UsageKey @@ -17,8 +18,8 @@ ) fake_transcript = 'This is the text version from the transcript' -date1 = datetime(2023, 1, 2, 3, 4, 5) -date2 = datetime(2023, 6, 7, 8, 9, 10) +date1 = datetime(2023, 1, 2, 3, 4, 5, 0, pytz.UTC) +date2 = datetime(2023, 6, 7, 8, 9, 10, 0, pytz.UTC) def fake_get_transcript(child, lang=None, output_format='SRT', youtube_id=None): # pylint: disable=unused-argument @@ -83,7 +84,7 @@ def setUp(self): def test_format_date(self): formatted_date = _format_date(date1) - self.assertEqual(formatted_date, '2023-01-02T03:04:05') + self.assertEqual(formatted_date, '2023-01-02T03:04:05+00:00') def test_format_date_with_invalid_input(self): invalid_date = '2023-05-01' @@ -291,8 +292,14 @@ def test_parse_children_contents_with_invalid_children(self): def test_render_hook_fragment(self): block = FakeBlock([]) items = [{ + 'published_on': None, + 'edited_on': None, + }, { 'published_on': date1, 'edited_on': date1, + }, { + 'published_on': None, + 'edited_on': None, }, { 'published_on': date2, 'edited_on': date1, @@ -306,7 +313,7 @@ def test_render_hook_fragment(self): data-course-id="course-v1:edX+A+B" data-content-id="block-v1:edX+A+B+type@vertical+block@verticalD" data-handler-url="http://handler.url" - data-last-updated="2023-06-07T08:09:10" + data-last-updated="2023-06-07T08:09:10+00:00" data-user-role="user role string" >