Skip to content

fix(ua_binary): avoid recursive list codec construction for mutual da…#1950

Open
AndreasHeine wants to merge 11 commits intomasterfrom
fix--_create_type_deserializer
Open

fix(ua_binary): avoid recursive list codec construction for mutual da…#1950
AndreasHeine wants to merge 11 commits intomasterfrom
fix--_create_type_deserializer

Conversation

@AndreasHeine
Copy link
Copy Markdown
Member

fix for: #1940

@AndreasHeine AndreasHeine marked this pull request as ready for review March 10, 2026 14:59
@AndreasHeine AndreasHeine requested a review from oroulet March 10, 2026 14:59
@AndreasHeine
Copy link
Copy Markdown
Member Author

"Python 3.10 end-of-life (EOL) October 2026."

(-_-)*

@oroulet
Copy link
Copy Markdown
Member

oroulet commented Mar 12, 2026

Can you rebase?

@AndreasHeine
Copy link
Copy Markdown
Member Author

did i ever mention that i hate merge conflicts ^^

@AndreasHeine
Copy link
Copy Markdown
Member Author

@oroulet could you have a look!? should fix the "recursive list codec construction" / "NotEnoughData..." and should improve the logs/trace if something similar happens again.

# Skip only if the existing class is already bound to this exact
# DataType node. Name-only checks can collide across companion specs.
if isinstance(existing_dtype, ua.NodeId) and existing_dtype == desc.NodeId:
continue
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am really not sure if we should do that. Everyhting is a bit wrong anyway. we should store some dict[datatype, object] somewhere in addition to using the ua namespace. I started on a MR somewhere

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be honnest... the ExtensionObject stuff will get hardened on the way and it's likely that things will break here...

the thing which i not really like is the registration under ua module... (maybe a namespace sorted collection of datatypes would be better e.g. an explicit registry) in standardization we try to avoid similar names via prefixing... but thats not a guaranty!

however its up to you to decide! i can change it to a proper warning so at least we can see if there is a collision!?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not here to make one handed decisions. If someone proposes a good solution I am all for it.
there are 2 not finished MR trying to fix that.
https://github.com/FreeOpcUa/opcua-asyncio/pull/1897/changes
and
https://github.com/FreeOpcUa/opcua-asyncio/pull/1899/changes

yes in my mind some dict[DataType, object] should do the tricks with a ua.object alias for legacy and simplicity. But making all these structure refere to that dict and not the ua type was not so easy to do...

yes maybe a big warning is the first step here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can revisit:

Preserve existing logic: skip when a type name already exists and overwrite_existing is False
Add warning when a discovered datatype is skipped
Add additional warning when the skipped entry has the same name but a different DataType NodeId

@functools.cache
def _create_list_deserializer(uatype: type, recursive: bool = False) -> Callable[[Buffer | IO], list[Any]]:
if recursive:
def _create_list_deserializer(uatype: Any, recursive: bool = False) -> Callable[[Buffer | IO[Any]], list[Any]]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not follow everything here but that typing change looks very strange. The entire point of that method is to take binary data and transform it into ojjects... hwy would it take Any??

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

somehow typechecking blamed it... i looked it up:

Why not just IO?
In Python typing, IO is generic. Writing bare IO is considered incomplete by type checkers. IO[Any] means “an IO object of unspecified content type,” which is practical here because many real stream objects are not strictly annotated as IO[bytes] even though they return bytes at runtime.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry somehow I missed the IO[] part ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants