From 766f24e8f39c29103f1a219b87261c319f2f7749 Mon Sep 17 00:00:00 2001 From: silentninja Date: Mon, 21 Feb 2022 20:30:44 +0530 Subject: [PATCH 1/3] mathesar-433 Implement display options for Duration type --- mathesar/api/serializers/shared_serializers.py | 15 ++++++++++++++- mathesar/tests/api/test_column_api.py | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mathesar/api/serializers/shared_serializers.py b/mathesar/api/serializers/shared_serializers.py index f05c369a13..1f41c2f3a7 100644 --- a/mathesar/api/serializers/shared_serializers.py +++ b/mathesar/api/serializers/shared_serializers.py @@ -165,7 +165,7 @@ def validate(self, datetime_obj, display_format, serializer_field): class TimeWithTimeZoneFormatValidator(AbstractDateTimeFormatValidator): def validate(self, datetime_obj, display_format, serializer_field): - time_only_format = 'HH:mm:ssZZ' + time_only_format = 'HH:mm:ss.SSSZZ' time_str = arrow.get('2013-09-30T15:34:00.000-07:00').format(time_only_format) parsed_time_str = arrow.get(time_str, time_only_format) if parsed_time_str.date() != datetime_obj.date(): @@ -180,6 +180,14 @@ def validate(self, datetime_obj, display_format, serializer_field): return super().validate(datetime_obj, display_format, serializer_field) +class DurationFormatValidator(TimeWithoutTimeZoneFormatValidator): + """ + The validation is same as Time Without TimeZone as of now, + it has been subclassed without any overrides so that the validation logic can be changed in future if needed + """ + pass + + class DateDisplayOptionSerializer(MathesarErrorMessageMixin, OverrideRootPartialMixin, serializers.Serializer): format = serializers.CharField(validators=[DateFormatValidator()]) @@ -216,6 +224,10 @@ class TimeWithoutTimezoneDisplayOptionSerializer( format = serializers.CharField(validators=[TimeWithoutTimeZoneFormatValidator()]) +class DurationDisplayOptionSerializer(MathesarErrorMessageMixin, OverrideRootPartialMixin, serializers.Serializer): + format = serializers.CharField(validators=[DurationFormatValidator()]) + + class DisplayOptionsMappingSerializer( MathesarErrorMessageMixin, ReadWritePolymorphicSerializerMappingMixin, @@ -231,6 +243,7 @@ class DisplayOptionsMappingSerializer( ('date', MathesarTypeIdentifier.DATETIME.value): DateDisplayOptionSerializer, ('time with time zone', MathesarTypeIdentifier.DATETIME.value): TimeWithTimezoneDisplayOptionSerializer, ('time without time zone', MathesarTypeIdentifier.DATETIME.value): TimeWithoutTimezoneDisplayOptionSerializer, + MathesarTypeIdentifier.DURATION.value: DurationDisplayOptionSerializer, } def get_mapping_field(self): diff --git a/mathesar/tests/api/test_column_api.py b/mathesar/tests/api/test_column_api.py index 877ddc7514..95729ce926 100644 --- a/mathesar/tests/api/test_column_api.py +++ b/mathesar/tests/api/test_column_api.py @@ -238,6 +238,7 @@ def test_column_create_invalid_default(column_test_table, client): ("BOOLEAN", {"input": "dropdown"}), ("BOOLEAN", {"input": "checkbox", "custom_labels": {"TRUE": "yes", "FALSE": "no"}}), ("DATE", {'format': 'YYYY-MM-DD'}), + ("INTERVAL", {'format': 'HH:mm:ss.SSS'}), ("NUMERIC", {"show_as_percentage": True}), ("NUMERIC", {"show_as_percentage": True, "locale": "en_US"}), ("TIMESTAMP WITH TIME ZONE", {'format': 'YYYY-MM-DD hh:mm'}), @@ -255,6 +256,7 @@ def test_column_create_display_options( name = "anewcolumn" data = {"name": name, "type": type_, "display_options": display_options} response = client.post(f"/api/db/v0/tables/{column_test_table.id}/columns/", data) + print(response.data) assert response.status_code == 201 # Ensure the correct serialized date is returned by the API From 683847db77f48ce206adbd557a10b3bf417943bf Mon Sep 17 00:00:00 2001 From: silentninja Date: Tue, 22 Feb 2022 22:04:22 +0530 Subject: [PATCH 2/3] Add `Duration` type display options to types list --- mathesar/api/display_options.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mathesar/api/display_options.py b/mathesar/api/display_options.py index 89d22498da..a4a4f63bdf 100644 --- a/mathesar/api/display_options.py +++ b/mathesar/api/display_options.py @@ -16,6 +16,10 @@ {"name": "locale", "type": "string"}] }, MathesarTypeIdentifier.DATETIME.value: + { + "options": [{"name": "format", "type": "string"}] + }, + MathesarTypeIdentifier.DURATION.value: { "options": [{"name": "format", "type": "string"}] } From f7692f31579e5818a4079d173b44829f858a4f81 Mon Sep 17 00:00:00 2001 From: silentninja Date: Wed, 23 Feb 2022 09:50:14 +0530 Subject: [PATCH 3/3] Fix duration display options to accept timestamp display options instead of time --- mathesar/api/serializers/shared_serializers.py | 13 +++++++------ mathesar/tests/api/test_column_api.py | 3 +-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mathesar/api/serializers/shared_serializers.py b/mathesar/api/serializers/shared_serializers.py index 1f41c2f3a7..dfc828bf9e 100644 --- a/mathesar/api/serializers/shared_serializers.py +++ b/mathesar/api/serializers/shared_serializers.py @@ -180,12 +180,13 @@ def validate(self, datetime_obj, display_format, serializer_field): return super().validate(datetime_obj, display_format, serializer_field) -class DurationFormatValidator(TimeWithoutTimeZoneFormatValidator): - """ - The validation is same as Time Without TimeZone as of now, - it has been subclassed without any overrides so that the validation logic can be changed in future if needed - """ - pass +class DurationFormatValidator(AbstractDateTimeFormatValidator): + + def validate(self, datetime_obj, display_format, serializer_field): + if 'z' in display_format.lower(): + raise serializers.ValidationError( + "Duration column cannot contain timezone display format" + ) class DateDisplayOptionSerializer(MathesarErrorMessageMixin, OverrideRootPartialMixin, serializers.Serializer): diff --git a/mathesar/tests/api/test_column_api.py b/mathesar/tests/api/test_column_api.py index 1c2ef25691..e4aa1b1431 100644 --- a/mathesar/tests/api/test_column_api.py +++ b/mathesar/tests/api/test_column_api.py @@ -239,7 +239,7 @@ def test_column_create_invalid_default(column_test_table, client): ("BOOLEAN", {"input": "dropdown"}), ("BOOLEAN", {"input": "checkbox", "custom_labels": {"TRUE": "yes", "FALSE": "no"}}), ("DATE", {'format': 'YYYY-MM-DD'}), - ("INTERVAL", {'format': 'HH:mm:ss.SSS'}), + ("INTERVAL", {'format': 'DD HH:mm:ss.SSS'}), ("NUMERIC", {"show_as_percentage": True}), ("NUMERIC", {"show_as_percentage": True, "locale": "en_US"}), ("TIMESTAMP WITH TIME ZONE", {'format': 'YYYY-MM-DD hh:mm'}), @@ -257,7 +257,6 @@ def test_column_create_display_options( name = "anewcolumn" data = {"name": name, "type": type_, "display_options": display_options} response = client.post(f"/api/db/v0/tables/{column_test_table.id}/columns/", data) - print(response.data) assert response.status_code == 201 # Ensure the correct serialized date is returned by the API