Esempio n. 1
0
    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')
Esempio n. 2
0
  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)",
    )
Esempio n. 3
0
    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')
Esempio n. 4
0
    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')
Esempio n. 5
0
File: lint.py Progetto: SDTN/Test
    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')
Esempio n. 6
0
    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")
Esempio n. 7
0
    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')
Esempio n. 8
0
  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",
    )