mirror of https://github.com/pyodide/pyodide.git
139 lines
3.8 KiB
Python
139 lines
3.8 KiB
Python
from pathlib import Path
|
|
from typing import Dict, Any, List, Optional
|
|
|
|
|
|
# TODO: support more complex types for validation
|
|
|
|
PACKAGE_CONFIG_SPEC: Dict[str, Dict[str, Any]] = {
|
|
"package": {
|
|
"name": str,
|
|
"version": str,
|
|
},
|
|
"source": {
|
|
"url": str,
|
|
"extract_dir": str,
|
|
"path": str,
|
|
"patches": list, # List[str]
|
|
"md5": str,
|
|
"sha256": str,
|
|
"extras": list, # List[Tuple[str, str]],
|
|
},
|
|
"build": {
|
|
"skip_host": bool,
|
|
"cflags": str,
|
|
"cxxflags": str,
|
|
"ldflags": str,
|
|
"library": bool,
|
|
"sharedlibrary": bool,
|
|
"script": str,
|
|
"post": str,
|
|
"replace-libs": list,
|
|
},
|
|
"requirements": {
|
|
"run": list, # List[str],
|
|
},
|
|
"test": {
|
|
"imports": list, # List[str]
|
|
},
|
|
}
|
|
|
|
|
|
def check_package_config(
|
|
config: Dict[str, Any], raise_errors: bool = True, file_path: Optional[Path] = None
|
|
) -> List[str]:
|
|
"""Check the validity of a loaded meta.yaml file
|
|
|
|
Currently the following checks are applied:
|
|
-
|
|
|
|
TODO:
|
|
- check for mandatory fields
|
|
|
|
Parameter
|
|
---------
|
|
config
|
|
loaded meta.yaml as a dict
|
|
raise_errors
|
|
if true raise errors, otherwise return the list of error messages.
|
|
file_path
|
|
optional meta.yaml file path. Only used for more explicit error output,
|
|
when raise_errors = True.
|
|
"""
|
|
errors_msg = []
|
|
|
|
# Check top level sections
|
|
wrong_keys = set(config.keys()).difference(PACKAGE_CONFIG_SPEC.keys())
|
|
if wrong_keys:
|
|
errors_msg.append(
|
|
f"Found unknown sections {list(wrong_keys)}. Expected "
|
|
f"sections are {list(PACKAGE_CONFIG_SPEC)}."
|
|
)
|
|
|
|
# Check subsections
|
|
for section_key in config:
|
|
if section_key not in PACKAGE_CONFIG_SPEC:
|
|
# Don't check subsections is the main section is invalid
|
|
continue
|
|
actual_keys = set(config[section_key].keys())
|
|
expected_keys = set(PACKAGE_CONFIG_SPEC[section_key].keys())
|
|
|
|
wrong_keys = set(actual_keys).difference(expected_keys)
|
|
if wrong_keys:
|
|
errors_msg.append(
|
|
f"Found unknown keys "
|
|
f"{[section_key + '/' + key for key in wrong_keys]}. "
|
|
f"Expected keys are "
|
|
f"{[section_key + '/' + key for key in expected_keys]}."
|
|
)
|
|
|
|
# Check value types
|
|
for section_key, section in config.items():
|
|
for subsection_key, value in section.items():
|
|
try:
|
|
expected_type = PACKAGE_CONFIG_SPEC[section_key][subsection_key]
|
|
except KeyError:
|
|
# Unkown key, which was already reported previously, don't
|
|
# check types
|
|
continue
|
|
if not isinstance(value, expected_type):
|
|
errors_msg.append(
|
|
f"Wrong type for '{section_key}/{subsection_key}': "
|
|
f"expected {expected_type.__name__}, got {type(value).__name__}."
|
|
)
|
|
|
|
if raise_errors and errors_msg:
|
|
if file_path is None:
|
|
file_path = Path("meta.yaml")
|
|
raise ValueError(
|
|
f"{file_path} validation failed: \n - " + "\n - ".join(errors_msg)
|
|
)
|
|
|
|
return errors_msg
|
|
|
|
|
|
def parse_package_config(path: Path, check: bool = True) -> Dict[str, Any]:
|
|
"""Load a meta.yaml file
|
|
|
|
Parameters
|
|
----------
|
|
path
|
|
path to the meta.yaml file
|
|
check
|
|
check the consitency of the config file
|
|
|
|
Returns
|
|
-------
|
|
the loaded config as a Dict
|
|
"""
|
|
# Import yaml here because pywasmcross needs to run in the built native
|
|
# Python, which won't have PyYAML
|
|
import yaml
|
|
|
|
with open(path, "rb") as fd:
|
|
config = yaml.safe_load(fd)
|
|
|
|
if check:
|
|
check_package_config(config, file_path=path)
|
|
|
|
return config
|