def pyang_plugin_init(): """Called by pyang plugin framework at to initialize the plugin.""" # Register the plugin plugin.register_plugin(SMIPlugin()) # Add our special argument syntax checkers syntax.add_arg_type("smi-oid", _chk_smi_oid) syntax.add_arg_type("smi-max-access", _chk_smi_max_access) # Register that we handle extensions from the YANG module 'ietf-yang-smiv2' grammar.register_extension_module(smi_module_name) # Register the special grammar for (stmt, occurance, (arg, rules), add_to_stmts) in smi_stmts: grammar.add_stmt((smi_module_name, stmt), (arg, rules)) grammar.add_to_stmts_rules(add_to_stmts, [((smi_module_name, stmt), occurance)]) # Add validation step statements.add_validation_phase("smi_set_oid", after="inherit_properties") statements.add_validation_fun("smi_set_oid", [(smi_module_name, "oid")], v_set_oid) statements.add_validation_fun("smi_set_oid", [(smi_module_name, "subid")], v_set_subid) # Register special error codes error.add_error_code("SMIv2_BAD_SUBID", 1, "subid needs an oid or subid statement in an ancestor") error.add_error_code("SMIv2_SUBID_AND_OID", 1, "subid and oid cannot be given at the same time")
def pyang_plugin_init(): """Called by pyang plugin framework at to initialize the plugin.""" # Register the plugin plugin.register_plugin(RESTCONFPlugin()) # Register that we handle extensions from the YANG module 'ietf-restconf' grammar.register_extension_module(restconf_module_name) yd = (restconf_module_name, 'yang-data') statements.add_data_keyword(yd) statements.add_keyword_with_children(yd) statements.add_keywords_with_no_explicit_config(yd) # Register the special grammar for (stmt, occurance, (arg, rules), add_to_stmts) in restconf_stmts: grammar.add_stmt((restconf_module_name, stmt), (arg, rules)) grammar.add_to_stmts_rules(add_to_stmts, [((restconf_module_name, stmt), occurance)]) # Add validation functions statements.add_validation_fun('expand_2', [yd], v_yang_data) # Register special error codes error.add_error_code('RESTCONF_YANG_DATA_CHILD', 1, "the 'yang-data' extension must have exactly one " + "child that is a container")
def pyang_plugin_init(): """Called by pyang plugin framework at to initialize the plugin.""" # Register the plugin plugin.register_plugin(SMIPlugin()) # Add our special argument syntax checkers syntax.add_arg_type('smi-oid', _chk_smi_oid) syntax.add_arg_type('smi-max-access', _chk_smi_max_access) # Register that we handle extensions from the YANG module 'smi' grammar.register_extension_module(smi_module_name) # Register the special grammar for (stmt, occurance, (arg, rules), add_to_stmts) in smi_stmts: grammar.add_stmt((smi_module_name, stmt), (arg, rules)) grammar.add_to_stmts_rules(add_to_stmts, [((smi_module_name, stmt), occurance)]) # Add validation step statements.add_validation_phase('smi_set_oid', after='inherit_properties') statements.add_validation_fun('smi_set_oid', [(smi_module_name, 'oid')], v_set_oid) statements.add_validation_fun('smi_set_oid', [(smi_module_name, 'subid')], v_set_subid) # Register special error codes error.add_error_code( 'SMIv2_BAD_SUBID', 1, "subid needs an oid or subid statement in an ancestor") error.add_error_code('SMIv2_SUBID_AND_OID', 1, "subid and oid cannot be given at the same time")
def pyang_plugin_init(): """Called by pyang plugin framework at to initialize the plugin.""" # Register the plugin plugin.register_plugin(RESTCONFPlugin()) # Register that we handle extensions from the YANG module 'ietf-restconf' grammar.register_extension_module(restconf_module_name) yd = (restconf_module_name, 'yang-data') statements.add_data_keyword(yd) statements.add_keyword_with_children(yd) statements.add_keywords_with_no_explicit_config(yd) # Register the special grammar for (stmt, occurance, (arg, rules), add_to_stmts) in restconf_stmts: grammar.add_stmt((restconf_module_name, stmt), (arg, rules)) grammar.add_to_stmts_rules(add_to_stmts, [((restconf_module_name, stmt), occurance)]) # Add validation functions statements.add_validation_fun('expand_2', [yd], v_yang_data) # Register special error codes error.add_error_code( 'RESTCONF_YANG_DATA_CHILD', 1, "the 'yang-data' extension must have exactly one " + "child that is a container")
def setup_ctx(self, ctx): if not ctx.opts.ieee: return self._setup_ctx(ctx) error.add_error_code( 'IEEE_BAD_NAMESPACE_VALUE', 4, 'the namespace should be on the form ' 'urn:ieee:std:{IEEE standard designation}:yang:%s') statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: self.v_chk_namespace(ctx, s))
def setup_ctx(self, ctx): if ctx.opts.ietf_help: print_help() sys.exit(0) if not ctx.opts.ietf: return self._setup_ctx(ctx) statements.add_validation_fun( 'grammar', ['description'], lambda ctx, s: self.v_chk_description(ctx, s)) # register our error codes error.add_error_code( 'IETF_MISSING_RFC8174', 4, 'the module seems to use RFC 2119 keywords, but the required' + ' text from RFC 8174 is not found or is not correct' + ' (see pyang --ietf-help for details).') error.add_error_code( 'IETF_MISSING_TRUST_LEGAL_PROVISIONING', 4, 'RFC 8407: 3.1: ' + 'The IETF Trust Copyright statement seems to be' + ' missing or is not correct' + ' (see pyang --ietf-help for details).') error.add_error_code( 'IETF_MISSING_RFC_TEXT', 4, 'RFC 8407: Appendix B: ' + 'The text about which RFC this module is part of seems to be' + ' missing or is not correct' + ' (see pyang --ietf-help for details).')
def setup_ctx(self, ctx): if ctx.opts.ietf_help: print_help() sys.exit(0) if not ctx.opts.ietf: return self._setup_ctx(ctx) statements.add_validation_fun( 'grammar', ['description'], lambda ctx, s: self.v_chk_description(ctx, s)) # register our error codes error.add_error_code( 'IETF_MISSING_RFC8174', 4, 'the module seems to use RFC 2119 keywords, but the required' + ' text from RFC 8174 is not found' + ' (see pyang --ietf-help for details).') error.add_error_code( 'IETF_MISSING_TRUST_LEGAL_PROVISIONING', 4, 'RFC 8407: 3.1: ' + 'The IETF Trust Copyright statement seems to be' + ' missing (see pyang --ietf-help for details).')
def setup_ctx(self, ctx): statements.add_validation_fun('grammar', ['module'], v_chk_module) statements.add_validation_fun('grammar', ['submodule'], v_chk_submodule) statements.add_validation_fun('grammar', ['module', 'submodule'], v_chk_both) error.add_error_code('COMPOSE_MODULE_ONLY', 2, 'Module-only validation called for %s %s') error.add_error_code('COMPOSE_SUBMODULE_ONLY', 2, 'Submodule-only validation called for %s %s') error.add_error_code('COMPOSE_CALLED', 4, 'Check %s issued for %s %s')
def add_opts(self, optparser): optlist = [ optparse.make_option("--check-update-from", metavar="OLDMODULE", dest="check_update_from", help="Verify that upgrade from OLDMODULE" \ " follows RFC 6020 and 7950 rules."), optparse.make_option("-P", "--check-update-from-path", dest="old_path", default=[], action="append", help=os.pathsep + "-separated search path" \ " for yin and yang modules used by" \ " OLDMODULE"), optparse.make_option("-D", "--check-update-from-deviation-module", dest="old_deviation", default=[], action="append", help="Old deviation module of the OLDMODULE." \ " This option can be given multiple" \ " times."), ] optparser.add_options(optlist) # register our error codes error.add_error_code( 'CHK_INVALID_MODULENAME', 1, "the module's name MUST NOT be changed" + " (RFC 6020: 10, p3)") error.add_error_code( 'CHK_INVALID_NAMESPACE', 1, "the module's namespace MUST NOT be changed" + " (RFC 6020: 10, p3)") error.add_error_code( 'CHK_NO_REVISION', 1, "a revision statement MUST be present" + " (RFC 6020: 10, p2)") error.add_error_code( 'CHK_BAD_REVISION', 1, "new revision %s is not newer than old revision %s" + " (RFC 6020: 10, p2)") error.add_error_code( 'CHK_DEF_REMOVED', 1, "the %s '%s', defined at %s is illegally removed") error.add_error_code( 'CHK_DEF_ADDED', 1, "the %s '%s' is illegally added") error.add_error_code( 'CHK_DEF_ADDED2', 1, "the %s '%s' is illegally added in %s %s") error.add_error_code( 'CHK_DEF_CHANGED', 1, "the %s '%s' is illegally changed from '%s'") error.add_error_code( 'CHK_INVALID_STATUS', 1, "new status %s is not valid since the old status was %s") error.add_error_code( 'CHK_CHILD_KEYWORD_CHANGED', 1, "the %s '%s' is illegally changed to a %s") error.add_error_code( 'CHK_MANDATORY_CONFIG', 1, "the node %s is changed to config true, but it is mandatory") error.add_error_code( 'CHK_NEW_MANDATORY', 1, "the mandatory node %s is illegally added") error.add_error_code( 'CHK_BAD_CONFIG', 1, "the node %s is changed to config false") error.add_error_code( 'CHK_NEW_MUST', 1, "a new must expression cannot be added") error.add_error_code( 'CHK_UNDECIDED_MUST', 4, "this must expression may be more constrained than before") error.add_error_code( 'CHK_NEW_WHEN', 1, "a new when expression cannot be added") error.add_error_code( 'CHK_UNDECIDED_WHEN', 4, "this when expression may be different than before") error.add_error_code( 'CHK_UNDECIDED_PRESENCE', 4, "this presence expression may be different than before") error.add_error_code( 'CHK_IMPLICIT_DEFAULT', 1, "the leaf had an implicit default") error.add_error_code( 'CHK_BASE_TYPE_CHANGED', 1, "the base type has illegally changed from %s to %s") error.add_error_code( 'CHK_LEAFREF_PATH_CHANGED', 1, "the leafref's path has illegally changed") error.add_error_code( 'CHK_ENUM_VALUE_CHANGED', 1, "the value for enum '%s', has changed from %s to %s" + " (RFC 6020: 10, p5, bullet 1)") error.add_error_code( 'CHK_BIT_POSITION_CHANGED', 1, "the position for bit '%s', has changed from %s to %s" + " (RFC 6020: 10, p5, bullet 2)") error.add_error_code( 'CHK_RESTRICTION_CHANGED', 1, "the %s has been illegally restricted" + " (RFC 6020: 10, p5, bullet 3)") error.add_error_code( 'CHK_UNION_TYPES', 1, "the member types in the union have changed")
def add_opts(self, optparser): optlist = [ optparse.make_option("--json-pretty", dest="json_pretty", action="store_true", help="""Pretty-print json-output"""), optparse.make_option( "--json-compact-need-when", dest="json_compact_when", action="store_true", help="""Include local when expressions in compact containers""" ), optparse.make_option( "--json-cli", dest="json_cli", action="store_true", help="""Process yang from CLI-parser perspective"""), optparse.make_option( "--json-fwhen", action="append", dest="json_fwhen", type="string", help= """One or more xpaths for which to force include of when-expression""" ), optparse.make_option( "--json-cli-module", action="store", dest="json_cli_module", type="string", help="""Name of module with cli-extensions"""), optparse.make_option( "--json-frelaxed", action="append", dest="json_frelaxed", type="string", help= """One or more xpaths for which to force relaxed-matching""") ] g = optparser.add_option_group("json format specific options") g.add_options(optlist) error.add_error_code('WAMBIGIOUS_NODE', 4, "Suggest cli-disallow-value or pattern in %s") error.add_error_code('WUNHANDLED_NODE', 4, "Node type not handled %s") error.add_error_code( 'BRACKETLEAFLIST_NODE', 4, "CLI-parser can't handle bracket leaf-lists currently, found here %s" ) error.add_error_code( 'EMPTYDROP_NODE', 4, "CLI-parser can't handle cli-drop-node-name in leaf of type empty currently, found here %s" ) error.add_error_code( 'UNSUPPORTED_CLIKEYFMT', 4, "CLI-parser can't handle the cli-key-format found here %s") error.add_error_code( 'UNSUPPORTED_COMBO', 4, "CLI-parser can't handle cli-annotations found here %s")
def pyang_plugin_init(): """Called by pyang plugin framework at to initialize the plugin.""" # Register the plugin plugin.register_plugin(ComplexTypesPlugin()) # check whether the plugin is enabled try: sys.argv.index("--enable-complex-types") except ValueError: return # Register that we handle extensions from the YANG module 'complex-types' grammar.register_extension_module(ct_module_name) # Register the special grammar for (stmt, occurance, (arg, rules), add_to_stmts) in complex_types_stmts: grammar.add_stmt((ct_module_name, stmt), (arg, rules)) grammar.add_to_stmts_rules(add_to_stmts, [((ct_module_name, stmt), occurance)]) # Add validation steps # init phase: initalizes the module/submodule statements statements.add_validation_phase('init_complex_type', after='init2') # grammar phase: # verifies that all complex-types are unique within a parent node statements.add_validation_phase('post_grammar_complex_type', after='grammar') # include phase: loads complex-types from a submodule and # checks for complex-type collisions in a submodule statements.add_validation_phase('include_complex_type', after='import') # validate typed instance identifiers statements.add_validation_phase('instance_type', after='type') # expand the 'extends' statements; statements.add_validation_phase('instantiate_extends', after='expand_1') # instantiate all 'instance'/'instance-list' statements; # this phase should be marked as v_i_children (validate i_children # instead of substatemets) so that we could expand the 'instance'/ # 'instance-list' created by augmentation nested into a 'uses' statement; statements.add_validation_phase('instantiate_instance', after='instantiate_extends') statements.set_phase_i_children('instantiate_instance') # inherit 'config' properties for statements nested into 'complex-type'; # set 'i_config' values; statements.add_validation_phase('inherit_properties_complex_type', after='inherit_properties') # validate augmentation statements that refer to 'instace'/'instance-list' statements.add_validation_phase('pre_expand_2', before='expand_2') # unique names phase: checks for complex type collisions in submodules statements.add_validation_phase('unique_name_complex_type', before='unique_name') # expand all recursive datastructures reffered by deviation statements.add_validation_phase('pre_reference_2', before='reference_2') # Add functions to the validation map statements.add_validation_fun('init_complex_type', ['*'], v_init_complex_type) statements.add_validation_fun('post_grammar_complex_type', ['*'], v_post_grammar_complex_type) statements.add_validation_fun('include_complex_type', ['module', 'submodule'], v_include_complex_type) statements.add_validation_fun('type', [(ct_module_name, str_complex_type)], v_type_complex_type) statements.add_validation_fun('type', [(ct_module_name, str_instance), (ct_module_name, str_instance_list)], v_type_instance) statements.add_validation_fun('instance_type', [(ct_module_name, str_instance_type)], v_type_instance_type) statements.add_validation_fun('instantiate_extends', [(ct_module_name, str_complex_type)], v_instantiate_extends) statements.add_validation_fun('instantiate_instance', [(ct_module_name, str_instance), (ct_module_name, str_instance_list)], v_instantiate_instance) statements.add_validation_fun('inherit_properties_complex_type', [(ct_module_name, str_complex_type)], v_inherit_properties_complex_type) statements.add_validation_fun('pre_expand_2', ['augment'], v_pre_expand_2_augment) statements.add_validation_fun('unique_name_complex_type', ['module'], v_unique_name_complex_type) statements.add_validation_fun('pre_reference_2', ['deviation'], v_reference_load_recursive_nodes) statements.add_validation_fun('reference_1', [(ct_module_name, str_complex_type)], v_reference_complex_type) statements.add_validation_fun('reference_2', [(ct_module_name, str_instance_list)], v_reference_instance_list) statements.add_validation_fun('unused', [(ct_module_name, str_complex_type)], v_unused_complex_type) # Add 'complex-type'/'instance'/'instance-list' to keywords with children statements.add_keyword_with_children((ct_module_name, str_complex_type)) statements.add_keyword_with_children((ct_module_name, str_instance)) statements.add_keyword_with_children((ct_module_name, str_instance_list)) # Add 'instance' and 'instance-list' to the data keywords statements.add_data_keyword((ct_module_name, str_instance)) statements.add_data_keyword((ct_module_name, str_instance_list)) # add 'instance'/'instance-list' to the possible refinements statements.add_refinement_element('description', (ct_module_name, str_instance)) statements.add_refinement_element('description', (ct_module_name, str_instance_list)) statements.add_refinement_element('reference', (ct_module_name, str_instance)) statements.add_refinement_element('reference', (ct_module_name, str_instance_list)) statements.add_refinement_element('config', (ct_module_name, str_instance)) statements.add_refinement_element('config', (ct_module_name, str_instance_list)) statements.add_refinement_element('must', (ct_module_name, str_instance)) statements.add_refinement_element('must', (ct_module_name, str_instance_list)) statements.add_refinement_element('mandatory', (ct_module_name, str_instance)) statements.add_refinement_element('min-elements', (ct_module_name, str_instance_list)) statements.add_refinement_element('max-elements', (ct_module_name, str_instance_list)) # add possibale deviation types for 'instance'/'instance-list' statements statements.add_deviation_element('config', (ct_module_name, str_instance)) statements.add_deviation_element('config', (ct_module_name, str_instance_list)) statements.add_deviation_element('must', (ct_module_name, str_instance)) statements.add_deviation_element('must', (ct_module_name, str_instance_list)) statements.add_deviation_element('mandatory', (ct_module_name, str_instance)) statements.add_deviation_element('min-elements', (ct_module_name, str_instance_list)) statements.add_deviation_element('max-elements', (ct_module_name, str_instance_list)) # define additional error messages: error.add_error_code('COMPLEX_TYPE_ALREADY_DEFINED', 1, 'complex-type "%s" is already defined at %s') error.add_error_code('COMPLEX_TYPE_NOT_FOUND', 1, 'complex type "%s" not found in module "%s"') error.add_error_code('ABSTRACT_NOT_ALLOWED', 1, 'base complex type "%s" of abstract type "%s" must be abstract') error.add_error_code('ABSTRACT_NOT_INSTANTIATED', 1, 'abstract complex type "%s" can not be instantiated') error.add_error_code('UNUSED_COMPLEX_TYPE', 4, 'complex type "%s" not used') error.add_error_code('REDEFINED_KEY', 1, 'key for complex type "%s" is already defined in base type "%s" at %s') error.add_error_code('KEY_REQUIRED', 1, 'complex-type "%s" instantiated at %s with config true must have key') error.add_error_code('REFINE_NOT_INHERITED', 1, '"refine" can not be applied to non-inherited node "%s" defined at %s') error.add_error_code('BAD_REF_AUG', 1, 'refinement and augmentation of instance "%s" at %s is not allowed') error.add_error_code('MANDATORY_AUGMENTATION', 1, 'the node "%s" at %s added by the augmentation must not be mandatory') error.add_error_code('INSTANCE_IDENTIFIER_REQUIRED', 1, 'instance-type may not be specified for "%s" type')
def _setup_ctx(self, ctx): "Should be called by any derived plugin's setup_ctx() function." ctx.strict = True ctx.canonical = True ctx.max_identifier_len = 64 ctx.implicit_errors = False # always add additional prefixes given on the command line self.namespace_prefixes.extend(ctx.opts.namespace_prefixes) self.modulename_prefixes.extend(ctx.opts.modulename_prefixes) # register our grammar validation funs statements.add_validation_var( '$chk_default', lambda keyword: keyword in _keyword_with_default) statements.add_validation_var( '$chk_required', lambda keyword: keyword in _required_substatements) statements.add_validation_var( '$chk_recommended', lambda keyword: keyword in _recommended_substatements) statements.add_validation_fun('grammar', ['$chk_default'], lambda ctx, s: v_chk_default(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_required'], lambda ctx, s: v_chk_required_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_recommended'], lambda ctx, s: v_chk_recommended_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: v_chk_namespace(ctx, s, self.namespace_prefixes)) statements.add_validation_fun( 'grammar', ['module', 'submodule'], lambda ctx, s: v_chk_module_name(ctx, s, self.modulename_prefixes)) # register our error codes error.add_error_code( 'LINT_EXPLICIT_DEFAULT', 4, 'RFC 6087: 4.3: ' + 'statement "%s" is given with its default value "%s"') error.add_error_code( 'LINT_MISSING_REQUIRED_SUBSTMT', 3, '%s: ' + 'statement "%s" must have a "%s" substatement') error.add_error_code( 'LINT_MISSING_RECOMMENDED_SUBSTMT', 4, '%s: ' + 'statement "%s" should have a "%s" substatement') error.add_error_code('LINT_BAD_NAMESPACE_VALUE', 4, 'RFC 6087: 4.8: namespace value should be "%s"') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_1', 4, 'RFC 6087: 4.1: ' + 'the module name should start with the string %s') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_N', 4, 'RFC 6087: 4.1: ' + 'the module name should start with one of the strings %s') error.add_error_code( 'LINT_NO_MODULENAME_PREFIX', 4, 'RFC 6087: 4.1: ' + 'no module name prefix string used') # override std error string error.add_error_code( 'LONG_IDENTIFIER', 3, 'RFC 6087: 4.2: identifier %s exceeds %s characters')
def setup_ctx(self, ctx): if not ctx.opts.threegpp: return self._setup_ctx(ctx) error.add_error_code('3GPP_BAD_NAMESPACE_VALUE', 3, '3GPP: the namespace should be urn:3gpp:sa5:%s') statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: self.v_chk_namespace(ctx, s)) error.add_error_code('3GPP_BAD_PREFIX_VALUE', 3, '3GPP: the prefix should end with 3gpp') error.add_error_code( '3GPP_TOO_LONG_PREFIX', 3, '3GPP: the prefix should not be longer than 13 characters') statements.add_validation_fun('grammar', ['prefix'], lambda ctx, s: self.v_chk_prefix(ctx, s)) error.add_error_code('3GPP_BAD_YANG_VERSION', 3, '3GPP: the yang-version should be 1.1') statements.add_validation_fun( 'grammar', ['yang-version'], lambda ctx, s: self.v_chk_yang_version(ctx, s)) # check that yang-version is present. If not, # it defaults to 1. which is bad for 3GPP statements.add_validation_fun( 'grammar', ['module'], lambda ctx, s: self.v_chk_yang_version_present(ctx, s)) error.add_error_code( '3GPP_STATEMENT_NOT_ALLOWED', 3, ('3GPP: YANG statements anydata, anyxml, deviation, rpc ' 'should not be used')) statements.add_validation_fun( 'grammar', ['anydata', 'anyxml', 'deviation', 'rpc'], lambda ctx, s: self.v_chk_not_allowed_statements(ctx, s)) error.add_error_code('3GPP_BAD_ORGANIZATION', 3, '3GPP: organization statement must include 3GPP') statements.add_validation_fun( 'grammar', ['organization'], lambda ctx, s: self.v_chk_organization(ctx, s)) error.add_error_code('3GPP_BAD_CONTACT', 3, '3GPP: incorrect contact statement') statements.add_validation_fun( 'grammar', ['contact'], lambda ctx, s: self.v_chk_contact(ctx, s)) error.add_error_code( '3GPP_MISSING_MODULE_REFERENCE', 3, '3GPP: the module should have a reference substatement') statements.add_validation_fun( 'grammar', ['module'], lambda ctx, s: self.v_chk_module_reference_present(ctx, s)) error.add_error_code( '3GPP_BAD_MODULE_REFERENCE', 3, '3GPP: the module\'s reference substatement is incorrect') statements.add_validation_fun( 'grammar', ['reference'], lambda ctx, s: self.v_chk_module_reference(ctx, s)) error.add_error_code( '3GPP_TAB_IN_FILE', 3, '3GPP: tab characters should not be used in YANG modules') error.add_error_code( '3GPP_WHITESPACE_AT_END_OF_LINE', 3, '3GPP: extra whitespace should not be added at the end of the line' ) error.add_error_code('3GPP_LONG_LINE', 3, '3GPP: line longer than 80 characters') error.add_error_code( '3GPP_CR_IN_FILE', 3, ('3GPP: Carriage-return characters should not be used. ' 'End-of-line should be just one LF character')) error.add_error_code( '3GPP_NON_ASCII', 4, '3GPP: the module should only use ASCII characters') statements.add_validation_fun( 'grammar', ['module'], lambda ctx, s: self.v_chk_3gpp_format(ctx, s)) error.add_error_code( '3GPP_LIMITED_CONTAINER_USE', 4, ('3GPP: containers should only be used to contain the attributes ' 'of a class')) statements.add_validation_fun( 'grammar', ['container'], lambda ctx, s: self.v_chk_limited_container_use(ctx, s))
def _setup_ctx(self, ctx): "Should be called by any derived plugin's setup_ctx() function." ctx.strict = True ctx.canonical = True ctx.max_identifier_len = 64 ctx.implicit_errors = False # always add additional prefixes given on the command line self.namespace_prefixes.extend(ctx.opts.lint_namespace_prefixes) self.modulename_prefixes.extend(ctx.opts.lint_modulename_prefixes) # register our grammar validation funs statements.add_validation_var( '$chk_default', lambda keyword: keyword in _keyword_with_default) statements.add_validation_var( '$chk_required', lambda keyword: keyword in _required_substatements) statements.add_validation_var( '$chk_recommended', lambda keyword: keyword in _recommended_substatements) statements.add_validation_fun( 'grammar', ['$chk_default'], lambda ctx, s: v_chk_default(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_required'], lambda ctx, s: v_chk_required_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_recommended'], lambda ctx, s: v_chk_recommended_substmt(ctx, s)) if ctx.opts.lint_ensure_hyphenated_names: statements.add_validation_fun( 'grammar', ['*'], lambda ctx, s: v_chk_hyphenated_names(ctx, s)) statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: v_chk_namespace(ctx, s, self.namespace_prefixes)) statements.add_validation_fun( 'grammar', ['module', 'submodule'], lambda ctx, s: v_chk_module_name(ctx, s, self.modulename_prefixes)) statements.add_validation_fun( 'strict', ['include'], lambda ctx, s: v_chk_include(ctx, s)) statements.add_validation_fun( 'strict', ['module'], lambda ctx, s: v_chk_mandatory_top_level(ctx, s)) # register our error codes error.add_error_code( 'LINT_EXPLICIT_DEFAULT', 4, 'RFC 8407: 4.4: ' + 'statement "%s" is given with its default value "%s"') error.add_error_code( 'LINT_MISSING_REQUIRED_SUBSTMT', 3, '%s: ' + 'statement "%s" must have a "%s" substatement') error.add_error_code( 'LINT_MISSING_RECOMMENDED_SUBSTMT', 4, '%s: ' + 'statement "%s" should have a "%s" substatement') error.add_error_code( 'LINT_BAD_NAMESPACE_VALUE', 4, 'RFC 8407: 4.9: namespace value should be "%s"') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_1', 4, 'RFC 8407: 4.1: ' + 'the module name should start with the string %s') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_N', 4, 'RFC 8407: 4.1: ' + 'the module name should start with one of the strings %s') error.add_error_code( 'LINT_NO_MODULENAME_PREFIX', 4, 'RFC 8407: 4.1: ' + 'no module name prefix string used') error.add_error_code( 'LINT_BAD_REVISION', 3, 'RFC 8407: 4.7: ' + 'the module\'s revision %s is older than ' + 'submodule %s\'s revision %s') error.add_error_code( 'LINT_TOP_MANDATORY', 3, 'RFC 8407: 4.10: ' + 'top-level node %s must not be mandatory') error.add_error_code( 'LINT_NOT_HYPHENATED', 4, '%s is not hyphenated, e.g., using upper-case or underscore') # override std error string error.add_error_code( 'LONG_IDENTIFIER', 3, 'RFC 8407: 4.3: identifier %s exceeds %s characters')
def setup_ctx(self, ctx): if not ctx.opts.ietf: return ctx.canonical = True; ctx.max_line_len = 70 ctx.max_identifier_len = 64 ctx.implicit_errors = False # register our grammar validation funs statements.add_validation_var( '$chk_default', lambda keyword: keyword in _keyword_with_default) statements.add_validation_var( '$chk_required', lambda keyword: keyword in _required_substatements) statements.add_validation_var( '$chk_recommended', lambda keyword: keyword in _recommended_substatements) statements.add_validation_fun( 'grammar', ['$chk_default'], lambda ctx, s: v_chk_default(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_required'], lambda ctx, s: v_chk_required_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_recommended'], lambda ctx, s: v_chk_recommended_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: v_chk_namespace(ctx, s)) statements.add_validation_fun( 'grammar', ['module', 'submodule'], lambda ctx, s: v_chk_module_name(ctx, s)) statements.add_validation_fun( 'unique_name', ['module'], lambda ctx, s: v_chk_top_level_nodes(ctx, s)) # register our error codes error.add_error_code( 'IETF_EXPLICIT_DEFAULT', 4, 'IETF rule: statement "%s" is given with its default value "%s"') error.add_error_code( 'IETF_MISSING_REQUIRED_SUBSTMT', 3, 'IETF rule: statement "%s" must have a "%s" substatement') error.add_error_code( 'IETF_MISSING_RECOMMENDED_SUBSTMT', 4, 'IETF rule: statement "%s" should have a "%s" substatement') error.add_error_code( 'IETF_BAD_NAMESPACE_VALUE', 4, 'IETF rule: namespace value should be "%s"') error.add_error_code( 'IETF_TOO_MANY_TOP_LEVEL_NODES', 4, 'IETF rule: too many top-level data nodes: %s') error.add_error_code( 'IETF_NO_MODULE_PREFIX', 4, 'IETF rule: no module name prefix used, suggest ietf-%s') # override std error string error.add_error_code( 'LONG_LINE', 4, 'IETF rule: line length %s exceeds %s characters') error.add_error_code( 'LONG_IDENTIFIER', 3, 'IETF rule: identifier %s exceeds %s characters')
def setup_ctx(self, ctx): if not ctx.opts.threegpp: return self._setup_ctx(ctx) error.add_error_code( '3GPP_BAD_NAMESPACE_VALUE', 3, '3GPP: the namespace should be on the form ' 'urn:3gpp:sa5:%s') statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: self.v_chk_namespace(ctx, s)) error.add_error_code('3GPP_BAD_PREFIX_VALUE', 3, '3GPP: the prefix should end with 3gpp') error.add_error_code( '3GPP_TOO_LONG_PREFIX', 3, '3GPP: the prefix should not be longer than 10 characters') statements.add_validation_fun('grammar', ['prefix'], lambda ctx, s: self.v_chk_prefix(ctx, s)) error.add_error_code('3GPP_BAD_YANG_VERSION', 3, '3GPP: the yang-version should be 1.1') statements.add_validation_fun( 'grammar', ['yang-version'], lambda ctx, s: self.v_chk_yang_version(ctx, s)) # check that yang-version is present. If not, # it defaults to 1. which is bad for 3GPP statements.add_validation_fun( 'grammar', ['module'], lambda ctx, s: self.v_chk_yang_version_present(ctx, s)) error.add_error_code( '3GPP_STATEMENT_NOT_ALLOWED', 3, ('3GPP: YANG statements anydata, anyxml, deviation, rpc ' 'should not be used')) error.add_error_code( '3GPP_LIMITED_CONTAINER_USE', 4, ('3GPP: containers should only be used to contain the attributes ' 'of a class')) statements.add_validation_fun( 'grammar', ['anydata', 'anyxml', 'deviation', 'rpc'], lambda ctx, s: self.v_chk_not_allowed_statements(ctx, s)) statements.add_validation_fun( 'grammar', ['container'], lambda ctx, s: self.v_chk_limited_container_use(ctx, s)) error.add_error_code('3GPP_BAD_CONTACT', 3, '3GPP: incorrect contact statement') statements.add_validation_fun( 'grammar', ['contact'], lambda ctx, s: self.v_chk_contact(ctx, s)) error.add_error_code('3GPP_BAD_ORGANIZATION', 3, '3GPP: incorrect organization statement') statements.add_validation_fun( 'grammar', ['organization'], lambda ctx, s: self.v_chk_organization(ctx, s)) error.add_error_code( '3GPP_MISSING_MODULE_REFERENCE', 3, '3GPP: the module should have a reference substatement')
def post_validate_ctx(self, ctx, modules): if not ctx.opts.threegpp: return """Remove some lint errors that 3GPP considers acceptable""" for ctx_error in ctx.errors[:]: if ((ctx_error[1] == "LINT_MISSING_REQUIRED_SUBSTMT" or ctx_error[1] == "LINT_MISSING_RECOMMENDED_SUBSTMT") and ctx_error[2][2] == 'description' and (ctx_error[2][1] == 'enum' or ctx_error[2][1] == 'bit' or ctx_error[2][1] == 'choice' or ctx_error[2][1] == 'container' or ctx_error[2][1] == 'leaf-list' or ctx_error[2][1] == 'leaf' or ctx_error[2][1] == 'typedef' or ctx_error[2][1] == 'grouping' or ctx_error[2][1] == 'augment')): # remove error from ctx ctx.errors.remove(ctx_error) # check 3gpp format: error.add_error_code( '3GPP_TAB_IN_FILE', 3, '3GPP: tab characters should not be used in YANG modules') error.add_error_code( '3GPP_WHITESPACE_AT_END_OF_LINE', 3, '3GPP: extra whitespace should not be added at the end of the line' ) error.add_error_code('3GPP_LONG_LINE', 3, '3GPP: line longer than 80 characters') error.add_error_code( '3GPP_CR_IN_FILE', 3, ('3GPP: Carriage-return characters should not be used. ' 'End-of-line should be just one LF character')) error.add_error_code( '3GPP_NON_ASCII', 4, '3GPP: the module should only use ASCII characters') for module in modules: filename = module.pos.ref try: fd = io.open(filename, "r", encoding="utf-8", newline='') lineno = 0 for line in fd: lineno += 1 self.pos = error.Position(module.pos.ref) self.pos.line = lineno # no tabs if (line.find('\t') != -1): err_add(ctx.errors, self.pos, '3GPP_TAB_IN_FILE', ()) # no whitespace after the line # removed for now as there are just too many of these # errors # if (re.search('.*\s+\n',line) != None ): # err_add(ctx.errors, self.pos, # '3GPP_WHITESPACE_AT_END_OF_LINE',()) # lines shorter then 80 char if (len(line) > 82): err_add(ctx.errors, self.pos, '3GPP_LONG_LINE', ()) # EOL should be just NL no CR if (line.find('\r') != -1): err_add(ctx.errors, self.pos, '3GPP_CR_IN_FILE', ()) # only us-ascii chars try: line.encode('ascii') except UnicodeEncodeError: err_add(ctx.errors, self.pos, '3GPP_NON_ASCII', ()) except IOError as ex: sys.stderr.write("error %s: %s\n" % (filename, ex)) sys.exit(1) except UnicodeDecodeError as ex: s = str(ex).replace('utf-8', 'utf8') sys.stderr.write("%s: unicode error: %s\n" % (filename, s)) sys.exit(1) return
def setup_ctx(self, ctx): if not (ctx.opts.openconfig): return if (not ctx.opts.openconfig_only): # call the standard linter setup self._setup_ctx(ctx) else: # don't call standard linter but have to set up some of the same rules # ourselves statements.add_validation_fun( 'grammar', ['module', 'submodule'], lambda ctx, s: lint.v_chk_module_name(ctx, s, self.modulename_prefixes)) error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX', 4, 'RFC 6087: 4.1: ' + 'no module name prefix used, suggest %s-%s') # Add OpenConfig validation phase statements.add_validation_phase('preinit', before='init') # Add an expensive function which we call one per module to check # things that cannot be checked in the later phases (e.g., text # conventions). statements.add_validation_fun('preinit', ['module'], lambda ctx, s: v_preinit_module_checks(ctx, s)) # add the OpenConfig validators # Check for all type statements statements.add_validation_fun( 'type_2', ['type', 'identity', 'identityref'], lambda ctx, s: v_chk_octypes(ctx, s)) # Checks module properties after the module has # been parsed statements.add_validation_fun( 'type_2', ['module'], lambda ctx, s: v_chk_ocmodule(ctx, s)) # Check for warnings that are style-guide specific statements.add_validation_fun( 'type_2', ['presence', 'choice', 'feature', 'if-feature'], lambda ctx, s: v_styleguide_warnings(ctx, s)) # Check properties that are related to data elements statements.add_validation_fun( 'type_2', ['leaf', 'leaf-list', 'list', 'container'], lambda ctx, s: v_chk_data_elements(ctx, s)) # Check grouping names statements.add_validation_fun( 'type_2', ['container'], lambda ctx, s: v_chk_standard_grouping_naming(ctx, s)) # Check the prefix of the module statements.add_validation_fun( 'type_2', ['prefix'], lambda ctx, s: v_chk_prefix(ctx, s)) # Checks relevant to placement of leaves and leaf lists within the # opstate structure statements.add_validation_fun( 'reference_2', ['leaf', 'leaf-list'], lambda ctx, s: v_chk_opstate_paths(ctx,s)) # Checks lists within the structure statements.add_validation_fun( 'reference_4', ['list'], lambda ctx, s: v_chk_list_placement(ctx, s)) # Checks relevant to the specifications of paths in the module statements.add_validation_fun( 'reference_2', ['path', 'augment'], lambda ctx, s: v_chk_path_refs(ctx,s)) # Check that leaves are mirrored between config and state containers statements.add_validation_fun( 'reference_4', ['container'], lambda ctx, s: v_chk_leaf_mirroring(ctx,s)) # add the OpenConfig error codes # capitalization of enumeration values error.add_error_code( 'OC_ENUM_CASE', 3, 'enum value' + ' "%s" should be all caps as "%s"') # UPPERCASE_WITH_UNDERSCORES required for enum values error.add_error_code( 'OC_ENUM_UNDERSCORES', 3, 'enum value ' + '"%s" should be of the form ' + 'UPPERCASE_WITH_UNDERSCORES: "%s"') # capitalization of identity values error.add_error_code( 'OC_IDENTITY_CASE', 3, 'identity name' + ' "%s" should be all caps as "%s"') # UPPERCASE_WITH_UNDERSCORES required for identity values error.add_error_code( 'OC_IDENTITY_UNDERSCORES', 3, 'identity name ' + '"%s" should be of the form ' + 'UPPERCASE_WITH_UNDERSCORES: "%s"') # single config / state container in the path error.add_error_code( 'OC_OPSTATE_CONTAINER_COUNT', 3, 'path "%s" should have a single "config" or "state" component') # leaves should be in a 'config' or 'state' container error.add_error_code( 'OC_OPSTATE_CONTAINER_NAME', 3, 'element "%s" at path "%s" should be in a "config" or "state" container') # list keys should be leafrefs to respective value in config / state error.add_error_code( 'OC_OPSTATE_KEY_LEAFREF', 3, 'list key "%s" should be type leafref with a reference to corresponding' + ' leaf in config or state container') # leaves in in config / state should have the correct config property error.add_error_code( 'OC_OPSTATE_CONFIG_PROPERTY', 3, 'element "%s" is in a "%s" container and should have config value %s') # references to nodes in the same module / namespace should use relative # paths error.add_error_code( 'OC_RELATIVE_PATH', 4, '"%s" path reference "%s" is intra-module but uses absolute path') # a config leaf does not have a mirrored applied config leaf in the state # container error.add_error_code( 'OC_OPSTATE_APPLIED_CONFIG', 3, '"%s" is not mirrored in the state container at %s') # a list is within a container that has elements other than the list within # it error.add_error_code( 'OC_LIST_SURROUNDING_CONTAINER', 3, 'List %s is within a container (%s) that has other elements ' + 'within it: %s') # A list does not have an enclosing container error.add_error_code( 'OC_LIST_NO_ENCLOSING_CONTAINER', 3, 'List %s is directly within a config or state container (%s)') # a module defines data nodes at the top-level error.add_error_code( 'OC_MODULE_DATA_DEFINITIONS', 3, 'Module %s defines data definitions at the top level: %s') # a module is missing an openconfig-version statement error.add_error_code( 'OC_MODULE_MISSING_VERSION', 3, 'Module %s is missing an ' + 'openconfig-version statement') # a module uses the 'choice' keyword error.add_error_code( 'OC_STYLE_AVOID_CHOICE', 4, 'Element %s uses the choice keyword, which ' + 'should be avoided') # a module uses the 'presence' keyword error.add_error_code( 'OC_STYLE_AVOID_PRESENCE', 4, 'Element %s uses the presence keyword, ' + 'which should be avoided') # a module uses the 'if-feature' or 'feature' keyword error.add_error_code( 'OC_STYLE_AVOID_FEATURES', 4, 'Element %s uses feature or if-feature ' + 'which should be avoided') # invalid semantic version argument to openconfig-version error.add_error_code( 'OC_INVALID_SEMVER', 3, 'Semantic version specified (%s) is invalid') # missing a revision statement that has a reference of the # current semantic version error.add_error_code( 'OC_MISSING_SEMVER_REVISION', 4, 'Revision statement should contain' + 'reference substatement corresponding to semantic version %s') # invalid data element naming error.add_error_code( 'OC_DATA_ELEMENT_INVALID_NAME', 4, 'Invalid naming for element %s ' + 'data elements should generally be lower-case-with-hypens') # the module uses an invalid form of prefix error.add_error_code( 'OC_PREFIX_INVALID', 4, 'Prefix %s for module does not match the ' + 'expected format - use the form oc-<shortdescription>') # the module is missing a standard grouping (e.g., -top) error.add_error_code( 'OC_MISSING_STANDARD_GROUPING', 4, 'Module %s is missing a grouping suffixed ' + 'with %s') # the module has a nonstandard grouping name error.add_error_code( 'OC_GROUPING_NAMING_NONSTANDARD', 4, 'In container %s, grouping %s does not ' + 'match standard naming - suffix with %s?') # key statements do not have quoted arguments error.add_error_code( 'OC_KEY_ARGUMENT_UNQUOTED', 3, 'All key arguments of a list should be ' + 'quoted (%s is not)')
def setup_ctx(self, ctx): if not ctx.opts.openconfig: return if not ctx.opts.openconfig_only: # Support IETF as a prefix for modules self.modulename_prefixes.extend(["ietf", "iana"]) # We do not want all RFC6087 rules, so we need to borrow some # from the standard linter. We cannot simply call the _setup_ctx # module as this adds rules that we do not want - this code block # is borrowed from that module. statements.add_validation_var( "$chk_default", lambda keyword: keyword in lint._keyword_with_default) statements.add_validation_var( "$chk_required", lambda keyword: keyword in ExternalValidationRules.required_substatements) statements.add_validation_var( "$chk_recommended", lambda keyword: keyword in lint._recommended_substatements) statements.add_validation_fun( "grammar", ["$chk_default"], lambda ctx, s: lint.v_chk_default(ctx, s)) statements.add_validation_fun( "grammar", ["$chk_required"], OCLintStages.openconfig_override_base_linter) statements.add_validation_fun( "grammar", ["$chk_recommended"], OCLintStages.openconfig_override_base_linter) statements.add_validation_fun( "grammar", ["namespace"], lambda ctx, s: lint.v_chk_namespace(ctx, s, self.namespace_prefixes)) statements.add_validation_fun( "grammar", ["module", "submodule"], lambda ctx, s: lint.v_chk_module_name(ctx, s, self.modulename_prefixes)) statements.add_validation_fun( "strict", ["include"], lambda ctx, s: lint.v_chk_include(ctx, s)) # Register the default linter error codes error.add_error_code( "LINT_EXPLICIT_DEFAULT", ErrorLevel.WARNING, "RFC 6087: 4.3: " "statement \"%s\" is given with its default value \"%s\"") error.add_error_code( "LINT_MISSING_REQUIRED_SUBSTMT", ErrorLevel.MINOR, "%s: " "statement \"%s\" must have a \"%s\" substatement") error.add_error_code( "LINT_MISSING_RECOMMENDED_SUBSTMT", ErrorLevel.WARNING, "%s: " "statement \"%s\" should have a \"%s\" substatement") error.add_error_code( "LINT_BAD_NAMESPACE_VALUE", ErrorLevel.WARNING, "RFC 6087: 4.8: namespace value should be \"%s\"") error.add_error_code( "LINT_BAD_MODULENAME_PREFIX_1", ErrorLevel.WARNING, "RFC 6087: 4.1: " "the module name should start with the string %s") error.add_error_code( "LINT_BAD_MODULENAME_PREFIX_N", ErrorLevel.WARNING, "RFC 6087: 4.1: " "the module name should start with one of the strings %s") error.add_error_code( "LINT_NO_MODULENAME_PREFIX", ErrorLevel.WARNING, "RFC 6087: 4.1: " "no module name prefix string used") error.add_error_code( "LINT_BAD_REVISION", ErrorLevel.MINOR, "RFC 6087: 4.6: " "the module's revision %s is older than " "submodule %s's revision %s") error.add_error_code( "LINT_TOP_MANDATORY", ErrorLevel.MINOR, "RFC 6087: 4.9: " "top-level node %s must not be mandatory") error.add_error_code( "LONG_IDENTIFIER", ErrorLevel.MINOR, "RFC 6087: 4.2: identifier %s exceeds %s characters") # Add a pre-initialisation phase where we can read the # modules before they have been parsed by pyang fully. statements.add_validation_phase("preinit", before="init") statements.add_validation_fun("preinit", ["*"], OCLintStages.preinitialisation) # Add an openconfig types validation phase where we can # get types and then validate them further. statements.add_validation_phase("openconfig_type", after="type_2") statements.add_validation_fun("openconfig_type", ["*"], OCLintStages.openconfig_type) # pyang manipulates the paths of elements during reference_2, such # that this is the only time that we get a chance to work statements.add_validation_fun("reference_2", ["*"], OCLintStages.openconfig_reference) # Error type for generic OpenConfig linter bugs - returned # when an error is encountered in linter logic. error.add_error_code( "OC_LINTER_ERROR", ErrorLevel.CRITICAL, "Linter error encountered: %s") # Enum values must be upper case error.add_error_code( "OC_ENUM_CASE", ErrorLevel.MAJOR, "enum value \"%s\" should be capitalised as \"%s\"") # Enum values must be of the form UPPERCASE_WITH_UNDERSCORES error.add_error_code( "OC_ENUM_UNDERSCORES", ErrorLevel.MAJOR, "enum value \"%s\" should be of the form " "UPPERCASE_WITH_UNDERSCORES: %s") # Identity values should be capitalised error.add_error_code( "OC_IDENTITY_CASE", ErrorLevel.MAJOR, "identity name \"%s\" should be capitalised as \"%s\"") # UPPERCASE_WITH_UNDERSCORES required for identity values error.add_error_code( "OC_IDENTITY_UNDERSCORES", ErrorLevel.MAJOR, "identity name \"%s\" should be of the form " "UPPERCASE_WITH_UNDERSCORES: \"%s\"") # There must be a single config / state container in the path error.add_error_code( "OC_OPSTATE_CONTAINER_COUNT", ErrorLevel.MAJOR, "path \"%s\" should have a single \"config\" or \"state\" component") # Leaves should be in a "config" or "state" container error.add_error_code( "OC_OPSTATE_CONTAINER_NAME", ErrorLevel.MAJOR, "element \"%s\" at path \"%s\" should be in a \"config\"" "or \"state\" container") # list keys should be leafrefs to respective value in config / state error.add_error_code( "OC_OPSTATE_KEY_LEAFREF", ErrorLevel.MAJOR, "list key \"%s\" should be type leafref with a reference to" " the corresponding leaf in config or state container") # list keys should be leafrefs to direct children of config / state error.add_error_code( "OC_OPSTATE_KEY_LEAFREF_DIRECT", ErrorLevel.MAJOR, "list key \"%s\" should be type leafref with a path to a" " a direct child of the config or state container") # leaves in in config / state should have the correct config property error.add_error_code( "OC_OPSTATE_CONFIG_PROPERTY", ErrorLevel.MAJOR, "element \"%s\" is in a \"%s\" container and should have " "config value %s") # references to nodes in the same module / namespace should use relative # paths error.add_error_code( "OC_RELATIVE_PATH", ErrorLevel.WARNING, "\"%s\" path reference \"%s\" is intra-module but uses absolute path") # a config leaf does not have a mirrored applied config leaf in the state # container error.add_error_code( "OC_OPSTATE_APPLIED_CONFIG", ErrorLevel.MAJOR, "\"%s\" is not mirrored in the state container at %s") # a list is within a container that has elements other than the list # within it error.add_error_code( "OC_LIST_SURROUNDING_CONTAINER", ErrorLevel.MAJOR, "List %s is within a container (%s) that has other elements " "within it: %s") # a list that does not have a container above it error.add_error_code( "OC_LIST_NO_ENCLOSING_CONTAINER", ErrorLevel.MAJOR, "List %s does not have a surrounding container") # when path compression is performed, the containers surrounding # lists are removed, if there are two lists with the same name # this results in a name collision. error.add_error_code( "OC_LIST_DUPLICATE_COMPRESSED_NAME", ErrorLevel.MAJOR, "List %s has a duplicate name when the parent container %s" + \ " is removed.") # a module defines data nodes at the top-level error.add_error_code( "OC_MODULE_DATA_DEFINITIONS", ErrorLevel.MAJOR, "Module %s defines data definitions at the top level: %s") # a module is missing an openconfig-version statement error.add_error_code( "OC_MODULE_MISSING_VERSION", ErrorLevel.MAJOR, "Module %s is missing an openconfig-version statement") # a module uses the "choice" keyword error.add_error_code( "OC_STYLE_AVOID_CHOICE", ErrorLevel.WARNING, "Element %s uses the choice keyword, which should be avoided") # a module uses the "presence" keyword error.add_error_code( "OC_STYLE_AVOID_PRESENCE", ErrorLevel.MINOR, "Element %s uses the presence keyword which should be avoided") # a module uses the "if-feature" or "feature" keyword error.add_error_code( "OC_STYLE_AVOID_FEATURES", ErrorLevel.MINOR, "Element %s uses feature or if-feature which should be avoided") # invalid semantic version argument to openconfig-version error.add_error_code( "OC_INVALID_SEMVER", ErrorLevel.MAJOR, "Semantic version specified (%s) is invalid") # missing a revision statement that has a reference of the # current semantic version error.add_error_code( "OC_MISSING_SEMVER_REVISION", ErrorLevel.MAJOR, "Revision statement should contain reference substatement " " corresponding to semantic version %s") # invalid data element naming error.add_error_code( "OC_DATA_ELEMENT_INVALID_NAME", ErrorLevel.MAJOR, "Invalid naming for element %s data elements should " " generally be lower-case-with-hypens") # the module uses an invalid form of prefix error.add_error_code( "OC_PREFIX_INVALID", ErrorLevel.MINOR, "Prefix %s for module does not match the expected " " format - use the form oc-<shortdescription>") # the module is missing a standard grouping (e.g., -top) error.add_error_code( "OC_MISSING_STANDARD_GROUPING", ErrorLevel.WARNING, "Module %s is missing a grouping suffixed with %s") # the module has a nonstandard grouping name error.add_error_code( "OC_GROUPING_NAMING_NONSTANDARD", ErrorLevel.WARNING, "In container %s, grouping %s does not match standard " "naming - suffix with %s?") # key statements do not have quoted arguments error.add_error_code( "OC_KEY_ARGUMENT_UNQUOTED", ErrorLevel.MINOR, "All key arguments of a list should be quoted (%s is not)") # bad type was used for a leaf or typedef error.add_error_code( "OC_BAD_TYPE", ErrorLevel.MAJOR, "Bad type %s used in leaf or typedef", ) # unequal number of posix-pattern and pattern statements. error.add_error_code( "OC_POSIX_PATTERN_COUNT_UNEQUAL", ErrorLevel.MAJOR, "unequal number of posix-pattern statements (%d) to pattern " "statements (%d)", )
def _setup_ctx(self, ctx): "Should be called by any derived plugin's setup_ctx() function." ctx.strict = True ctx.canonical = True ctx.max_identifier_len = 64 ctx.implicit_errors = False # always add additional prefixes given on the command line self.namespace_prefixes.extend(ctx.opts.namespace_prefixes) self.modulename_prefixes.extend(ctx.opts.modulename_prefixes) # register our grammar validation funs statements.add_validation_var( '$chk_default', lambda keyword: keyword in _keyword_with_default) statements.add_validation_var( '$chk_required', lambda keyword: keyword in _required_substatements) statements.add_validation_var( '$chk_recommended', lambda keyword: keyword in _recommended_substatements) statements.add_validation_fun( 'grammar', ['$chk_default'], lambda ctx, s: v_chk_default(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_required'], lambda ctx, s: v_chk_required_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_recommended'], lambda ctx, s: v_chk_recommended_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: v_chk_namespace(ctx, s, self.namespace_prefixes)) statements.add_validation_fun( 'grammar', ['module', 'submodule'], lambda ctx, s: v_chk_module_name(ctx, s, self.modulename_prefixes)) # register our error codes error.add_error_code( 'LINT_EXPLICIT_DEFAULT', 4, 'RFC 6087: 4.3: ' + 'statement "%s" is given with its default value "%s"') error.add_error_code( 'LINT_MISSING_REQUIRED_SUBSTMT', 3, '%s: ' + 'statement "%s" must have a "%s" substatement') error.add_error_code( 'LINT_MISSING_RECOMMENDED_SUBSTMT', 4, '%s: ' + 'statement "%s" should have a "%s" substatement') error.add_error_code( 'LINT_BAD_NAMESPACE_VALUE', 4, 'RFC 6087: 4.8: namespace value should be "%s"') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_1', 4, 'RFC 6087: 4.1: ' + 'the module name should start with the string %s') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_N', 4, 'RFC 6087: 4.1: ' + 'the module name should start with one of the strings %s') error.add_error_code( 'LINT_NO_MODULENAME_PREFIX', 4, 'RFC 6087: 4.1: ' + 'no module name prefix string used') # override std error string error.add_error_code( 'LONG_IDENTIFIER', 3, 'RFC 6087: 4.2: identifier %s exceeds %s characters')
def _setup_ctx(self, ctx): "Should be called by any derived plugin's setup_ctx() function." ctx.strict = True ctx.canonical = True ctx.max_identifier_len = 64 ctx.implicit_errors = False # always add additional prefixes given on the command line self.namespace_prefixes.extend(ctx.opts.lint_namespace_prefixes) self.modulename_prefixes.extend(ctx.opts.lint_modulename_prefixes) # copy other lint options to instance variables, taking care not to # overwrite any settings from derived class constructors if ctx.opts.lint_ensure_hyphenated_names: self.ensure_hyphenated_names = True # register our grammar validation funs statements.add_validation_var( '$chk_default', lambda keyword: keyword in _keyword_with_default) statements.add_validation_var( '$chk_required', lambda keyword: keyword in _required_substatements) statements.add_validation_var( '$chk_recommended', lambda keyword: keyword in _recommended_substatements) statements.add_validation_fun( 'grammar', ['$chk_default'], lambda ctx, s: v_chk_default(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_required'], lambda ctx, s: v_chk_required_substmt(ctx, s)) statements.add_validation_fun( 'grammar', ['$chk_recommended'], lambda ctx, s: v_chk_recommended_substmt(ctx, s)) if self.ensure_hyphenated_names: statements.add_validation_fun( 'grammar', ['*'], lambda ctx, s: v_chk_hyphenated_names(ctx, s)) statements.add_validation_fun( 'grammar', ['namespace'], lambda ctx, s: v_chk_namespace(ctx, s, self.namespace_prefixes)) statements.add_validation_fun( 'grammar', ['module', 'submodule'], lambda ctx, s: v_chk_module_name(ctx, s, self.modulename_prefixes)) statements.add_validation_fun( 'strict', ['include'], lambda ctx, s: v_chk_include(ctx, s)) statements.add_validation_fun( 'strict', ['module'], lambda ctx, s: v_chk_mandatory_top_level(ctx, s)) # register our error codes error.add_error_code( 'LINT_EXPLICIT_DEFAULT', 4, 'RFC 8407: 4.4: ' + 'statement "%s" is given with its default value "%s"') error.add_error_code( 'LINT_MISSING_REQUIRED_SUBSTMT', 3, '%s: ' + 'statement "%s" must have a "%s" substatement') error.add_error_code( 'LINT_MISSING_RECOMMENDED_SUBSTMT', 4, '%s: ' + 'statement "%s" should have a "%s" substatement') error.add_error_code( 'LINT_BAD_NAMESPACE_VALUE', 4, 'RFC 8407: 4.9: namespace value should be "%s"') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_1', 4, 'RFC 8407: 4.1: ' + 'the module name should start with the string %s') error.add_error_code( 'LINT_BAD_MODULENAME_PREFIX_N', 4, 'RFC 8407: 4.1: ' + 'the module name should start with one of the strings %s') error.add_error_code( 'LINT_NO_MODULENAME_PREFIX', 4, 'RFC 8407: 4.1: ' + 'no module name prefix string used') error.add_error_code( 'LINT_BAD_REVISION', 3, 'RFC 8407: 4.7: ' + 'the module\'s revision %s is older than ' + 'submodule %s\'s revision %s') error.add_error_code( 'LINT_TOP_MANDATORY', 3, 'RFC 8407: 4.10: ' + 'top-level node %s must not be mandatory') error.add_error_code( 'LINT_NOT_HYPHENATED', 4, '%s is not hyphenated, e.g., using upper-case or underscore') # override std error string error.add_error_code( 'LONG_IDENTIFIER', 3, 'RFC 8407: 4.3: identifier %s exceeds %s characters')
def _setup_ctx(self, ctx): "Should be called by any derived plugin's setup_ctx() function." ctx.strict = True ctx.canonical = True ctx.max_identifier_len = 64 ctx.implicit_errors = False # always add additional prefixes given on the command line self.namespace_prefixes.extend(ctx.opts.namespace_prefixes) self.modulename_prefixes.extend(ctx.opts.modulename_prefixes) # register our grammar validation funs statements.add_validation_var("$chk_default", lambda keyword: keyword in _keyword_with_default) statements.add_validation_var("$chk_required", lambda keyword: keyword in _required_substatements) statements.add_validation_var("$chk_recommended", lambda keyword: keyword in _recommended_substatements) statements.add_validation_fun("grammar", ["$chk_default"], lambda ctx, s: v_chk_default(ctx, s)) statements.add_validation_fun("grammar", ["$chk_required"], lambda ctx, s: v_chk_required_substmt(ctx, s)) statements.add_validation_fun("grammar", ["$chk_recommended"], lambda ctx, s: v_chk_recommended_substmt(ctx, s)) statements.add_validation_fun( "grammar", ["namespace"], lambda ctx, s: v_chk_namespace(ctx, s, self.namespace_prefixes) ) statements.add_validation_fun( "grammar", ["module", "submodule"], lambda ctx, s: v_chk_module_name(ctx, s, self.modulename_prefixes) ) statements.add_validation_fun("strict", ["include"], lambda ctx, s: v_chk_include(ctx, s)) statements.add_validation_fun("strict", ["module"], lambda ctx, s: v_chk_mandatory_top_level(ctx, s)) # register our error codes error.add_error_code( "LINT_EXPLICIT_DEFAULT", 4, "RFC 6087: 4.3: " + 'statement "%s" is given with its default value "%s"' ) error.add_error_code( "LINT_MISSING_REQUIRED_SUBSTMT", 3, "%s: " + 'statement "%s" must have a "%s" substatement' ) error.add_error_code( "LINT_MISSING_RECOMMENDED_SUBSTMT", 4, "%s: " + 'statement "%s" should have a "%s" substatement' ) error.add_error_code("LINT_BAD_NAMESPACE_VALUE", 4, 'RFC 6087: 4.8: namespace value should be "%s"') error.add_error_code( "LINT_BAD_MODULENAME_PREFIX_1", 4, "RFC 6087: 4.1: " + "the module name should start with the string %s" ) error.add_error_code( "LINT_BAD_MODULENAME_PREFIX_N", 4, "RFC 6087: 4.1: " + "the module name should start with one of the strings %s", ) error.add_error_code("LINT_NO_MODULENAME_PREFIX", 4, "RFC 6087: 4.1: " + "no module name prefix string used") error.add_error_code( "LINT_BAD_REVISION", 3, "RFC 6087: 4.6: " + "the module's revision %s is older than " + "submodule %s's revision %s", ) error.add_error_code("LINT_TOP_MANDATORY", 3, "RFC 6087: 4.9: " + "top-level node %s must not be mandatory") # override std error string error.add_error_code("LONG_IDENTIFIER", 3, "RFC 6087: 4.2: identifier %s exceeds %s characters")
def add_opts(self, optparser): optlist = [ optparse.make_option("--check-update-from", metavar="OLDMODULE", dest="check_update_from", help="Verify that upgrade from OLDMODULE" \ " follows RFC 6020 and 7950 rules."), optparse.make_option("-P", "--check-update-from-path", dest="old_path", default=[], action="append", help=os.pathsep + "-separated search path" \ " for yin and yang modules used by" \ " OLDMODULE"), optparse.make_option("-D", "--check-update-from-deviation-module", dest="old_deviation", default=[], action="append", help="Old deviation module of the OLDMODULE." \ " This option can be given multiple" \ " times."), ] optparser.add_options(optlist) # register our error codes error.add_error_code( 'CHK_INVALID_MODULENAME', 1, "the module's name MUST NOT be changed" + " (RFC 6020: 10, p3)") error.add_error_code( 'CHK_INVALID_NAMESPACE', 1, "the module's namespace MUST NOT be changed" + " (RFC 6020: 10, p3)") error.add_error_code( 'CHK_NO_REVISION', 1, "a revision statement MUST be present" + " (RFC 6020: 10, p2)") error.add_error_code( 'CHK_BAD_REVISION', 1, "new revision %s is not newer than old revision %s" + " (RFC 6020: 10, p2)") error.add_error_code( 'CHK_DEF_REMOVED', 1, "the %s '%s', defined at %s is illegally removed") error.add_error_code( 'CHK_DEF_ADDED', 1, "the %s '%s' is illegally added") error.add_error_code( 'CHK_DEF_CHANGED', 1, "the %s '%s' is illegally changed from '%s'") error.add_error_code( 'CHK_INVALID_STATUS', 1, "new status %s is not valid since the old status was %s") error.add_error_code( 'CHK_CHILD_KEYWORD_CHANGED', 1, "the %s '%s' is illegally changed to a %s") error.add_error_code( 'CHK_MANDATORY_CONFIG', 1, "the node %s is changed to config true, but it is mandatory") error.add_error_code( 'CHK_NEW_MANDATORY', 1, "the mandatory node %s is illegally added") error.add_error_code( 'CHK_BAD_CONFIG', 1, "the node %s is changed to config false") error.add_error_code( 'CHK_NEW_MUST', 1, "a new must expression cannot be added") error.add_error_code( 'CHK_UNDECIDED_MUST', 4, "this must expression may be more constrained than before") error.add_error_code( 'CHK_NEW_WHEN', 1, "a new when expression cannot be added") error.add_error_code( 'CHK_UNDECIDED_WHEN', 4, "this when expression may be different than before") error.add_error_code( 'CHK_UNDECIDED_PRESENCE', 4, "this presence expression may be different than before") error.add_error_code( 'CHK_IMPLICIT_DEFAULT', 1, "the leaf had an implicit default") error.add_error_code( 'CHK_BASE_TYPE_CHANGED', 1, "the base type has illegally changed from %s to %s") error.add_error_code( 'CHK_LEAFREF_PATH_CHANGED', 1, "the leafref's path has illegally changed") error.add_error_code( 'CHK_ENUM_VALUE_CHANGED', 1, "the value for enum '%s', has changed from %s to %s" + " (RFC 6020: 10, p5, bullet 1)") error.add_error_code( 'CHK_BIT_POSITION_CHANGED', 1, "the position for bit '%s', has changed from %s to %s" + " (RFC 6020: 10, p5, bullet 2)") error.add_error_code( 'CHK_RESTRICTION_CHANGED', 1, "the %s has been illegally restricted" + " (RFC 6020: 10, p5, bullet 3)") error.add_error_code( 'CHK_UNION_TYPES', 1, "the member types in the union have changed")
def setup_ctx(self, ctx): if not ctx.opts.openconfig: return if not ctx.opts.openconfig_only: # Support IETF as a prefix for modules self.modulename_prefixes.extend(["ietf", "iana"]) # We do not want all RFC6087 rules, so we need to borrow some # from the standard linter. We cannot simply call the _setup_ctx # module as this adds rules that we do not want - this code block # is borrowed from that module. statements.add_validation_var( "$chk_default", lambda keyword: keyword in lint._keyword_with_default) statements.add_validation_var( "$chk_required", lambda keyword: keyword in ExternalValidationRules.required_substatements) statements.add_validation_var( "$chk_recommended", lambda keyword: keyword in lint._recommended_substatements) statements.add_validation_fun( "grammar", ["$chk_default"], lambda ctx, s: lint.v_chk_default(ctx, s)) statements.add_validation_fun( "grammar", ["$chk_required"], OCLintStages.openconfig_override_base_linter) statements.add_validation_fun( "grammar", ["$chk_recommended"], OCLintStages.openconfig_override_base_linter) statements.add_validation_fun( "grammar", ["namespace"], lambda ctx, s: lint.v_chk_namespace(ctx, s, self.namespace_prefixes)) statements.add_validation_fun( "grammar", ["module", "submodule"], lambda ctx, s: lint.v_chk_module_name(ctx, s, self.modulename_prefixes)) statements.add_validation_fun( "strict", ["include"], lambda ctx, s: lint.v_chk_include(ctx, s)) # Register the default linter error codes error.add_error_code( "LINT_EXPLICIT_DEFAULT", ErrorLevel.WARNING, "RFC 6087: 4.3: " "statement \"%s\" is given with its default value \"%s\"") error.add_error_code( "LINT_MISSING_REQUIRED_SUBSTMT", ErrorLevel.MINOR, "%s: " "statement \"%s\" must have a \"%s\" substatement") error.add_error_code( "LINT_MISSING_RECOMMENDED_SUBSTMT", ErrorLevel.WARNING, "%s: " "statement \"%s\" should have a \"%s\" substatement") error.add_error_code( "LINT_BAD_NAMESPACE_VALUE", ErrorLevel.WARNING, "RFC 6087: 4.8: namespace value should be \"%s\"") error.add_error_code( "LINT_BAD_MODULENAME_PREFIX_1", ErrorLevel.WARNING, "RFC 6087: 4.1: " "the module name should start with the string %s") error.add_error_code( "LINT_BAD_MODULENAME_PREFIX_N", ErrorLevel.WARNING, "RFC 6087: 4.1: " "the module name should start with one of the strings %s") error.add_error_code( "LINT_NO_MODULENAME_PREFIX", ErrorLevel.WARNING, "RFC 6087: 4.1: " "no module name prefix string used") error.add_error_code( "LINT_BAD_REVISION", ErrorLevel.MINOR, "RFC 6087: 4.6: " "the module's revision %s is older than " "submodule %s's revision %s") error.add_error_code( "LINT_TOP_MANDATORY", ErrorLevel.MINOR, "RFC 6087: 4.9: " "top-level node %s must not be mandatory") error.add_error_code( "LONG_IDENTIFIER", ErrorLevel.MINOR, "RFC 6087: 4.2: identifier %s exceeds %s characters") # Add a pre-initialisation phase where we can read the # modules before they have been parsed by pyang fully. statements.add_validation_phase("preinit", before="init") statements.add_validation_fun("preinit", ["*"], OCLintStages.preinitialisation) # Add an openconfig types validation phase where we can # get types and then validate them further. statements.add_validation_phase("openconfig_type", after="type_2") statements.add_validation_fun("openconfig_type", ["*"], OCLintStages.openconfig_type) # pyang manipulates the paths of elements during reference_2, such # that this is the only time that we get a chance to work statements.add_validation_fun("reference_2", ["*"], OCLintStages.openconfig_reference) # Error type for generic OpenConfig linter bugs - returned # when an error is encountered in linter logic. error.add_error_code( "OC_LINTER_ERROR", ErrorLevel.CRITICAL, "Linter error encountered: %s") # Enum values must be upper case error.add_error_code( "OC_ENUM_CASE", ErrorLevel.MAJOR, "enum value \"%s\" should be capitalised as \"%s\"") # Enum values must be of the form UPPERCASE_WITH_UNDERSCORES error.add_error_code( "OC_ENUM_UNDERSCORES", ErrorLevel.MAJOR, "enum value \"%s\" should be of the form " "UPPERCASE_WITH_UNDERSCORES: %s") # Identity values should be capitalised error.add_error_code( "OC_IDENTITY_CASE", ErrorLevel.MAJOR, "identity name \"%s\" should be capitalised as \"%s\"") # UPPERCASE_WITH_UNDERSCORES required for identity values error.add_error_code( "OC_IDENTITY_UNDERSCORES", ErrorLevel.MAJOR, "identity name \"%s\" should be of the form " "UPPERCASE_WITH_UNDERSCORES: \"%s\"") # There must be a single config / state container in the path error.add_error_code( "OC_OPSTATE_CONTAINER_COUNT", ErrorLevel.MAJOR, "path \"%s\" should have a single \"config\" or \"state\" component") # Leaves should be in a "config" or "state" container error.add_error_code( "OC_OPSTATE_CONTAINER_NAME", ErrorLevel.MAJOR, "element \"%s\" at path \"%s\" should be in a \"config\"" "or \"state\" container") # list keys should be leafrefs to respective value in config / state error.add_error_code( "OC_OPSTATE_KEY_LEAFREF", ErrorLevel.MAJOR, "list key \"%s\" should be type leafref with a reference to" " the corresponding leaf in config or state container") # leaves in in config / state should have the correct config property error.add_error_code( "OC_OPSTATE_CONFIG_PROPERTY", ErrorLevel.MAJOR, "element \"%s\" is in a \"%s\" container and should have " "config value %s") # references to nodes in the same module / namespace should use relative # paths error.add_error_code( "OC_RELATIVE_PATH", ErrorLevel.WARNING, "\"%s\" path reference \"%s\" is intra-module but uses absolute path") # a config leaf does not have a mirrored applied config leaf in the state # container error.add_error_code( "OC_OPSTATE_APPLIED_CONFIG", ErrorLevel.MAJOR, "\"%s\" is not mirrored in the state container at %s") # a list is within a container that has elements other than the list # within it error.add_error_code( "OC_LIST_SURROUNDING_CONTAINER", ErrorLevel.MAJOR, "List %s is within a container (%s) that has other elements " "within it: %s") # a list that does not have a container above it error.add_error_code( "OC_LIST_NO_ENCLOSING_CONTAINER", ErrorLevel.MAJOR, "List %s does not have a surrounding container") # when path compression is performed, the containers surrounding # lists are removed, if there are two lists with the same name # this results in a name collision. error.add_error_code( "OC_LIST_DUPLICATE_COMPRESSED_NAME", ErrorLevel.MAJOR, "List %s has a duplicate name when the parent container %s" + \ " is removed.") # a module defines data nodes at the top-level error.add_error_code( "OC_MODULE_DATA_DEFINITIONS", ErrorLevel.MAJOR, "Module %s defines data definitions at the top level: %s") # a module is missing an openconfig-version statement error.add_error_code( "OC_MODULE_MISSING_VERSION", ErrorLevel.MAJOR, "Module %s is missing an openconfig-version statement") # a module uses the "choice" keyword error.add_error_code( "OC_STYLE_AVOID_CHOICE", ErrorLevel.WARNING, "Element %s uses the choice keyword, which should be avoided") # a module uses the "presence" keyword error.add_error_code( "OC_STYLE_AVOID_PRESENCE", ErrorLevel.MINOR, "Element %s uses the presence keyword which should be avoided") # a module uses the "if-feature" or "feature" keyword error.add_error_code( "OC_STYLE_AVOID_FEATURES", ErrorLevel.MINOR, "Element %s uses feature or if-feature which should be avoided") # invalid semantic version argument to openconfig-version error.add_error_code( "OC_INVALID_SEMVER", ErrorLevel.MAJOR, "Semantic version specified (%s) is invalid") # missing a revision statement that has a reference of the # current semantic version error.add_error_code( "OC_MISSING_SEMVER_REVISION", ErrorLevel.MAJOR, "Revision statement should contain reference substatement " " corresponding to semantic version %s") # invalid data element naming error.add_error_code( "OC_DATA_ELEMENT_INVALID_NAME", ErrorLevel.MAJOR, "Invalid naming for element %s data elements should " " generally be lower-case-with-hypens") # the module uses an invalid form of prefix error.add_error_code( "OC_PREFIX_INVALID", ErrorLevel.MINOR, "Prefix %s for module does not match the expected " " format - use the form oc-<shortdescription>") # the module is missing a standard grouping (e.g., -top) error.add_error_code( "OC_MISSING_STANDARD_GROUPING", ErrorLevel.WARNING, "Module %s is missing a grouping suffixed with %s") # the module has a nonstandard grouping name error.add_error_code( "OC_GROUPING_NAMING_NONSTANDARD", ErrorLevel.WARNING, "In container %s, grouping %s does not match standard " "naming - suffix with %s?") # key statements do not have quoted arguments error.add_error_code( "OC_KEY_ARGUMENT_UNQUOTED", ErrorLevel.MINOR, "All key arguments of a list should be quoted (%s is not)") # bad type was used for a leaf or typedef error.add_error_code( "OC_BAD_TYPE", ErrorLevel.MAJOR, "Bad type %s used in leaf or typedef", )