Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: allow incomplete specs during intermediate parsing stages #5555

Merged
merged 7 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions conda_build/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1597,21 +1597,34 @@ def ms_depends(self, typ="run"):
try:
ms = MatchSpec(spec)
except AssertionError:
raise RuntimeError(f"Invalid package specification: {spec!r}")
if len(self.undefined_jinja_vars) == 0:
raise RuntimeError(f"Invalid package specification: {spec!r}")
else:
continue
except (AttributeError, ValueError) as e:
raise RuntimeError(
"Received dictionary as spec. Note that pip requirements are "
"not supported in conda-build meta.yaml. Error message: " + str(e)
)
if len(self.undefined_jinja_vars) == 0:
raise RuntimeError(
"Received dictionary as spec. Note that pip requirements are "
"not supported in conda-build meta.yaml. Error message: "
+ str(e)
)
else:
continue

if ms.name == self.name() and not (
typ == "build" and self.config.host_subdir != self.config.build_subdir
):
raise RuntimeError(f"{self.name()} cannot depend on itself")

# TODO: IDK what this does since AFAIK the inner continue applies only
# to the inner loop
for name, ver in name_ver_list:
if ms.name == name:
if self.noarch:
continue

# TODO: the validation here appears to be a waste of time since MatchSpec
# appears to validate?
for c in "=!@#$%^&*:;\"'\\|<>?/":
if c in ms.name:
sys.exit(
Expand Down
19 changes: 19 additions & 0 deletions news/5555-skip-bad-specs-while-still-parsing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* Fixed a bug where bad match specs from intermediate parsing results would cause parsing to fail. (#5555)

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>
2 changes: 1 addition & 1 deletion tests/test_api_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,7 @@ def test_conda_build_script_errors_without_conda_info_handlers(tmp_path, recipe,

def test_api_build_inject_jinja2_vars_on_first_pass(testing_config):
recipe_dir = os.path.join(metadata_dir, "_inject_jinja2_vars_on_first_pass")
with pytest.raises(RuntimeError):
with pytest.raises((RuntimeError, CondaBuildUserError)):
api.build(recipe_dir, config=testing_config)

testing_config.variant = {"python_min": "3.12"}
Expand Down
53 changes: 53 additions & 0 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,3 +655,56 @@ def test_parse_until_resolved_skip_avoids_undefined_jinja(
pytest.fail(
"Undefined variable caused error, even though this build is skipped"
)


@pytest.mark.parametrize("have_variant", [True, False])
def test_parse_until_resolved_missing_jinja_in_spec(
testing_metadata: MetaData,
tmp_path: Path,
have_variant: bool,
) -> None:
(recipe := tmp_path / (name := "meta.yaml")).write_text(
"""
package:
name: dummy
version: 1.0.0

build:
noarch: python
number: 0

requirements:
host:
- python ={{ python_min }}
run:
- python >={{ python_min }}
"""
)
(tmp_path / "conda_build_config.yaml").write_text(
"""
python_min:
- 3.6
"""
)
testing_metadata._meta_path = recipe
testing_metadata._meta_name = name
if have_variant:
testing_metadata.config.variant = {"python_min": "3.6"}
else:
delattr(testing_metadata.config, "variant")
delattr(testing_metadata.config, "variant_config_files")
delattr(testing_metadata.config, "variants")

try:
testing_metadata.parse_until_resolved()
if not have_variant:
pytest.fail("Undefined variable did NOT cause spec parsing error!")
else:
print("parsed OK!")
except (Exception, SystemExit):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a more concrete exception set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not reliably no. I have already fixed a bug where when the exception handling in one part of the code changed, the test suite broke because a new kind of exception was raised in another part of the code. For now, any exception will work.

if have_variant:
pytest.fail(
"Undefined variable caused spec parsing error even if we have the variant!"
)
else:
print("did not parse OK!")
Loading