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

ENH: Stop ignoring E721

Not necessary anymore
parent 14aaf6bd
Branches
Tags
1 merge request!22Release 0.3
# -*- mode:conf; -*- # -*- mode:conf; -*-
# generated
src/caosadvancedtools/version.py
# compiled python and dist stuff # compiled python and dist stuff
*.egg *.egg
......
...@@ -109,9 +109,7 @@ style: ...@@ -109,9 +109,7 @@ style:
stage: style stage: style
image: $CI_REGISTRY_IMAGE image: $CI_REGISTRY_IMAGE
script: script:
# For the moment, ignore type comparisons in datamodel_problems.py - autopep8 -ar --diff --exit-code .
- autopep8 -ar --diff --exit-code --exclude ./src/caosadvancedtools/datamodel_problems.py .
- autopep8 -ar --diff --exit-code --ignore E721 ./src/caosadvancedtools/datamodel_problems.py
allow_failure: true allow_failure: true
unittest: unittest:
......
...@@ -40,6 +40,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -40,6 +40,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- instead of `get_entity`, type-specific functions are used in - instead of `get_entity`, type-specific functions are used in
`cfood.py` when the type of the entity in question is known. `cfood.py` when the type of the entity in question is known.
- Logger is used instead of `print` for errors in `crawler.py`. - Logger is used instead of `print` for errors in `crawler.py`.
- complies with new exception handling, i.e., TransactionErros with
children being raised in all cases of EntityErrors (see
[#32](https://gitlab.com/caosdb/caosdb-pylib/-/issues/32) in
caosdb-pylib)
- `caosadvancedtools.cfood.assure_object_is_in_list` conducts in-place - `caosadvancedtools.cfood.assure_object_is_in_list` conducts in-place
updates if no `to_be_updated` object is supplied. updates if no `to_be_updated` object is supplied.
......
...@@ -30,7 +30,8 @@ class in crawler.py and cfood.py can be found in full-tests. ...@@ -30,7 +30,8 @@ class in crawler.py and cfood.py can be found in full-tests.
import caosdb as db import caosdb as db
import pytest import pytest
from caosadvancedtools.datamodel_problems import DataModelProblems from caosadvancedtools.datamodel_problems import DataModelProblems
from caosdb.exceptions import (UnqualifiedParentsError, from caosdb.exceptions import (TransactionError,
UnqualifiedParentsError,
UnqualifiedPropertiesError) UnqualifiedPropertiesError)
...@@ -65,8 +66,9 @@ def test_missing_parent(): ...@@ -65,8 +66,9 @@ def test_missing_parent():
missing_name = "TestType" missing_name = "TestType"
rec = db.Record(name="TestRecord") rec = db.Record(name="TestRecord")
rec.add_parent(name=missing_name) rec.add_parent(name=missing_name)
with pytest.raises(UnqualifiedParentsError): with pytest.raises(TransactionError) as te:
_insert_and_evaluate_exception(rec) _insert_and_evaluate_exception(rec)
assert te.value.has_error(UnqualifiedParentsError)
assert missing_name in DataModelProblems.missing assert missing_name in DataModelProblems.missing
...@@ -74,8 +76,9 @@ def test_missing_property(): ...@@ -74,8 +76,9 @@ def test_missing_property():
"""Test if missing Property is in datamodel problems.""" """Test if missing Property is in datamodel problems."""
missing_name = "TestProp" missing_name = "TestProp"
rec = db.Record(name="TestRecord").add_property(name=missing_name) rec = db.Record(name="TestRecord").add_property(name=missing_name)
with pytest.raises(UnqualifiedPropertiesError): with pytest.raises(TransactionError) as te:
_insert_and_evaluate_exception(rec) _insert_and_evaluate_exception(rec)
assert te.value.has_error(UnqualifiedPropertiesError)
assert missing_name in DataModelProblems.missing assert missing_name in DataModelProblems.missing
...@@ -89,8 +92,9 @@ def test_missing_property_existing_type(): ...@@ -89,8 +92,9 @@ def test_missing_property_existing_type():
db.RecordType(name=existing_rt).insert() db.RecordType(name=existing_rt).insert()
rec = db.Record(name="TestRecord").add_parent(name=existing_rt) rec = db.Record(name="TestRecord").add_parent(name=existing_rt)
rec.add_property(name=missing_prop) rec.add_property(name=missing_prop)
with pytest.raises(UnqualifiedPropertiesError): with pytest.raises(TransactionError) as te:
_insert_and_evaluate_exception(rec) _insert_and_evaluate_exception(rec)
assert te.value.has_error(UnqualifiedPropertiesError)
assert missing_prop in DataModelProblems.missing assert missing_prop in DataModelProblems.missing
assert existing_rt not in DataModelProblems.missing assert existing_rt not in DataModelProblems.missing
...@@ -107,7 +111,8 @@ def test_wrong_property_value(): ...@@ -107,7 +111,8 @@ def test_wrong_property_value():
prop = db.Property(name=prop_name, datatype=prop_dtype).insert() prop = db.Property(name=prop_name, datatype=prop_dtype).insert()
rec = db.Record(name="TestRecord").add_parent( rec = db.Record(name="TestRecord").add_parent(
name=rt_name).add_property(name=prop_name, value="bla") name=rt_name).add_property(name=prop_name, value="bla")
with pytest.raises(UnqualifiedPropertiesError): with pytest.raises(TransactionError) as te:
_insert_and_evaluate_exception(rec) _insert_and_evaluate_exception(rec)
assert te.value.has_error(UnqualifiedPropertiesError)
# Should be empty # Should be empty
assert not DataModelProblems.missing assert not DataModelProblems.missing
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
# #
# Copyright (C) 2018 Research Group Biomedical Physics, # Copyright (C) 2018 Research Group Biomedical Physics,
# Max-Planck-Institute for Dynamics and Self-Organization Göttingen # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
# Copyright (C) 2019,2020 IndiScale GmbH <info@indiscale.com>
# Copyright (C) 2019,2020 Henrik tom Wörden # Copyright (C) 2019,2020 Henrik tom Wörden
# Copyright (C) 2020 Florian Spreckelsen <f.spreckelsen@indiscale.com> # Copyright (C) 2020 Florian Spreckelsen <f.spreckelsen@indiscale.com>
# Copyright (C) 2021 University Medical Center Göttingen, Institute for Medical Informatics # Copyright (C) 2021 University Medical Center Göttingen, Institute for Medical Informatics
...@@ -46,7 +47,8 @@ from abc import ABCMeta, abstractmethod ...@@ -46,7 +47,8 @@ from abc import ABCMeta, abstractmethod
from datetime import datetime from datetime import datetime
import caosdb as db import caosdb as db
from caosdb.exceptions import AmbiguityException, EntityDoesNotExistError from caosdb.exceptions import (BadQueryError, EmptyUniqueQueryError,
QueryNotUniqueError, TransactionError)
from .datamodel_problems import DataModelProblems from .datamodel_problems import DataModelProblems
from .guard import global_guard as guard from .guard import global_guard as guard
...@@ -75,12 +77,12 @@ def get_entity(name): ...@@ -75,12 +77,12 @@ def get_entity(name):
def get_property(name): def get_property(name):
"""Returns the record type with a given name, preferably from a local """Returns the property with a given name, preferably from a local
cache. cache.
If the local cache does not contain the record type, try to If the local cache does not contain the record type, try to
retrieve it from CaosDB. If it does not exist, add it to the data retrieve it from CaosDB. If it does not exist, see whether it
model problems could be a record type used as a property.
""" """
...@@ -89,7 +91,7 @@ def get_property(name): ...@@ -89,7 +91,7 @@ def get_property(name):
prop = db.execute_query("FIND Property with name='{}'".format( prop = db.execute_query("FIND Property with name='{}'".format(
name), name),
unique=True) unique=True)
except (EntityDoesNotExistError, AmbiguityException): except (EmptyUniqueQueryError, QueryNotUniqueError):
# Property might actually be a RecordTypes # Property might actually be a RecordTypes
prop = get_recordtype(name) prop = get_recordtype(name)
PROPERTIES[name] = prop PROPERTIES[name] = prop
...@@ -127,7 +129,7 @@ def get_recordtype(name): ...@@ -127,7 +129,7 @@ def get_recordtype(name):
try: try:
rec = db.execute_query("FIND RecordType WITH name='{}'".format(name), rec = db.execute_query("FIND RecordType WITH name='{}'".format(name),
unique=True) unique=True)
except (EntityDoesNotExistError, AmbiguityException) as e: except (EmptyUniqueQueryError, QueryNotUniqueError) as e:
DataModelProblems.add(name) DataModelProblems.add(name)
raise e raise e
RECORDTYPES[name] = rec RECORDTYPES[name] = rec
...@@ -266,7 +268,7 @@ def get_entity_for_path(path): ...@@ -266,7 +268,7 @@ def get_entity_for_path(path):
FILES[path] = db.execute_query(q, unique=True) FILES[path] = db.execute_query(q, unique=True)
return FILES[path] return FILES[path]
except EntityDoesNotExistError: except BadQueryError:
path_prefix = "**" path_prefix = "**"
if not path.startswith("/"): if not path.startswith("/"):
......
...@@ -82,7 +82,7 @@ class Importer(object): ...@@ -82,7 +82,7 @@ class Importer(object):
p = db.Property(name=element['title'], unit=element['unit'], datatype=db.DOUBLE) p = db.Property(name=element['title'], unit=element['unit'], datatype=db.DOUBLE)
try: try:
p.insert() p.insert()
except db.exceptions.EntityError as e: except db.exceptions.TransactionError as e:
print(e) print(e)
return return
......
...@@ -48,7 +48,7 @@ from datetime import datetime ...@@ -48,7 +48,7 @@ from datetime import datetime
from sqlite3 import IntegrityError from sqlite3 import IntegrityError
import caosdb as db import caosdb as db
from caosdb.exceptions import TransactionError from caosdb.exceptions import BadQueryError
from .cache import Cache, UpdateCache, get_pretty_xml from .cache import Cache, UpdateCache, get_pretty_xml
from .cfood import RowCFood, add_files, get_ids_for_entities_with_names from .cfood import RowCFood, add_files, get_ids_for_entities_with_names
...@@ -653,7 +653,8 @@ carefully and if the changes are ok, click on the following link: ...@@ -653,7 +653,8 @@ carefully and if the changes are ok, click on the following link:
# is using the unique keyword # is using the unique keyword
try: try:
r = q.execute(unique=True) r = q.execute(unique=True)
except TransactionError: except BadQueryError:
# either empty or ambiguous response
r = None r = None
# if r is not None: # if r is not None:
......
...@@ -28,6 +28,7 @@ or updating entities with missing parents and/or properties. ...@@ -28,6 +28,7 @@ or updating entities with missing parents and/or properties.
""" """
from caosdb.exceptions import (EntityDoesNotExistError, from caosdb.exceptions import (EntityDoesNotExistError,
TransactionError,
UnqualifiedParentsError, UnqualifiedParentsError,
UnqualifiedPropertiesError) UnqualifiedPropertiesError)
...@@ -42,48 +43,51 @@ class DataModelProblems(object): ...@@ -42,48 +43,51 @@ class DataModelProblems(object):
DataModelProblems.missing.add(ent) DataModelProblems.missing.add(ent)
@staticmethod @staticmethod
def evaluate_exception(e): def _evaluate_unqualified(e):
"""Take an exception, see whether it was caused by datamodel problems, """Evaluate all UnqualifiedParentsErrors and
and update missing parents and/or properties if this was the UnqualifiedPropertiesErrors and check for possible datamodel
case. Otherwise, raise the exception. problems.
""" """
# type(e) == type(Exception()) seems to be necessary because # UnqualifiedParentsErrors are always possible problems:
# of EntityMultiErrors that are instances of (all? some of?) if isinstance(e, UnqualifiedParentsError):
# theirchild errors. So isinstance doesn't show the desired for err in e.errors:
# behavior. DataModelProblems.add(err.entity.name)
elif isinstance(e, UnqualifiedPropertiesError):
# Only those UnqualifiedPropertiesErrors that were caused
# by (at least) an EntityDoesNotExistError are possible
# datamodel problems
for err in e.errors:
if isinstance(err, EntityDoesNotExistError):
DataModelProblems.add(err.entity.name)
# If there is at least one UnqualifiedParentsError or at least
# one UnqualifiedPropertiesError on some level below, go
# through the children.
elif (e.has_error(UnqualifiedParentsError) or
e.has_error(UnqualifiedPropertiesError)):
for err in e.errors:
DataModelProblems._evaluate_unqualified(err)
@staticmethod
def evaluate_exception(e):
"""Take a TransactionError, see whether it was caused by datamodel
problems, and update missing parents and/or properties if this
was the case. Afterwards, raise the exception.
if type(e) == type(UnqualifiedPropertiesError()): Parameters
for err in e.get_errors(): ----------
# Here, it doesn't matter if there is an actual e : TransactionError
# EntityDoesNotExistError or a MultiEntityError TransactionError, the children of which are checked for
# including an EntityDoesNotExistError. The latter possible datamodel problems.
# case happens when a wrong entity with a value is
# given since then, an EntityHasNoDatatypeError is
# raised as well. Still, the problem is the missing
# property, so this is okay.
if isinstance(err, EntityDoesNotExistError): """
property_missing = True if not isinstance(e, TransactionError):
DataModelProblems.add(err.get_entity().name) raise ValueError(
raise e "Only TransactionErrors can be checked for datamodel problems")
elif type(e) == type(UnqualifiedParentsError()):
# This is always caused by missing/wrong parents if (e.has_error(UnqualifiedParentsError) or
e.has_error(UnqualifiedPropertiesError)):
for err in e.errors:
DataModelProblems._evaluate_unqualified(err)
for err in e.get_errors(): raise e
DataModelProblems.add(err.get_entity().name)
raise e
# This is the ugly workaround for a MultiEntityError that
# stems from a UnqualifiedParentsError: an
# EntityDoesNotExistError is raised AND the causing entity has
# type PARENT.
elif ((type(e) == type(EntityDoesNotExistError())) and
((str(type(e.get_entity()).__name__).upper() == "PARENT"))):
DataModelProblems.add(e.get_entity().name)
raise e
# Evaluate children of real MultiEntityErrors:
elif hasattr(e, "errors") and len(e.get_errors()) > 0:
for err in e.get_errors():
DataModelProblems.evaluate_exception(err)
else:
raise e
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment