Skip to content

Commit

Permalink
Fixes #650 - bad expansion of multiple related augments
Browse files Browse the repository at this point in the history
  • Loading branch information
mbj4668 committed Nov 1, 2023
1 parent 1b1c3e0 commit 4ba83e7
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 13 deletions.
41 changes: 28 additions & 13 deletions pyang/statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class Abort(Exception):

# second expansion: expand augmentations into i_children
'expand_2',
'expand_3',

# unique name check phase:
'unique_name',
Expand Down Expand Up @@ -216,6 +217,7 @@ class Abort(Exception):
lambda ctx, s: v_inherit_properties(ctx, s),

('expand_2', 'augment'):lambda ctx, s: v_expand_2_augment(ctx, s),
('expand_3', 'augment'):lambda ctx, s: v_expand_3_augment(ctx, s),

('unique_name', 'module'): \
lambda ctx, s: v_unique_name_defintions(ctx, s),
Expand Down Expand Up @@ -252,10 +254,11 @@ class Abort(Exception):
_v_i_children = {
'unique_name':True,
'expand_2':True,
'expand_3':True,
'reference_1':True,
'reference_2':True,
}
"""Phases in this dict are run over the stmts which has i_children.
"""Phases in this dict are run over the stmts that have i_children.
Note that the tests are not run in grouping definitions."""

_v_i_children_keywords = {
Expand Down Expand Up @@ -1464,6 +1467,8 @@ def v_expand_1_children(ctx, stmt):
v_inherit_properties(ctx, stmt)
for a in s.search('augment'):
v_expand_2_augment(ctx, a)
for a in s.search('augment'):
v_expand_3_augment(ctx, a)

elif s.keyword in data_keywords and hasattr(stmt, 'i_children'):
stmt.i_children.append(s)
Expand Down Expand Up @@ -1726,18 +1731,19 @@ def walk(s, config_value, allow_explicit):

def v_expand_2_augment(ctx, stmt):
"""
One-pass augment expansion algorithm: First observation: since we
validate each imported module, all nodes that are augmented by
other modules already exist. For each node in the path to the
target node, if it does not exist, it might get created by an
augment later in this module. This only applies to nodes defined
in our namespace (since all other modules already are validated).
For each such node, we add a temporary Statement instance, and
store a pointer to it. If we find such a temporary node in the
nodes we add, we replace it with our real node, and delete it from
the list of temporary nodes created. When we're done with all
augment statements, the list of temporary nodes should be empty,
otherwise it is an error.
First pass of two-pass augment expansion algorithm.
First observation: since we validate each imported module, all
nodes that are augmented by other modules already exist. For each
node in the path to the target node, if it does not exist, it
might get created by an augment later in this module. This only
applies to nodes defined in our namespace (since all other modules
already are validated). For each such node, we add a temporary
Statement instance, and store a pointer to it. If we find such a
temporary node in the nodes we add, we replace it with our real
node, and delete it from the list of temporary nodes created.
When we're done with all augment statements, the list of temporary
nodes should be empty, otherwise it is an error.
"""
if hasattr(stmt, 'i_target_node'):
# already expanded
Expand Down Expand Up @@ -1868,6 +1874,15 @@ def is_expected_keyword(parent, child):
stmt.i_target_node.substmts.append(s)
s.parent = stmt.i_target_node

def v_expand_3_augment(ctx, stmt):
"""
Second pass of two-pass augment expansion algorithm.
Find the (possibly expanded) target nodes again. The reason for
this is that stmt.i_target_node may point to a __tmp_augment__ node.
"""
stmt.i_target_node = find_target_node(ctx, stmt, is_augment=True)

def create_new_case(ctx, choice, child, expand=True):
new_case = new_statement(child.top, choice, child.pos, 'case', child.arg)
v_init_stmt(ctx, new_case)
Expand Down
4 changes: 4 additions & 0 deletions test/test_issues/test_i650/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
test: test1

test1:
$(PYANG) -Werror a.yang
64 changes: 64 additions & 0 deletions test/test_issues/test_i650/a.yang
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module a {
yang-version 1.1;
namespace "urn:a";

prefix ex;

container interfaces {

list interface {
key "name";

leaf name {
type string;
}

leaf type {
type string;
mandatory true;
}

}

}


augment '/ex:interfaces/ex:interface/ex:frame-processing/ex:inline-frame-processingx/ex:inline-frame-processing/ex:ingress-rule/ex:rule/ex:flexible-match' {

when
"../../../../ex:type = 'value'";

}

augment '/ex:interfaces/ex:interface' {

choice frame-processing {

case inline-frame-processingx {

container inline-frame-processing {

container ingress-rule {

list rule {
key "name";

leaf name {
type string;
}

container flexible-match {
}
}
}
}
}
}
}






}

0 comments on commit 4ba83e7

Please sign in to comment.