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

add support for lyd_attr #77

Closed
wants to merge 2 commits into from
Closed

Conversation

nvxf
Copy link
Contributor

@nvxf nvxf commented Jan 22, 2024

No description provided.

libyang/data.py Outdated
@@ -204,6 +204,7 @@ def __init__(self, context: "libyang.Context", cdata):
"""
self.context = context
self.cdata = cdata # C type: "struct lyd_node *"
self.cdata_attrs = [] # C tupe: "struct lyd_attr *"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please fix the typo here ("tupe" => "type").

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in the DNodeAttrs class

Comment on lines 876 to 971
dnode = self.ctx.parse_data_mem(self.JSON_CONFIG, "json", validate_present=True)

hostname = dnode.find_one("hostname")
hostname.free(with_siblings=False)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Same question as the other commit, can you explain why you load the configuration, and delete the hostname in it at the beginning of your test? Why not start with an empty configuration instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done for all the tests

libyang/data.py Outdated
Comment on lines 261 to 288
def attr(self):
ret = {}
for attr in self.cdata_attrs:
key = self._get_attr_key(attr)
ret[key] = c2str(attr.value)
return ret

def new_attr(self, name: str, value: str):
attrs = ffi.new("struct lyd_attr **")
ret = lib.lyd_new_attr(
self.cdata,
ffi.NULL,
str2c(name),
str2c(value),
attrs,
)
if ret != lib.LY_SUCCESS:
raise self.context.error("cannot create attr")
self.cdata_attrs.append(attrs[0])

def attr_free(self, name):
for attr in self.cdata_attrs:
key = self._get_attr_key(attr)

if name == key:
lib.lyd_free_attr_single(self.context.cdata, attr)
self.cdata_attrs.remove(attr)
break
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we need a dedicated class for those attributes. @rjarry, what do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

That may be overkill. These attributes don't make sense without a host DNode.

Copy link
Collaborator

Choose a reason for hiding this comment

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

OK.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I sent my message too fast :D

Actually, yes. It would be better to have:

dnode.attrs().get("foo")

for key, val in dnode.attrs():
    print(key, val)

dnode.attrs().set("foo", "bar")
dnode.attrs().remove("foo")

API stub:

class DNodeAttrs:
    def get(self, name: str) -> str:
        ...
    def set(self, name: str, value: str):
        ...
    def remove(self, name: str):
        ...
    def __contains__(self, name: str):
        ...
    def __iter__(self):
        ...
    def __len__(self):
        ...

class DNode:
    def attrs(self) -> DNodeAttrs:
        ...

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, I had something like that in mind. Agreed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I implemented your API suggestion

@samuel-gauthier
Copy link
Collaborator

Could you rebase that on the current master when you submit the changes?

In case of a call to DNode.new with cdata containing an opaque node
the new method tries to access cdata.schema.nodetype, which results
in a NULL pointer dereference.

To get the schema for an opaque node retrieve the schema from the
context using the path of the node.

Fixes: CESNET#73
Signed-off-by: nvxf <[email protected]>
@nvxf nvxf force-pushed the feat/add-new-attr branch from d3e1db2 to d571671 Compare January 30, 2024 10:04
@samuel-gauthier
Copy link
Collaborator

Can you check what it fails on 3.6?

@nvxf
Copy link
Contributor Author

nvxf commented Jan 30, 2024

Can you check what it fails on 3.6?

The import from __future__ import annotations fails. This is required for the type hint of the attrs() method, because the DNodeAttrs class is defined later in the file. I see 2 options, either move the DNodeAttrs class before the DNode class or remove the typehint, what would be your preferred solution?

@samuel-gauthier
Copy link
Collaborator

I prefer moving the DNoteAttrs class.

data: add support for lyd_attr to DNode

Signed-off-by: nvxf <[email protected]>
@nvxf nvxf force-pushed the feat/add-new-attr branch from d571671 to 0d74391 Compare January 30, 2024 14:02
@nvxf
Copy link
Contributor Author

nvxf commented Jan 30, 2024

Done

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.

3 participants