Skip to content

Commit

Permalink
Merge pull request #52 from openedx/cag/serializer
Browse files Browse the repository at this point in the history
fix: serialize datetime objects as strings
  • Loading branch information
Ian2012 committed May 22, 2024
2 parents fa2ce28 + 41293d3 commit 99bcf4e
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 8 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ Change Log
Unreleased
**********

0.9.4 - 2024-05-16
******************

Fixes
=====

* Allow to serialize dates as strings in JSON.

0.9.3 - 2024-05-15
******************

Expand Down
2 changes: 1 addition & 1 deletion platform_plugin_aspects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
import os
from pathlib import Path

__version__ = "0.9.3"
__version__ = "0.9.4"

ROOT_DIRECTORY = Path(os.path.dirname(os.path.abspath(__file__)))
1 change: 0 additions & 1 deletion platform_plugin_aspects/extensions/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ def run_filter(
"show_dashboard_link": show_dashboard_link,
}

print(section_data)
context["sections"].append(section_data)
return {
"context": context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ def record_to_clickhouse(self, event_type, extra) -> None:
output = io.StringIO()
writer = csv.writer(output)
writer.writerow((self.run_id, event_type, json.dumps(extra)))
print(output.getvalue().encode("utf-8"))

response = requests.post(
url=self.ch_url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def run(self) -> None:
lag = None

current_stats = {"clickhouse": self.get_clickhouse_stats()}
lag = -1
if collect_redis_bus:
current_stats["redis_bus"] = self.get_redis_bus_stats()
lag = current_stats["redis_bus"]["lag"]
Expand Down
28 changes: 27 additions & 1 deletion platform_plugin_aspects/sinks/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,39 @@

import json
import uuid
from datetime import date, datetime

from django.utils import timezone
from pytz import UTC
from rest_framework import serializers

from platform_plugin_aspects.utils import get_model, get_tags_for_block


class DateTimeJSONEncoder(json.JSONEncoder):
"""JSON encoder aware of datetime.datetime and datetime.date objects"""

def default(self, obj): # pylint: disable=arguments-renamed
"""
Serialize datetime and date objects of iso format.
datetime objects are converted to UTC.
"""

if isinstance(obj, datetime):
if obj.tzinfo is None:
# Localize to UTC naive datetime objects
obj = UTC.localize(obj) # pylint: disable=no-value-for-parameter
else:
# Convert to UTC datetime objects from other timezones
obj = obj.astimezone(UTC)
return obj.isoformat()
elif isinstance(obj, date):
return obj.isoformat()

return super().default(obj)


class BaseSinkSerializer(serializers.Serializer): # pylint: disable=abstract-method
"""Base sink serializer for ClickHouse."""

Expand Down Expand Up @@ -148,7 +174,7 @@ def get_course_data_json(self, overview):
"language": getattr(overview, "language", ""),
"tags": get_tags_for_block(overview.id),
}
return json.dumps(json_fields)
return json.dumps(json_fields, cls=DateTimeJSONEncoder)

def get_course_key(self, overview):
"""Return the course key as a string."""
Expand Down
7 changes: 5 additions & 2 deletions platform_plugin_aspects/sinks/tests/test_serializers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import json
from datetime import datetime
from unittest.mock import Mock, patch

from django.test import TestCase

from platform_plugin_aspects.sinks.serializers import (
BaseSinkSerializer,
CourseOverviewSerializer,
DateTimeJSONEncoder,
)
from test_utils.helpers import course_key_factory

Expand Down Expand Up @@ -60,7 +62,7 @@ def test_get_course_data_json(self, mock_get_tags):
"""
expected_tags = ["TAX1=tag1", "TAX2=tag2"]
json_fields = {
"advertised_start": "2018-01-01T00:00:00Z",
"advertised_start": datetime.now(),
"announcement": "announcement",
"lowest_passing_grade": 0.0,
"invitation_only": "invitation_only",
Expand All @@ -80,7 +82,8 @@ def test_get_course_data_json(self, mock_get_tags):
mock_get_tags.return_value = expected_tags

self.assertEqual(
self.serializer.get_course_data_json(mock_overview), json.dumps(json_fields)
self.serializer.get_course_data_json(mock_overview),
json.dumps(json_fields, cls=DateTimeJSONEncoder),
)
mock_get_tags.assert_called_once_with(mock_overview.id)

Expand Down
6 changes: 4 additions & 2 deletions platform_plugin_aspects/tests/test_xblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ def test_render_translations(self, mock_get_language, mock_resource_exists):
for resource in student_view.resources:
if resource.kind == "url":
url_resource = resource
self.assertIsNotNone(url_resource, "No 'url' resource found in fragment")
self.assertIn("eo/text.js", url_resource.data)
self.assertIsNotNone(
url_resource, "No 'url' resource found in fragment"
)
self.assertIn("eo/text.js", url_resource.data)
mock_get_language.assert_called_once()
mock_resource_exists.assert_called_once()

Expand Down

0 comments on commit 99bcf4e

Please sign in to comment.