Skip to content

Commit

Permalink
properly convert env interactions into context
Browse files Browse the repository at this point in the history
This input:

```yaml
{% set a = environ["a"] %}
{% set b = environ.get("b", "0") %}

package:
  name: abc
  version: 0
```

on `main` emits this recipe that needs manual correction:

```yaml
schema_version: 1

context:
  a: "\"env.get(\"a\")\""
  b: "\"environ | get(\"b\", \"0\")\""

package:
  name: abc
  version: 0
```

but after this PR, it will instead emit:
```yaml
schema_version: 1

context:
  a: ${{env.get("a")}}
  b: ${{env.get("b", default="0")}}

package:
  name: abc
  version: 0
```
which does not need any further editing.
  • Loading branch information
AaronOpfer committed Dec 13, 2024
1 parent b02a878 commit 42414ba
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 2 deletions.
5 changes: 5 additions & 0 deletions conda_recipe_manager/parser/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ class Regex:
# Finds `environ[]` used by a some recipe files. Requires a whitespace character to prevent matches with
# `os.environ[]`, which is very rare.
PRE_PROCESS_ENVIRON: Final[re.Pattern[str]] = re.compile(r"\s+environ\[(\"|')(.*)(\"|')\]")

# Finds `environ.get` which is used in a closed source community of which the author of this comment
# participates in.
PRE_PROCESS_ENVIRON_GET: Final[re.Pattern[str]] = re.compile(r"\s+environ \| get\((\"|')(.*)(\"|'), *(\"|')(.*)(\"|')\)")

# Finds commonly used variants of `{{ hash_type }}:` which is a substitution for the `sha256` field
PRE_PROCESS_JINJA_HASH_TYPE_KEY: Final[re.Pattern[str]] = re.compile(
r"'{0,1}\{\{ (hash_type|hash|hashtype) \}\}'{0,1}:"
Expand Down
12 changes: 11 additions & 1 deletion conda_recipe_manager/parser/recipe_parser_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def _upgrade_jinja_to_context_obj(self) -> None:
self._msg_tbl.add_message(MessageCategory.WARNING, f"The variable `{name}` is an unsupported type.")
continue
# Function calls need to preserve JINJA escaping or else they turn into unevaluated strings.
if isinstance(value, str) and search_any_regex(Regex.JINJA_FUNCTIONS_SET, value):
if isinstance(value, str) and (search_any_regex(Regex.JINJA_FUNCTIONS_SET, value) or value.startswith("env.get")):
value = "{{" + value + "}}"
context_obj[name] = value
# Ensure that we do not include an empty context object (which is forbidden by the schema).
Expand Down Expand Up @@ -738,6 +738,16 @@ def pre_process_recipe_text(content: str) -> str:
f"env.get({quote_char}{key}{quote_char})",
)
)

for groups in cast(list[str], Regex.PRE_PROCESS_ENVIRON_GET.findall(content)):
key_quote_char, key, _, default_quote_char, default, _ = groups
replacements.append(
(
f"environ | get({key_quote_char}{key}{key_quote_char}, {default_quote_char}{default}{default_quote_char})",
f"env.get({key_quote_char}{key}{key_quote_char}, default={default_quote_char}{default}{default_quote_char})"
)
)

for old, new in replacements:
content = content.replace(old, new, 1)

Expand Down
2 changes: 1 addition & 1 deletion conda_recipe_manager/parser/recipe_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ def render(self) -> str:
if self._schema_version == SchemaVersion.V0:
for key, val in self._vars_tbl.items():
# Double quote strings
if isinstance(val, str):
if isinstance(val, str) and not val.startswith('env.get('):
val = f'"{val}"'
lines.append(f"{{% set {key} = {val} %}}")
# Add spacing if variables have been set
Expand Down

0 comments on commit 42414ba

Please sign in to comment.