Skip to content

Commit

Permalink
Merge pull request #565 from rhubert/clean_dep
Browse files Browse the repository at this point in the history
input: add 'inherit' dependency property
  • Loading branch information
jkloetzke authored May 27, 2024
2 parents cc29acc + 92710ed commit 277e1ae
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 16 deletions.
10 changes: 10 additions & 0 deletions doc/manual/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,16 @@ The following settings are supported:
| | | At the dependency both names will refer to the same |
| | | tool. |
+-------------+-----------------+-----------------------------------------------------+
| inherit | Boolean | Inherit current environment, tools and sandbox to |
| | | this dependency. When set to ``false``, all |
| | | environment variables are reset to their default |
| | | and no tools or sandbox are passed down to the |
| | | dependency. This is mostly useful to make an |
| | | existing root-package become a dependency of |
| | | another (root) package. |
| | | |
| | | Default: ``true`` |
+-------------+-----------------+-----------------------------------------------------+

.. _configuration-recipes-env:

Expand Down
50 changes: 34 additions & 16 deletions pym/bob/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -1855,10 +1855,11 @@ class Recipe(object):
"""

class Dependency(object):
def __init__(self, recipe, env, fwd, use, cond, tools, checkoutDep):
def __init__(self, recipe, env, fwd, use, cond, tools, checkoutDep, inherit):
self.recipe = recipe
self.envOverride = env
self.provideGlobal = fwd
self.inherit = inherit
self.use = use
self.useEnv = "environment" in self.use
self.useTools = "tools" in self.use
Expand All @@ -1870,9 +1871,9 @@ def __init__(self, recipe, env, fwd, use, cond, tools, checkoutDep):
self.checkoutDep = checkoutDep

@staticmethod
def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep):
def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep, inherit):
if isinstance(dep, str):
return [ Recipe.Dependency(dep, env, fwd, use, cond, tools, checkoutDep) ]
return [ Recipe.Dependency(dep, env, fwd, use, cond, tools, checkoutDep, inherit) ]
else:
envOverride = dep.get("environment")
if envOverride:
Expand All @@ -1884,6 +1885,7 @@ def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep):
tools.update(toolOverride)
fwd = dep.get("forward", fwd)
use = dep.get("use", use)
inherit = dep.get("inherit", inherit)
newCond = dep.get("if")
if newCond is not None:
cond = cond + [newCond] if cond is not None else [ newCond ]
Expand All @@ -1892,22 +1894,22 @@ def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep):
if name:
if "depends" in dep:
raise ParseError("A dependency must not use 'name' and 'depends' at the same time!")
return [ Recipe.Dependency(name, env, fwd, use, cond, tools, checkoutDep) ]
return [ Recipe.Dependency(name, env, fwd, use, cond, tools, checkoutDep, inherit) ]
dependencies = dep.get("depends")
if dependencies is None:
raise ParseError("Either 'name' or 'depends' required for dependencies!")
return Recipe.Dependency.parseEntries(dependencies, env, fwd,
use, cond, tools,
checkoutDep)
checkoutDep, inherit)

@staticmethod
def parseEntries(deps, env={}, fwd=False, use=["result", "deps"],
cond=None, tools={}, checkoutDep=False):
cond=None, tools={}, checkoutDep=False, inherit=True):
"""Returns an iterator yielding all dependencies as flat list"""
# return flattened list of dependencies
return chain.from_iterable(
Recipe.Dependency.__parseEntry(dep, env, fwd, use, cond, tools,
checkoutDep)
checkoutDep, inherit)
for dep in deps )

@staticmethod
Expand Down Expand Up @@ -2311,6 +2313,21 @@ def prepare(self, inputEnv, sandboxEnabled, inputStates, inputSandbox=None,
env.setFunArgs({ "recipe" : self, "sandbox" : bool(sandbox) and sandboxEnabled,
"__tools" : tools })

thisDepEnv = depEnv
thisDepTools = depTools
thisDepDiffTools = depDiffTools
thisDepSandbox = depSandbox
thisDepDiffSandbox = depDiffSandbox
if not dep.inherit:
thisDepEnv = self.getRecipeSet().getRootEnv()
thisDepTools = Env()
# Compute the diff to remove all tools that were passed to the
# package.
thisDepDiffTools = { n : None for n in inputTools.inspect().keys() }
thisDepSandbox = None
# Clear sandbox, if any
thisDepDiffSandbox = None

recipe = env.substitute(dep.recipe, "dependency::"+dep.recipe)
resolvedDeps.append(recipe)

Expand All @@ -2319,20 +2336,17 @@ def prepare(self, inputEnv, sandboxEnabled, inputStates, inputSandbox=None,

if dep.toolOverride:
try:
thisDepTools = depTools.derive({
thisDepTools = thisDepTools.derive({
k : depTools[v] for k,v in dep.toolOverride.items() })
except KeyError as e:
raise ParseError("Cannot remap unkown tool '{}' for dependency '{}'!"
.format(e.args[0], recipe))
thisDepDiffTools = depDiffTools.copy()
thisDepDiffTools = thisDepDiffTools.copy()
thisDepDiffTools.update({
k : depDiffTools.get(v, v)
for k, v in dep.toolOverride.items() })
else:
thisDepTools = depTools
thisDepDiffTools = depDiffTools

thisDepEnv = depEnv.derive(
thisDepEnv = thisDepEnv.derive(
{ key : env.substitute(value, "depends["+recipe+"].environment["+key+"]")
for key, value in dep.envOverride.items() })

Expand All @@ -2342,11 +2356,11 @@ def prepare(self, inputEnv, sandboxEnabled, inputStates, inputSandbox=None,
raise ParseError("Recipes are cyclic (1st package in cylce)")
depStack = stack + [r.__packageName]
p, s = r.prepare(thisDepEnv, sandboxEnabled, depStates,
depSandbox, thisDepTools, depStack)
thisDepSandbox, thisDepTools, depStack)
subTreePackages.add(p.getName())
subTreePackages.update(s)
depCoreStep = p.getCorePackageStep()
depRef = CoreRef(depCoreStep, [p.getName()], thisDepDiffTools, depDiffSandbox)
depRef = CoreRef(depCoreStep, [p.getName()], thisDepDiffTools, thisDepDiffSandbox)
except ParseError as e:
e.pushFrame(r.getPackageName())
raise e
Expand All @@ -2365,7 +2379,7 @@ def prepare(self, inputEnv, sandboxEnabled, inputStates, inputSandbox=None,

# Remember dependency diffs before changing them
origDepDiffTools = thisDepDiffTools
origDepDiffSandbox = depDiffSandbox
origDepDiffSandbox = thisDepDiffSandbox

# pick up various results of package
for (n, s) in states.items():
Expand Down Expand Up @@ -3340,6 +3354,9 @@ async def getScmStatus(self):
def getBuildHook(self, name):
return self.__buildHooks.get(name)

def getRootEnv(self):
return self.__rootEnv

def getSandboxMounts(self):
return self.__sandboxOpts.get("mount", [])

Expand Down Expand Up @@ -3564,6 +3581,7 @@ def __createSchemas(self):
schema.Optional('name') : str,
schema.Optional('use') : useClauses,
schema.Optional('forward') : bool,
schema.Optional('inherit') : bool,
schema.Optional('environment') : VarDefineValidator("depends::environment"),
schema.Optional('if') : schema.Or(str, IfExpression),
schema.Optional('tools') : { toolNameSchema : toolNameSchema },
Expand Down
88 changes: 88 additions & 0 deletions test/unit/test_input_recipeset.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,94 @@ def testCheckoutDepVariants(self):

self.assertNotEqual(paVId, pbVId, "checkout steps are different")

def testDepInherit(self):
""" Test the `inherit` property for dependencies """

self.writeDefault(
{"environment" : {"DEFAULT" : "42" }})

self.writeClass("foo", """\
root: True
depends:
- name: foo
use: [tools]
forward: True
packageTools: [foo]
""")

self.writeRecipe("a", """\
inherit: [foo]
depends:
- name: sandbox
use: [sandbox]
forward: True
- name: b-env
use: [environment]
forward: true
- name: b
inherit: False
- name: c
inherit: False
environment:
C: "1"
tools:
c: foo
- d
packageScript: "true"
""")

self.writeRecipe("b-env", """\
provideVars:
B: "2"
""")

self.writeRecipe("b", """\
inherit: [foo]
packageVars: [DEFAULT, B]
packageScript: "true"
""")

self.writeRecipe("c", """\
packageVars: [C]
packageTools: [c]
packageScript: "true"
""")

self.writeRecipe("d", """\
packageVars: [B]
packageTools: [foo]
packageScript: "true"
""")

self.writeRecipe("foo", """\
packageTools: [foo]
packageScript: "true"
provideTools:
foo: .
""")

self.writeRecipe("sandbox", """\
provideSandbox:
paths: ["."]
""")

recipes = RecipeSet()
recipes.parse()
packages = recipes.generatePackages(lambda s,m: "unused", True)

pa_b = packages.walkPackagePath("a/b")
pb = packages.walkPackagePath("b")
pb_e = packages.walkPackagePath("a/b-env")
pc = packages.walkPackagePath("a/c")
pd = packages.walkPackagePath("a/d")
self.assertEqual(pa_b.getPackageStep().getVariantId(),
pb.getPackageStep().getVariantId())
self.assertEqual({"DEFAULT" : "42"}, pb.getPackageStep().getEnv())
self.assertEqual({"C" : "1"}, pc.getPackageStep().getEnv())
self.assertEqual(list(pc.getPackageStep().getTools()), ["c"])
self.assertEqual(pc.getPackageStep().getSandbox(), None)
self.assertNotEqual(pb_e.getPackageStep().getSandbox(), None)
self.assertNotEqual(pd.getPackageStep().getSandbox(), None)

class TestDependencyEnv(RecipesTmp, TestCase):
"""Tests related to "environment" block in dependencies"""
Expand Down

0 comments on commit 277e1ae

Please sign in to comment.