Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support python 3.11 #1103

Merged
merged 5 commits into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.10', 'pypy-3.8']
python-version: ['3.7', '3.11', 'pypy-3.8']

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion asyncua/common/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def _make_model(self, root):
# Optional Field
field.is_optional = True
struct.option_counter += 1
field.value = get_default_value(field.uatype, enums)
field.value = get_default_value(field.uatype, enums, hack=True)
if array:
field.array = True
field.value = "field(default_factory=list)"
Expand Down
10 changes: 7 additions & 3 deletions asyncua/common/structures104.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def clean_name(name):
return newname


def get_default_value(uatype, enums=None):
def get_default_value(uatype, enums=None, hack=False):
if hasattr(ua, uatype):
# That type is know, make sure this is not a subtype
dtype = getattr(ua, uatype)
Expand All @@ -157,7 +157,11 @@ def get_default_value(uatype, enums=None):
# We have an enum, try to initilize it correctly
val = list(getattr(ua, uatype).__members__)[0]
return f"ua.{uatype}.{val}"
return f"ua.{uatype}()"
if hack:
# FIXME: This is horrible but necssary for old struc support until
# someone fixes dependencies og we deprecated it
return f"field(default_factory=lambda :ua.{uatype}())"
return f"field(default_factory=ua.{uatype})"
Copy link
Contributor

Choose a reason for hiding this comment

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

This changes breaks the old struct code.
The problem is that the old code registers the variables to ua namespace after executing the codes in another step.
This would require some reworking of the old struct code.

Copy link
Member Author

Choose a reason for hiding this comment

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

I do not understand that one. That change should only change the way the dataclass is initiliazed. How does it change the registratoin to the ua namespace?

Copy link
Contributor

Choose a reason for hiding this comment

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

The old code first creates all classes and after that they are registered to the ua namespace. So if they are used in the default_factory that will fail.

Copy link
Contributor

@schroeder- schroeder- Oct 30, 2022

Choose a reason for hiding this comment

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

If you change the line back the test will pass. But the 1.04 will fail ...

Copy link
Member Author

Choose a reason for hiding this comment

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

arrgg. OK now I remember I found out that yesterday, but then you cannot simply register because you also need to reorder dependencies and that is not done in that code... Not sure what to do. either we do not support 3.11 or we break old structure support. Or we need someone to implement that reodering because I really do not have time



def make_structure_code(data_type, struct_name, sdef, log_error=True):
Expand Down Expand Up @@ -356,7 +360,7 @@ async def _get_parent_types(node: Node):
refs = await tmp_node.get_references(refs=ua.ObjectIds.HasSubtype, direction=ua.BrowseDirection.Inverse)
if not refs or refs[0].NodeId.NamespaceIndex == 0 and refs[0].NodeId.Identifier == 22:
return parents
tmp_node = Node(tmp_node.server, refs[0])
tmp_node = Node(tmp_node.session, refs[0])
parents.append(tmp_node)
logger.warning("Went 10 layers up while look of subtype of given node %s, something is wrong: %s", node, parents)

Expand Down
40 changes: 20 additions & 20 deletions asyncua/common/xmlimporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __init__(self, server, strict_mode=True):
but the import continues
'''
self.parser = None
self.server = server
self.session = server
self.namespaces: Dict[int, int] = {} # Dict[IndexInXml, IndexInServer]
self.aliases: Dict[str, ua.NodeId] = {}
self._unmigrated_aliases: Dict[str, str] = {} # Dict[name, nodeId string]
Expand All @@ -38,14 +38,14 @@ async def _map_namespaces(self):
if not present the namespace is registered.
"""
xml_uris = self.parser.get_used_namespaces()
server_uris = await self.server.get_namespace_array()
server_uris = await self.session.get_namespace_array()
namespaces_map = {}
for ns_index, ns_uri in enumerate(xml_uris):
ns_index += 1 # since namespaces start at 1 in xml files
if ns_uri in server_uris:
namespaces_map[ns_index] = server_uris.index(ns_uri)
else:
ns_server_index = await self.server.register_namespace(ns_uri)
ns_server_index = await self.session.register_namespace(ns_uri)
namespaces_map[ns_index] = ns_server_index
return namespaces_map

Expand All @@ -60,7 +60,7 @@ def _map_aliases(self, aliases: dict):

async def _get_existing_model_in_namespace(self):
server_model_list = []
server_namespaces_node = await self.server.nodes.namespaces.get_children()
server_namespaces_node = await self.session.nodes.namespaces.get_children()
for model_node in server_namespaces_node:
server_model_list.append({
"ModelUri": await (await model_node.get_child("NamespaceUri")).read_value(),
Expand Down Expand Up @@ -98,12 +98,12 @@ async def _check_if_namespace_meta_information_is_added(self):
check if the NamespaceMetadata objects in server namespaces exists otherwise add them
to prevent errors when other nodesets depend on this namespace.
"""
descs = await self.server.nodes.namespaces.get_children_descriptions()
descs = await self.session.nodes.namespaces.get_children_descriptions()
ns_objs = [n.BrowseName.Name for n in descs]
for uri, version, pub_date in self.parser.get_nodeset_namespaces():
if uri not in ns_objs:
idx = await self.server.register_namespace(uri)
obj = await self.server.nodes.namespaces.add_object(idx, uri, ua.ObjectIds.NamespaceMetadataType, False)
idx = await self.session.register_namespace(uri)
obj = await self.session.nodes.namespaces.add_object(idx, uri, ua.ObjectIds.NamespaceMetadataType, False)
ns_uri = await obj.get_child('NamespaceUri')
await ns_uri.write_value(uri, ua.VariantType.String)
ns_ver = await obj.get_child('NamespaceVersion')
Expand Down Expand Up @@ -166,7 +166,7 @@ async def _add_missing_reverse_references(self, new_nodes):
node_reference_map: Dict[RefSpecKey, ua.ReferenceDescription] = {}

for new_node_id in new_nodes:
node = self.server.get_node(new_node_id)
node = self.session.get_node(new_node_id)
node_ref_list: List[ua.ReferenceDescription] = await node.get_references()

for ref in node_ref_list:
Expand Down Expand Up @@ -205,8 +205,8 @@ def _add_missing_parents(self, dnodes):
for ref in nd.refs:
if ref.forward:
if ref.reftype in [
self.server.nodes.HasComponent.nodeid,
self.server.nodes.HasProperty.nodeid]:
self.session.nodes.HasComponent.nodeid,
self.session.nodes.HasProperty.nodeid]:
# if a node has several links, the last one will win
if ref.target in childs:
_logger.warning(
Expand Down Expand Up @@ -243,9 +243,9 @@ async def _add_node_data(self, nodedata, no_namespace_migration=False) -> ua.Nod
return node

def _get_server(self):
if hasattr(self.server, "iserver"):
return self.server.iserver.isession
return self.server.uaclient
if hasattr(self.session, "iserver"):
return self.session.iserver.isession
return self.session.uaclient

async def _add_references(self, refs):
res = await self._get_server().add_references(refs)
Expand Down Expand Up @@ -402,7 +402,7 @@ async def _make_ext_obj(self, obj):
try:
extclass = self._get_ext_class(obj.objname)
except Exception:
await self.server.load_data_type_definitions() # load new data type definitions since a customn class should be created
await self.session.load_data_type_definitions() # load new data type definitions since a customn class should be created
extclass = self._get_ext_class(obj.objname)
args = {}
for name, val in obj.body:
Expand Down Expand Up @@ -578,17 +578,17 @@ async def add_datatype(self, obj, no_namespace_migration=False):
if not obj.definitions:
pass
else:
if obj.parent == self.server.nodes.enum_data_type.nodeid:
if obj.parent == self.session.nodes.enum_data_type.nodeid:
attrs.DataTypeDefinition = self._get_edef(obj)
elif obj.parent == self.server.nodes.base_structure_type.nodeid:
elif obj.parent == self.session.nodes.base_structure_type.nodeid:
attrs.DataTypeDefinition = self._get_sdef(obj)
else:
parent_node = self.server.get_node(obj.parent)
parent_node = self.session.get_node(obj.parent)
path = await parent_node.get_path()
if self.server.nodes.option_set_type in path:
if self.session.nodes.option_set_type in path:
# nodes below option_set_type are enums, not structs
attrs.DataTypeDefinition = self._get_edef(obj)
elif self.server.nodes.base_structure_type in path:
elif self.session.nodes.base_structure_type in path:
attrs.DataTypeDefinition = self._get_sdef(obj)
else:
_logger.warning(
Expand Down Expand Up @@ -639,7 +639,7 @@ def _get_sdef(self, obj):
if obj.parent:
sdef.BaseDataType = obj.parent
for refdata in obj.refs:
if refdata.reftype == self.server.nodes.HasEncoding.nodeid:
if refdata.reftype == self.session.nodes.HasEncoding.nodeid:
# supposing that default encoding is the first one...
sdef.DefaultEncodingId = refdata.target
break
Expand Down
2 changes: 1 addition & 1 deletion asyncua/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ def new_node(sync_node, nodeid):
"""
given a sync node, create a new SyncNode with the given nodeid
"""
return SyncNode(sync_node.tloop, node.Node(sync_node.aio_obj.server, nodeid))
return SyncNode(sync_node.tloop, node.Node(sync_node.aio_obj.session, nodeid))


class SyncNode:
Expand Down
6 changes: 3 additions & 3 deletions asyncua/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ async def _lsprint_0(node, depth, indent=""):
)
)
if depth:
await _lsprint_0(Node(node.server, desc.NodeId), depth - 1, indent + " ")
await _lsprint_0(Node(node.session, desc.NodeId), depth - 1, indent + " ")


async def _lsprint_1(node, depth, indent=""):
Expand All @@ -394,7 +394,7 @@ async def _lsprint_1(node, depth, indent=""):
for desc in await node.get_children_descriptions():
if desc.NodeClass == ua.NodeClass.Variable:
try:
val = await Node(node.server, desc.NodeId).read_value()
val = await Node(node.session, desc.NodeId).read_value()
except UaStatusCodeError as err:
val = "Bad (0x{0:x})".format(err.code)
print(
Expand All @@ -416,7 +416,7 @@ async def _lsprint_1(node, depth, indent=""):
)
)
if depth:
await _lsprint_1(Node(node.server, desc.NodeId), depth - 1, indent + " ")
await _lsprint_1(Node(node.session, desc.NodeId), depth - 1, indent + " ")


async def _lsprint_long(pnode, depth, indent=""):
Expand Down