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.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.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)) # 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.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.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 _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.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", )