Skip to content
Snippets Groups Projects
Commit ab1703a1 authored by Florian Spreckelsen's avatar Florian Spreckelsen
Browse files

Merge branch 'dev' into f-tsv-importer

parents e0fda37d 2658d443
No related branches found
No related tags found
1 merge request!22Release 0.3
Pipeline #14728 failed
...@@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Introduce a cfood that can create a Record structure based on the contents of a hdf5 file - Introduce a cfood that can create a Record structure based on the contents of a hdf5 file
h5py is now an optional dependency h5py is now an optional dependency
- table importer implementations for csv and tsv - table importer implementations for csv and tsv
- string-in-list check for table imports
### Changed ### ### Changed ###
......
...@@ -9,6 +9,7 @@ Experiment: ...@@ -9,6 +9,7 @@ Experiment:
# TODO empty recommended_properties is a problem # TODO empty recommended_properties is a problem
#recommended_properties: #recommended_properties:
responsible: responsible:
datatype: LIST<Person>
Project: Project:
SoftwareVersion: SoftwareVersion:
recommended_properties: recommended_properties:
...@@ -30,8 +31,6 @@ Person: ...@@ -30,8 +31,6 @@ Person:
email: email:
datatype: TEXT datatype: TEXT
description: 'Email of a Person.' description: 'Email of a Person.'
responsible:
datatype: REFERENCE
revisionOf: revisionOf:
datatype: REFERENCE datatype: REFERENCE
results: results:
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# Copyright (C) 2020 Daniel Hornung <d.hornung@indiscale.com> # Copyright (C) 2020 Daniel Hornung <d.hornung@indiscale.com>
# Copyright (C) 2021 Henrik tom Wörden <h.tomwoerden@indiscale.com> # Copyright (C) 2021 Henrik tom Wörden <h.tomwoerden@indiscale.com>
# Copyright (C) 2021 Alexander Kreft # Copyright (C) 2021 Alexander Kreft
# Copyright (C) 2021 Laboratory for Fluid Physics and Biocomplexity, # Copyright (C) 2021 Laboratory for Fluid Physics and Biocomplexity,
# Max-Planck-Insitute für Dynamik und Selbstorganisation <www.lfpn.ds.mpg.de> # Max-Planck-Insitute für Dynamik und Selbstorganisation <www.lfpn.ds.mpg.de>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
......
...@@ -252,9 +252,8 @@ class Parser(object): ...@@ -252,9 +252,8 @@ class Parser(object):
# is it a property # is it a property
and "datatype" in definition and "datatype" in definition
# but not simply an RT of the model # but not simply an RT of the model
and not (definition["datatype"] in self.model and not (_get_listdatatype(definition["datatype"]) == name and
or _get_listdatatype( _get_listdatatype(definition["datatype"]) in self.model)):
definition["datatype"]) in self.model)):
# and create the new property # and create the new property
self.model[name] = db.Property(name=name, self.model[name] = db.Property(name=name,
......
...@@ -88,7 +88,10 @@ def date_converter(val, fmt="%Y-%m-%d"): ...@@ -88,7 +88,10 @@ def date_converter(val, fmt="%Y-%m-%d"):
converts it using format string converts it using format string
""" """
return datetime_converter(val, fmt=fmt).date() if val is None:
return None
else:
return datetime_converter(val, fmt=fmt).date()
def incomplete_date_converter(val, fmts={"%Y-%m-%d": "%Y-%m-%d", def incomplete_date_converter(val, fmts={"%Y-%m-%d": "%Y-%m-%d",
...@@ -145,6 +148,43 @@ def win_path_converter(val): ...@@ -145,6 +148,43 @@ def win_path_converter(val):
return path.as_posix() return path.as_posix()
def string_in_list(val, options, ignore_case=True):
"""Return the given value if it is contained in options, raise an
error otherwise.
Parameters
----------
val : str
String value to be checked.
options : list<str>
List of possible values that val may obtain
ignore_case : bool, optional
Specify whether the comparison of val and the possible options
should ignor capitalization. Default is True.
Returns
-------
val : str
The original value if it is contained in options
Raises
------
ValueError
If val is not contained in options.
"""
if ignore_case:
val = val.lower()
options = [o.lower() for o in options]
if val not in options:
raise ValueError(
"Field value is '{}', but it should be one of the following "
"values: {}.".format(val, ", ".join(
["'{}'".format(o) for o in options])))
return val
class TableImporter(object): class TableImporter(object):
def __init__(self, converters, obligatory_columns=None, unique_keys=None): def __init__(self, converters, obligatory_columns=None, unique_keys=None):
""" """
......
...@@ -274,6 +274,22 @@ A: ...@@ -274,6 +274,22 @@ A:
parse_model_from_string(yaml) parse_model_from_string(yaml)
self.assertIn("line 3", yde.exception.args[0]) self.assertIn("line 3", yde.exception.args[0])
def test_reference_property(self):
"""Test correct creation of reference property using an RT."""
modeldef = """A:
recommended_properties:
ref:
datatype: LIST<A>
"""
model = parse_model_from_string(modeldef)
self.assertEqual(len(model), 2)
for key in model.keys():
if key == "A":
self.assertTrue(isinstance(model[key], db.RecordType))
elif key == "ref":
self.assertTrue(isinstance(model[key], db.Property))
self.assertEqual(model[key].datatype, "LIST<A>")
class ExternTest(unittest.TestCase): class ExternTest(unittest.TestCase):
"""TODO Testing the "extern" keyword in the YAML.""" """TODO Testing the "extern" keyword in the YAML."""
......
...@@ -36,6 +36,7 @@ from caosadvancedtools.table_importer import (XLSImporter, assure_name_format, ...@@ -36,6 +36,7 @@ from caosadvancedtools.table_importer import (XLSImporter, assure_name_format,
incomplete_date_converter, incomplete_date_converter,
win_path_converter, win_path_converter,
win_path_list_converter, win_path_list_converter,
string_in_list,
yes_no_converter) yes_no_converter)
...@@ -52,6 +53,16 @@ class ConverterTest(unittest.TestCase): ...@@ -52,6 +53,16 @@ class ConverterTest(unittest.TestCase):
self.assertRaises(ValueError, yes_no_converter, "True") self.assertRaises(ValueError, yes_no_converter, "True")
self.assertRaises(ValueError, yes_no_converter, "true") self.assertRaises(ValueError, yes_no_converter, "true")
def test_string_in_list(self):
self.assertEqual("false", string_in_list("false",
["FALSE", "TRUE"]))
self.assertEqual("FALSE", string_in_list("FALSE",
["FALSE", "TRUE"], False))
self.assertRaises(ValueError, string_in_list, "FALSE", [])
self.assertRaises(ValueError, string_in_list, "FALSE", ["fals"])
self.assertRaises(ValueError, string_in_list,
"FALSE", ["false"], False)
def test_assure_name_format(self): def test_assure_name_format(self):
self.assertEqual(assure_name_format("Müstermann, Max"), self.assertEqual(assure_name_format("Müstermann, Max"),
"Müstermann, Max") "Müstermann, Max")
...@@ -65,7 +76,7 @@ class ConverterTest(unittest.TestCase): ...@@ -65,7 +76,7 @@ class ConverterTest(unittest.TestCase):
["/this/computer"]) ["/this/computer"])
self.assertEqual(win_path_list_converter( self.assertEqual(win_path_list_converter(
r"\this\computer,\this\computer"), r"\this\computer,\this\computer"),
["/this/computer", "/this/computer"]) ["/this/computer", "/this/computer"])
@pytest.mark.xfail(reason="To be fixed, see Issue #34") @pytest.mark.xfail(reason="To be fixed, see Issue #34")
def test_datetime(self): def test_datetime(self):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment