Skip to content

Commit f8e2838

Browse files
authored
Merge pull request #358 from OpenDataServices/357-format-date
schema: Handle `"format": "date"` correctly
2 parents b7c9a88 + 040e90e commit f8e2838

File tree

5 files changed

+67
-6
lines changed

5 files changed

+67
-6
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased]
88

9+
## [0.12.0] - 2020-08-25
10+
11+
### Added
12+
13+
- Add support for `"format": "date"` in a JSON schema
914

1015
### Changed
1116

flattentool/schema.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,16 @@ def parse_schema_dict(
372372
)
373373
)
374374
elif "string" in property_type_set or not property_type_set:
375-
self.flattened[
376-
parent_path.replace("/0/", "/") + property_name
377-
] = "string"
375+
# We only check for date here, because its the only format
376+
# for which we need to specially transform the input
377+
if property_schema_dict.get("format") == "date":
378+
self.flattened[
379+
parent_path.replace("/0/", "/") + property_name
380+
] = "date"
381+
else:
382+
self.flattened[
383+
parent_path.replace("/0/", "/") + property_name
384+
] = "string"
378385
yield property_name, title
379386
elif "number" in property_type_set:
380387
self.flattened[

flattentool/tests/test_input_SpreadsheetInput_unflatten.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"""
77
from __future__ import unicode_literals
88

9+
import datetime
910
from collections import OrderedDict
1011
from decimal import Decimal
1112

@@ -48,6 +49,7 @@ def inject_root_id(root_id, d):
4849
[{"ROOT_ID": "1", "id": 2, "testA": 3}],
4950
[],
5051
True,
52+
True,
5153
),
5254
(
5355
"Basic with float",
@@ -58,41 +60,63 @@ def inject_root_id(root_id, d):
5860
[{"ROOT_ID": "1", "id": 2, "testA": 3}],
5961
[],
6062
True,
63+
True,
6164
),
6265
(
6366
"Basic with zero",
6467
[{"ROOT_ID": "1", "id": 2, "testA": 0}],
6568
[{"ROOT_ID": "1", "id": 2, "testA": 0}],
6669
[],
6770
True,
71+
True,
72+
),
73+
(
74+
"Basic with date-time",
75+
[{"ROOT_ID": "1", "id": 2, "testDateTime": datetime.datetime(2020, 1, 1)}],
76+
[{"ROOT_ID": "1", "id": 2, "testDateTime": "2020-01-01T00:00:00+00:00"}],
77+
[],
78+
False,
79+
True,
80+
),
81+
(
82+
"Basic with date",
83+
[{"ROOT_ID": "1", "id": 2, "testDate": datetime.datetime(2020, 1, 1)}],
84+
[{"ROOT_ID": "1", "id": 2, "testDate": "2020-01-01"}],
85+
[],
86+
False,
87+
False,
6888
),
6989
(
7090
"Nested",
7191
[{"ROOT_ID": "1", "id": 2, "testO/testB": 3, "testO/testC": 4,}],
7292
[{"ROOT_ID": "1", "id": 2, "testO": {"testB": 3, "testC": 4}}],
7393
[],
7494
True,
95+
True,
7596
),
7697
(
7798
"Unicode",
7899
[{"ROOT_ID": UNICODE_TEST_STRING, "testU": UNICODE_TEST_STRING}],
79100
[{"ROOT_ID": UNICODE_TEST_STRING, "testU": UNICODE_TEST_STRING}],
80101
[],
81102
True,
103+
True,
82104
),
83105
(
84106
"Single item array",
85107
[{"ROOT_ID": "1", "id": 2, "testL/0/id": 3, "testL/0/testB": 4}],
86108
[{"ROOT_ID": "1", "id": 2, "testL": [{"id": 3, "testB": 4}],}],
87109
[],
88110
False,
111+
True,
89112
),
90113
(
91114
"Single item array without parent ID",
92115
[{"ROOT_ID": "1", "testL/0/id": "2", "testL/0/testB": "3",}],
93116
[{"ROOT_ID": "1", "testL": [{"id": "2", "testB": "3"}],}],
94117
[],
95118
False,
119+
True,
96120
),
97121
(
98122
"Empty",
@@ -110,6 +134,7 @@ def inject_root_id(root_id, d):
110134
[],
111135
[],
112136
False,
137+
True,
113138
),
114139
(
115140
"Empty except for root id",
@@ -127,6 +152,7 @@ def inject_root_id(root_id, d):
127152
[{"ROOT_ID": 1}],
128153
[],
129154
False,
155+
True,
130156
),
131157
# Previously this caused the error: TypeError: unorderable types: str() < int()
132158
# Now one of the columns is ignored
@@ -142,6 +168,7 @@ def inject_root_id(root_id, d):
142168
"Column newtest/0/a has been ignored, because it treats newtest as an array, but another column does not."
143169
],
144170
False,
171+
True,
145172
),
146173
# Previously this caused the error: TypeError: unorderable types: str() < int()
147174
# Now one of the columns is ignored
@@ -157,6 +184,7 @@ def inject_root_id(root_id, d):
157184
"Column newtest/a has been ignored, because it treats newtest as an object, but another column does not."
158185
],
159186
False,
187+
True,
160188
),
161189
# Previously this caused the error: 'Cell' object has no attribute 'get'
162190
# Now one of the columns is ignored
@@ -168,6 +196,7 @@ def inject_root_id(root_id, d):
168196
"Column newtest/0/a has been ignored, because it treats newtest as an array, but another column does not."
169197
],
170198
False,
199+
True,
171200
),
172201
(
173202
"str / object mixing",
@@ -177,6 +206,7 @@ def inject_root_id(root_id, d):
177206
"Column newtest/a has been ignored, because it treats newtest as an object, but another column does not."
178207
],
179208
False,
209+
True,
180210
),
181211
(
182212
"array / str mixing",
@@ -195,6 +225,7 @@ def inject_root_id(root_id, d):
195225
"Column nest/newtest has been ignored, because another column treats it as an array or object"
196226
],
197227
False,
228+
True,
198229
),
199230
(
200231
"object / str mixing",
@@ -204,6 +235,7 @@ def inject_root_id(root_id, d):
204235
"Column newtest has been ignored, because another column treats it as an array or object"
205236
],
206237
False,
238+
True,
207239
),
208240
(
209241
"Mismatch of object/array for field not in schema (multiline)",
@@ -216,6 +248,7 @@ def inject_root_id(root_id, d):
216248
"Column nest/newtest/0/a has been ignored, because it treats newtest as an array, but another column does not"
217249
],
218250
False,
251+
True,
219252
),
220253
# Previously this caused the error: TypeError: unorderable types: str() < int()
221254
# Now one of the columns is ignored
@@ -230,6 +263,7 @@ def inject_root_id(root_id, d):
230263
"Column newtest/a has been ignored, because it treats newtest as an object, but another column does not"
231264
],
232265
False,
266+
True,
233267
),
234268
# Previously this caused the error: 'Cell' object has no attribute 'get'
235269
# Now one of the columns is ignored
@@ -252,6 +286,7 @@ def inject_root_id(root_id, d):
252286
"Column nest/newtest/0/b has been ignored, because it treats newtest as an array, but another column does not",
253287
],
254288
False,
289+
True,
255290
),
256291
(
257292
"array / str mixing multiline",
@@ -265,6 +300,7 @@ def inject_root_id(root_id, d):
265300
"Column nest/newtest has been ignored, because another column treats it as an array or object"
266301
],
267302
False,
303+
True,
268304
),
269305
# WARNING: Conflict when merging field "newtest" for id "2" in sheet custom_main: "3"
270306
(
@@ -281,6 +317,7 @@ def inject_root_id(root_id, d):
281317
"Column newtest/b has been ignored, because it treats newtest as an object, but another column does not",
282318
],
283319
False,
320+
True,
284321
),
285322
(
286323
"object / str mixing multiline",
@@ -293,6 +330,7 @@ def inject_root_id(root_id, d):
293330
"Column newtest has been ignored, because another column treats it as an array or object"
294331
],
295332
False,
333+
True,
296334
),
297335
# Previously this caused the error: KeyError('ocid',)
298336
# Now it works, but probably not as intended
@@ -304,6 +342,7 @@ def inject_root_id(root_id, d):
304342
[{"id": 2, "testA": 3}],
305343
[],
306344
False,
345+
True,
307346
),
308347
# We should be able to handle numbers as column headings
309348
(
@@ -329,6 +368,7 @@ def inject_root_id(root_id, d):
329368
'Column "4" has been ignored because it is a number.',
330369
],
331370
False,
371+
True,
332372
),
333373
]
334374

@@ -377,6 +417,8 @@ def create_schema(root_id):
377417
"properties": {
378418
"id": {"title": "Identifier", "type": "integer",},
379419
"testA": {"title": "A title", "type": "integer",},
420+
"testDateTime": {"type": "string", "format": "date-time",},
421+
"testDate": {"type": "string", "format": "date"},
380422
"testB": {
381423
"title": "B title",
382424
"type": "object",
@@ -685,7 +727,8 @@ def create_schema(root_id):
685727
@pytest.mark.parametrize("use_schema", [True, False])
686728
@pytest.mark.parametrize("root_id,root_id_kwargs", ROOT_ID_PARAMS)
687729
@pytest.mark.parametrize(
688-
"comment,input_list,expected_output_list,warning_messages,reversible", testdata
730+
"comment,input_list,expected_output_list,warning_messages,reversible,works_without_schema",
731+
testdata,
689732
)
690733
def test_unflatten(
691734
convert_titles,
@@ -698,7 +741,11 @@ def test_unflatten(
698741
comment,
699742
warning_messages,
700743
reversible,
744+
works_without_schema,
701745
):
746+
if not use_schema and not works_without_schema:
747+
pytest.skip()
748+
702749
# Not sure why, but this seems to be necessary to have warnings picked up
703750
# on Python 2.7 and 3.3, but 3.4 and 3.5 are fine without it
704751
import warnings
@@ -764,6 +811,7 @@ def test_unflatten_pointer(
764811
comment=comment,
765812
warning_messages=warning_messages,
766813
reversible=False,
814+
works_without_schema=True,
767815
)
768816

769817

@@ -802,4 +850,5 @@ def test_unflatten_titles(
802850
comment=comment,
803851
warning_messages=warning_messages,
804852
reversible=reversible,
853+
works_without_schema=True,
805854
)

flattentool/tests/test_json_input_is_unflatten_reversed.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
@pytest.mark.parametrize("root_id,root_id_kwargs", ROOT_ID_PARAMS)
3333
@pytest.mark.parametrize(
3434
"comment,expected_output_list,input_list,warning_messages,reversible",
35-
[x for x in testdata if x[4]],
35+
[x[:5] for x in testdata if x[4]],
3636
)
3737
def test_flatten(
3838
use_titles,

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
setup(
1414
name="flattentool",
15-
version="0.11.0",
15+
version="0.12.0",
1616
author="Open Data Services",
1717
author_email="[email protected]",
1818
packages=["flattentool"],

0 commit comments

Comments
 (0)