コード例 #1
0
def test_optional_loop_list(snippetcompiler):
    snippetcompiler.setup_for_snippet("""
entity Thing:
    string name
end

implement Thing using std::none

Thing.other [0:] -- Thing.that [0:]

implementation setother for Thing:
    t = Thing(name="it")
    t.that = self
end

implement Thing using setother when std::count(other) == 1

t = Thing(name="a")
t.other = Thing(name="b")
""")
    with pytest.raises(AttributeException) as e:
        compiler.do_compile()

    print(ExplainerFactory().explain_and_format(e.value))
    assert (ExplainerFactory().explain_and_format(e.value) == """
Exception explanation
=====================
The compiler could not figure out how to execute this model.

During compilation, the compiler has to decide when it expects a relation to have all its elements.
In this compiler run, it guessed that the relation 'other' on the instance __config__::Thing (instantiated at %(dir)s/main.cf:17) would be complete with the values [__config__::Thing (instantiated at %(dir)s/main.cf:18)], but the value __config__::Thing (instantiated at %(dir)s/main.cf:11) was added at %(dir)s/main.cf:12:14

This can mean one of two things:

1. The model is incorrect. Most often, this is due to something of the form:

    implementation mydefault for MyEntity:
      self.relation += "default"
    end

    implement MyEntity using mydefault when std::count(relation) == 0


   This is always wrong, because the relation can not at the same time have length 0 and contain the value "default"

2. The model is too complicated for the compiler to resolve.

The procedure to solve this is the following

1. Ensure the model is correct by checking that the problematic assignment at %(dir)s/main.cf:12:14 is not conditional on the value it assigns.
2. Report a bug to the inmanta issue tracker at https://github.com/inmanta/inmanta/issues or directly contact inmanta. This is a priority issue to us, so you will be helped rapidly and by reporting the problem, we can fix it properly.
3. [applies] If the exception is on the reverse relation, try to give a hint by explicitly using the problematic relation: self.other = t
4. Simplify the model by reducing the number of implements calls that pass a list into a plugin function in their when clause.

"""

            # noqa: E501
            % {
                "dir": snippetcompiler.project_dir
            })
コード例 #2
0
def test_optional_loop_forward_tty(snippetcompiler):
    snippetcompiler.setup_for_snippet("""
entity Thing:
    string name
end

implement Thing using std::none

Thing.other [0:1] -- Thing

implementation setother for Thing:
    self.other = Thing(name="it")
end

implement Thing using setother when not (other is defined)

Thing(name="a")
""")
    with pytest.raises(AttributeException) as e:
        compiler.do_compile()

    value = ExplainerFactory().explain_and_format(e.value, plain=False)

    assert (value == """
\033[1mException explanation
=====================\033[0m
The compiler could not figure out how to execute this model.

During compilation, the compiler has to decide when it expects an optional relation to remain undefined. In this compiler run, it guessed that the relation '\033[4mother\033[0m' on the instance \033[4m__config__::Thing (instantiated at %(dir)s/main.cf:16)\033[0m would never get a value assigned, but the value \033[4m__config__::Thing (instantiated at %(dir)s/main.cf:11)\033[0m was assigned at \033[4m%(dir)s/main.cf:11\033[0m

This can mean one of two things:

1. The model is incorrect. Most often, this is due to something of the form:

    \033[1mimplementation mydefault for MyEntity:
        self.relation = "default"
    end

    implement MyEntity using mydefault when not (relation is defined)\033[0m

  This is always wrong, because the relation can not at the same time be undefined and have the value "default".

2. The model is too complicated for the compiler to resolve.

The procedure to solve this is the following:

1. Ensure the model is correct by checking that the problematic assignment at \033[4m%(dir)s/main.cf:11\033[0m is not conditional on the value it assigns.
2. Set a relation precedence policy on the Inmanta project (See: https://docs.inmanta.com/community/latest/troubleshooting.html#compilation-fails).
3. Report a bug to the inmanta issue tracker at https://github.com/inmanta/inmanta/issues or directly contact inmanta. This is a priority issue to us, so you will be helped rapidly and by reporting the problem, we can fix it properly.
4. [does not apply here] If the exception is on the reverse relation, try to give a hint by explicitly using the problematic relation.
5. Simplify the model by relying less on `is defined` but use a boolean instead.
"""

            # noqa: E501
            % {
                "dir": snippetcompiler.project_dir
            })
コード例 #3
0
ファイル: app.py プロジェクト: inmanta/inmanta-core
    def report(e: BaseException) -> None:
        minus_x_set_top_level_command = options.errors
        minus_x_set_subcommand = hasattr(options, "errors_subcommand") and options.errors_subcommand
        if not minus_x_set_top_level_command and not minus_x_set_subcommand:
            if isinstance(e, CompilerException):
                print(e.format_trace(indent="  "), file=sys.stderr)
            else:
                print(str(e), file=sys.stderr)
        else:
            sys.excepthook(*sys.exc_info())

        if isinstance(e, CompilerException):
            from inmanta.compiler.help.explainer import ExplainerFactory

            helpmsg = ExplainerFactory().explain_and_format(e, plain=not _is_on_tty())
            if helpmsg is not None:
                print(helpmsg)
コード例 #4
0
ファイル: test_modules.py プロジェクト: inmanta/inmanta-core
def test_module_v2_from_v1_path(
    local_module_package_index: str,
    modules_v2_dir: str,
    snippetcompiler_clean,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    """
    Verify that attempting to load a v2 module from the v1 modules path fails with an appropriate message when a v2 module is
    found in a v1 module source.
    """
    with pytest.raises(module.ModuleLoadingException) as excinfo:
        snippetcompiler_clean.setup_for_snippet(
            "import minimalv2module", add_to_module_path=[modules_v2_dir])
    cause: CompilerException = excinfo.value.__cause__
    assert cause.msg == (
        "Module at %s looks like a v2 module. Please have a look at the documentation on how to use v2 modules."
        % os.path.join(modules_v2_dir, "minimalv2module"))
    assert (ExplainerFactory().explain_and_format(excinfo.value,
                                                  plain=True).strip() == (
                                                      f"""
Exception explanation
=====================
This error occurs when a v2 module was found in v1 modules path. To resolve this you should either convert this module to be v1 or install it as a v2 module and set up your project accordingly.

If you want to use the module as a v1 module, make sure to use the v1 cookiecutter template to create new modules.

If you want to use the module as a v2 module:
- set up your project with a module source of type "package" (see documentation)
- if you would like to work in editable mode on a local copy of the module, run `inmanta module install -e {modules_v2_dir}/minimalv2module`
- run `inmanta module add --v2 minimalv2module` to add the module as a dependency and to install the module if required.
        """

                                                      # noqa: E501
                                                  ).strip())

    # verify that adding it as a v2 resolves the issue
    project: module.Project = snippetcompiler_clean.setup_for_snippet(
        "",
        autostd=False,
        python_package_sources=[local_module_package_index],
        install_project=False,
    )
    os.chdir(project.path)
    project_init = module.Project.__init__

    # patch Project.__init__ to set autostd=False because v2 std does not exist yet
    def project_init_nostd(self, *args, **kwargs) -> None:
        project_init(self,
                     *args,
                     autostd=False,
                     **{
                         key: value
                         for key, value in kwargs.items() if key != "autostd"
                     })

    monkeypatch.setattr(module.Project, "__init__", project_init_nostd)
    ModuleTool().add("minimalv2module", v2=True)
    snippetcompiler_clean.setup_for_snippet(
        "import minimalv2module",
        autostd=False,
        # run with the same module path
        add_to_module_path=[modules_v2_dir],
        python_package_sources=[local_module_package_index],
        install_project=True,
    )