Skip to content

Commit 7a38f8b

Browse files
committed
Revert "Merge branch 'refactor/data-model' into develop"
This reverts commit bfd0b29, reversing changes made to 86d8def.
1 parent bfd0b29 commit 7a38f8b

31 files changed

Lines changed: 1065 additions & 89746 deletions

src/hermes/model/context.py

Lines changed: 445 additions & 0 deletions
Large diffs are not rendered by default.

src/hermes/model/context_manager.py

Lines changed: 0 additions & 72 deletions
This file was deleted.

src/hermes/model/errors.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import typing as t
88

9+
from hermes.model import path as path_model
10+
911

1012
class HermesValidationError(Exception):
1113
"""
@@ -28,7 +30,7 @@ class MergeError(Exception):
2830
"""
2931
This exception should be raised when there is an error during a merge / set operation.
3032
"""
31-
def __init__(self, path: t.List[str | int], old_Value: t.Any, new_value: t.Any, **kwargs):
33+
def __init__(self, path: path_model.ContextPath, old_Value: t.Any, new_value: t.Any, **kwargs):
3234
"""
3335
Create a new merge incident.
3436

src/hermes/model/merge.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# SPDX-FileContributor: Michael Meinel
6+
7+
from hermes.model.path import ContextPath, set_in_dict
8+
9+
10+
class MergeStrategies:
11+
def __init__(self):
12+
self._strategies = []
13+
14+
def select(self, **kwargs):
15+
fitting_strategies = [
16+
strategy
17+
for strategy in self._strategies
18+
if strategy.can_handle(kwargs)
19+
]
20+
if fitting_strategies:
21+
return fitting_strategies[0]
22+
else:
23+
return None
24+
25+
def register(self, strategy):
26+
self._strategies.append(strategy)
27+
28+
29+
class MergeStrategy:
30+
@staticmethod
31+
def _check_types(item, value):
32+
match item:
33+
case list(): return any(t in value for t in item)
34+
case str(): return item in value
35+
return False
36+
37+
@staticmethod
38+
def _check_path(item, value):
39+
item = ContextPath.parse(item)
40+
value = ContextPath.parse(value)
41+
if item == value or item in value:
42+
return True
43+
return False
44+
45+
checks = {
46+
'type': _check_types,
47+
'path': _check_path,
48+
}
49+
50+
def __init__(self, **filter):
51+
self._filter = filter
52+
53+
def _check(self, key, filter, value):
54+
if key in filter:
55+
check = self.checks.get(key, lambda item, value: item in value)
56+
return check(filter[key], value)
57+
return True
58+
59+
def can_handle(self, filter: dict):
60+
return all(
61+
self._check(key, filter, value)
62+
for key, value in self._filter.items()
63+
)
64+
65+
def are_equal(self, left, right):
66+
return left == right
67+
68+
69+
class CollectionMergeStrategy(MergeStrategy):
70+
def __init__(self, **filter):
71+
super().__init__(**filter)
72+
73+
def are_equal(self, left, right):
74+
return all(
75+
any(a == b for b in right)
76+
for a in left
77+
)
78+
79+
def __call__(self, target, path, value, **kwargs):
80+
match target, path._item:
81+
case list(), int() as index if index < len(target):
82+
match target[index]:
83+
case dict() as item: item.update(value)
84+
case list() as item: item[:] = value
85+
case _: target[index] = value
86+
87+
case list(), '*':
88+
path._item = len(target)
89+
target.append(value)
90+
91+
case list(), int() as index if index == len(target):
92+
target.append(value)
93+
94+
case list(), int() as index:
95+
raise IndexError(f'Index {index} out of bounds to set in {path.parent}.')
96+
case list(), _ as index:
97+
raise TypeError(f'Invalid index type {type(index)} to set in {path.parent}.')
98+
99+
case dict(), str() as key if key in target:
100+
match target[key]:
101+
case dict() as item: item.update(value)
102+
case list() as item: item[:] = value
103+
case _: set_in_dict(target, key, value, kwargs)
104+
105+
case dict(), str() as key:
106+
target[key] = value
107+
108+
case dict(), _ as key:
109+
raise TypeError(f'Invalid key type {type(key)} to set in {path.parent}.')
110+
111+
case _, _:
112+
raise TypeError(f'Cannot handle target type {type(target)} to set {path}.')
113+
114+
return value
115+
116+
117+
class ObjectMergeStrategy(MergeStrategy):
118+
def __init__(self, *id_keys, **filter):
119+
super().__init__(**filter)
120+
self.id_keys = id_keys or ('@id', )
121+
122+
def are_equal(self, left, right):
123+
if not self.id_keys:
124+
return super().are_equal(left, right)
125+
else:
126+
return any(left[key] == right[key] for key in self.id_keys if key in left and key in right)
127+
128+
def __call__(self, target, path, value, **kwargs):
129+
match target, path._item:
130+
case dict(), str() as key if key in target:
131+
match target[key]:
132+
case dict() as item: item.update(value)
133+
case list() as item: item[:] = value
134+
case _: set_in_dict(target, key, value, kwargs)
135+
136+
case dict(), str() as key:
137+
target[key] = value
138+
139+
case dict(), _ as key:
140+
raise TypeError(f'Invalid key type {type(key)} to set in {path.parent}.')
141+
142+
case list(), int() as index if index < len(target):
143+
match target[index]:
144+
case dict() as item: item.update(value)
145+
case list() as item: item[:] = value
146+
case _: target[index] = value
147+
148+
case list(), '*':
149+
path._item = len(target)
150+
target.append(value)
151+
152+
case list(), int() as index if index == len(target):
153+
target.append(value)
154+
155+
case list(), int() as index:
156+
raise IndexError(f'Index {index} out of bounds to set in {path.parent}.')
157+
case list(), _ as index:
158+
raise TypeError(f'Invalid index type {type(index)} to set in {path.parent}.')
159+
160+
case _, _:
161+
raise TypeError(f'Cannot handle target type {type(target)} to set {path}.')
162+
163+
return value
164+
165+
166+
default_merge_strategies = [
167+
ObjectMergeStrategy(
168+
'@id', 'email', 'name',
169+
path='author[*]',
170+
),
171+
172+
CollectionMergeStrategy(
173+
type=['list'],
174+
),
175+
176+
ObjectMergeStrategy(
177+
type=['map'],
178+
)
179+
]

0 commit comments

Comments
 (0)