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

Merge branch 'dev' into f-json-schema-datamodel

parents a323f4c0 412fb71c
Branches
Tags
2 merge requests!39Release 0.4.0,!33F json schema datamodel
Pipeline #21053 failed
...@@ -27,6 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -27,6 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### ### Fixed ###
- CaosDB internal properties `name`, `unit` and `description` can now be used via the `extern`
keyword in YAML datamodel specifications.
### Security ### ### Security ###
## [0.3.1] - 2021-12-06 ## ## [0.3.1] - 2021-12-06 ##
......
...@@ -57,10 +57,11 @@ then ...@@ -57,10 +57,11 @@ then
exit 1 exit 1
fi fi
set -e set -e
echo "undo changes" echo "Undoing previous changes to extroot content..."
cd extroot cd extroot
egrep -liRZ 'A description of this example' . | xargs -0 -l sed -i -e 's/A description of this example/A description of another example/g' egrep -liRZ 'A description of this example' . | xargs -0 -l sed -i -e 's/A description of this example/A description of another example/g'
cd .. cd ..
echo "Done."
python3 test_table.py python3 test_table.py
# TODO the following test deletes lots of the data inserted by the crawler # TODO the following test deletes lots of the data inserted by the crawler
echo "Testing im and export" echo "Testing im and export"
...@@ -85,5 +86,8 @@ python3 -m pytest test_base_table_exporter_integration.py ...@@ -85,5 +86,8 @@ python3 -m pytest test_base_table_exporter_integration.py
echo "Testing json-schema datamodel parser" echo "Testing json-schema datamodel parser"
python3 -m pytest test_json_schema_datamodel_parser.py python3 -m pytest test_json_schema_datamodel_parser.py
echo "Testing yaml datamodel parser"
python3 -m pytest test_yaml_parser.py
# Obsolete due to teardown in the above test. # Obsolete due to teardown in the above test.
# echo "/n/n/n YOU NEED TO RESTART THE SERVER TO REDO TESTS!!!" # echo "/n/n/n YOU NEED TO RESTART THE SERVER TO REDO TESTS!!!"
# encoding: utf-8
#
# This file is a part of the CaosDB Project.
#
# Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
# Copyright (C) 2022 Florian Spreckelsen <f.spreckelsen@indiscale.com>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
import caosdb as db
from caosadvancedtools.models.parser import parse_model_from_string
def _delete_everything():
ents = db.execute_query("FIND ENTITY WITH ID > 99")
if ents:
ents.delete()
def setup_module():
_delete_everything()
def teardown_module():
_delete_everything()
def test_internal_props_in_extern():
"""Test adding the internal `name` property as a parent to an existing
property.
"""
model = """
extern:
- name
- test_name
- description
- unit
test_name:
inherit_from_suggested:
- name
- description
- unit
"""
db.Property(name="test_name", datatype=db.TEXT).insert()
ents = parse_model_from_string(model)
ents.sync_data_model(noquestion=True)
test_prop = db.Property(name="test_name").retrieve()
assert len(test_prop.parents) == 3
desc_prop = db.Property(name="description").retrieve()
name_prop = db.Property(name="name").retrieve()
unit_prop = db.Property(name="unit").retrieve()
assert test_prop.has_parent(desc_prop)
assert test_prop.has_parent(name_prop)
assert test_prop.has_parent(unit_prop)
...@@ -33,6 +33,13 @@ import caosdb as db ...@@ -33,6 +33,13 @@ import caosdb as db
from caosdb.apiutils import compare_entities, describe_diff from caosdb.apiutils import compare_entities, describe_diff
CAOSDB_INTERNAL_PROPERTIES = [
"description",
"name",
"unit",
]
class DataModel(dict): class DataModel(dict):
"""Provides tools for managing a data model. """Provides tools for managing a data model.
...@@ -129,8 +136,13 @@ class DataModel(dict): ...@@ -129,8 +136,13 @@ class DataModel(dict):
any_change = False any_change = False
for ent in existing_entities: for ent in existing_entities:
q = db.Query("FIND * with id={}".format(ent.id)) if ent.name in CAOSDB_INTERNAL_PROPERTIES:
ref = q.execute(unique=True) # Workaround for the usage of internal properties like name
# in via the extern keyword:
ref = db.Property(name=ent.name).retrieve()
else:
query = db.Query(f"FIND * with id={ent.id}")
ref = query.execute(unique=True)
diff = (describe_diff(*compare_entities(ent, ref diff = (describe_diff(*compare_entities(ent, ref
), name=ent.name)) ), name=ent.name))
......
...@@ -45,7 +45,7 @@ from typing import List ...@@ -45,7 +45,7 @@ from typing import List
import jsonschema import jsonschema
import caosdb as db import caosdb as db
from .data_model import DataModel from .data_model import CAOSDB_INTERNAL_PROPERTIES, DataModel
# Keywords which are allowed in data model descriptions. # Keywords which are allowed in data model descriptions.
KEYWORDS = ["parent", # deprecated, use inherit_from_* instead: KEYWORDS = ["parent", # deprecated, use inherit_from_* instead:
...@@ -234,6 +234,9 @@ class Parser(object): ...@@ -234,6 +234,9 @@ class Parser(object):
ymlmodel["extern"] = [] ymlmodel["extern"] = []
for name in ymlmodel["extern"]: for name in ymlmodel["extern"]:
if name in CAOSDB_INTERNAL_PROPERTIES:
self.model[name] = db.Property(name=name).retrieve()
continue
for role in ("Property", "RecordType", "Record", "File"): for role in ("Property", "RecordType", "Record", "File"):
if db.execute_query("COUNT {} {}".format(role, name)) > 0: if db.execute_query("COUNT {} {}".format(role, name)) > 0:
self.model[name] = db.execute_query( self.model[name] = db.execute_query(
......
...@@ -50,7 +50,7 @@ This example defines 3 ``RecordType``s: ...@@ -50,7 +50,7 @@ This example defines 3 ``RecordType``s:
- A Person with a ``firstName`` and a ``lastName`` (as recommended properties) - A Person with a ``firstName`` and a ``lastName`` (as recommended properties)
- A ``LabbookEntry`` with multiple recommended properties of different data types - A ``LabbookEntry`` with multiple recommended properties of different data types
- It is assumed that the server knows a RecordType or Property with the name - It is assumed that the server knows a RecordType or Property with the name
"Textfile". ``Textfile``.
One major advantage of using this interface (in contrast to the standard python interface) is that properties can be defined and added to record types "on-the-fly". E.g. the three lines for ``firstName`` as sub entries of ``Person`` have two effects on CaosDB: One major advantage of using this interface (in contrast to the standard python interface) is that properties can be defined and added to record types "on-the-fly". E.g. the three lines for ``firstName`` as sub entries of ``Person`` have two effects on CaosDB:
...@@ -66,7 +66,8 @@ Note the difference between the three property declarations of ``LabbookEntry``: ...@@ -66,7 +66,8 @@ Note the difference between the three property declarations of ``LabbookEntry``:
- ``responsible``: This defines and adds a property with name "responsible" to ``LabbookEntry`, which has a datatype ``Person``. ``Person`` is defined above. - ``responsible``: This defines and adds a property with name "responsible" to ``LabbookEntry`, which has a datatype ``Person``. ``Person`` is defined above.
- ``firstName``: This defines and adds a property with the standard data type ``TEXT`` to record type ``Person``. - ``firstName``: This defines and adds a property with the standard data type ``TEXT`` to record type ``Person``.
If the data model depends on already existing parts, those can be added using the ``extern`` keyword. If the data model depends on record types or properties which already exist in CaosDB, those can be
added using the ``extern`` keyword: ``extern`` takes a list of previously defined names.
Datatypes Datatypes
--------- ---------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment