robshakir / pyangbind

A plugin for pyang that creates Python bindings for a YANG model.
Other
204 stars 121 forks source link

Default values in pybindJSON.dumps #356

Open skarpe-github opened 3 months ago

skarpe-github commented 3 months ago

Hi all,

not completely sure whether this is an issue or I am just expecting the wrong results....

When we set a default value in our example module:

module test {
    yang-version 1.1;
    namespace "http://example.com/example-module";
    prefix ex;

    organization "Test organization";
    contact "test@test.com";
    description "This is a test";
    revision "2024-08-02" {
        description "Initial revision.";
        reference "self";
    }

    container example-container {
        description "A container for the example.";

        leaf example-leaf {
            type string;
            default "default-value";
            description "An example leaf with a default value.";
        }
    }
}

...and then generate the Python module with pyangbind and load it:

import json
import pyangbind.lib.pybindJSON as pybindJSON
from pyangbind.lib.serialise import pybindJSONDecoder
from test_yang import test

test_obj = test()

data = {"example-container": {}}
data_json = json.loads(json.dumps(data))
output = pybindJSONDecoder.load_ietf_json(data_json, None, None, obj=test_obj)

... I would expect the default value to show up in any of these print commands:


print(pybindJSON.dumps(output, indent=4, mode="ietf", with_defaults=True))
print(pybindJSON.dumps(output, indent=4, mode="ietf", with_defaults="report-all"))
print(pybindJSON.dumps(output, indent=4, mode="ietf", with_defaults="report-all-tagged"))

print(pybindJSON.dumps(output, indent=4, mode="yang", with_defaults=True))
print(pybindJSON.dumps(output, indent=4, mode="yang", with_defaults="report-all"))
print(pybindJSON.dumps(output, indent=4, mode="yang", with_defaults="report-all-tagged"))

But the output is an empty dictionary. When we use the get method ( print(test_obj.get()) ), it shows the expected output {'example-container': {'example-leaf': 'default-value'}}, but the pybindJSON.dumps does not. Is this a bug or on purpose?

Tested with: Python 3.11.9 pyangbind==0.8.5

Any input would be much appreciated! Thank you!

xavier-contreras commented 3 months ago

I believe this is by design, see filter option: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md#serialising-data-into-json-

Though it does not seem to work for mode ietf, that is not clear to me if it is by design. The behavior for ietf in general is a bit suspect. That does feel more like a bug.

>>> print(pybindJSON.dumps(output, indent=4, mode="default", with_defaults=True, filter=False))
{
    "example-container": {
        "example-leaf": "default-value"
    }
}

>>> print(pybindJSON.dumps(output, indent=4, mode="yang", with_defaults=True, filter=False))
{
    "example-container": {
        "example-leaf": "default-value"
    }
}

>>> print(pybindJSON.dumps(output, indent=4, mode="ietf", with_defaults=True, filter=False))
{}

>>> print(pybindJSON.dumps(output, indent=4, mode="ietf", filter=False, select=False))
{
    "test:example-container": {
        "example-leaf": ""
    }
}
>>> 
>>> print(pybindJSON.dumps(output, indent=4, mode="ietf", filter=False))
{
    "test:example-container": {
        "example-leaf": ""
    }
}

>>> print(pybindJSON.dumps(output, indent=4, mode="ietf", filter=False, select={'example-leaf': ''}))
{
    "test:example-container": {
        "example-leaf": ""
    }
}
skarpe-github commented 3 months ago

Very good catch with the filteroption, thank you @xavier-contreras !

Indeed, the ietf mode does not look right then...

skarpe-github commented 3 months ago

The reason why the dumps method does not work for ietf mode in the example above seems to be here: https://github.com/robshakir/pyangbind/blob/35fb9a81670a900d6580f725ad624d82f591d736/pyangbind/lib/pybindJSON.py#L106 According to the class' docstring: https://github.com/robshakir/pyangbind/blob/35fb9a81670a900d6580f725ad624d82f591d736/pyangbind/lib/serialise.py#L292 the object is restructured to fit IETF requirements. Since the example schema does not follow IETF requirements, it makes sense that the dumps method does not work. Therefore, it is probably not a bug.

xavier-contreras commented 3 months ago

Yes I see, and if you follow your second link the next function also refers to this: https://github.com/robshakir/pyangbind/blob/35fb9a81670a900d6580f725ad624d82f591d736/pyangbind/lib/serialise.py#L392