Skip to content

Commit ed13b31

Browse files
committed
[IMP] util.adapt_domains: handle dotted expressions in old argument
Needed when a m2o is replaced by local fields. i.e. `foo_id` is removed and `foo_id.code` get replaced by a `code` field on self. closes #40 Signed-off-by: Christophe Simonis (chs) <[email protected]>
1 parent 2581e7e commit ed13b31

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

src/base/tests/test_util.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,27 @@ def test_force_adapt(self, left, model, target_model="res.users", old="partner_i
236236
self.mock_adapter.assert_called_once()
237237
self.assertEqual(res, self.mock_adapter.return_value)
238238

239+
@parametrize(
240+
[
241+
("partner_id.old", "new"),
242+
("partner_id.user_id.partner_id.old", "partner_id.user_id.new"),
243+
("partner_id.old.foo", "new.foo"),
244+
# from another model
245+
("user_id.partner_id.old", "user_id.new", "res.partner"),
246+
# no change expected
247+
("old", None),
248+
("partner_id", None),
249+
("partner_id.name", None),
250+
]
251+
)
252+
def test_dotted_old(self, left, expected, model="res.users"):
253+
domain = [(left, "=", "test")]
254+
new_domain = _adapt_one_domain(self.cr, "res.users", "partner_id.old", "new", model, domain)
255+
if expected is not None:
256+
self.assertEqual(new_domain, [(expected, "=", "test")])
257+
else:
258+
self.assertIsNone(new_domain)
259+
239260

240261
class TestAdaptDomainView(UnitTestCase):
241262
def test_adapt_domain_view(self):

src/util/domains.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,15 @@ def _adapt_one_domain(cr, target_model, old, new, model, domain, adapter=None, f
196196
_logger.log(NEARLYWARN, "Invalid %r domain: %r: %s", model, domain, oops)
197197
return None
198198

199+
dot_old = old.split(".")
200+
dot_new = new.split(".")
201+
199202
def clean_path(left):
200203
path = left.split(".")
201-
for idx in range(1, len(path) + 1):
202-
if path[-idx] == old and _valid_path_to(cr, path[:-idx], model, target_model):
203-
path[-idx] = new
204+
for idx in range(len(path) - len(dot_old), -1, -1):
205+
r = slice(idx, idx + len(dot_old))
206+
if path[r] == dot_old and _valid_path_to(cr, path[:idx], model, target_model):
207+
path[r] = dot_new
204208
return ".".join(path)
205209

206210
def clean_term(term):
@@ -247,9 +251,13 @@ def clean_term(term):
247251
leaf = expression.normalize_leaf(element)
248252
path = leaf[0].split(".")
249253
# force_adapt=True -> always adapt if found anywhere on left path
250-
# otherwise adapt only when {old} field is the last part of left path
251-
search_range = range(len(path)) if force_adapt else [-1]
252-
if any(path[i] == old and _valid_path_to(cr, path[:i], model, target_model) for i in search_range):
254+
# otherwise adapt only when {old} field is the last parts of left path
255+
search_limit = len(path) - len(dot_old)
256+
search_range = range(search_limit + 1) if force_adapt else [search_limit]
257+
if any(
258+
path[i : i + len(dot_old)] == dot_old and _valid_path_to(cr, path[:i], model, target_model)
259+
for i in search_range
260+
):
253261
dom = [clean_term(term) for term in adapter(leaf, is_or, neg)]
254262
else:
255263
dom = [clean_term(leaf)]

0 commit comments

Comments
 (0)