mbj4668 / pyang

An extensible YANG validator and converter in python
ISC License
530 stars 342 forks source link

`AttributeError: i_default` in `v_unique_name_leaf_list` #834

Open edvgui opened 1 year ago

edvgui commented 1 year ago

Pyang version

$ pyang --version
pyang 2.5.3

How to reproduce

The following archive contains a few yang files originating from https://github.com/nokia/7x50_YangModels/tree/303e5bb6d08d76f75e8359dcfed53a9fd20c0b90/latest_sros_22.7 pyang-bug.zip

Running pyang with the file in the given archive will result in this failure:

$ pyang ~/Desktop/pyang-bug/*.yang
Traceback (most recent call last):
  File "/home/guillaume/.virtualenvs/yang-module-generator/bin/pyang", line 580, in <module>
    run()
  File "/home/guillaume/.virtualenvs/yang-module-generator/bin/pyang", line 433, in run
    ctx_validate_and_prune()
  File "/home/guillaume/.virtualenvs/yang-module-generator/bin/pyang", line 429, in ctx_validate_and_prune
    ctx.validate()
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/context.py", line 348, in validate
    statements.validate_module(self, m)
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/statements.py", line 414, in validate_module
    iterate(module, phase)
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  [Previous line repeated 1 more time]
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/statements.py", line 371, in iterate
    res = f(ctx, stmt)
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/statements.py", line 225, in <lambda>
    lambda ctx, s: v_unique_name_leaf_list(ctx, s),
  File "/home/guillaume/.virtualenvs/yang-module-generator/lib/python3.9/site-packages/pyang/statements.py", line 1942, in v_unique_name_leaf_list
    for defval in stmt.i_default: # getattr(stmt, "i_default", []):
AttributeError: i_default

Workaround/Fix

Applying this diff fixed it for me:

diff --git a/pyang/statements.py b/pyang/statements.py
index b938d09..01a0146 100644
--- a/pyang/statements.py
+++ b/pyang/statements.py
@@ -1939,7 +1939,7 @@ def v_unique_name_leaf_list(ctx, stmt):
     if not stmt.i_config:
         return
     seen = []
-    for defval in stmt.i_default:
+    for defval in getattr(stmt, "i_default", []):
         if defval in seen:
             err_add(ctx.errors, stmt.pos, 'DUPLICATE_DEFAULT', (defval))
         else:

I am not sure this is the correct way to go though, I have very weak knowledge of this code base. Could someone tell me whether it is right?

dody commented 1 year ago

Reproducible with 3 commands:

git clone -b sros_22.10  https://github.com/nokia/7x50_YangModels
cd  7x50_YangModels/YANG/
pyang --no-path-recurse  -p .:nokia-submodule nokia-submodule/nokia-conf.yang

pyang and python versions:

$pyang --version
pyang 2.5.3
$ python -V
Python 3.8.10

Crash:

Traceback (most recent call last):
  File ".../venv/bin/pyang", line 580, in <module>
    run()
  File ".../venv/bin/pyang", line 433, in run
    ctx_validate_and_prune()
  File ".../venv/bin/pyang", line 429, in ctx_validate_and_prune
    ctx.validate()
  File ".../venv/lib/python3.8/site-packages/pyang/context.py", line 348, in validate
    statements.validate_module(self, m)
  File ".../venv/lib/python3.8/site-packages/pyang/statements.py", line 414, in validate_module
    iterate(module, phase)
  File ".../venv/lib/python3.8/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  File ".../venv/lib/python3.8/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  File ".../venv/lib/python3.8/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  [Previous line repeated 1 more time]
  File ".../venv/lib/python3.8/site-packages/pyang/statements.py", line 371, in iterate
    res = f(ctx, stmt)
  File ".../venv/lib/python3.8/site-packages/pyang/statements.py", line 225, in <lambda>
    lambda ctx, s: v_unique_name_leaf_list(ctx, s),
  File ".../venv/lib/python3.8/site-packages/pyang/statements.py", line 1942, in v_unique_name_leaf_list
    for defval in stmt.i_default:
AttributeError: i_default
bobh66 commented 11 months ago

I can reproduce this and it appears to be a LeafLeaflistStatement object that was not initialized with i_default = [] in v_type_leaf_list()

@mbj4668 - do you have any suggestions for debugging? I can't see any obvious scenarios where the LeafLeaflistStatement object gets created without calling the initialization function but clearly it must be happening somehow. We could work around it by checking for the i_default attribute but that seems like it might be masking a larger problem.

wouterdb commented 11 months ago

I looked into this a while ago and what I found is:

  1. i_default is set in v_type_typedef
  2. this method is in the _validation_map as ('type_2', 'typedef'):lambda ctx, s: v_type_typedef(ctx, s),

So I think that for some reason this validation phase is never run on this statement, but I could not figure out why.

dylanbob commented 11 months ago

Hi. The same problem is occuring to me, with different versions of pyang/python and the nokia SROS v22.5 yang files. Note : this is inside a fresh pyenv virtualenv with only pip, wheel, pyang and their dependencies installed (with pip).

~/yang/yang/vendor/nokia/7x50_YangModels/latest_sros_22.5 (master) » pyang --version
pyang 2.5.3
~/yang/yang/vendor/nokia/7x50_YangModels/latest_sros_22.5 (master) » python --version
Python 3.11.4

~/yang/yang/vendor/nokia/7x50_YangModels/latest_sros_22.7 (master) » pyang nokia-oper-admin.yang -f jstree -p nokia-submodule
Traceback (most recent call last):
  File "/home/das/.pyenv/versions/pyang/bin/pyang", line 580, in <module>
    run()
  File "/home/das/.pyenv/versions/pyang/bin/pyang", line 433, in run
    ctx_validate_and_prune()
  File "/home/das/.pyenv/versions/pyang/bin/pyang", line 429, in ctx_validate_and_prune
    ctx.validate()
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/context.py", line 348, in validate
    statements.validate_module(self, m)
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 414, in validate_module
    iterate(module, phase)
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 371, in iterate
    res = f(ctx, stmt)
          ^^^^^^^^^^^^
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 190, in <lambda>
    ('import', 'module'):lambda ctx, s: v_import_module(ctx, s),
                                        ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 611, in v_import_module
    module = add_module(i, False)
             ^^^^^^^^^^^^^^^^^^^^
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 602, in add_module
    validate_module(ctx, m)
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 414, in validate_module
    iterate(module, phase)
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 402, in iterate
    iterate(s, phase)
  [Previous line repeated 1 more time]
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 371, in iterate
    res = f(ctx, stmt)
          ^^^^^^^^^^^^
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 225, in <lambda>
    lambda ctx, s: v_unique_name_leaf_list(ctx, s),
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/das/.pyenv/versions/3.11.4/envs/pyang/lib/python3.11/site-packages/pyang/statements.py", line 1942, in v_unique_name_leaf_list
    for defval in stmt.i_default:
                  ^^^^^^^^^^^^^^
AttributeError: 'LeafLeaflistStatement' object has no attribute 'i_default'. Did you mean: 'i_default_str'?