Skip to content

Commit 4075dc1

Browse files
authored
Merge pull request #451 from andlaus/weakref_fix
odxlink: make ODX references work if they point to proxy objects
2 parents 7b52177 + cd337eb commit 4075dc1

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

odxtools/odxlink.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ class OdxDocFragment:
3333
doc_type: DocType
3434

3535

36+
def _wrap_referenced_object(obj: Any, use_weakref: bool | None) -> Any:
37+
if not use_weakref:
38+
return obj
39+
40+
if isinstance(obj, (weakref.CallableProxyType, weakref.ProxyType)):
41+
# if the referenced object already is a
42+
# weakref proxy object, we can and must return
43+
# it directly. (weakref.proxy() raises an
44+
# exception if called for a proxy object.)
45+
return obj
46+
47+
return weakref.proxy(obj)
48+
49+
3650
@dataclass(frozen=True)
3751
class OdxLinkId:
3852
"""The identifier of an ODX object.
@@ -204,6 +218,10 @@ def resolve(self,
204218
If the database does not contain any object which is referred to, a
205219
KeyError exception is raised.
206220
"""
221+
222+
if use_weakrefs is None:
223+
use_weakrefs = self.use_weakrefs
224+
207225
for ref_frag in reversed(ref.ref_docs):
208226
doc_frag_db = self._db.get(ref_frag)
209227
if doc_frag_db is None:
@@ -226,10 +244,7 @@ def resolve(self,
226244
f"{type(obj).__name__} which is not a subclass of expected "
227245
f"type {expected_type.__name__}")
228246

229-
if use_weakrefs or (use_weakrefs is None and self.use_weakrefs):
230-
return weakref.proxy(obj)
231-
else:
232-
return obj
247+
return _wrap_referenced_object(obj, use_weakrefs)
233248

234249
odxraise(
235250
f"ODXLINK reference {ref} could not be resolved for any "
@@ -264,6 +279,9 @@ def resolve_lenient(self,
264279
is returned.
265280
"""
266281

282+
if use_weakrefs is None:
283+
use_weakrefs = self.use_weakrefs
284+
267285
for ref_frag in reversed(ref.ref_docs):
268286
doc_frag_db = self._db.get(ref_frag)
269287
if doc_frag_db is None:
@@ -282,10 +300,7 @@ def resolve_lenient(self,
282300
if expected_type is not None:
283301
odxassert(isinstance(obj, expected_type))
284302

285-
if use_weakrefs or (use_weakrefs is None and self.use_weakrefs):
286-
return weakref.proxy(obj)
287-
else:
288-
return obj
303+
return _wrap_referenced_object(obj, use_weakrefs)
289304

290305
return None
291306

@@ -358,7 +373,4 @@ def resolve_snref(target_short_name: str,
358373
odxraise(f"Reference '{target_short_name}' points to a {type(candidates[0]).__name__}"
359374
f"object while expecting {expected_type.__name__}")
360375

361-
if use_weakrefs:
362-
return weakref.proxy(candidates[0])
363-
else:
364-
return candidates[0]
376+
return _wrap_referenced_object(candidates[0], use_weakrefs)

0 commit comments

Comments
 (0)