1"""RESTCONF plugin 2 3Verifies RESTCONF YANG statements as defined in RFC 8040. 4 5Verifies the grammar of the restconf extension statements. 6""" 7 8import pyang 9from pyang import plugin 10from pyang import grammar 11from pyang import statements 12from pyang import error 13from pyang.error import err_add 14 15restconf_module_name = 'ietf-restconf' 16 17class RESTCONFPlugin(plugin.PyangPlugin): 18 def __init__(self): 19 plugin.PyangPlugin.__init__(self, 'restconf') 20 21def pyang_plugin_init(): 22 """Called by pyang plugin framework at to initialize the plugin.""" 23 24 # Register the plugin 25 plugin.register_plugin(RESTCONFPlugin()) 26 27 # Register that we handle extensions from the YANG module 'ietf-restconf' 28 grammar.register_extension_module(restconf_module_name) 29 30 yd = (restconf_module_name, 'yang-data') 31 statements.add_data_keyword(yd) 32 statements.add_keyword_with_children(yd) 33 statements.add_keywords_with_no_explicit_config(yd) 34 35 # Register the special grammar 36 for (stmt, occurance, (arg, rules), add_to_stmts) in restconf_stmts: 37 grammar.add_stmt((restconf_module_name, stmt), (arg, rules)) 38 grammar.add_to_stmts_rules(add_to_stmts, 39 [((restconf_module_name, stmt), occurance)]) 40 41 # Add validation functions 42 statements.add_validation_fun('expand_2', 43 [yd], 44 v_yang_data) 45 46 # Register special error codes 47 error.add_error_code('RESTCONF_YANG_DATA_CHILD', 1, 48 "the 'yang-data' extension must have exactly one " + 49 "child that is a container") 50 51restconf_stmts = [ 52 53 # (<keyword>, <occurance when used>, 54 # (<argument type name | None>, <substmts>), 55 # <list of keywords where <keyword> can occur>) 56 57 ('yang-data', '*', 58 ('identifier', grammar.data_def_stmts), 59 ['module', 'submodule']), 60 61] 62 63def v_yang_data(ctx, stmt): 64 65 def ensure_container(s): 66 if len(s.i_children) != 1: 67 return False 68 ch = s.i_children[0] 69 if ch.keyword == 'choice': 70 for c in ch.i_children: 71 if not ensure_container(c): 72 return False 73 elif ch.keyword != 'container': 74 return False 75 return True 76 77 if not ensure_container(stmt): 78 err_add(ctx.errors, stmt.pos, 'RESTCONF_YANG_DATA_CHILD', ()) 79