def emit_stmt(ctx, stmt, fd, indent, indentstep): if util.is_prefixed(stmt.raw_keyword): (prefix, identifier) = stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = stmt.keyword fd.write(indent + keyword) if stmt.arg != None: if keyword in grammar.stmt_map: (arg_type, _subspec) = grammar.stmt_map[keyword] if arg_type in ['identifier', 'identifier-ref', 'boolean']: fd.write(' ' + stmt.arg) else: emit_arg(stmt.arg, fd, indent, indentstep) else: emit_arg(stmt.arg, fd, indent, indentstep) if len(stmt.substmts) == 0: fd.write(';\n') else: fd.write(' {\n') if ctx.opts.yang_canonical: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) else: substmts = stmt.substmts for s in substmts: emit_stmt(ctx, s, fd, indent + indentstep, indentstep) fd.write(indent + '}\n')
def _chk_stmts(ctx, pos, stmts, parent, spec, canonical): for stmt in stmts: stmt.is_grammatically_valid = False if not util.is_prefixed(stmt.keyword): chk_grammar = True else: (modname, _identifier) = stmt.keyword if modname in extension_modules: chk_grammar = True else: chk_grammar = False if chk_grammar == True: match_res = _match_stmt(ctx, stmt, spec, canonical) else: match_res = None if match_res is None and chk_grammar == True: error.err_add(ctx.errors, stmt.pos, 'UNEXPECTED_KEYWORD', util.keyword_to_str(stmt.raw_keyword)) elif match_res is not None and chk_grammar == True: try: (arg_type, subspec) = stmt_map[stmt.keyword] except KeyError: error.err_add(ctx.errors, stmt.pos, 'UNEXPECTED_KEYWORD', util.keyword_to_str(stmt.raw_keyword)) return # verify the statement's argument if arg_type is None and stmt.arg is not None: error.err_add(ctx.errors, stmt.pos, 'UNEXPECTED_ARGUMENT', stmt.arg) elif arg_type is not None and stmt.arg is None: error.err_add(ctx.errors, stmt.pos, 'EXPECTED_ARGUMENT', util.keyword_to_str(stmt.keyword)) elif (arg_type is not None and arg_type != 'string' and syntax.arg_type_map[arg_type](stmt.arg) == False): error.err_add(ctx.errors, stmt.pos, 'BAD_VALUE', (stmt.arg, arg_type)) else: stmt.is_grammatically_valid = True _chk_stmts(ctx, stmt.pos, stmt.substmts, stmt, subspec, canonical) spec = match_res else: # unknown extension stmt.is_grammatically_valid = True _chk_stmts(ctx, stmt.pos, stmt.substmts, stmt, [('$any', '*')], canonical) # update last know position pos = stmt.pos # any non-optional statements left are errors for (keywd, occurance) in spec: if occurance == '1' or occurance == '+': if parent is None: error.err_add(ctx.errors, pos, 'EXPECTED_KEYWORD', util.keyword_to_str(keywd)) else: error.err_add(ctx.errors, pos, 'EXPECTED_KEYWORD_2', (util.keyword_to_str(keywd), util.keyword_to_str(parent.raw_keyword)))
def get_kwd_class(keyword): if util.is_prefixed(keyword): return 'extension' else: try: return _kwd_class[keyword] except KeyError: return 'body'
def emit_stmt(ctx, module, stmt, fd, indent, indentstep): if util.is_prefixed(stmt.raw_keyword): # this is an extension. need to find its definition (prefix, identifier) = stmt.raw_keyword tag = prefix + ':' + identifier if stmt.i_extension is not None: ext_arg = stmt.i_extension.search_one('argument') if ext_arg is not None: yin_element = ext_arg.search_one('yin-element') if yin_element is not None and yin_element.arg == 'true': argname = prefix + ':' + ext_arg.arg argiselem = True else: # explicit false or no yin-element given argname = ext_arg.arg argiselem = False else: argiselem = False argname = None else: argiselem = False argname = None else: (argname, argiselem) = syntax.yin_map[stmt.raw_keyword] tag = stmt.raw_keyword if argiselem == False or argname is None: if argname is None: attr = '' else: attr = ' ' + argname + '=' + quoteattr(stmt.arg) if len(stmt.substmts) == 0: fd.write(indent + '<' + tag + attr + '/>\n') else: fd.write(indent + '<' + tag + attr + '>\n') for s in stmt.substmts: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep) fd.write(indent + '</' + tag + '>\n') else: fd.write(indent + '<' + tag + '>\n') if ctx.opts.yin_pretty_strings: # since whitespace is significant in XML, the current # code is strictly speaking incorrect. But w/o the whitespace, # it looks too ugly. fd.write(indent + indentstep + '<' + argname + '>\n') fd.write(fmt_text(indent + indentstep + indentstep, stmt.arg)) fd.write('\n' + indent + indentstep + '</' + argname + '>\n') else: fd.write(indent + indentstep + '<' + argname + '>' + \ escape(stmt.arg) + \ '</' + argname + '>\n') if ctx.opts.yin_canonical: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) else: substmts = stmt.substmts for s in substmts: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep) fd.write(indent + '</' + tag + '>\n')
def convert_module(ctx, stmt): if ctx.opts.yang_remove_unused_imports and stmt.keyword == 'import': for p in stmt.parent.i_unused_prefixes: if stmt.parent.i_unused_prefixes[p] == stmt: return if util.is_prefixed(stmt.raw_keyword): (prefix, identifier) = stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = stmt.keyword if keyword in ['module', 'submodule']: # Change the module name. module_name = stmt.arg stmt.arg = module_name + '-2' # Look for config/state containers to convert. if len(stmt.substmts) != 0: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) for substmt in substmts: if substmt.keyword in ['namespace', 'belongs-to']: substmt.arg = substmt.arg + '-2' if substmt.keyword == 'typedef' and substmt.arg == 'interface-state-ref': stmt.substmts.remove(substmt) # Fix up import references to point to the combined modules. if (substmt.keyword in ['import', 'include'] and substmt.arg.startswith("ietf-") and substmt.arg not in ["ietf-yang-types", "ietf-inet-types"]): substmt.arg = substmt.arg + "-2" # Handle top level config/state containers. if is_config_container(substmt): for s in substmts: if (substmt.arg + "-state" == s.arg and is_state_container(s)): convert_stmt(substmt, s) stmt.substmts.remove(s) # Handle top level augmentations of config/state containers. if is_state_augmentation(substmt): cfg_augment = [ c for c in substmts if matches_cfg_augment(c, substmt) ] if cfg_augment: cfg_stmt = cfg_augment[0] convert_stmt(cfg_stmt, substmt) stmt.substmts.remove(substmt) else: # If it is just a state augmentation then just rename the augmentation. cfg_arg = matching_cfg_augment(substmt.arg) substmt.arg = cfg_arg # Run the fixup on any groupings (e.g. to fix up type references) if substmt.keyword == 'grouping': fixup_stmt(substmt)
def emit_stmt(ctx, stmt, fd, level, prev_kwd_class, indent, indentstep): if ctx.opts.strip_module and stmt.keyword == 'import' and stmt.arg in ctx.opts.strip_module: return if isinstance(stmt.keyword, tuple): kw_module, _ = stmt.keyword if kw_module in ctx.opts.strip_module: return if ctx.opts.strip_yang_remove_unused_imports and stmt.keyword == 'import': for p in stmt.parent.i_unused_prefixes: if stmt.parent.i_unused_prefixes[p] == stmt: return if util.is_prefixed(stmt.raw_keyword): (prefix, identifier) = stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = stmt.keyword kwd_class = get_kwd_class(stmt.keyword) if ((level == 1 and kwd_class != prev_kwd_class and kwd_class != 'extension') or stmt.keyword in _keyword_with_trailing_newline): fd.write('\n') if keyword == '_comment': emit_comment(stmt.arg, fd, indent) return fd.write(indent + keyword) if stmt.arg != None: if keyword in grammar.stmt_map: (arg_type, _subspec) = grammar.stmt_map[keyword] if arg_type in _non_quote_arg_type: fd.write(' ' + stmt.arg) else: emit_arg(stmt, fd, indent, indentstep) else: emit_arg(stmt, fd, indent, indentstep) if len(stmt.substmts) == 0: fd.write(';\n') else: fd.write(' {\n') if ctx.opts.strip_yang_canonical: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) else: substmts = stmt.substmts if level == 0: kwd_class = 'header' for s in substmts: emit_stmt(ctx, s, fd, level + 1, kwd_class, indent + indentstep, indentstep) kwd_class = get_kwd_class(s.keyword) fd.write(indent + '}\n')
def emit_stmt(ctx, stmt, fd, level, prev_kwd_class, indent, indentstep): if ctx.opts.yang_remove_unused_imports and stmt.keyword == 'import': for p in stmt.parent.i_unused_prefixes: if stmt.parent.i_unused_prefixes[p] == stmt: return if util.is_prefixed(stmt.raw_keyword): (prefix, identifier) = stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = stmt.keyword kwd_class = get_kwd_class(stmt.keyword) if ((level == 1 and kwd_class != prev_kwd_class and kwd_class != 'extension') or stmt.keyword in _keyword_with_trailing_newline): fd.write('\n') fd.write(indent + keyword) if stmt.arg != None: if keyword in grammar.stmt_map: (arg_type, _subspec) = grammar.stmt_map[keyword] if arg_type in _non_quote_arg_type: fd.write(' ' + stmt.arg) else: emit_arg(stmt, fd, indent, indentstep) else: emit_arg(stmt, fd, indent, indentstep) if len(stmt.substmts) == 0: fd.write(';\n') else: fd.write(' {\n') if ctx.opts.yang_canonical: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) else: substmts = stmt.substmts if level == 0: kwd_class = 'header' for s in substmts: emit_stmt(ctx, s, fd, level + 1, kwd_class, indent + indentstep, indentstep) kwd_class = get_kwd_class(s.keyword) fd.write(indent + '}\n')
def emit_stmt(ctx, module, stmt, fd, indent, indentstep, keys=[]): if util.is_prefixed(stmt.raw_keyword): # this is an extension. need to find its definition (prefix, identifier) = stmt.raw_keyword tag = prefix + ':' + identifier if stmt.i_extension is not None: ext_arg = stmt.i_extension.search_one('argument') if ext_arg is not None: wyin_element = ext_arg.search_one('yin-element') if wyin_element is not None and wyin_element.arg == 'true': argname = prefix + ':' + ext_arg.arg argiselem = True else: # explicit false or no yin-element given argname = ext_arg.arg argiselem = False else: argiselem = False argname = None else: argiselem = False argname = None else: (argname, argiselem) = syntax.yin_map[stmt.raw_keyword] tag = stmt.raw_keyword if argiselem == False or argname is None: if argname is None: attr = '' else: attr = ' ' + argname + '=' + quoteattr(stmt.arg) if len(stmt.substmts) == 0: fd.write(indent + '<' + tag + attr + '/>\n') else: if argname and argname in "name": fd.write(indent + ('<%s eltype="%s"' % (stmt.arg, tag))) else: fd.write(indent + '<' + tag + attr) used_substmts = 0 printed_config = False got_keys = False for s in stmt.substmts: if not printed_config: conf_val = None # find predecesor with i_config or use s' i_config p = s if not hasattr(p, "i_config"): while (not hasattr(p, "i_config")) and (p != None): p = p.parent # searching finished if p: conf_val = p.i_config.__str__().lower() if conf_val == "none": conf_val = "true" # write config attribute fd.write(' config="%s"' % conf_val) printed_config = True del p if s.raw_keyword == "key": fd.write(' key="%s"' % s.arg) keys = re.findall(r'\S+', s.arg) got_keys = True if s.raw_keyword in [ "config", "type", "default", "description", "mandatory" ]: # already written if s.raw_keyword in "config": setattr(s, "i_config", s.arg) else: fd.write(' %s="%s"' % (s.raw_keyword, escape2xml(s.arg))) if s.raw_keyword == "type": if s.arg == "enumeration": fd.write(' enumval="') first_written = False for charg in s.substmts: if first_written: fd.write(ctx.opts.enum_delim) else: first_written = True fd.write(charg.arg) fd.write('"') elif s.arg == "identityref": basename = get_basename(s) if identityrefs.has_key(basename): fd.write(" enumval=\"") sep = False for i in identityrefs[basename]: if sep: fd.write("|") else: sep = True fd.write(i) fd.write("\"") else: print "no basename %s" % basename else: if s.substmts: #other type "attributes" for charg in s.substmts: if charg.raw_keyword == "range": fd.write(' range="' + charg.arg + '"') # count used substatements to know what is the rest used_substmts += 1 # mark key elements if stmt.arg in keys: fd.write(' iskey="true"') else: fd.write(' iskey="false"') if not got_keys: keys = [] # the rest of substatements: if used_substmts < stmt.substmts.__len__(): # Need to generate pair tag fd.write('>\n') for s in stmt.substmts: if s.raw_keyword not in ["config", "type",\ "default", "description", "mandatory",\ "must", "when", "key"]: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep, keys) if argname and argname in "name": fd.write(indent + ('</%s>' % stmt.arg)) else: fd.write(indent + '</' + tag + '>\n') else: # Everything from child elements was used fd.write('/>\n') else: fd.write(indent + '<' + tag + '>\n') if ctx.opts.wyin_pretty_strings: # since whitespace is significant in XML, the current # code is strictly speaking incorrect. But w/o the whitespace, # it looks too ugly. fd.write(indent + indentstep + '<' + argname + '>\n') fd.write(fmt_text(indent + indentstep + indentstep, stmt.arg)) fd.write('\n' + indent + indentstep + '</' + argname + '>\n') else: try: fd.write(indent + indentstep + '<' + argname + '>' + \ escape(stmt.arg) + \ '</' + argname + '>\n') except Exception as e: print argname if ctx.opts.wyin_canonical: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) else: substmts = stmt.substmts for s in substmts: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep) fd.write(indent + '</' + tag + '>\n')
def emit_stmt(ctx, module, stmt, fd, indent, indentstep): global revision_added if stmt.raw_keyword == "revision" and revision_added == False: revision_added = True elif stmt.raw_keyword == "revision" and revision_added == True: #Only add the latest revision return #Don't keep the following keywords as they are not used in CVL # stmt.raw_keyword == "revision" or if ((stmt.raw_keyword == "organization" or stmt.raw_keyword == "contact" or stmt.raw_keyword == "rpc" or stmt.raw_keyword == "notification" or stmt.raw_keyword == "description") or (len(stmt.substmts) > 0 and stmt.substmts[0].raw_keyword == "config" and stmt.substmts[0].arg == "false")): return if util.is_prefixed(stmt.raw_keyword): # this is an extension. need to find its definition (prefix, identifier) = stmt.raw_keyword tag = prefix + ':' + identifier if stmt.i_extension is not None: ext_arg = stmt.i_extension.search_one('argument') if ext_arg is not None: yin_element = ext_arg.search_one('yin-element') if yin_element is not None and yin_element.arg == 'true': argname = prefix + ':' + ext_arg.arg argiselem = True else: # explicit false or no yin-element given argname = ext_arg.arg argiselem = False else: argiselem = False argname = None else: argiselem = False argname = None else: (argname, argiselem) = syntax.yin_map[stmt.raw_keyword] tag = stmt.raw_keyword if argiselem == False or argname is None: if argname is None: attr = '' else: attr = ' ' + argname + '=' + quoteattr(stmt.arg) if len(stmt.substmts) == 0: fd.write(indent + '<' + tag + attr + '/>' + new_line) else: fd.write(indent + '<' + tag + attr + '>' + new_line) for s in stmt.substmts: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep) fd.write(indent + '</' + tag + '>' + new_line) else: fd.write(indent + '<' + tag + '>' + new_line) fd.write(indent + indentstep + '<' + argname + '>' + \ escape(stmt.arg) + \ '</' + argname + '>' + new_line) substmts = stmt.substmts for s in substmts: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep) fd.write(indent + '</' + tag + '>' + new_line)
def convert_module(ctx, m_stmt): if ctx.opts.yang_remove_unused_imports and m_stmt.keyword == 'import': for p in m_stmt.parent.i_unused_prefixes: if m_stmt.parent.i_unused_prefixes[p] == m_stmt: return if util.is_prefixed(m_stmt.raw_keyword): (prefix, identifier) = m_stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = m_stmt.keyword if keyword in ['module', 'submodule']: # Don't change the module name, but could update the revision number? #module_name = m_stmt.arg #m_stmt.arg = module_name + '-2' # Look for config/state containers to convert. if len(m_stmt.substmts) != 0: m_substmts = grammar.sort_canonical(m_stmt.keyword, m_stmt.substmts) for substmt in m_substmts: if substmt.keyword in ['namespace', 'belongs-to']: substmt.arg = substmt.arg + '-2' # Remove the interface state ref? # Or, is this even appropriate. if substmt.keyword == 'typedef' and substmt.arg == 'interface-state-ref': m_stmt.substmts.remove(substmt) # Fix up import references to point to the combined modules. #if (substmt.keyword in ['import', 'include'] # and substmt.arg.startswith("ietf-") # and substmt.arg not in ["ietf-yang-types","ietf-inet-types"]): # substmt.arg = substmt.arg + "-2" # Handle top level config/state containers. if is_config_container(substmt): for s in m_substmts: if (s.arg == (substmt.arg + "-state") and is_state_container(s)): convert_stmt(substmt, s) # Either remove the m_substmts, or mark it as status deprecated. if IetfModelPlugin.remove_state: m_stmt.substmts.remove(s) else: mark_stmt_deprecated(s) # Handle top level augmentations of config/state containers. if is_state_augmentation(substmt): cfg_augment = [ c for c in m_substmts if matches_cfg_augment(c, substmt) ] if cfg_augment: cfg_stmt = cfg_augment[0] convert_stmt(cfg_stmt, substmt) # Either remove the m_substmts, or mark it as status deprecated. if IetfModelPlugin.remove_state: m_stmt.substmts.remove(substmt) else: mark_stmt_deprecated(substmt) else: # If it is just a state augmentation then just rename the augmentation. cfg_arg = matching_cfg_augment(substmt.arg) substmt.arg = cfg_arg # Run the fixup on any groupings (e.g. to fix up type references) if substmt.keyword == 'grouping': fixup_stmt(substmt) # Assume that a grouping only contains state if it is has state in its name. if substmt.keyword == 'grouping' and "-state" in substmt.arg: fixup_state_grouping(substmt)
def convert_module(ctx, m_stmt): if ctx.opts.yang_remove_unused_imports and m_stmt.keyword == 'import': for p in m_stmt.parent.i_unused_prefixes: if m_stmt.parent.i_unused_prefixes[p] == m_stmt: return if util.is_prefixed(m_stmt.raw_keyword): (prefix, identifier) = m_stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = m_stmt.keyword if keyword in ['module', 'submodule']: # Don't change the module name, but could update the revision number? #module_name = m_stmt.arg #m_stmt.arg = module_name + '-2' # Look for config/state containers to convert. if len(m_stmt.substmts) != 0: m_substmts = grammar.sort_canonical(m_stmt.keyword, m_stmt.substmts) for substmt in m_substmts: if substmt.keyword in ['namespace', 'belongs-to']: substmt.arg = substmt.arg + '-2' # Remove the interface state ref? # Or, is this even appropriate. if substmt.keyword == 'typedef' and substmt.arg == 'interface-state-ref': m_stmt.substmts.remove(substmt) # Fix up import references to point to the combined modules. #if (substmt.keyword in ['import', 'include'] # and substmt.arg.startswith("ietf-") # and substmt.arg not in ["ietf-yang-types","ietf-inet-types"]): # substmt.arg = substmt.arg + "-2" # Handle top level config/state containers. if is_config_container(substmt): for s in m_substmts: if (s.arg == (substmt.arg + "-state") and is_state_container(s)): convert_stmt(substmt, s) # Either remove the m_substmts, or mark it as status deprecated. if IetfModelPlugin.remove_state: m_stmt.substmts.remove(s) else: mark_stmt_deprecated(s) # Handle top level augmentations of config/state containers. if is_state_augmentation(substmt): cfg_augment = [c for c in m_substmts if matches_cfg_augment(c, substmt)] if cfg_augment: cfg_stmt = cfg_augment[0] convert_stmt(cfg_stmt, substmt) # Either remove the m_substmts, or mark it as status deprecated. if IetfModelPlugin.remove_state: m_stmt.substmts.remove(substmt) else: mark_stmt_deprecated(substmt) else: # If it is just a state augmentation then just rename the augmentation. cfg_arg = matching_cfg_augment(substmt.arg) substmt.arg = cfg_arg # Run the fixup on any groupings (e.g. to fix up type references) if substmt.keyword == 'grouping': fixup_stmt(substmt) # Assume that a grouping only contains state if it is has state in its name. if substmt.keyword == 'grouping' and "-state" in substmt.arg: fixup_state_grouping(substmt)
def convert_stmt(ctx, stmt, level): if ctx.opts.yang_remove_unused_imports and stmt.keyword == 'import': for p in stmt.parent.i_unused_prefixes: if stmt.parent.i_unused_prefixes[p] == stmt: return if util.is_prefixed(stmt.raw_keyword): (prefix, identifier) = stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = stmt.keyword if keyword == 'module': # Change the module name. module_name = stmt.arg stmt.arg = module_name + '-state' # Find the module prefix. prefix_stmt = next(x for x in stmt.substmts if x.keyword == 'prefix') # Rename the prefix statement. prefix = prefix_stmt.arg prefix_stmt.arg = prefix + '-s' # Add an import statement back to the original module. import_stmt = Statement(stmt.top, stmt, stmt.pos, 'import', module_name) add_substmt_canonical(stmt, import_stmt) add_substmt_canonical(import_stmt, Statement(stmt.top, import_stmt, import_stmt.pos, 'prefix', prefix)) if keyword == 'namespace': stmt.arg = stmt.arg + '-state' # Remove any feature statements, reference the original module feature instead. if keyword == 'feature': stmt.parent.substmts.remove(stmt) if keyword == 'if-feature': fix_references(stmt, stmt.i_module.i_features) # Remove any identity statements, reference the original identity instead. # Identity base won't matter because they are all removed. if keyword == 'identity': stmt.parent.substmts.remove(stmt) if keyword in ('must', 'when'): fix_references(stmt, stmt.i_module.i_identities) if keyword == 'type' and stmt.arg == 'identityref': base_stmt = next(x for x in stmt.substmts if x.keyword == 'base') fix_references(base_stmt, stmt.i_module.i_identities) # Remove any typedef statements, reference the original typedef instead. if keyword == 'typedef': stmt.parent.substmts.remove(stmt) if keyword == 'type': fix_references(stmt, stmt.i_module.i_typedefs) # Remove all config statements, only the top level config false is necessary. if keyword == 'config': stmt.parent.substmts.remove(stmt) if len(stmt.substmts) != 0: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) for s in substmts: convert_stmt(ctx, s, level + 1) # Convert top level containers from "foo" to "foo-state", and mark it as config false. if keyword == 'container' and stmt.parent.keyword == 'module': if not stmt.arg.endswith('-state'): stmt.arg = stmt.arg + '-state' add_substmt_canonical(stmt, Statement(stmt.top, stmt, stmt.pos, 'config', 'false'))
def emit_stmt(ctx, module, stmt, fd, indent, indentstep, keys = []): if util.is_prefixed(stmt.raw_keyword): # this is an extension. need to find its definition (prefix, identifier) = stmt.raw_keyword tag = prefix + ':' + identifier if stmt.i_extension is not None: ext_arg = stmt.i_extension.search_one('argument') if ext_arg is not None: wyin_element = ext_arg.search_one('yin-element') if wyin_element is not None and wyin_element.arg == 'true': argname = prefix + ':' + ext_arg.arg argiselem = True else: # explicit false or no yin-element given argname = ext_arg.arg argiselem = False else: argiselem = False argname = None else: argiselem = False argname = None else: (argname, argiselem) = syntax.yin_map[stmt.raw_keyword] tag = stmt.raw_keyword if argiselem == False or argname is None: if argname is None: attr = '' else: attr = ' ' + argname + '=' + quoteattr(stmt.arg) if len(stmt.substmts) == 0: fd.write(indent + '<' + tag + attr + '/>\n') else: if argname and argname in "name": fd.write(indent + ('<%s eltype="%s"' % (stmt.arg, tag))) else: fd.write(indent + '<' + tag + attr) used_substmts = 0 printed_config = False got_keys = False for s in stmt.substmts: if not printed_config: conf_val = None # find predecesor with i_config or use s' i_config p = s if not hasattr(p, "i_config"): while (not hasattr(p, "i_config")) and (p != None): p = p.parent # searching finished if p: conf_val = p.i_config.__str__().lower() if conf_val == "none": conf_val = "true" # write config attribute fd.write(' config="%s"' % conf_val) printed_config = True del p if s.raw_keyword == "key": fd.write(' key="%s"' % s.arg) keys = re.findall(r'\S+', s.arg) got_keys = True if s.raw_keyword in ["config", "type", "default", "description", "mandatory"]: # already written if s.raw_keyword in "config": setattr(s, "i_config", s.arg) else: fd.write(' %s="%s"' % (s.raw_keyword, escape2xml(s.arg))) if s.raw_keyword == "type": if s.arg == "enumeration": fd.write(' enumval="') first_written = False for charg in s.substmts: if first_written: fd.write(ctx.opts.enum_delim) else: first_written = True fd.write(charg.arg) fd.write('"') elif s.arg == "identityref": basename = get_basename(s) if identityrefs.has_key(basename): fd.write(" enumval=\"") sep = False for i in identityrefs[basename]: if sep: fd.write("|") else: sep = True fd.write(i) fd.write("\"") else: print "no basename %s" % basename else: if s.substmts: #other type "attributes" for charg in s.substmts: if charg.raw_keyword == "range": fd.write(' range="' + charg.arg + '"') # count used substatements to know what is the rest used_substmts += 1 # mark key elements if stmt.arg in keys: fd.write(' iskey="true"') else: fd.write(' iskey="false"') if not got_keys: keys = [] # the rest of substatements: if used_substmts < stmt.substmts.__len__(): # Need to generate pair tag fd.write('>\n') for s in stmt.substmts: if s.raw_keyword not in ["config", "type",\ "default", "description", "mandatory",\ "must", "when", "key"]: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep, keys) if argname and argname in "name": fd.write(indent + ('</%s>' % stmt.arg)) else: fd.write(indent + '</' + tag + '>\n') else: # Everything from child elements was used fd.write('/>\n') else: fd.write(indent + '<' + tag + '>\n') if ctx.opts.wyin_pretty_strings: # since whitespace is significant in XML, the current # code is strictly speaking incorrect. But w/o the whitespace, # it looks too ugly. fd.write(indent + indentstep + '<' + argname + '>\n') fd.write(fmt_text(indent + indentstep + indentstep, stmt.arg)) fd.write('\n' + indent + indentstep + '</' + argname + '>\n') else: fd.write(indent + indentstep + '<' + argname + '>' + \ escape(stmt.arg) + \ '</' + argname + '>\n') if ctx.opts.wyin_canonical: substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) else: substmts = stmt.substmts for s in substmts: emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep) fd.write(indent + '</' + tag + '>\n')
def is_appinfo(keyword): if util.is_prefixed(keyword) == True: return False (argname, argiselem, argappinfo) = yang_keywords[keyword] return argappinfo
def _match_stmt(ctx, stmt, spec, canonical): """Match stmt against the spec. Return None | spec' spec' is an updated spec with the matching spec consumed """ i = 0 while i < len(spec): (keywd, occurance) = spec[i] if keywd == '$any': return spec elif keywd == stmt.keyword: if occurance == '1' or occurance == '?': # consume this match if canonical == True: return spec[i + 1:] else: return spec[:i] + spec[i + 1:] if occurance == '+': # mark that we have found the one that was needed c = (keywd, '*') if canonical == True: return [c] + spec[i + 1:] else: return spec[:i] + [c] + spec[i + 1:] else: # occurane == '*' if canonical == True: return spec[i:] else: return spec elif keywd == '$choice': cases = occurance j = 0 while j < len(cases): # check if this alternative matches - check for a # match with each optional keyword save_errors = ctx.errors match_res = _match_stmt(ctx, stmt, cases[j], canonical) if match_res != None: # this case branch matched, use it # remove the choice and add res to the spec return spec[:i] + match_res + spec[i + 1:] # we must not report errors on non-matching branches ctx.errors = save_errors j += 1 elif keywd == '$interleave': cspec = occurance match_res = _match_stmt(ctx, stmt, cspec, canonical) if match_res != None: # we got a match return spec elif util.is_prefixed(stmt.keyword): # allow extension statements mixed with these # set canonical to False in this call to just remove the # matching stmt from the spec match_res = _match_stmt(ctx, stmt, spec[i + 1:], False) if match_res != None: return spec[:i + 1] + match_res else: return None elif keywd == '$cut': # any non-optional statements left are errors for (keywd, occurance) in spec[:i]: if occurance == '1' or occurance == '+': error.err_add(ctx.errors, stmt.pos, 'UNEXPECTED_KEYWORD_1', (util.keyword_to_str(stmt.raw_keyword), util.keyword_to_str(keywd))) # consume them so we don't report the same error again spec = spec[i:] i = 0 elif canonical == True: if occurance == '1' or occurance == '+': error.err_add(ctx.errors, stmt.pos, 'UNEXPECTED_KEYWORD_1', (util.keyword_to_str(stmt.raw_keyword), util.keyword_to_str(keywd))) # consume it so we don't report the same error again spec = spec[i:] i = 0 # check next in spec i += 1 return None
def _match_stmt(ctx, stmt, spec, canonical): """Match stmt against the spec. Return None | spec' spec' is an updated spec with the matching spec consumed """ i = 0 while i < len(spec): (keywd, occurance) = spec[i] if keywd == '$any': return spec elif keywd == stmt.keyword: if occurance == '1' or occurance == '?': # consume this match if canonical == True: return spec[i+1:] else: return spec[:i] + spec[i+1:] if occurance == '+': # mark that we have found the one that was needed c = (keywd, '*') if canonical == True: return [c] + spec[i+1:] else: return spec[:i] + [c] + spec[i+1:] else: # occurane == '*' if canonical == True: return spec[i:] else: return spec elif keywd == '$choice': cases = occurance j = 0 while j < len(cases): # check if this alternative matches - check for a # match with each optional keyword save_errors = ctx.errors match_res = _match_stmt(ctx, stmt, cases[j], False) if match_res != None: # this case branch matched, use it # remove the choice and add res to the spec return spec[:i] + match_res + spec[i+1:] # we must not report errors on non-matching branches ctx.errors = save_errors j += 1 elif keywd == '$interleave': cspec = occurance match_res = _match_stmt(ctx, stmt, cspec, canonical) if match_res != None: # we got a match return spec elif util.is_prefixed(stmt.keyword): # allow extension statements mixed with these # set canonical to False in this call to just remove the # matching stmt from the spec match_res = _match_stmt(ctx, stmt, spec[i+1:], False) if match_res != None: return spec[:i+1] + match_res else: return None elif keywd == '$cut': # any non-optional statements left are errors for (keywd, occurance) in spec[:i]: if occurance == '1' or occurance == '+': error.err_add(ctx.errors, stmt.pos, 'UNEXPECTED_KEYWORD_1', (util.keyword_to_str(stmt.raw_keyword), util.keyword_to_str(keywd))) # consume them so we don't report the same error again spec = spec[i:] i = 0 elif canonical == True: if occurance == '1' or occurance == '+': error.err_add(ctx.errors, stmt.pos, 'UNEXPECTED_KEYWORD_1', (util.keyword_to_str(stmt.raw_keyword), util.keyword_to_str(keywd))) # consume it so we don't report the same error again spec = spec[i:] i = 0 # check next in spec i += 1 return None
def convert_stmt(ctx, stmt, level): if ctx.opts.yang_remove_unused_imports and stmt.keyword == 'import': for p in stmt.parent.i_unused_prefixes: if stmt.parent.i_unused_prefixes[p] == stmt: return if util.is_prefixed(stmt.raw_keyword): (prefix, identifier) = stmt.raw_keyword keyword = prefix + ':' + identifier else: keyword = stmt.keyword if keyword == 'module': # Change the module name. module_name = stmt.arg stmt.arg = module_name + '-state' # Find the module prefix. prefix_stmt = next(x for x in stmt.substmts if x.keyword == 'prefix') # Rename the prefix statement. prefix = prefix_stmt.arg prefix_stmt.arg = prefix + '-s' # Add an import statement back to the original module. import_stmt = Statement(stmt.top, stmt, stmt.pos, 'import', module_name) add_substmt_canonical(stmt, import_stmt) add_substmt_canonical( import_stmt, Statement(stmt.top, import_stmt, import_stmt.pos, 'prefix', prefix)) if keyword == 'submodule': # Change the module name. submodule_name = stmt.arg stmt.arg = submodule_name + '-state' if keyword == 'namespace': stmt.arg = stmt.arg + '-state' # Remove any feature statements, reference the original module feature instead. if keyword == 'feature': stmt.parent.substmts.remove(stmt) if keyword == 'if-feature': fix_references(stmt, stmt.i_module.i_features) # Remove any identity statements, reference the original identity instead. # Identity base won't matter because they are all removed. if keyword == 'identity': stmt.parent.substmts.remove(stmt) if keyword in ('include', 'belongs-to'): stmt.arg = stmt.arg + "-state" if keyword == "prefix" and stmt.parent.keyword == "belongs-to": stmt.arg = stmt.arg + "-s" # Remove must/when statements. if keyword in ('must', 'when'): stmt.parent.substmts.remove(stmt) #fix_references(stmt, stmt.i_module.i_identities) if keyword == 'type' and stmt.arg == 'identityref': base_stmt = next(x for x in stmt.substmts if x.keyword == 'base') fix_references(base_stmt, stmt.i_module.i_identities) # Remove any typedef statements, reference the original typedef instead. if keyword == 'typedef': stmt.parent.substmts.remove(stmt) if keyword == 'type': fix_references(stmt, stmt.i_module.i_typedefs) # Remove all config statements, only the top level config false is necessary. if keyword == 'config': stmt.parent.substmts.remove(stmt) if len(stmt.substmts) != 0: #substmts = grammar.sort_canonical(stmt.keyword, stmt.substmts) for s in stmt.substmts[:]: convert_stmt(ctx, s, level + 1) # Convert top level containers from "foo" to "foo-state", and mark it as config false. if keyword in ('container', 'list', 'leaf-list') and (stmt.parent.keyword == 'module' or stmt.parent.keyword == 'grouping'): if not stmt.arg.endswith('-state'): #stmt.arg = stmt.arg + '-state' add_substmt_canonical( stmt, Statement(stmt.top, stmt, stmt.pos, 'config', 'false'))
def v_instantiate_extends(ctx, stmt): """Instantiate 'extends' statements, expand the complex type with the nodes from the base complex type. Applies refinements. """ # the complex type is not grammatically valid if hasattr(stmt, 'is_grammatically_valid') and \ not stmt.is_grammatically_valid: return # there is a circular dependency, don't process the 'extends' statement if stmt.i_is_circular: return bt = stmt.i_base_type # the complex type does not extend any other class if bt is None: return if hasattr(stmt, 'i_base_type_expanded'): return extends = stmt.search_one((ct_module_name, str_extends)) v_instantiate_extends(ctx, bt) # copy the base complex type definitions into stmt.i_children names = {} for ch in bt.i_children: # don't copy the type since it cannot be modified anyway. if not (ch.i_module.i_modulename, ch.arg) in names: newnode = ch.copy(stmt, extends, nocopy=['type','uses','unique','typedef','grouping'], copyf=post_copy_fnc(extends, True)) stmt.i_children.append(newnode) newnode.i_is_inherited = True names[(ch.i_module.i_modulename, ch.arg)] = True stmt.i_base_type_expanded = True refined = {} # then apply all refinements for refinement in stmt.search('refine'): # process 'refine' statements target = find_target_node(ctx, refinement) if target is None: continue if target in refined: err_add(ctx.errors, refinement.pos, 'MULTIPLE_REFINE', (target.arg, refined[target])) continue if not hasattr(target, 'i_inherited'): err_add(ctx.errors, refinement.pos, 'REFINE_NOT_INHERITED', (target.arg, target.pos)) continue refined[target] = refinement.pos def replace_from_refinement(target, refinement, keyword, \ valid_keywords, v_fun=None, is_additional = False): """allow `keyword` as a refinement in `valid_keywords`""" new = refinement.search_one(keyword) if new is not None and target.keyword in valid_keywords: old = target.search_one(keyword) if old is not None and not is_additional: target.substmts.remove(old) if v_fun is not None: v_fun(target, new) target.substmts.append(new) elif new is not None: err_add(ctx.errors, refinement.pos, 'BAD_REFINEMENT', (target.keyword, target.i_module.i_modulename, target.arg, keyword)) return def v_default(target, default): type = target.search_one('type') if (type is not None and type.i_type_spec is not None): defval = type.i_type_spec.str_to_val(ctx.errors, default.pos, default.arg) target.i_default = defval target.i_default_str = default.arg if defval is not None: type.i_type_spec.validate(ctx.errors, default.pos, defval, ' for the default value') replace_from_refinement(target, refinement, 'description', ['container', 'leaf', 'leaf-list', 'list', 'choice', 'case', 'anyxml', (ct_module_name, str_instance), (ct_module_name, str_instance_list)]) replace_from_refinement(target, refinement, 'reference', ['container', 'leaf', 'leaf-list', 'list', 'choice', 'case', 'anyxml', (ct_module_name, str_instance), (ct_module_name, str_instance_list)]) replace_from_refinement(target, refinement, 'config', ['container', 'leaf', 'leaf-list', 'list', 'choice', 'anyxml', (ct_module_name, str_instance), (ct_module_name, str_instance_list)]) replace_from_refinement(target, refinement, 'presence', ['container']) replace_from_refinement(target, refinement, 'must', ['container', 'leaf', 'leaf-list', 'list', (ct_module_name, str_instance), (ct_module_name, str_instance_list)], is_additional = True) replace_from_refinement(target, refinement, 'default', ['leaf', 'choice'], v_default) replace_from_refinement(target, refinement, 'mandatory', ['leaf', 'choice', (ct_module_name, str_instance)]) replace_from_refinement(target, refinement, 'min-elements', ['leaf-list', 'list', (ct_module_name, str_instance_list)]) replace_from_refinement(target, refinement, 'max-elements', ['leaf-list', 'list', (ct_module_name, str_instance_list)]) # replace all vendor-specific statements for s in refinement.substmts: if util.is_prefixed(s.keyword): old = target.search_one(s.keyword) if old is not None: target.substmts.remove(old) target.substmts.append(s)