Skip to content

Commit

Permalink
Added environment interpolation rule.
Browse files Browse the repository at this point in the history
Allows rules/targets to easily support values that can be pulled from
the environment.

Alternative solution to pantsbuild#12797.
  • Loading branch information
xlevus authored and kaos committed Sep 30, 2021
1 parent 8ba0dfa commit 7ec8b3e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
37 changes: 37 additions & 0 deletions src/python/pants/engine/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

name_value_re = re.compile(r"([A-Za-z_]\w*)=(.*)")
shorthand_re = re.compile(r"([A-Za-z_]\w*)")
interpolation_re = re.compile(r"^\$\{([A-Za-z_]{1,}[A-Za-z0-9]{0,})\}$")


class CompleteEnvironment(FrozenDict):
Expand Down Expand Up @@ -84,6 +85,21 @@ def __init__(self, requested: Sequence[str], allowed: Optional[Sequence[str]] =
self.allowed = None if allowed is None else FrozenOrderedSet(allowed)


class InterpolatedEnvironmentRequest(FrozenDict[str, str]):
"""Request a map of key:values w/ simple environment variable interpolation.
e.g.
{
"FOO_BAR": "${FOO_BAR}",
"WIZ_BOING": "WIZ_BOING"
} == {
"FOO_BAR": os.getenv("FOO_BAR", None),
"WIZ_BOING": "WIZ_BOING",
}
"""


class Environment(FrozenDict[str, str]):
"""A subset of the variables set in the environment."""

Expand All @@ -105,5 +121,26 @@ def environment_subset(session_values: SessionValues, request: EnvironmentReques
)


@rule
def interpolated_subset(
session_values: SessionValues, request: InterpolatedEnvironmentRequest
) -> Environment:
env = session_values[CompleteEnvironment]
values = {}

for key, value in request.items():
match = interpolation_re.match(value)
if match:
env_key = match.groups()[0]
try:
values[key] = env[env_key]
except KeyError:
pass
else:
values[key] = value

return Environment(values)


def rules():
return collect_rules()
25 changes: 24 additions & 1 deletion src/python/pants/engine/environment_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

import pytest

from pants.engine.environment import CompleteEnvironment
from pants.engine.environment import (
CompleteEnvironment,
InterpolatedEnvironmentRequest,
interpolated_subset,
)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -37,3 +41,22 @@ def test_invalid_variable() -> None:
"An invalid variable was requested via the --test-extra-env-var mechanism: 3INVALID"
in str(exc)
)


@pytest.mark.parametrize(
"input_dict, environment, expected",
[
({"foo": "FOO"}, {}, {"foo": "FOO"}),
({"foo": "$FOO"}, {}, {"foo": "$FOO"}),
({"foo": "${FOO}"}, {}, {}),
({"foo": "${FOO}"}, {"FOO": "bar"}, {"foo": "bar"}),
({"foo": "${FOO}", "bar": "BAR"}, {"FOO": "bar"}, {"foo": "bar", "bar": "BAR"}),
],
)
def test_interpolated_subset(input_dict, environment, expected):
session_values = {CompleteEnvironment: environment}
request = InterpolatedEnvironmentRequest(input_dict)

subset = interpolated_subset(session_values, request)

assert dict(subset) == expected

0 comments on commit 7ec8b3e

Please sign in to comment.