diff --git a/conda_build/post.py b/conda_build/post.py index 42bf319753..6ebd328338 100644 --- a/conda_build/post.py +++ b/conda_build/post.py @@ -15,7 +15,7 @@ from fnmatch import filter as fnmatch_filter from fnmatch import fnmatch from fnmatch import translate as fnmatch_translate -from functools import partial +from functools import cache, partial from os.path import ( basename, dirname, @@ -1687,46 +1687,67 @@ def check_menuinst_json(files, prefix) -> None: return print("Validating Menu/*.json files") + for json_file in json_files: + _check_one_menuinst_json(join(prefix, json_file)) + + +@cache +def _build_validator(url): + import jsonschema + import requests + log = utils.get_logger(__name__, dedupe=False) - try: - import jsonschema - from menuinst.utils import data_path - except ImportError as exc: - log.warning( - "Found 'Menu/*.json' files but couldn't validate: %s", - ", ".join(json_files), - exc_info=exc, - ) + r = requests.get(url) + if not r.ok: + log.error("Could not fetch '%s', status code %s", r.status_code) return + schema = r.json() try: - schema_path = data_path("menuinst.schema.json") - with open(schema_path) as f: - schema = json.load(f) ValidatorClass = jsonschema.validators.validator_for(schema) - validator = ValidatorClass(schema) + return ValidatorClass(schema) except (jsonschema.SchemaError, json.JSONDecodeError, OSError) as exc: - log.warning("'%s' is not a valid menuinst schema", schema_path, exc_info=exc) + log.error("'%s' is not a valid menuinst schema", url, exc_info=exc) return - for json_file in json_files: - try: - with open(join(prefix, json_file)) as f: - text = f.read() - if "$schema" not in text: - log.warning( - "menuinst v1 JSON document '%s' won't be validated.", json_file - ) - continue - validator.validate(json.loads(text)) - except (jsonschema.ValidationError, json.JSONDecodeError, OSError) as exc: - log.warning( - "'%s' is not a valid menuinst JSON document!", - json_file, - exc_info=exc, + +def _check_one_menuinst_json(json_file): + import jsonschema + + log = utils.get_logger(__name__, dedupe=False) + + try: + with open(json_file) as f: + text = f.read() + if "$schema" not in text: + log.warning("menuinst v1 JSON document '%s' won't be validated.", json_file) + return + loaded = json.loads(text) + schema_url = loaded.get("$schema") + if not schema_url: + log.error( + "Invalid empty value for $schema. '%s' won't be validated", json_file ) - else: - log.info("'%s' is a valid menuinst JSON document", json_file) + return + elif schema_url == "https://json-schema.org/draft-07/schema": + fallback_schema = ( + "https://github.com/conda/menuinst/raw/refs/tags/2.2.0/" + "menuinst/data/menuinst.schema.json" + ) + log.debug( + "Known wrong value for $schema, defaulting to '%s'", fallback_schema + ) + schema_url = fallback_schema + validator = _build_validator(schema_url) + validator.validate(loaded) + except (jsonschema.ValidationError, json.JSONDecodeError, OSError) as exc: + log.error( + "'%s' is not a valid menuinst JSON document!", + json_file, + exc_info=exc, + ) + else: + log.info("'%s' is a valid menuinst JSON document", json_file) def post_build(m, files, build_python, host_prefix=None, is_already_linked=False): diff --git a/news/5569-jsonschema-menuinst b/news/5569-jsonschema-menuinst new file mode 100644 index 0000000000..e2f76d4fa1 --- /dev/null +++ b/news/5569-jsonschema-menuinst @@ -0,0 +1,19 @@ +### Enhancements + +* + +### Bug fixes + +* Validate menuinst JSON documents using the included `$schema` value. `menuinst` is no longer a dependency. (#5569) + +### Deprecations + +* + +### Docs + +* + +### Other + +* diff --git a/pyproject.toml b/pyproject.toml index e6235850b4..9c43201de3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,6 @@ dependencies = [ "jinja2", "jsonschema >=4.19", "libarchive-c", - "menuinst >=2", "packaging", "pkginfo", "psutil", diff --git a/recipe/meta.yaml b/recipe/meta.yaml index 7bb7c812bc..6fa3325c6f 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -39,7 +39,6 @@ requirements: - jinja2 - jsonschema >=4.19 - m2-patch >=2.6 # [win] - - menuinst >=2 - packaging - patch >=2.6 # [not win] - patchelf # [linux] diff --git a/tests/requirements.txt b/tests/requirements.txt index aad6b706e8..30d1661923 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -8,7 +8,6 @@ filelock frozendict >=2.4.2 jinja2 jsonschema >=4.19 -menuinst >=2 packaging pkginfo psutil