Skip to content

Commit a1f0975

Browse files
SIMPLE-6429 fix potentially mishandled data structures (#94)
* SIMPLE-6429 changed several functions to not modify shared parameters * SIMPLE-6429 fixed more mishandled data structures and various other small issues
1 parent 9fcfc78 commit a1f0975

File tree

6 files changed

+41
-32
lines changed

6 files changed

+41
-32
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ classifiers = [
1515
"Environment :: Console",
1616
"License :: OSI Approved :: Apache Software License",
1717
"Operating System :: OS Independent",
18-
"Programming Language :: Python :: 3.8",
18+
"Programming Language :: Python :: 3.12",
1919
"Topic :: System :: Networking",
2020
]
2121

virl2_client/models/annotation.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,8 @@ def update(
365365
:param push_to_server: Whether to push the changes to the server.
366366
Defaults to True; should only be False when used by internal methods.
367367
"""
368-
if "type" not in annotation_data:
369-
annotation_data["type"] = self._type
370-
elif annotation_data["type"] != self._type:
371-
raise ValueError("Can't update annotation type.")
368+
if annotation_data.get("type") not in (None, self._type):
369+
raise ValueError("Can't change annotation type.")
372370

373371
# make sure all properties we want to update are valid
374372
for key, value in annotation_data.items():
@@ -397,9 +395,9 @@ def _set_annotation_property(self, key: str, val: Any) -> None:
397395
@check_stale
398396
def _set_annotation_properties(self, annotation_data: dict[str, Any]) -> None:
399397
"""Update annotation properties server-side."""
400-
if "type" not in annotation_data:
401-
annotation_data["type"] = self._type
402-
self._session.patch(url=self._url_for("annotation"), json=annotation_data)
398+
self._session.patch(
399+
url=self._url_for("annotation"), json=annotation_data | {"type": self._type}
400+
)
403401

404402

405403
# ~~~~~< Annotation subclasses >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

virl2_client/models/lab.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,19 +1312,22 @@ def import_lab(self, topology: dict) -> None:
13121312
self._handle_import_annotations(topology)
13131313

13141314
@locked
1315-
def _import_lab(self, topology: dict) -> None:
1315+
def _import_lab(self, topology: dict, created: bool = False) -> None:
13161316
"""
13171317
Replace lab properties with the given topology.
13181318
13191319
:param topology: The topology to import.
1320+
:param created: The node create API endpoint returns data in the old format,
1321+
which would print an unnecessary old schema warning;
1322+
setting this flag to True skips that warning.
13201323
:raises KeyError: If any property is missing in the topology.
13211324
"""
13221325
lab_dict = topology.get("lab")
13231326

13241327
if lab_dict is None:
13251328
# If we just created the lab, we skip the warning, since the
13261329
# lab post endpoint returns data in the old format
1327-
if not topology.pop("_created", False):
1330+
if not created:
13281331
warnings.warn(
13291332
"Labs created in older CML releases (schema version 0.0.5 or lower)"
13301333
" are deprecated. Use labs with schema version 0.1.0 or higher.",
@@ -1347,15 +1350,15 @@ def _handle_import_nodes(self, topology: dict) -> None:
13471350
13481351
:param topology: The topology to import nodes from.
13491352
"""
1350-
for node in topology["nodes"]:
1353+
for node in topology["nodes"]: # type: dict
13511354
node_id = node["id"]
13521355

13531356
if node_id in self._nodes:
13541357
raise ElementAlreadyExists("Node already exists")
13551358

1356-
interfaces = node.pop("interfaces", [])
13571359
self._import_node(node_id, node)
13581360

1361+
interfaces = node.get("interfaces", [])
13591362
if not interfaces:
13601363
continue
13611364

@@ -1477,10 +1480,12 @@ def _import_node(self, node_id: str, node_data: dict) -> Node:
14771480
if "data" in node_data:
14781481
node_data = node_data["data"]
14791482

1480-
node_data.pop("id", None)
1481-
state = node_data.pop("state", None)
1482-
node_data.pop("lab_id", None)
1483-
node_data.pop("boot_progress", None)
1483+
state = node_data.get("state", None)
1484+
node_data = {
1485+
key: node_data[key]
1486+
for key in node_data
1487+
if key not in ("id", "state", "lab_id", "boot_progress", "interfaces")
1488+
}
14841489

14851490
for key in ("image_definition", "configuration"):
14861491
if key not in node_data:
@@ -1503,11 +1508,15 @@ def _import_annotation(
15031508
:param annotation_data: The data of the annotation.
15041509
:returns: The imported Annotation object.
15051510
"""
1506-
annotation_data.pop("id", None)
1507-
ann_type = annotation_data.pop("type")
1511+
annotation_type = annotation_data["type"]
1512+
annotation_data = {
1513+
key: annotation_data[key]
1514+
for key in annotation_data
1515+
if key not in ("id", "type")
1516+
}
15081517

15091518
annotation = self._create_annotation_local(
1510-
annotation_id, ann_type, **annotation_data
1519+
annotation_id, annotation_type, **annotation_data
15111520
)
15121521
return annotation
15131522

@@ -1647,12 +1656,12 @@ def _add_nodes(self, topology: dict, new_nodes, new_interfaces):
16471656
:param new_nodes: Iterable of node IDs to be added.
16481657
:param new_interfaces: Iterable of interface IDs to be added.
16491658
"""
1650-
for node in topology["nodes"]:
1659+
for node in topology["nodes"]: # type: dict
16511660
node_id = node["id"]
1652-
interfaces = node.pop("interfaces", [])
1661+
interfaces = node.get("interfaces", [])
16531662
if node_id in new_nodes:
1654-
node = self._import_node(node_id, node)
1655-
_LOGGER.info(f"Added node {node}")
1663+
new_node = self._import_node(node_id, node)
1664+
_LOGGER.info(f"Added node {new_node}")
16561665

16571666
if not interfaces:
16581667
continue

virl2_client/models/node.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,9 @@ def sync_operational(self, response: dict[str, Any] = None):
841841
"""
842842
Synchronize the operational state of the node.
843843
844-
:param response: The response from the server.
844+
:param response: If the operational data was fetched from the server elsewhere,
845+
it can be passed here to save an API call. Will be fetched automatically
846+
otherwise.
845847
"""
846848
if response is None:
847849
url = self._url_for("operational")

virl2_client/models/resource_pools.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -438,12 +438,14 @@ def _set_resource_pool_property(self, key: str, val: Any) -> None:
438438

439439
def _set_resource_pool_properties(self, resource_pool_data: dict[str, Any]) -> None:
440440
"""Helper method to set multiple properties on the server."""
441-
for key in list(resource_pool_data):
442-
# drop unmodifiable properties
443-
if key in ("id", "template", "users", "user_pools"):
444-
resource_pool_data.pop(key)
441+
# drop unmodifiable properties
442+
resource_pool_data_post = {
443+
key: resource_pool_data[key]
444+
for key in resource_pool_data
445+
if key not in ("id", "template", "users", "user_pools")
446+
}
445447
url = self._url_for("resource_pool")
446-
self._session.patch(url, json=resource_pool_data)
448+
self._session.patch(url, json=resource_pool_data_post)
447449

448450

449451
ResourcePools = Dict[str, ResourcePool]

virl2_client/virl2_client.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -732,9 +732,7 @@ def create_lab(
732732
wait_time=self.convergence_wait_time,
733733
resource_pool_manager=self.resource_pool_management,
734734
)
735-
# This is just to skip a deprecation warning in _import_lab
736-
result["_created"] = True
737-
lab._import_lab(result)
735+
lab._import_lab(result, created=True)
738736
self._labs[lab_id] = lab
739737
return lab
740738

0 commit comments

Comments
 (0)