The goal of modulemd_resolver Python library is to resolve module-level dependencies between modules the same way as DNF does for RPMs.
The modules metadata, and therefore also the dependencies between them,
are defined using the modulemd
YAML format. Therefore the modulemd_resolver
works with modulemd.ModuleMetadata
objects.
There are two lists into which the modulemd.ModuleMetadata
objects can be
added:
Once you fill-in these lists with data, you can ask modulemd_resolver
to do the dependency resolving. Currently there are following methods:
In this example, we create metadata for "parent" and "child" modules. Child module depends on the Parent module. We then try to get all the actions we need to do to enable the "child" module.
# Create the ModulesResolver instance. solver = ModulesResolver() # Create the "parent" module in version "1.0-1" in the available list. mmd = ModuleMetadata() mmd.name = "parent" mmd.version = "1.0" mmd.release = "1" solver.add_available_mmd(mmd) # Create the "child" module in version "1.0-1" in the available list. mmd = ModuleMetadata() mmd.name = "child" mmd.version = "1.0" mmd.release = "1" # Set the dependency on "parent" module, minimal version 0.9. mmd.add_requires("parent", "0.9") solver.add_available_mmd(mmd) # Try to get the list of all actions which need to be done to enable "child". ret = solver.solve_enable("child") print(ret.to_enable)
As you see here, ModulesResolver
returns ModulesResolverResult
object. It is described
in next chapter.
This object is the result of the resolving. It contains following lists:
to_disable
- List of modules to disable to fulfill the dependencies.to_enable
- List of modules to enable to fulfill the dependencies.to_downgrade
- List of modules to dowgrade to fulfill the dependencies.to_upgrade
- List of modules to upgrade to fulfill the dependencies.These lists are containing the modulemd.ModuleMetadata
of modules
with which you have to take the particular action to fulfill the dependencies.
In case when the resolving fails for some reason, there are one or more
ModulesResolverProblem
instances stored in the the problems
list of
ModulesResolverResult
object.
This object appears in the ModulesResolverResult.problems
list in case
of resolving problem.
It contains basic description of the problem (desc
), the name of the
unknown dependency (dep
) and other information about the problem.
One of the most important information is the list of solutions (solutions
list).
It contains the ModulesResolverSolution objects.
This object appears in the ModulesResolverProblem.solutions
list in case
the resolving problem has some solution.
Every ModulesResolverSolution object has following attributes:
desc
- human-readable description of the solutionsolution
- list to pass to another call of ModulesResolver.solve_enable
or ModulesResolver.solve_disable
.In this example, we create the child/parent modules again, but this time in the "enabled" list. This means ModulesResolver treats them as a enabled on the system.
We then try to disable "parent" module. The dependency resolving will fail, because removing "parent" also means removing "child", but we did not instruct ModulesResolver to do that.
ModulesResolver proposes us the solution - to also remove the "child". In this example, we just blindly accept this solution, but in the real application, we could just for example ask the user if he wants to remove also "child" module.
# Create the ModulesResolver instance. solver = ModulesResolver() # Create the "parent" module in version "1.0" in the enabled list. mmd = ModuleMetadata() mmd.name = "parent" mmd.version = "1.0" solver.add_enabled_mmd(mmd) # Create the "child" module in version "1.0" in the enabled list. # It also depends on the "parent" module. mmd = ModuleMetadata() mmd.name = "child" mmd.version = "1.0" mmd.add_requires("parent", "1.0") solver.add_enabled_mmd(mmd) # Try to disable the parent module. ret = solver.solve_disable("parent") # Check if we had a problem with disabling the "parent". if len(ret.problems) != 0: # "package child-1.0 requires parent >= 1.0, but none of the providers can be installed" print ret.problems[0].desc if len(ret.problems[0].solutions) > 0: # "- allow deinstallation of child-1.0.x86_64\n" print ret.problems[0].solutions[0].desc # Apply the solution ret = solver.solve_disable("parent", ret.problems[0].solutions[0].solution) # Prints empty erray now: "[]", so success. print ret.problems