Skip to content

Commit 693d59d

Browse files
authored
fix: fixed serialization of datetime to iso format (#629)
1 parent 74e328b commit 693d59d

File tree

3 files changed

+102
-8
lines changed

3 files changed

+102
-8
lines changed

renku/models/_jsonld.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,18 @@ def asjsonld(
228228
)
229229
rv = dict_factory()
230230

231-
def convert_value(v):
232-
"""Convert special types."""
233-
if isinstance(v, Path):
234-
v = str(v)
235-
return os.path.relpath(v, str(basedir)) if basedir else v
236-
if isinstance(v, datetime):
237-
return str(v)
238-
return v
231+
def convert_value(value):
232+
"""Convert non-serializable types."""
233+
if isinstance(value, Path):
234+
result = str(value)
235+
if basedir:
236+
result = os.path.relpath(result, str(basedir))
237+
return result
238+
239+
if isinstance(value, datetime):
240+
return value.isoformat()
241+
242+
return value
239243

240244
for a in attrs:
241245
v = getattr(inst, a.name)

renku/utils/datetime8601.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Copyright 2019 - Swiss Data Science Center (SDSC)
4+
# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
5+
# Eidgenössische Technische Hochschule Zürich (ETHZ).
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
"""Renku datetime utilities."""
19+
import re
20+
21+
regex = (
22+
r'^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12]['
23+
r'0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|['
24+
r'+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$'
25+
)
26+
match_iso8601 = re.compile(regex).match
27+
28+
29+
def validate_iso8601(str_val):
30+
"""Check if datetime string is in ISO8601 format."""
31+
try:
32+
if match_iso8601(str_val) is not None:
33+
return True
34+
except re.error:
35+
pass
36+
return False

tests/cli/test_datasets.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import git
2626
import pytest
27+
import yaml
2728

2829
from renku import cli
2930
from renku._compat import Path
@@ -32,6 +33,7 @@
3233
from renku.cli._format.dataset_files import FORMATS as DATASET_FILES_FORMATS
3334
from renku.cli._format.datasets import FORMATS as DATASETS_FORMATS
3435
from renku.models.refs import LinkReference
36+
from renku.utils.datetime8601 import validate_iso8601
3537

3638

3739
def test_datasets_create_clean(data_repository, runner, project, client):
@@ -851,3 +853,55 @@ def test_dataset_edit_dirty(runner, client, project):
851853
cli.cli, ['dataset', 'edit', dataset.identifier], input='wq'
852854
)
853855
assert 0 == result.exit_code
856+
857+
858+
def test_dataset_date_created_format(runner, client, project):
859+
"""Check format of date created field."""
860+
# Create a dataset.
861+
result = runner.invoke(cli.cli, ['dataset', 'create', 'dataset'])
862+
assert 0 == result.exit_code
863+
assert 'OK' in result.output
864+
865+
path = client.dataset_path('dataset')
866+
assert path.exists()
867+
868+
with path.open(mode='r') as fp:
869+
import dateutil.parser as dp
870+
data_yaml = yaml.safe_load(fp)
871+
872+
assert 'created' in data_yaml
873+
assert dp.parse(data_yaml['created'])
874+
assert validate_iso8601(data_yaml['created'])
875+
876+
877+
def test_dataset_file_date_created_format(tmpdir, runner, client, project):
878+
"""Check format of date created field."""
879+
# Create a dataset.
880+
result = runner.invoke(cli.cli, ['dataset', 'create', 'dataset'])
881+
assert 0 == result.exit_code
882+
assert 'OK' in result.output
883+
884+
path = client.dataset_path('dataset')
885+
assert path.exists()
886+
887+
# Create data file.
888+
new_file = tmpdir.join('datafile.csv')
889+
new_file.write('1,2,3')
890+
891+
# Add data to dataset.
892+
result = runner.invoke(
893+
cli.cli, ['dataset', 'add', 'dataset',
894+
str(new_file)]
895+
)
896+
assert 0 == result.exit_code
897+
898+
with path.open(mode='r') as fp:
899+
import dateutil.parser as dp
900+
data_yaml = yaml.safe_load(fp)
901+
902+
assert 'created' in data_yaml
903+
assert 'files' in data_yaml
904+
assert dp.parse(data_yaml['files'][0]['added'])
905+
assert dp.parse(data_yaml['created'])
906+
assert validate_iso8601(data_yaml['created'])
907+
assert validate_iso8601(data_yaml['files'][0]['added'])

0 commit comments

Comments
 (0)