robshakir / pyangbind Goto Github PK
View Code? Open in Web Editor NEWA plugin for pyang that creates Python bindings for a YANG model.
License: Other
A plugin for pyang that creates Python bindings for a YANG model.
License: Other
My pyang version uses python3, and i think that this requires pyangbind to use python3 as well.
Run the program "2to3" on the .py files. You can see that there are only few lines of code that need to be changed.
Run "2to3 -w pybind.py" and "2to3 -w lib/yangtypes.py" and "2to3 -w lib/xpathhelper.py" to update.
The generated code itself must be ported to python 3 separately.
Hi Rob,
I have a special use case, whereby the REST/JSON API I'm using sends Yang objects in parts.
So each REST call retrieves a single YANG container. When a child container is needed, a new rest call is made. This is done recursively in my case to populate a local set of class bindings.
My trouble is, that the JSON Decoder doesn't seem to like it when a container of type YANGBaseClass is passed to it, instead of a PybindBase class.
Is there a way that the decoder could accept both types?
Hi Rob,
I've recently been trying to import a new Yang Model. I'm not sure if this problem I'm having is a result of that, or a new issue as part of the latest pyangbind codebase.
Anyhow, I'm getting the following error:
Traceback (most recent call last):
File "C:/Projects/git/genband-oneems-service/src/main.py", line 24, in <module>
test = yangtypes.YANGDynClass(base=yangtypes.RestrictedClassType(base_type=yangtypes.RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..4294967295']}), default=yangtypes.RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32)(0), is_leaf=True, yang_name="region-id", register_paths=True, namespace='http://genband.com/acs', defining_module='acs', yang_type='uint32', is_config=True)
File "C:\Projects\git\genband-oneems-service\pyangbind\lib\yangtypes.py", line 345, in RestrictedClassType
return type(RestrictedClass(*args, **kwargs))
File "C:\Projects\git\genband-oneems-service\pyangbind\lib\yangtypes.py", line 271, in __new__
ranges.append(build_length_range_tuples(range_spec))
File "C:\Projects\git\genband-oneems-service\pyangbind\lib\yangtypes.py", line 190, in build_length_range_tuples
high = base_type(high) if not high == "max" else None
File "C:\Projects\git\genband-oneems-service\pyangbind\lib\yangtypes.py", line 320, in __new__
obj = base_type.__new__(self, *args, **kwargs)
OverflowError: Python int too large to convert to C long
When attempting to run the following:
test = yangtypes.YANGDynClass(base=yangtypes.RestrictedClassType(base_type=yangtypes.RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..4294967295']}), default=yangtypes.RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32)(0), is_leaf=True, yang_name="region-id", register_paths=True, namespace='http://genband.com/acs', defining_module='acs', yang_type='uint32', is_config=True)
As you can see, I've tried to isolate the issue a little bit, but in actual practice my code is running something like:
acs = yang_acs.acs()
route_name = "000TestK_%s" % sql_call_route.CR_NAME
cr = acs.call_routing.route.add(route_name)
That in turn is instantiating the bindings object which runs this line in my bindings file:
self.__region_id = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..4294967295']}), default=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32)(0), is_leaf=True, yang_name="region-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://genband.com/acs', defining_module='acs', yang_type='uint32', is_config=True)
The yang for the region_id is as follows:
leaf region-id {
// add description from attribute, name=regionId
description "An identifier to logically group a set of calling routes in a region; the Region ID is only used in percentage based routing; Default=0.";
// match attribute mode=type: name=regionId type=long
type uint32 {
// match constraint type=range: # values=1
range "0..4294967295";
}
default "0";
} // leaf region-id
Anyway, the range seems valid for a 32bit unsigned integer. I'm not really sure what the point is in providing a range when that range is the full capacity of the data type.
Any ideas?
Cheers,
Mark
Hi Rob,
I feel like I'm missing something very simple at this end. I just did a pull from the Master branch, and tried to generate my Class Bindings.
I get the following error message now:
Running: python C:\Python\Libraries\pyang\bin\pyang --plugindir C:\Python\Libraries\pyangbind -f pybind C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\sbc-common.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\signaling-firewall.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\system.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\feature-profiles.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\rate-limiting.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\vnets.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\media.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\message-manipulation.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\call-admission-control.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\fmm.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\signaling-firewall.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\realms.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\call-routing.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\sip.yang C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\acs-yang\endpoints.yang
Traceback (most recent call last):
File "C:\Python\Libraries\pyang\bin\pyang", line 425, in <module>
run()
File "C:\Python\Libraries\pyang\bin\pyang", line 30, in run
plugin.init(plugindirs)
File "C:\Projects\git\genband-oneems-service\.venv\lib\site-packages\pyang\plugin.py", line 37, in init
pluginmod = __import__(fname[:-3])
File "C:\Python\Libraries\pyangbind\pybind.py", line 1, in <module>
Pyangbind/plugin/pybind.py
NameError: name 'Pyangbind' is not defined
This is a Windows 10, Python 2.7.11 installation.
Any ideas?
I'm trying to write some serialisation code to output Netconf XML. My problem is that when examining a node I can't tell whether it's empty
or boolean
. For example in the test case boolean-empty.yang
:
container container {
leaf b1 {
type boolean;
description
"A test leaf";
}
leaf b2 {
type boolean;
default "false";
description
"A test leaf with a default";
}
leaf e1 {
type empty;
description
"A test empty leaf";
}
}
t.container.b1
and t.container.e1
seem to look and act identically to my code, but I need to differentiate them in order to generate valid XML.
I can see how I could add another metadata field to the YangDynType
for this, but I want to make sure I'm not missing some way of differentiating these cases using the information that's already available.
Hi,
I see pyangbind doesn't have support of type bits. I think this could be a good feature to extend the pyangbind plugin.
Hi,
I had a problem where extensions for a model are not added to the extensions dictionary when they are specified for a container.
I used the following setup:
The python classes have been generated using the following command:
pyang --plugindir /path/to/python/venv/lib/python2.7/site-packages/pyangbind/plugin --interesting-extension test-ext -f pybind -o test.py test.yang
The following results are observed (ipython output):
In [1]: import test
In [2]: test.test()._get_c1()._extensions()
In [3]: test.test()._get_l1()._extensions()
Out[3]: {u'test-ext': {u'version': u'1.0'}}
Aren't the extensions supposed to be extracted also for containers?
Hi Rob,
I've got a snippet of code, which takes a generic bindings object, and tries to determine an appropriate SQL Datatype to use for it. The code is roughly based on the JSON Serialiser functionality. Or at least, an older iteration of that code.
The code takes a PybindBase
decendant, and attempts to map a SQL datatype...
# Key definition
self.is_key_val = obj._is_keyval
# Column data type
if hasattr(obj, "_pybind_base_class"):
# Special Data Type, could include constraints
pybind_type = getattr(obj, "_pybind_base_class")
if pybind_type == "pyangbind.lib.yangtypes.RestrictedClass":
pybind_type = getattr(obj, "_restricted_class_base")[0]
else:
pybind_type = obj.__name__
if pybind_type in ['int', 'long']:
self.mapped_type = "Integer"
# TODO
# elif pybind_type in ["pyangbind.lib.yangtypes.RestrictedPrecisionDecimal"]:
# self.mapped_type = "Float"
elif pybind_type in ["pyangbind.lib.yangtypes.YANGBool"]:
self.mapped_type = "Boolean"
elif pybind_type == "unicode":
self.mapped_type = "Unicode"
# TODO
# elif pybind_type in ["bitarray.bitarray", "lib.yangtypes.ReferencePathType"]:
# self.mapped_type = "None" #to-do
else:
raise Exception('Unmapped PyangBind Type Encountered: ', pybind_type)
This all works fine, and I'm now trying to see if I can improve this to include a maximum column size in the case of restricted values.
Case in point,
leaf registration-id {
description "The registration-id of the default destination endpoint.";
type string {
length "1..67";
}
}
self.__registration_id = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'length': [u'1..67']}), is_leaf=True, yang_name="registration-id", parent=self, choice=(u'selection', u'use-endpoint-default-server'), path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://genband.com/acs', defining_module='acs', yang_type='string', is_config=True)
I have a difficult time with the YANGDynClass definitions, and how one can inspect them during run-time. My debugger (PyCharm Community Edition) seems to show me very little when I attempt to inspect these.
I'm curious what information I might be able to pull out at run-time that might help me, such as the restriction-dict relating to the pybinding element.
I hope this makes sense,
Thanks,
Mark
Hi Rob,
I came across a Yang module that uses the 'bits' built-in Yang type.
Is this currently supported/implemented?
On that note, I wonder if it might be worth adding to the readme somewhere the currently supported/unsupported Yang features. (Sorry if I've missed that somewhere).
Here is a sample of some 'bits' yang...
module test {
namespace "http://test.com/test";
prefix "test";
typedef NacmAccessOperationsType {
type bits {
bit create {
position "0";
}
bit read {
position "1";
}
bit update {
position "2";
}
bit delete {
position "3";
}
bit exec {
position "4";
}
}
}
}
If bits is supported, I'm having the following issue when I try to generate class bindings. Program output:
Pyangbind Version: 0.1.1
Running: python C:\Python\Libraries\pyang\bin\pyang --plugindir C:\Python\Libraries\pyangbind\pyangbind\plugin -f pybind C:\Projects\git\genband-oneems-service\doc\genview_1.0\yang\model\test.yang
[(0, 255)]
[(0, 65535)]
[(0, 4294967295L)]
[(0L, 18446744073709551615L)]
[(-127, 127)]
[(-32767, 32767)]
[(-2147483647, 2147483647)]
[(-9223372036854775807L, 9223372036854775807L)]
from operator import attrgetter
from pyangbind.lib.yangtypes import RestrictedPrecisionDecimalType, RestrictedClassType, TypedListType
from pyangbind.lib.yangtypes import YANGBool, YANGListType, YANGDynClass, ReferenceType
from pyangbind.lib.base import PybindBase
from decimal import Decimal
from bitarray import bitarray
could not find a match for test:NacmAccessOperationsType type -> [u'bits']
could not find a match for NacmAccessOperationsType type -> [u'bits']
Traceback (most recent call last):
File "C:\Python\Libraries\pyang\bin\pyang", line 434, in <module>
run()
File "C:\Python\Libraries\pyang\bin\pyang", line 408, in run
emit_obj.emit(ctx, modules, fd)
File "C:\Python\Libraries\pyangbind\pyangbind\plugin\pybind.py", line 205, in emit
build_pybind(ctx, modules, fd)
File "C:\Python\Libraries\pyangbind\pyangbind\plugin\pybind.py", line 361, in build_pybind
build_typedefs(ctx, defn['typedef'])
File "C:\Python\Libraries\pyangbind\pyangbind\plugin\pybind.py", line 542, in build_typedefs
raise TypeError("could not resolve typedefs %s" % error_ids)
TypeError: could not resolve typedefs [u'test:NacmAccessOperationsType', u'NacmAccessOperationsType']
Process finished with exit code 0
Rob, I notice that my program output is printing some odd values at the start prior to outputting the class bindings, is there some debug code which has been left in the current master branch?
Cheers,
Mark
A number of folks have commented that numpy
is heavy; and the code really doesn't justify its use. This issue tracks implementing an alternative approach to use of numpy for (u)?int{8,16,32,64}.
I just tried to generate bindings for some modules, one of which happens to have a 'continue' field. When you try to use the binding, python gets very confused:
File "/home/msuther/Repositories/netconf-utils/bindings.py", line 5106
continue = property(_get_continue, _set_continue)
^
SyntaxError: invalid syntax
I suspect this will probably happen for most python built-ins.
No support for cases where a restriction is placed on a typedef - for example (from ietf-inet-types.yang):
typedef ipv4-address-no-zone {
type inet:ipv4-address {
pattern '[0-9\.]*';
}
description
"An IPv4 address without a zone index. This type, derived from
ipv4-address, may be used in situations where the zone is
known from the context and hence no zone index is needed.";
}
In this case, pyangbind will not parse the "pattern" statement.
RFC6020 states that the following stmts should be supported (but with restrictions to their applicability based on the base type):
+------------------+---------+-------------+
| substatement | section | cardinality |
+------------------+---------+-------------+
| bit | 9.7.4 | 0..n |
| enum | 9.6.4 | 0..n |
| length | 9.4.4 | 0..1 |
| path | 9.9.2 | 0..1 |
| pattern | 9.4.6 | 0..n |
| range | 9.2.4 | 0..1 |
| require-instance | 9.13.2 | 0..1 |
| type | 7.4 | 0..n |
+------------------+---------+-------------+
It is not clear (and the fix for this issue needs to determine) how restrictions are layered - for example, should a string type with a specified pattern then have another pattern that is applied on top of it?
Hi ,
I have following yang file.
identity address-family {
description
"Base identity from which address
families are derived.";
}
identity lcaf {
base address-family;
description
"address family.";
}
identity source-dest {
base lcaf;
description
"Source/Dest LCAF type.";
}
typedef address-family-ref {
type identityref {
base address-family;
}
description
"address family reference.";
}
grouping address {
description
"Generic address.";
leaf address-type {
type address-family-ref;
mandatory true;
description
"Type of the address.";
}
}
Here address -> address-type is of type address-family-ref which is identityref deriving the address-family. Now I want to set leaf address-type in address as source-dest type but It is giving me value error. source-dest is not directly inheriting from the address-type, Is that the case?
Error:
Traceback (most recent call last):
File "generate.py", line 7, in <module>
Object.eid.address_type = 'source-dest-key-lcaf'
File "/home/ashish/odl_test/bindings.py", line 70, in _set_address_type
raise ValueError("""address_type must be of a type compatible with base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'foo:lcaf': {}, u'lcaf': {}},), is_leaf=True, yang_name="address-type", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True""")
ValueError: address_type must be of a type compatible with base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'foo:lcaf': {}, u'lcaf': {}},), is_leaf=True, yang_name="address-type", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True
When testing pybind against the OpenConfig routing policy models, there is a problem resolving one of the complex union types (that has a dependency on external YANG modules)
could not find a match for tag-type type
could not find a match for pt:tag-type type
...
TypeError: could not resolve typedefs ['tag-type', 'pt:tag-type']
the type in question (in policy-types.yang):
typedef tag-type {
type union {
type uint32;
type yang:hex-string;
}
description "type for expressing route tags on a local system,
including IS-IS and OSPF; may be expressed as either decimal or
hexidecimal integer";
reference
"RFC 2178 OSPF Version 2
RFC 5130 A Policy Control Mechanism in IS-IS Using
Administrative Tags";
}
the hex-string type is in ietf-yang-types
typedef hex-string {
type string {
pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
}
description
"A hexadecimal string with octets represented as hex digits
separated by colons. The canonical representation uses
lowercase characters.";
}
I'm not yet familiar with the plugin's type processing, but it seems this type is not found in the list passed to build_typedefs()
With the following structure:
module mod-1 {
include remote-one { prefix rem1; }
}
module mod-2 {
include remote-two { prefix rem2; }
}
remote-two is never parsed - and hence any type definitions in remote-two are not known. We need to build a list of modules, which must ensure that depth is preserved, so that referenced typedefs are known.
Hi,
I was trying to parse the yang models using pyangbind. It includes import, does pyangbind plugin supports import because, I am getting following error.
pyangbind-example.yang:36: error: unexpected keyword "import"
pyangbind-example.yang:36: error: module "ietf-yang-types" not found in search path
pyangbind-example.yang:36: warning: imported module ietf-yang-types not used
FATAL: pyangbind cannot build module that pyang has found errors with.
My file is something like:
module pyangbind-example {
namespace "urn:ietf:params:xml:ns:yang:ietf-lisp-address-types";
prefix laddr;
import ietf-yang-types { prefix yang; }
// Omitted later part
Please help me if I am missing something. I am new to yang models and trying to understand various yang concepts as well.
Are groupings supported? If not please consider adding the feature.
From my short look at the code i would conclude that groupings are not supported yet.
For a YANG type containing a list which has a String Key, the Add and Get function expects a space delimited key string representation.
For example, a list which has a key of a String Value and an Integer value, the add function might expect:
somelist.add("somekeystring 1")
This logic breaks when the String key value contains a space
somelist.add("some key string 1")
On another note, is it possible for yangtypes.YANGListType.YANGList.add() to return a pointer to the newly created list object? Rather than the key value?
This shortens the following from
somelist.add("somekeystring 1")
newitem = somelist.get("somekeystring 1")
to be
newitem = somelist.add("somekeystring 1")
Thanks,
Mark
Hi,
I'm developing an app using pyangbind and I found a problem with the serialization of decimal64 leafs.
Example Model:
module test {
namespace "urn:test:test";
prefix t;
typedef Interval { type decimal64 { fraction-digits 2; } }
container cont { leaf period { type Interval; default "0"; } }
}
I'm generating the binding python module by running:
export PYBINDPLUGIN=`/usr/bin/env python -c 'import pyangbind; import os; print "%s/plugin" % os.path.dirname(pyangbind.__file__)'`
pyang --plugindir $PYBINDPLUGIN -f pybind -o test.py test.yang
And the test app in python:
from test import test
import pyangbind.lib.pybindJSON as pybindJSON
t = test()
t.cont.period = 1
pybindJSON.dump(t, 'output.json', filter=False, mode="ietf")
When I run the app with:
python Main.py
Next exception is thrown:
Traceback (most recent call last):
File "Main.py", line 8, in <module>
pybindJSON.dump(t, 'output.json', filter=False, mode="ietf")
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/pybindJSON.py", line 168, in dump
skip_subtrees=skip_subtrees, mode=mode))
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/pybindJSON.py", line 158, in dumps
return json.dumps(tree, cls=cls, indent=indent)
File "/usr/lib/python2.7/json/__init__.py", line 250, in dumps
sort_keys=sort_keys, **kw).encode(obj)
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/serialise.py", line 489, in encode
self._preprocess_element(obj, mode="ietf"))
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/serialise.py", line 54, in _preprocess_element
nd[k] = self._preprocess_element(d[k], mode=mode)
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/serialise.py", line 58, in _preprocess_element
nd[k] = self.default(d[k], mode=mode)
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/serialise.py", line 492, in default
return pybindJSONEncoder().default(obj, mode="ietf")
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/serialise.py", line 156, in default
type(obj), obj))
AttributeError: Unmapped type: period, Interval, RestrictedPrecisionDecimal, RestrictedPrecisionDecimal, <class 'pyangbind.lib.yangtypes.YANGBaseClass'>, 1.00
If I modify the YANG module replacing type decimal64 { fraction-digits 2; }
by type uint32
and regenerate the binding module the app works as expected.
Am I doing something wrong or is it a bug in pyangbind?
Thanks in advance!
Lluis
I'm writing some code that's attempting to make automated changes to a Pyangbind object tree (for model-based testing). In order for my code to make valid changes, it needs to know the types of fields, their constraints and which of them are non-configurable status fields. Obviously I can extract this information from the Yang model separately, but it seems a shame that I've already got the Pyangbind object in front of me but I can't query it to find metadata.
One obvious problem is how to expose this. The ideal would be something like:
>>> config.users.username.is_config
True
>>> config.users.date_created.is_config
False
But if this ends up applied to non-leafs it could get confused with a real Yang member. Perhaps it actually belongs on the type (since it's a property of the type and not the value stored in it), so it would be something like:
>>> type(config.users.username).is_config
True
This is currently unhanded, and is used in routing-policy.yang:
grouping generic-actions {
description
"Definitions for common set of policy action statements that
manage the disposition or control flow of the policy";
choice route-disposition {
description
"Select the final disposition for the route, either
accept or reject.";
leaf accept-route {
type empty;
description "accepts the route into the routing table";
}
leaf reject-route {
type empty;
description "rejects the route";
}
}
}
When "config: false" is set on a container, the leaves that are contained in it are not marked as config: false. A mechanism for the config state of the parent container to be carried between get_children()
methods is needed.
I'm using yang files - turing_machine.yang and second_tape.yang under doc/tutorials/examples at https://github.com/mbj4668/pyang.git for generating python bindings, and observed that pyangbind plugin is not generating bindings for yang files that have augment keyword. Below is the generated bindings for the second_tape.yang that augments turning_machine.yang. Is this intentional or is it a bug? Any input on this issue will be of great help.
class second_tape(PybindBase):
"""
This class was auto-generated by the PythonClass plugin for PYANG
from YANG module second-tape - based on the path /second-tape. Each member element of
the container is represented as a class variable - with a specific
YANG type.
"""
pass
Hi Rob,
I see that currently there is no support for generating netconf request from generated classes. Is there any plans to add that support?
Thanks,
Arpit
If we release the module to PyPI we wont face below issues while importing
>>> import bgp
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "bgp/__init__.py", line 3, in <module>
from lib.yangtypes import RestrictedPrecisionDecimalType, RestrictedClassType, TypedListType
ImportError: No module named lib.yangtypes
currently to get rid of this issue, we have to define PYTHONPATH to the cloned folder path.
openconfig-rib-bgp.yang requires support for the binary type, which is currently unsupported in pyangbind.
Steps to reproduce:
[~/Code/pyangbind/tmp(master*)]
(9:21 - s029) latte> python
Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>> from ocbind import openconfig_interfaces
>>> o = openconfig_interfaces()
>>>
>>> from pyangbind.lib.serialise import pybindIETFJSONEncoder
>>> import json
>>>
>>> json.dumps(o, cls=pybindIETFJSONEncoder)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 250, in dumps
sort_keys=sort_keys, **kw).encode(obj)
File "/Users/rjs/Library/Python/2.7/lib/python/site-packages/pyangbind/lib/serialise.py", line 459, in encode
self._preprocess_element(obj, mode="ietf"))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
File "/Users/rjs/Library/Python/2.7/lib/python/site-packages/pyangbind/lib/serialise.py", line 462, in default
return pybindJSONEncoder().default(obj, mode="ietf")
File "/Users/rjs/Library/Python/2.7/lib/python/site-packages/pyangbind/lib/serialise.py", line 155, in default
(elem_name, orig_yangt, pybc, pyc))
AttributeError: Unmapped type: None, None, None, None
Suspected cause: pybindIETFJSONEncoder may not handle native types that don't have wrapper classes - determine where these might occur in the non-filtered get() output.
See: #23 (comment)
Hi,
The yang model of "openconfig-local-routing.yang" is changed against you described, so static_route_example.py
is not working anymore. See below:
module: openconfig-local-routing
+--rw local-routes
+--rw config
+--ro state
+--rw static-routes
| +--rw static* [prefix]
| +--rw prefix -> ../config/prefix
| +--rw config
| | +--rw prefix? inet:ip-prefix
| | +--rw set-tag? oc-pt:tag-type
| +--ro state
| | +--ro prefix? inet:ip-prefix
| | +--ro set-tag? oc-pt:tag-type
| +--rw next-hops
| +--rw next-hop* [index]
| +--rw index -> ../config/index
| +--rw config
| | +--rw index? string
| | +--rw next-hop? union
| | +--rw metric? uint32
| | +--rw recurse? boolean
| +--ro state
| | +--ro index? string
| | +--ro next-hop? union
| | +--ro metric? uint32
| | +--ro recurse? boolean
| +--rw interface-ref
| +--rw config
| | +--rw interface? -> /oc-if:interfaces/interface/name
| | +--rw subinterface? -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
| +--ro state
| +--ro interface? -> /oc-if:interfaces/interface/name
| +--ro subinterface? -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
+--rw local-aggregates
+--rw aggregate* [prefix]
+--rw prefix -> ../config/prefix
+--rw config
| +--rw prefix? inet:ip-prefix
| +--rw discard? boolean
| +--rw set-tag? oc-pt:tag-type
+--ro state
+--ro prefix? inet:ip-prefix
+--ro discard? boolean
+--ro set-tag? oc-pt:tag-type
So, I modified the example code in "static_route_example.py" in accordance with this change, specifically, from rt.config.next_hop.append("10.0.0.1")
to rt.next_hops.next_hop.add("10.0.0.1")
. However, it occurs AttributeError: 'YANGBaseClass' object has no attribute 'next_hop'
.
Am I missing something?
Thanks~
Hi,
I am adding some values to the YANG list. In the output I am getting an extra field of "__yang_order". Can someone please tell me how to remove it from the output because I think it is for some internal use of pyangbind which is getting reflected to my final output.
{'locator_id': 'ISP1'}
{'hop_id': 'Hop 1'}
{'hop_id': 'Hop 2'}
{
"input": {
"LocatorRecord": {
"ISP1": {
"locator-id": "ISP1",
"rlocProbed": false,
"weight": 1,
"multicastPriority": 255,
"localLocator": true,
"routed": false,
"priority": 1,
"rloc": {
"address-type": "ietf-lisp-address-types:explicit-locator-path-lcaf",
"explicit-locator-path": {
"hop": {
"Hop 1": {
"__yang_order": 0,
"hop-id": "Hop 1",
"lrs-bits": "lookup rloc-prob strict",
"address": "20.20.20.20"
},
"Hop 2": {
"__yang_order": 1,
"hop-id": "Hop 2",
"lrs-bits": "lookup strict",
"address": "30.30.30.30"
}
}
}
},
"multicastWeight": 0
}
},
"mapping-record": {
"recordTtl": 1440,
"action": "NoAction",
"authoritative": true,
"mapVersion": 10
}
}
}
Hi Rob,
In the application I'm developing, I need to navigate through a datastore using a path that is not known in advance. Then, when an object is found, I need to modify that object. To implement this functionality I considered using a scheme such as that proposed by you in the tutorial: obj["local-routes"]["static-routes"]["static"]["192.0.2.1/32"]. However, this scheme reports an exception.
Let me illustrate what I want to do with an example:
Assume we have the next simple model:
module local-routing {
namespace "urn:local-routing:local-routing";
prefix "t";
container local-routes {
list static {
key prefix;
leaf prefix { type string; }
leaf next-hop { type string; }
}
}
}
We generate the Python bindings using:
export PYBINDPLUGIN=`/usr/bin/env python -c 'import pyangbind; import os; print "%s/plugin" % os.path.dirname(pyangbind.__file__)'`
pyang -V --plugindir $PYBINDPLUGIN -f pybind -o local_routing.py local-routing.yang
Assume that we pre-loaded the datamodel using the next code:
from local_routing import local_routing
import pyangbind.lib.pybindJSON as pybindJSON
lr = local_routing()
rt1 = lr.local_routes.static.add("192.0.1.0")
rt1.next_hop = "192.0.0.1"
So a dump with print pybindJSON.dumps(lr, filter=False)
reports:
{
"local-routes": {
"static": {
"192.0.1.0": {
"next-hop": "192.0.0.1",
"prefix": "192.0.1.0"
}
}
}
}
Then, given an input path in a string variable, split the route into its parts and adapt the names to your internal representation:
path = "/local-routes/static/192.0.1.0"
pathHops = path.split('/')
pathHops = filter(lambda x: len(x) > 0, pathHops)
pathHops = map(lambda x: x.replace('-', '_'), pathHops)
print pathHops # reports: ['local_routes', 'static', '192.0.1.0']
Then starting from the root, we navigate to the desired element:
ptr = lr # lr is the root object in the pre-loading code
for pathHop in pathHops:
ptr = ptr[pathHop]
This code reports the next Exception:
Traceback (most recent call last):
File "Main.py", line 21, in <module>
ptr = ptr[pathHop]
File "/usr/local/lib/python2.7/dist-packages/pyangbind/lib/base.py", line 88, in __getitem__
return element()
TypeError: 'YANGBaseClass' object is not callable
I think the problem is with that ()
in return element()
. I tried removing such ()
and seems to work, but I do not know whether I'm breaking some other things.
Could you confirm that it is a bug and that is the right way to navigate through the datastore?
TIA.
Lluis
leafrefs are currently supported as a string, there is no validation against the path that is used - a pointer type needs to be implemented.
Hi Rob,
Please see pull request #61
I've included an example in my pull request (texts\int\int.yang) to demonstrate the broken functionality, but here's an example:
leaf restricted-ueight-min-alias {
type int8 {
range "min..max";
}
}
I couldn't work out where the min and max keywords get translated into an integer representation. Perhaps it's done via pyang, I don't know.
Thanks,
Mark
Hi Rob,
The Yang model I'm using, makes use of ietf-inet-types, specifically the ip-address type, which is a union of either an ipv4 address, or an ipv6 address.
I can import and generate class bindings OK, setting or getting an IP-Address is no problem.
I've however noticed that the REST API I'm communicating with is passing this object in a strange way when passing JSON. Let me provide an example, but first, here is the relevant YANG
(Please note, prefix, namespace, descriptions and other non-relevant items have been omitted)
File: ietf-inet-types.yang
module ietf-inet-types {
typedef ip-address {
type union {
type inet:ipv4-address;
type inet:ipv6-address;
}
}
typedef ipv4-address {
type string {
pattern
'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+ '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+ '(%[\p{N}\p{L}]+)?';
}
}
typedef ipv6-address {
type string {
pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+ '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+ '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+ '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+ '(%[\p{N}\p{L}]+)?';
pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+ '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+ '(%.+)?';
}
}
}
File: sbc-common.yang
module sbc-common {
import ietf-inet-types {
prefix inet;
}
grouping ip-address {
leaf ip-address {
description
"An IPv4 or IPv6 address.";
type inet:ip-address;
}
}
}
File: endpoints.yang
module endpoints {
grouping endpoint-list {
list endpoint {
uses sbc-common:ip-address {
refine "ip-address" {
description
"The IPv4 or IPv6 address of the endpoint.";
}
}
}
}
}
Here is the IP Address declaration in the endpoint __init__
function
self.__ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\\p{N}\\p{L}]+)?'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\\p{N}\\p{L}]+)?'}),], is_leaf=True, yang_name="ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='<omitted>', defining_module='sbc-common', yang_type='inet:ip-address')
And here is the Setter method:
def _set_ip_address(self, v, load=False):
try:
t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\\p{N}\\p{L}]+)?'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\\p{N}\\p{L}]+)?'}),], is_leaf=True, yang_name="ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://genband.com/sbc/sbc-common', defining_module='sbc-common', yang_type='inet:ip-address')
except (TypeError, ValueError):
raise ValueError("""ip_address must be of a type compatible with base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\\p{N}\\p{L}]+)?'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\\p{N}\\p{L}]+)?'}),], is_leaf=True, yang_name="ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://genband.com/sbc/sbc-common', defining_module='sbc-common', yang_type='inet:ip-address'""")
self.__ip_address = t
if hasattr(self, '_set'):
self._set()
The trouble comes with the API end, and how it passes IP Address information back and forward.
What I might have expected out of a REST/JSON API, would be something like:
"ipAddress": "10.64.1.101"
Instead what I am seeing is the following:
"ipAddress": {
"ipv6Address": null,
"ipv4Address": "10.64.1.101"
}
Even if I can manage to massage the data when deserializing this, I don't see how I could serialize this back to JSON, and know which type of IP-Address is in use.
In the class bindings, is there a way to figure out which union type is in use?
I'm not sure what approach to take here. I could fudge things a bit, and manually work out what IP Address type is in use, and tweak the JSON values before serialization/deserialization.. however I'd pefer a way to identify which IP Address is in use via the Class Bindings object.
I hope I'm not missing something more obvious, or some other better way to remedy this situation.
Any Ideas?
Thanks,
Mark
Hi Rob,
Is there a good way to dynamically iterate through the class structure of a binding object?
At the moment I am doing the following:
for element_name in obj._pyangbind_elements:
element = getattr(obj, element_name, self._element_error)
if hasattr(element, "get"):
if isinstance(element, PybindBase):
# YANG Container that has its own GET
# Call recursive function, with create_table set to False
self._build_tables(element, False, parent_table, heirachy)
else:
# YANG List, requires a new child table
if hasattr(element, "_contained_class"):
print 'list: ' + element_name
child_obj = self._get_item_from_list(element)
if create_table:
self._build_tables(child_obj, True, table, heirachy)
else:
self._build_tables(child_obj, True, parent_table, heirachy)
else:
print 'leaf list: ' + element_name
print element
I can't help but feel like there could be a simpler way to iterate through the hierarchy. What do you think?
Thanks,
Mark
Hi Rob,
In the case of a Keyed list, is it possible to append an item which has already been instantiated to the list?
Currently my code looks like this when creating list items:
ep_list = ep_container.endpoint
ep = ep_list.add(registration_id="Test-Endpoint")
What I would like to achieve is the following:
ep_list = ep_container.endpoint
ep = yc_endpoint_endpoints__endpoints_endpoint()
ep.registration_id = "Test-Endpoint"
ep_list.add(ep)
Alternatively some sort of Assign might be useful:
ep1 = yc_endpoint_endpoints__endpoints_endpoint()
ep2 = yc_endpoint_endpoints__endpoints_endpoint()
ep1.assign(ep2)
RFC 6020 allows ranges to be discontinuous, using the | to separate each sub-range, as long as the range delimiters increase from left to right. For example the following is allowed:
type int8 {
range "-10 .. -5 | 5 .. 10 | 20 .. 30"
}
See section 9.2.4 for details: https://tools.ietf.org/html/rfc6020#section-9.2.4
This also seems to apply to string lengths: https://tools.ietf.org/html/rfc6020#section-9.4.4
If such a range exists in an input yang file, the follow error occurs:
File "/home/msuther/Repositories/pyangbind/lib/yangtypes.py", line 839, in YANGDynClass
return YANGBaseClass(*args, **kwargs)
File "/home/msuther/Repositories/pyangbind/lib/yangtypes.py", line 717, in __init__
raise TypeError, "couldn't generate dynamic type -> %s -> %s" % (type(e),e)
TypeError: couldn't generate dynamic type -> <type 'exceptions.ValueError'> -> too many values to unpack
Hi I have following YANG object
module pyangbind-example {
yang-version "1";
namespace "http://rob.sh/pyangbind/example";
prefix "example";
organization "pyangbind";
contact "[email protected]";
description
"A test module that checks that the plugin works OK";
revision 2015-04-30 {
description "Initial Release";
reference "release.00";
}
container parent {
description
"A container";
leaf integer {
type int8;
description
"A test leaf for uint8";
}
}
container mapping-record {
leaf recordTtl {
type int32;
}
leaf maskLength {
type uint8;
}
leaf mapVersion {
type int16;
}
leaf action {
type enumeration {
enum NoAction;
enum NativelyForward;
enum SendMapRequest;
enum Drop;
}
}
leaf authoritative {
type boolean;
}
}
list LocatorRecord {
key "locator-id";
leaf locator-id {
type string;
}
leaf priority {
type uint8;
}
leaf weight {
type uint8;
}
leaf multicastPriority {
type uint8;
}
leaf multicastWeight {
type uint8;
}
leaf localLocator {
type boolean;
}
leaf rlocProbed {
type boolean;
}
leaf routed {
type boolean;
}
}
}
I have written a python script to produce the json output from the python bindings provided by pyangbind but I am not getting the correct output
Python script
import json
from bindings import pyangbind_example
from pyangbind.lib.serialise import pybindJSONEncoder
### Generate rpc_add-mapping_ipv4_elp.json
Object = pyangbind_example()
## - replaced by _
Object.mapping_record.authoritative = True
Object.mapping_record.mapVersion = 10
Object.mapping_record.action = "NoAction"
Object.mapping_record.recordTtl = 1440
## List
Object.LocatorRecord.add("ISP1")
Object.LocatorRecord["ISP1"].priority = 1
Object.LocatorRecord["ISP1"].weight = 1
Object.LocatorRecord["ISP1"].multicastPriority = 255
Object.LocatorRecord["ISP1"].multicastWeight = 0 ## From Here Not Getting printed in the JSON output
Object.LocatorRecord["ISP1"].localLocator = True
Object.LocatorRecord["ISP1"].rlocProbed = False
Object.LocatorRecord["ISP1"].routed = False
print json.dumps(Object.get(filter=True), \
cls=pybindJSONEncoder, indent=4)
Current Output:
{
"LocatorRecord": {
"ISP1": {
"priority": 1,
"localLocator": true,
"locator-id": "ISP1",
"weight": 1,
"multicastPriority": 255
}
},
"mapping-record": {
"recordTtl": 1440,
"action": "NoAction",
"authoritative": true,
"mapVersion": 10
}
}
Expected output should contain multicastWeight, localLocator, rlocProbed, etc. But It is not showing. Any help please.
Thanks
If I have a choice node that has a list node in each subtree (with the same name in each), then I can't insert elements into the list. I've got a branch that illustrates this in a unit test (https://github.com/timmartin/pyangbind/tree/nested_branch_list), but here's the summary:
Yang:
choice choice-one {
case case-one {
container case-one-container {
list user {
key "username";
//...
}
}
container case-two-container {
list user {
key "username";
//...
}
}
}
}
}
Python:
>>> t.container.case_one_container.user.add("first")
>>> t.container.case_one_container.user["first"]
KeyError: 'first'
I notice that in the bindings.py
there are two identically-named classes (yc_user_choice__container_choice_one_user
) generated for the list in each branch. I haven't figured out whether this is the root cause.
Note: Two changes to resolve under this ticket:
According to RFC6020, a list that is config: false may not have a key statement - this is currently not supported in pyangbind.
Example module - yang/vendor/cisco/xr/530/Cisco-IOS-XR-cdp-oper.yang
container neighbors {
xr:xr-xml-map "cdp_oper:Neighbors";
description "The CDP neighbor tables on this node";
container details {
xr:xr-xml-map "cdp_oper:DetailTable";
description "The detailed CDP neighbor table";
list detail {
xr:xr-xml-map "cdp_oper:Detail";
description
"Detailed information about a CDP neighbor
entry";
leaf interface-name {
xr:xr-xml-map "cdp_oper:InterfaceName";
type xr:Interface-name;
description "The interface name";
}
leaf device-id {
xr:xr-xml-map "cdp_oper:DeviceID";
type string;
description "The neighboring device identifier";
}
uses CDP-NEIGHBOR;
}
}
I am working with a REST/JSON implementation, and serializing from JSON into Class Bindings
In the Yang model, there is a leaf with a range specified.
leaf max-call-duration {
description
"The limit in seconds on how long calls or call attempts can be in the system for the endpoint; Default=0.";
type uint16 {
range "1..max";
}
units "seconds";
}
In the JSON being received, I am receiving a null value
maxCallDuration": null,
(Please ignore the different key name format in camel case, that's a quirk of the API)
In python, it generates a ValueError:
ValueError: max_call_duration must be of a type compatible with base=RestrictedClassType(base_type=np.uint16, restriction_dict={'range': [u'1..max']}), is_leaf=True, yang_name="max-call-duration", parent=self, path_helper=self._path_helper, extmethods=self._extmethods
I'm curious if this is a problem with the YANG definition, or potentially the Yang Blinding object should accept Null?
Any thoughts?
Thanks,
Mark
The errors returned today are too verbose, and do not give useful information - update them to be more user-friendly.
OS: Windows 10
IDE: PyCharm Community Edition 5.0.2
Repo: https://pypi.python.org/pypi
Python: 2.7.11 (venv)
PyangBind version: 0.2.1
Attempt to install pyangbind into my venv gives me the following error (extraneous detail omitted)
ERROR: 'xslt-config' is not recognized as an internal or external command,
operable program or batch file.** make sure the development packages of libxml2 and libxslt are installed **
..
file: 'libxml/xpath.h': No such file or directory
Could not find function xmlCheckVersion in library libxml2. Is libxml2 installed?
Is there a package dependency I'm missing? I tried installing libxml2-python, however that installation fails too:
Collecting libxml2-python
Could not find a version that satisfies the requirement libxml2-python (from versions: )
No matching distribution found for libxml2-python
When a container is specified without any child, the container is not captured in the classes generated by pyangbind (version 0.5.2). For example, new-topo.yang with the following content:
module new-topo {
namespace "urn:network:new-topo";
prefix "new-topo";
container network-types {
container new-net {
presence "Presence of this container indicates that network type is new-net";
}
}
}
Pyangbind does not create a class for new-net.
Output of pyang --strict -f tree new-topo.yang:
module: new-topo
+--rw network-types
+--rw new-net!
I am trying to bind using following command but getting unsupported format 'pybind' error.
sudo pyang --plugindir site-packages/pyangbind/plugin -f pybind turing-machine.yang -o bindings.py
Can someone please help me with this.
Issue to track feature branch to create a factory class that can take a pyangbind class hierarchy and create JSON.
Where a list has a key that is composed of >1 value, this is not supported. It is used in routing-policy.yang:
list prefix {
key "address masklength masklength-range";
description
"list of prefix expressions that are part of the set";
leaf address {
type inet:ip-address;
mandatory true;
description
"address portion of the prefix";
}
leaf masklength {
type uint8 {
// simple range covers both ipv4 and ipv6 --
// could separate this into different types
// for IPv4 and IPv6 prefixes
range 0..128;
}
mandatory true;
description
"masklength for the prefix specification";
}
leaf masklength-range {
type string {
// pattern modeled after ietf-inet-types
pattern '(([0-9])|([1-9][0-9])|(1[0-1][0-9])|'
+ '(12[0-8]))\.\.'
+ '(([0-9])|([1-9][0-9])|(1[0-1][0-9])|'
+ '(12[0-8]))';
}
description
"Defines an optional range for the masklength. Absence
of the masklength-length implies that the prefix has an
exact masklength given by the masklength parameter.
Example: 10.3.192.0/21 through 10.3.192.0/24 would be
expressed as address: 10.3.192.0, masklength: 21,
masklength-range: 21..24";
}
}
}
}
Hi Rob,
I'm figuring out how to get a list using XPATH and then add an element to that list.
For example, given the model:
module local-routing {
namespace "urn:local-routing:local-routing";
prefix "t";
container local-routes {
list static {
key prefix;
leaf prefix { type string; }
leaf next-hop { type string; }
}
}
}
I want to do something like (idea, not ):
from lr import local_routing
from pyangbind.lib.serialise import pybindJSONDecoder
from pyangbind.lib.xpathhelper import YANGPathHelper
ph = YANGPathHelper()
lr = local_routing(path_helper=ph)
path = "/local-routes/static/"
data = { "next_hop": "192.0.0.1" } # for example loaded with json.loads
selectedList = ph.get_unique(path)
rt = selectedList.add("192.0.4.0")
pybindJSONDecoder.load_ietf_json(data, None, None, obj=rt, path_helper=ph)
Is there any way to do that? I tried with several combinations but none of them worked.
TIA!
Lluis
Hi,
I'm wondering if pyangbind is likely to be able to provide metadata about leafs, particularly their yang type and constraints. It seems as they are mapped directly to python types there's no obvious way to access this information, other than a mention of the yang type in their doc string. Am I missing something?
Mark
I'm seeing the following with the latest master, I have pyang 1.4.1 installed
RUNNING BASE
TESTING /home/msuther/Repositories/pyangbind/tests/xpath/03-current...
/home/msuther/Repositories/pyangbind/tests/xpath/03-current/current-tc03.yang:40: error: current-tc03:referenced in the path's predicate for reference at /home/msuther/Repositories/pyangbind/tests/xpath/03-current/current-tc03.yang:38 is compared with a leaf that is not a correct leafref
FATAL: pyangbind cannot build module that pyang has found errors with.
Traceback (most recent call last):
File "/home/msuther/Repositories/pyangbind/tests/xpath/03-current/run.py", line 69, in <module>
main()
File "/home/msuther/Repositories/pyangbind/tests/xpath/03-current/run.py", line 29, in main
from bindings import current_tc03
ImportError: No module named bindings
TEST FAILED /home/msuther/Repositories/pyangbind/tests/xpath/03-current
TESTING /home/msuther/Repositories/pyangbind/tests/xpath/01-list_leaflist...
TESTING /home/msuther/Repositories/pyangbind/tests/xpath/02-static_ptr...
RESULT: 1 tests failed
# pyang --version
pyang 1.4.1
Looking at the pyang repository this is actually quite an old version. Is pyang 1.6 a requirement?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.