GithubHelp home page GithubHelp logo

pyangbind's Introduction

๐Ÿž Bread Crumbs

  • ๐Ÿ”: Reviewed a pull request in openconfig/gnmi at 2024-04-19 18:41:09 -0700 PDT
  • ๐Ÿšข: Pushed some commits to openconfig/gribigo at 2024-04-19 07:25:18 -0700 PDT
  • ๐Ÿ—‘: Deleted a branch in openconfig/gribigo at 2024-04-19 07:25:18 -0700 PDT
  • ๐Ÿšข: Pushed some commits to openconfig/gribigo at 2024-04-19 07:25:16 -0700 PDT
  • โœ๐Ÿผ: Created a pull request in openconfig/gribigo at 2024-04-19 07:25:15 -0700 PDT
  • ๐Ÿ”: Reviewed a pull request in openconfig/gribigo at 2024-04-19 07:25:10 -0700 PDT
  • ๐Ÿ˜ƒ: Commented on an issue in openconfig/gribigo at 2024-04-19 07:25:02 -0700 PDT
  • ๐Ÿ’ฌ: Commented on a PR in openconfig/ygot at 2024-04-18 23:06:46 -0700 PDT
  • ๐Ÿ”: Reviewed a pull request in openconfig/ygot at 2024-04-18 23:06:47 -0700 PDT
  • โœ๐Ÿผ: Created a pull request in openconfig/ygot at 2024-04-18 11:33:06 -0700 PDT

๐Ÿ•˜ Recent Activity

 21 โ”ผ                                              โ•ญโ”€โ•ฎ
 19 โ”ค                                              โ”‚ โ”‚
 18 โ”ค                                              โ”‚ โ”‚
 17 โ”ค                                             โ•ญโ•ฏ โ•ฐโ•ฎ
 15 โ”ค                                             โ”‚   โ”‚                                       โ•ญโ•ฎ
 14 โ”ค                                            โ•ญโ•ฏ   โ•ฐโ•ฎ                                      โ”‚โ•ฐโ•ฎ
 12 โ”ค                                            โ”‚     โ”‚                                      โ”‚ โ”‚
 11 โ”ค                             โ•ญโ•ฎ             โ”‚     โ•ฐโ•ฎ                                    โ•ญโ•ฏ โ”‚
 10 โ”ค                             โ”‚โ•ฐโ•ฎ           โ•ญโ•ฏ      โ”‚                                    โ”‚  โ•ฐโ•ฎ
  8 โ”ค                            โ•ญโ•ฏ โ”‚           โ”‚       โ•ฐโ•ฎ                                  โ•ญโ•ฏ   โ”‚
  7 โ”ค                            โ”‚  โ•ฐโ•ฎ          โ”‚        โ•ฐโ•ฎ         โ•ญโ”€โ•ฎ      โ•ญโ”€โ”€โ”€โ•ฎ โ•ญโ”€โ”€โ”€โ•ฎ    โ”‚    โ•ฐโ•ฎ
  6 โ”ค                           โ•ญโ•ฏ   โ”‚         โ•ญโ•ฏ         โ”‚        โ•ญโ•ฏ โ•ฐโ•ฎ    โ•ญโ•ฏ   โ•ฐโ”€โ•ฏ   โ•ฐโ•ฎ   โ”‚     โ”‚
  4 โ”ค                           โ”‚    โ•ฐโ•ฎ      โ•ญโ”€โ•ฏ          โ•ฐโ•ฎ      โ•ญโ•ฏ   โ•ฐโ•ฎ  โ•ญโ•ฏ           โ•ฐโ•ฎ โ•ญโ•ฏ     โ”‚
  3 โ”ค                          โ•ญโ•ฏ     โ•ฐโ•ฎ    โ•ญโ•ฏ             โ•ฐโ•ฎ    โ•ญโ•ฏ     โ”‚  โ”‚             โ•ฐโ•ฎโ”‚      โ•ฐโ•ฎ
  1 โ”ค                          โ”‚       โ•ฐโ”€โ”€โ”€โ”€โ•ฏ               โ•ฐโ”€โ”€โ”€โ”€โ•ฏ      โ•ฐโ•ฎโ•ญโ•ฏ              โ•ฐโ•ฏ       โ”‚ โ•ญโ”€โ”€
 -0 โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ                                         โ•ฐโ•ฏ                        โ•ฐโ”€โ•ฏ
    +โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€โ”€โ”€โ”€+โ”€โ”€โ”€โ”€
  00:00   02:00   04:00   06:00   08:00   10:00   12:00   14:00   16:00   18:00   20:00   22:00   00:00   

						Commits by Hour of Day


Since 2024-03-04 13:07:07 -0800 PST, I'm most active between 11:00-11:59 - with 22 events in that hour.

                               |############
 openconfig/gnmi               |############
                               |############

                               |######
 openconfig/ygot               |######
                               |######

                               |#################
 openconfig/featureprofiles    |#################
                               |#################

                               |################
 openconfig/gnoi               |################
                               |################

                               |##################
 openconfig/public             |##################
                               |##################

                               |#
 openconfig/gnsi               |#
                               |#

                               |###########
 openconfig/gribigo            |###########
                               |###########

                               |###########
 openconfig/reference          |###########
                               |###########

                               |#######
 openconfig/magna              |#######
                               |#######

                               |#
 openconfig/bootz              |#
                               |#



Since 2024-03-04 13:07:07 -0800 PST, I've been most active in openconfig/public, with 18 events.

robshakir is not an official Google product.

Last Updated: 2024-04-20 19:10:53.495564966 -0700 PDT

pyangbind's People

Contributors

alf-tierno avatar asloboda-cisco avatar dbarrosop avatar dgjustice avatar eqvinox avatar fperrin avatar gil-obradors avatar gunhanoral avatar joseignaciotamayo avatar krishn2014 avatar ktbyers avatar kvikas avatar marksutherland avatar miguelbf-alb avatar mpainenz avatar robshakir avatar tarkatronic avatar timmartin avatar unsignedint avatar xavier-contreras avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyangbind's Issues

Quirky REST API behavior - Unions

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

Yang definitions:

(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.";
        }
      }
    }
  }

}

Binding Class definitions:

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()

JSON issues:

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

Unable to serialize leafs with 'decimal64' type

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

__yang_order in the YANG lists

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
        }
    }
}

Iterating through the Class structure

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

Lists nested within branches of a choice don't work

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.

YANGList type with string key containing a space char

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

Restrictions on typedefs are not supported

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?

Support for leafref type

leafrefs are currently supported as a string, there is no validation against the path that is used - a pointer type needs to be implemented.

Yang bits built-in type

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

Release for PyPI

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.

Extensions are not put in the dictionary for containers

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?

Support of bits type.

Hi,

I see pyangbind doesn't have support of type bits. I think this could be a good feature to extend the pyangbind plugin.

No support for complex ranges

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

Composite list keys are not supported

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";                                                                                                                        
          }                                                                                                                                                     
        }                                                                                                                                                       
      }                                                                                                                                                         
    }

Documentation Updates for XPathHelper [was Bug accessing elements using obj['key'] scheme]

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

Identityref In pyangbind

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

Serialising OpenConfig Interfaces with mode="ietf" results in AttributeError

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.

config: false Lists may not have a "key" sub-stmt / ordered-by

Note: Two changes to resolve under this ticket:

  • ordered-by user is not supported
  • lists without keys are not yet supported

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;
            }
          }

Question: Get a list by means of XPATH and add element to that list

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

Expose information about field constraints

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

Leaf metadata?

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

"example/oc-local-routing" is not working due to the yang model changed

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~

unsupported format 'pybind'

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.

Update the code generator to python 3

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.

Help with RestrictedClassType/YANGBaseClass

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.

image

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

Import In Yang Models

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.

Empty container is not captured in the binding

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!

Is there a way to append an existing Object to a Keyed List?

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)

Not dumping all fields of YANG list

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

Question: RestrictedClassType and Null value

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

pyangbind fails to install via PyPi

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

Issue running pyangbind class generation plugin

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?

Differentiate between empty and boolean nodes

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.

pybindJSONDecoder, diving deeper into the hierachy

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?

Restriction/Range that uses keyword 'min' does not work

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

XPath tests fail with pyang 1.4.1

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?

config: false is not properly inherited

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.

Remove numpy dependency

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}.

Support for groupings?

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.

Resolving nested typedefs

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()

Bindings for Augment keyword are not generating

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

Includes in included files are not correctly parsed

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.

Support for choice keyword

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";
      }
    }
  }

Fields which share the name of python keywords cause issues

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.

OverflowError: Python int too large to convert to C long

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.