Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
C
caosdb-pylib
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
caosdb
Software
caosdb-pylib
Commits
cc0221ac
Commit
cc0221ac
authored
3 months ago
by
Florian Spreckelsen
Browse files
Options
Downloads
Plain Diff
Merge branch 'dev' into f-bug-fit-96-print-recursion
parents
8778db51
4ba40593
No related branches found
Branches containing commit
No related tags found
Tags containing commit
2 merge requests
!175
BUG: Request responses without the "Set-Cookie" header no longer overwrite the...
,
!166
Detect infinite recursion in Entity.to_xml
Pipeline
#58675
passed
3 months ago
Stage: code_style
Stage: linting
Stage: test
Stage: deploy
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
CHANGELOG.md
+2
-0
2 additions, 0 deletions
CHANGELOG.md
src/linkahead/apiutils.py
+29
-15
29 additions, 15 deletions
src/linkahead/apiutils.py
unittests/test_apiutils.py
+28
-0
28 additions, 0 deletions
unittests/test_apiutils.py
with
59 additions
and
15 deletions
CHANGELOG.md
+
2
−
0
View file @
cc0221ac
...
...
@@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
*
[
#103
](
https://gitlab.com/linkahead/linkahead-pylib/-/issues/103
)
`authentication/interface/on_response()`
does not overwrite
`auth_token`
if new value is
`None`
*
[
#119
](
https://gitlab.com/linkahead/linkahead-pylib/-/issues/119
)
The diff returned by compare_entities now uses id instead of name as key if either property does not have a name
### Security ###
...
...
This diff is collapsed.
Click to expand it.
src/linkahead/apiutils.py
+
29
−
15
View file @
cc0221ac
...
...
@@ -197,13 +197,19 @@ def compare_entities(entity0: Optional[Entity] = None,
properties and SPECIAL_ATTRIBUTES if they are missing or different from
their counterparts in the other entity.
The key used to represent a parent in the parent list or a
property in the property dictionary is the entity
'
s name if the
name is present for both compared entities, the id otherwise.
The value of the properties dict for each listed property is again a dict
detailing the differences between this property and its counterpart.
The characteristics that are checked to determine whether two properties
match are the following:
- datatype
- importance
- value
- datatype
- importance
- value
If any of these characteristics differ for a property, the respective
string (datatype, importance, value) is added as a key to the dict of the
property with its value being the characteristics value,
...
...
@@ -224,9 +230,9 @@ def compare_entities(entity0: Optional[Entity] = None,
Params
------
entity0
:
Entity
entity0
:
Entity
First entity to be compared.
entity1
:
Entity
entity1
:
Entity
Second entity to be compared.
compare_referenced_records: bool, default: False
If set to True, values with referenced records
...
...
@@ -242,6 +248,7 @@ def compare_entities(entity0: Optional[Entity] = None,
entity and an int or str also checks whether
the int/str matches the name or id of the
entity, so Entity(id=100) == 100 ==
"
100
"
.
"""
# ToDo: Discuss intended behaviour
# Questions that need clarification:
...
...
@@ -377,15 +384,20 @@ def compare_entities(entity0: Optional[Entity] = None,
# compare properties
for
prop
in
entity0
.
properties
:
matching
=
entity1
.
properties
.
filter
(
name
=
prop
.
name
,
pid
=
prop
.
id
)
# ToDo: Would making id default break anything?
key
=
prop
.
name
if
prop
.
name
is
not
None
else
prop
.
id
matching
=
entity1
.
properties
.
filter
(
prop
)
if
len
(
matching
)
==
0
:
# entity1 has prop, entity0 does not
diff
[
0
][
"
properties
"
][
prop
.
name
]
=
{}
diff
[
0
][
"
properties
"
][
key
]
=
{}
elif
len
(
matching
)
==
1
:
diff
[
0
][
"
properties
"
][
prop
.
name
]
=
{}
diff
[
1
][
"
properties
"
][
prop
.
name
]
=
{}
propdiff
=
(
diff
[
0
][
"
properties
"
][
prop
.
name
],
diff
[
1
][
"
properties
"
][
prop
.
name
])
# It's possible that prop has name and id, but match only has id
key
=
prop
.
name
if
(
prop
.
name
is
not
None
and
matching
[
0
].
name
==
prop
.
name
)
else
prop
.
id
diff
[
0
][
"
properties
"
][
key
]
=
{}
diff
[
1
][
"
properties
"
][
key
]
=
{}
propdiff
=
(
diff
[
0
][
"
properties
"
][
key
],
diff
[
1
][
"
properties
"
][
key
])
# We should compare the wrapped properties instead of the
# wrapping entities if possible:
...
...
@@ -417,8 +429,8 @@ def compare_entities(entity0: Optional[Entity] = None,
# in case there is no difference, we remove the dict keys again
if
len
(
propdiff
[
0
])
==
0
and
len
(
propdiff
[
1
])
==
0
:
diff
[
0
][
"
properties
"
].
pop
(
prop
.
name
)
diff
[
1
][
"
properties
"
].
pop
(
prop
.
name
)
diff
[
0
][
"
properties
"
].
pop
(
key
)
diff
[
1
][
"
properties
"
].
pop
(
key
)
else
:
raise
NotImplementedError
(
...
...
@@ -426,11 +438,12 @@ def compare_entities(entity0: Optional[Entity] = None,
# we have not yet compared properties that do not exist in entity0
for
prop
in
entity1
.
properties
:
key
=
prop
.
name
if
prop
.
name
is
not
None
else
prop
.
id
# check how often the property appears in entity0
num_prop_in_ent0
=
len
(
entity0
.
properties
.
filter
(
prop
))
if
num_prop_in_ent0
==
0
:
# property is only present in entity0 - add to diff
diff
[
1
][
"
properties
"
][
prop
.
name
]
=
{}
diff
[
1
][
"
properties
"
][
key
]
=
{}
if
num_prop_in_ent0
>
1
:
# Check whether the property is present multiple times in entity0
# and raise error - result would be incorrect
...
...
@@ -441,9 +454,10 @@ def compare_entities(entity0: Optional[Entity] = None,
for
index
,
parents
,
other_entity
in
[(
0
,
entity0
.
parents
,
entity1
),
(
1
,
entity1
.
parents
,
entity0
)]:
for
parent
in
parents
:
key
=
parent
.
name
if
parent
.
name
is
not
None
else
parent
.
id
matching
=
other_entity
.
parents
.
filter
(
parent
)
if
len
(
matching
)
==
0
:
diff
[
index
][
"
parents
"
].
append
(
parent
.
name
)
diff
[
index
][
"
parents
"
].
append
(
key
)
continue
return
diff
...
...
This diff is collapsed.
Click to expand it.
unittests/test_apiutils.py
+
28
−
0
View file @
cc0221ac
...
...
@@ -991,3 +991,31 @@ def test_describe_diff():
assert
"
first
"
not
in
diffout
assert
"
second
"
not
in
diffout
def
test_diff_without_names
():
"""
Test compare_entities in case of properties and parents with
ids and without names
(cf. https://gitlab.com/linkahead/linkahead-pylib/-/issues/119).
"""
r1
=
db
.
Record
(
name
=
"
Test
"
).
add_parent
(
name
=
"
TestType
"
)
r2
=
db
.
Record
(
name
=
"
Test
"
).
add_parent
(
name
=
"
TestType
"
)
r2
.
add_property
(
id
=
123
,
value
=
"
Test
"
)
diff1
,
diff2
=
compare_entities
(
r1
,
r2
)
assert
len
(
diff1
[
"
properties
"
])
==
0
assert
len
(
diff2
[
"
properties
"
])
==
1
assert
123
in
diff2
[
"
properties
"
]
assert
None
not
in
diff2
[
"
properties
"
]
r3
=
db
.
Record
().
add_parent
(
id
=
101
)
r4
=
db
.
Record
().
add_parent
(
id
=
102
)
diff3
,
diff4
=
compare_entities
(
r3
,
r4
)
assert
len
(
diff3
[
"
parents
"
])
==
1
assert
101
in
diff3
[
"
parents
"
]
assert
None
not
in
diff3
[
"
parents
"
]
assert
len
(
diff4
[
"
parents
"
])
==
1
assert
102
in
diff4
[
"
parents
"
]
assert
None
not
in
diff3
[
"
parents
"
]
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment