Skip to content
Snippets Groups Projects
Commit e42b3155 authored by Henrik tom Wörden's avatar Henrik tom Wörden
Browse files

Merge branch 'release-0.6.1' into 'main'

RELEASE: 0.6.1

See merge request !36
parents 62d875c6 641b7d2e
Branches
Tags
1 merge request!36RELEASE: 0.6.1
Pipeline #16942 passed
...@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. ...@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.6.1] - 2021-12-03 ##
### Fixed ###
- #50 keyring can be used as password input method again
* #81 compare_entities from apiutils does not compare entity values
## [0.6.0] - 2021-10-19 ## ## [0.6.0] - 2021-10-19 ##
### Added ### ### Added ###
......
...@@ -47,7 +47,7 @@ from setuptools import find_packages, setup ...@@ -47,7 +47,7 @@ from setuptools import find_packages, setup
MAJOR = 0 MAJOR = 0
MINOR = 6 MINOR = 6
MICRO = 0 MICRO = 1
PRE = "" # e.g. rc0, alpha.1, 0.beta-23 PRE = "" # e.g. rc0, alpha.1, 0.beta-23
ISRELEASED = True ISRELEASED = True
......
...@@ -30,15 +30,15 @@ Some simplified functions for generation of records etc. ...@@ -30,15 +30,15 @@ Some simplified functions for generation of records etc.
import sys import sys
import tempfile import tempfile
from collections.abc import Iterable
import warnings import warnings
from collections.abc import Iterable
from subprocess import call from subprocess import call
from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER, from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER,
REFERENCE, TEXT, is_reference) REFERENCE, TEXT, is_reference)
from caosdb.common.models import (Container, Entity, File, Property, Query, from caosdb.common.models import (Container, Entity, File, Property, Query,
Record, RecordType, get_config, Record, RecordType, execute_query,
execute_query) get_config)
def new_record(record_type, name=None, description=None, def new_record(record_type, name=None, description=None,
...@@ -561,7 +561,23 @@ def getCommitIn(folder): ...@@ -561,7 +561,23 @@ def getCommitIn(folder):
COMPARED = ["name", "role", "datatype", "description", "importance"] COMPARED = ["name", "role", "datatype", "description", "importance"]
def compare_entities(old_entity, new_entity): def compare_entities(old_entity: Entity, new_entity: Entity):
"""
Compare two entites.
Return a tuple of dictionaries, the first index belongs to additional information for old
entity, the second index belongs to additional information for new entity.
Additional information means in detail:
- Additional parents (a list under key "parents")
- Information about properties:
- Each property lists either an additional property or a property with a changed:
- ... datatype
- ... importance or
- ... value (not implemented yet)
In case of changed information the value listed under the respective key shows the
value that is stored in the respective entity.
"""
olddiff = {"properties": {}, "parents": []} olddiff = {"properties": {}, "parents": []}
newdiff = {"properties": {}, "parents": []} newdiff = {"properties": {}, "parents": []}
...@@ -616,13 +632,16 @@ def compare_entities(old_entity, new_entity): ...@@ -616,13 +632,16 @@ def compare_entities(old_entity, new_entity):
newdiff["properties"][prop.name]["importance"] = \ newdiff["properties"][prop.name]["importance"] = \
new_entity.get_importance(prop.name) new_entity.get_importance(prop.name)
if ((prop.datatype is not None and if (prop.datatype != matching[0].datatype):
matching[0].datatype is not None) and
(prop.datatype != matching[0].datatype)):
olddiff["properties"][prop.name]["datatype"] = prop.datatype olddiff["properties"][prop.name]["datatype"] = prop.datatype
newdiff["properties"][prop.name]["datatype"] = \ newdiff["properties"][prop.name]["datatype"] = \
matching[0].datatype matching[0].datatype
if (prop.value != matching[0].value):
olddiff["properties"][prop.name]["value"] = prop.value
newdiff["properties"][prop.name]["value"] = \
matching[0].value
if (len(newdiff["properties"][prop.name]) == 0 if (len(newdiff["properties"][prop.name]) == 0
and len(olddiff["properties"][prop.name]) == 0): and len(olddiff["properties"][prop.name]) == 0):
newdiff["properties"].pop(prop.name) newdiff["properties"].pop(prop.name)
...@@ -700,6 +719,7 @@ def apply_to_ids(entities, func): ...@@ -700,6 +719,7 @@ def apply_to_ids(entities, func):
entities : list of Entity entities : list of Entity
func : function with one parameter. func : function with one parameter.
""" """
for entity in entities: for entity in entities:
_apply_to_ids_of_entity(entity, func) _apply_to_ids_of_entity(entity, func)
......
...@@ -28,7 +28,7 @@ retrieve the password. ...@@ -28,7 +28,7 @@ retrieve the password.
""" """
import sys import sys
import imp import importlib
from getpass import getpass from getpass import getpass
from caosdb.exceptions import ConfigurationError from caosdb.exceptions import ConfigurationError
from .external_credentials_provider import ExternalCredentialsProvider from .external_credentials_provider import ExternalCredentialsProvider
...@@ -52,17 +52,13 @@ def get_authentication_provider(): ...@@ -52,17 +52,13 @@ def get_authentication_provider():
def _get_external_keyring(): def _get_external_keyring():
try: try:
fil, pathname, desc = imp.find_module("keyring", sys.path[1:]) return importlib.import_module("keyring")
module = imp.load_module("external_keyring", fil, pathname, desc)
return module
except ImportError: except ImportError:
raise RuntimeError( raise RuntimeError(
"The keyring password method requires installation of the" "The keyring password method requires installation of the"
"keyring python package. On linux with python < 3.5, " "keyring python package. On linux with python < 3.5, "
"this requires the installation of dbus-python as a " "this requires the installation of dbus-python as a "
"system package.") "system package.")
finally:
fil.close()
def _call_keyring(**config): def _call_keyring(**config):
...@@ -74,7 +70,6 @@ def _call_keyring(**config): ...@@ -74,7 +70,6 @@ def _call_keyring(**config):
url = config.get("url") url = config.get("url")
username = config.get("username") username = config.get("username")
app = "caosdb — {}".format(url) app = "caosdb — {}".format(url)
password = _call_keyring(app=app, username=username)
external_keyring = _get_external_keyring() external_keyring = _get_external_keyring()
password = external_keyring.get_password(app, username) password = external_keyring.get_password(app, username)
if password is None: if password is None:
......
...@@ -98,7 +98,7 @@ def yaml_to_xml(yamlstr): ...@@ -98,7 +98,7 @@ def yaml_to_xml(yamlstr):
The string to load the yaml document from. The string to load the yaml document from.
""" """
return dict_to_xml(yaml.safe_load(yamlstr)) return dict_to_xml(yaml.load(yamlstr, Loader=yaml.SafeLoader))
def process(text): def process(text):
......
...@@ -26,11 +26,14 @@ ...@@ -26,11 +26,14 @@
# Test apiutils # Test apiutils
# A. Schlemmer, 02/2018 # A. Schlemmer, 02/2018
import caosdb as db
import pickle import pickle
import tempfile import tempfile
from caosdb.apiutils import apply_to_ids, create_id_query, resolve_reference
import caosdb as db
import caosdb.apiutils import caosdb.apiutils
from caosdb.apiutils import (apply_to_ids, compare_entities, create_id_query,
resolve_reference)
from .test_property import testrecord from .test_property import testrecord
...@@ -67,7 +70,8 @@ def test_apply_to_ids(): ...@@ -67,7 +70,8 @@ def test_apply_to_ids():
def test_id_query(): def test_id_query():
ids = [1, 2, 3, 4, 5] ids = [1, 2, 3, 4, 5]
assert create_id_query(ids) == 'FIND ENTITY WITH ID=1 OR ID=2 OR ID=3 OR ID=4 OR ID=5' assert create_id_query(ids) == 'FIND ENTITY WITH ID=1 OR ID=2 OR ID=3 OR '\
'ID=4 OR ID=5'
def test_resolve_reference(): def test_resolve_reference():
...@@ -77,8 +81,10 @@ def test_resolve_reference(): ...@@ -77,8 +81,10 @@ def test_resolve_reference():
prop = db.Property(id=1, datatype=db.REFERENCE, value=100) prop = db.Property(id=1, datatype=db.REFERENCE, value=100)
prop.is_valid = lambda: True prop.is_valid = lambda: True
items = [200, 300, 400] items = [200, 300, 400]
prop_list = db.Property(datatype=db.LIST(db.REFERENCE), value=items) prop_list = db.Property(datatype=db.LIST(db.REFERENCE),
prop_list2 = db.Property(datatype=db.LIST(db.REFERENCE), value=[db.Record(id=500)]) value=items)
prop_list2 = db.Property(datatype=db.LIST(db.REFERENCE),
value=[db.Record(id=500)])
resolve_reference(prop) resolve_reference(prop)
resolve_reference(prop_list) resolve_reference(prop_list)
resolve_reference(prop_list2) resolve_reference(prop_list2)
...@@ -86,6 +92,7 @@ def test_resolve_reference(): ...@@ -86,6 +92,7 @@ def test_resolve_reference():
assert isinstance(prop.value, db.Entity) assert isinstance(prop.value, db.Entity)
prop_list_ids = [] prop_list_ids = []
for i in prop_list.value: for i in prop_list.value:
prop_list_ids.append(i.id) prop_list_ids.append(i.id)
assert isinstance(i, db.Entity) assert isinstance(i, db.Entity)
...@@ -102,3 +109,38 @@ def test_resolve_reference(): ...@@ -102,3 +109,38 @@ def test_resolve_reference():
# restore retrive_entity_with_id # restore retrive_entity_with_id
caosdb.apiutils.retrieve_entity_with_id = original_retrieve_entity_with_id caosdb.apiutils.retrieve_entity_with_id = original_retrieve_entity_with_id
def test_compare_entities():
r1 = db.Record()
r2 = db.Record()
r1.add_parent("bla")
r2.add_parent("bla")
r1.add_parent("lopp")
r1.add_property("test", value=2)
r2.add_property("test", value=2)
r1.add_property("tests", value=3)
r2.add_property("tests", value=45)
r1.add_property("tester", value=3)
r2.add_property("tester", )
r1.add_property("tests_234234", value=45)
r2.add_property("tests_TT", value=45)
diff_r1, diff_r2 = compare_entities(r1, r2)
assert len(diff_r1["parents"]) == 1
assert len(diff_r2["parents"]) == 0
assert len(diff_r1["properties"]) == 3
assert len(diff_r2["properties"]) == 3
assert "test" not in diff_r1["properties"]
assert "test" not in diff_r2["properties"]
assert "tests" in diff_r1["properties"]
assert "tests" in diff_r2["properties"]
assert "tester" in diff_r1["properties"]
assert "tester" in diff_r2["properties"]
assert "tests_234234" in diff_r1["properties"]
assert "tests_TT" in diff_r2["properties"]
...@@ -24,15 +24,18 @@ ...@@ -24,15 +24,18 @@
# ** end header # ** end header
# #
"""Tests for the Property class.""" """Tests for the Property class."""
import os
import caosdb as db import caosdb as db
from caosdb import Entity, Property, Record from caosdb import Entity, Property, Record
# pylint: disable=missing-docstring # pylint: disable=missing-docstring
from lxml import etree from lxml import etree
parser = etree.XMLParser(remove_comments=True) parser = etree.XMLParser(remove_comments=True)
testrecord = Record._from_xml(Record(), testrecord = Record._from_xml(
etree.parse("unittests/test_record.xml", Record(),
parser).getroot()) etree.parse(os.path.join(os.path.dirname(__file__), "test_record.xml"),
parser).getroot())
def test_is_entity(): def test_is_entity():
...@@ -48,7 +51,8 @@ def test_instance_variables(): ...@@ -48,7 +51,8 @@ def test_instance_variables():
def test_null_empty_text_value_1(): def test_null_empty_text_value_1():
assert testrecord.get_property("LISTofTEXT").value == ["One", "Two", "Three", None, ""] assert testrecord.get_property("LISTofTEXT").value == ["One", "Two",
"Three", None, ""]
def test_null_empty_text_value_2(): def test_null_empty_text_value_2():
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment