-
Notifications
You must be signed in to change notification settings - Fork 18
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
SIMPLE-6124 annotations support #85
Conversation
added docstrings to annotation properties fixed issues with syncing
added as_dict method to annotations
Lab.update_lab() and Lab.import_lab() is currently the only untested part of the PR. |
virl2_client/models/lab.py
Outdated
@@ -617,7 +658,7 @@ def remove_node(self, node: Node | str, wait: bool | None = None) -> None: | |||
""" | |||
Remove a node from the lab. | |||
|
|||
If you have a node object, you can also simply do:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this was a typo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will revert it then, after you finish review.
is there a simple branch with some annotation tests? |
Sadly there isn't, not sure if you mean unit tests or any tests... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll review the annotation parts when you are done redoing them, ping me then pls&ty.
virl2_client/models/lab.py
Outdated
""" | ||
Return the list of nodes in the lab. | ||
|
||
:returns: A list of Node objects. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nodes -> annotations
virl2_client/models/lab.py
Outdated
Creates a lab annotation | ||
|
||
:param type: type of annotation (rectangle, ellipse, line or text) | ||
:returns: the created annotation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've unified the formatting of docstrings to use imperative mood ("Create", not "Creates") and proper capitalization and punctuation in the :param:
s etc.
Not exactly critical, but I'd rather not revert to the standardless lawlessness just yet.
reverted some minor docstring changes fixed various issues mostly related to Lab methods and syncing
virl2_client/models/annotation.py
Outdated
|
||
AnnotationTypeString = Literal["text", "line", "ellipse", "rectangle"] | ||
AnnotationType = Union[ | ||
Annotation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably just to shut linters up
Annotation, | |
"Annotation", |
virl2_client/models/annotation.py
Outdated
return annotation_map[annotation_type] & ANNOTATION_PROPERTY_MAP[_property] > 0 | ||
|
||
@locked | ||
def as_dict(self) -> dict[str, str]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that we need as_dict in PCL. We should deprecate it in interface.py and link.py (not in this PR).
# --X-: ellipse | ||
# -X--: line | ||
# X---: text | ||
ANNOTATION_PROPERTY_MAP = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd remove these mappings too. We don't need as_dict
, get_default_property_values
or is_valid_property
methods.
|
||
# create POST json with default annotation property values | ||
# override some values by new, expected ones | ||
annotation_data = Annotation.get_default_property_values(annotation_type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's server provide the defaults. If that's not possible, we should really consider changing the API. It makes no sense to require defaults (and probably not just in this API endpoint).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every property for each ann. type is required therefore when creating new annotation, you have to provide all of its properties.
I created map of default values, which are the same default values than the one you get when creating annotation through ui.
I made this so you dont have to insert all (required) property values when creating new annotation through PCL, so now you can just do: lab.create_annotation("rectangle")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd prefer to have a set of functions which defines the properties for annotation, not defined on the backend but locally in the PCL. This is about abstracting complexity and making the use of the API easier by providing "quality of life" functions for the user of the PCL.
Annotation.get_default_properties(annotation_type)
as Patrik proposes which define sane defaultsAnnotation.set_default_properties(annotation_type, defaults)
which provides additional values the user wants for this annotation type, they will be merged with the default propertiesAnnotation.clear_properties(annotation_type)
which will clear the user properties
When the user then creates annotations, the union of the defaults and the user provided properties and the create function are passed to the backend API call to have a complete set of attributes/properties
Example
"defaults for rect": { bg_color="#FFFFFFFF", border_color="#808080FF", border_style="solid", border_thickness="1", corner_radius=0, layer=0 }
user calls Annotation.create_rect(0,0, 100, 100) -> properties taken from defaults
user calls Annotation.create_rect(0,0, 100, 100, border_color="#ff000000") -> red rectangle
user calls
Annotations.set_default_properties(Rectangle, border_color="#00ff0000")
Annotations.create_rect(0,0, 100,100) -> blue rectangle
Annotations.create_rect(100,100, 100,100) -> another blue rectangle
Annotations.clear_default_properties(Rectangle)
Annotations.create_rect(200,200, 100,100) -> rectangle is black again
This way, the actual creation ALWAYS provides a complete set of defaults and it's easy for the user to control the properties of annotations without having to repeat themselves for every object created. And the backend does (and should) not have any say in what is a default... the API wants and gets a complete set of properties for every annotation created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the reset to defaults is clearly something that we don't do in PCL (we don't even have such options in CML maybe except of sync from a node def)
we do not reset annotations to default in UI either
do we really think that this would be useful? why don't we just delete and create a new annotation instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I like the idea of having something like "default properties overlay", in reality its not really bringing that much of a QoL change.
While now you have to always provide your custom defaults as a second argument to "create" method (Lab.create_annotation("rectangle", user_defined_defaults)), with your proposal in-place, it would be only one (Lab.create_annotation("rectangle")).
I dont think saving one dict var with user-defined defaults and sending one extra parameter in each create call is that much of a pain, sometimes more abstraction hurts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another issue is we run async, which means there's a miniscule chance that before you send the request with expected defaultsA, other method might update these class-level defaults to defaultsB and they will be used for the first call, expecting defaultsA, too.
Therefore sending the (user-defined subset of) defaults explicitly, while not being overly painful, gives you more control over what is happening.
…e annotation body minor tweak of AnnotationType typings
self, | ||
annotation_data: dict[str, Any], | ||
push_to_server: bool = False, | ||
self, annotation_data: dict[str, Any], push_to_server: bool = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should drop the push_to_server parameter in the entirety of the PCL and just make the update functions always push to server, since there is really no situation where the user would want to not push to server. We only ever do that internally, so it should be its own separate private function. @tmikuska can we discuss that/make a ticket for it? (You can leave it here for now I think)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get the idea of WHY we initially wanted to give the user a possibility to handle the objects only locally, but in reality it makes little to no sense, so as you are saying, I think we should always try to force push it to server, which is something most of the users will expect to happen automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is true (and I think it is) then the entire "offline/async" mode should be removed from the PCL as it makes things overly complicated for little to no gain as people are likely not using it in this async mode but rather expect things to be synchronous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raised a new ticket for this
001c698
to
055951f
Compare
* SIMPLE-5780 replace change test dir fixture (#54) * SIMPLE-5377 PCL general improvements (#59) * SIMPLE-5953 pcl update for smbios parameters (#61) * SIMPLE-5974 Support for locked_compute_id (#64) * SIMPLE-5806 PCL support for multiple config files (#60) * SIMPLE-5806 fix for a missed bug (#65) * SIMPLE-5949 Deprecated licensing certificate support in PCL (#66) * updated pyproject.toml and poetry.lock; versions: poetry-1.4, lock for… (#68) * SIMPLE-6084 Fixed regressions in create_node method to preserve compatibility with older CML releases * SIMPLE-6020 sped up syncing operational by removing unneeded API calls (#72) * SIMPLE-5747 added .iol files to list of accepted image files (#71) * SIMPLE-5829 Backported fix for missing image extension * SIMPLE-6087 creating a lab no longer raises a warning (#74) * SIMPLE-6105 node.remove no longer always raises NodeNotFound (#75) * SIMPLE-6073: Avoid using unneeded pyats features when parsing our generated testbed file, which uses none of them. Refactor checking whether pyats is installed. (#76) * SIMPLE-6168 Added missing copyright info, fixed invalid copyright year * SIMPLE-6204 rename locked compute to pinned (#79) * SIMPLE-6093 Implemented controller property (#82) * SIMPLE-6285 Improvements to multiple node configuration API (#83) * SIMPLE-6124 Annotations support (#85) * SIMPLE-6428 Fixed annotation update on lab sync (#89)
Added basic annotations support.
Most notable additions:
Lab.annotations()
Lab.get_annotation_by_id()
Lab.create_annotation()
Lab.remove_annotations()
Lab.remove_annotation()
Updated functionalities:
Lab.update_lab()
Lab.import_lab()
Other changes: