From 85fdd54fd12a87b299ce12d8a49bb05377546a97 Mon Sep 17 00:00:00 2001 From: Irvin Zhan Date: Tue, 21 Jul 2015 17:37:14 -0700 Subject: [PATCH 1/2] creating tests for adding fields in activity with semicolons --- stream_framework/tests/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_framework/tests/serializers.py b/stream_framework/tests/serializers.py index 1c035ace..d91ba8f6 100644 --- a/stream_framework/tests/serializers.py +++ b/stream_framework/tests/serializers.py @@ -18,7 +18,7 @@ class ActivitySerializationTest(unittest.TestCase): serialization_class = BaseSerializer serialization_class_kwargs = { 'activity_class': Activity, 'aggregated_activity_class': AggregatedActivity} - activity_extra_context = {'xxx': 'yyy'} + activity_extra_context = {'xxx': 'yyy', 'with_semicolons': 'foo;bar;;'} def setUp(self): from stream_framework.verbs.base import Love as LoveVerb From 15b9e88c1c5a935862e5652ed1af0644d4340459 Mon Sep 17 00:00:00 2001 From: Irvin Zhan Date: Fri, 17 Jul 2015 18:50:12 -0700 Subject: [PATCH 2/2] escape semicolons when serializing aggregated activities --- .../aggregated_activity_serializer.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/stream_framework/serializers/aggregated_activity_serializer.py b/stream_framework/serializers/aggregated_activity_serializer.py index b4aa22e7..b325a7aa 100644 --- a/stream_framework/serializers/aggregated_activity_serializer.py +++ b/stream_framework/serializers/aggregated_activity_serializer.py @@ -5,6 +5,7 @@ from stream_framework.utils import epoch_to_datetime, datetime_to_epoch from stream_framework.serializers.base import BaseAggregatedSerializer import six +import re class AggregatedActivitySerializer(BaseAggregatedSerializer): @@ -23,7 +24,6 @@ class AggregatedActivitySerializer(BaseAggregatedSerializer): #: indicates if dumps returns dehydrated aggregated activities dehydrate = True identifier = 'v3' - reserved_characters = [';', ',', ';;'] date_fields = ['created_at', 'updated_at', 'seen_at', 'read_at'] activity_serializer_class = ActivitySerializer @@ -55,7 +55,8 @@ def dumps(self, aggregated): else: for activity in aggregated.activities: serialized = activity_serializer.dumps(activity) - check_reserved(serialized, [';', ';;']) + # we use semicolons as delimiter, so need to escape + serialized = serialized.replace(";", "\;") serialized_activities.append(serialized) serialized_activities_part = ';'.join(serialized_activities) @@ -86,15 +87,20 @@ def loads(self, serialized_aggregated): date_value = epoch_to_datetime(float(v)) setattr(aggregated, k, date_value) + # looks for ; not \; + unescaped_semicolons_regex = re.compile("(?<=[^\\\]);") # write the activities - serializations = parts[5].split(';') + serializations = unescaped_semicolons_regex.split(parts[5]) if self.dehydrate: activity_ids = list(map(int, serializations)) aggregated._activity_ids = activity_ids aggregated.dehydrated = True else: - activities = [activity_serializer.loads(s) - for s in serializations] + activities = [] + for s in serializations: + s = s.replace("\;", ";") + deserialized = activity_serializer.loads(s) + activities.append(deserialized) aggregated.activities = activities aggregated.dehydrated = False