| #! /usr/bin/python |
| # |
| # SPDX-License-Identifier: Apache-2.0 |
| # Zephyr's Twister library |
| # |
| # pylint: disable=unused-import |
| # |
| # Set of code that other projects can also import to do things on |
| # Zephyr's sanity check testcases. |
| |
| import logging |
| import yaml |
| try: |
| # Use the C LibYAML parser if available, rather than the Python parser. |
| # It's much faster. |
| from yaml import CLoader as Loader |
| from yaml import CSafeLoader as SafeLoader |
| from yaml import CDumper as Dumper |
| except ImportError: |
| from yaml import Loader, SafeLoader, Dumper |
| |
| log = logging.getLogger("scl") |
| |
| |
| class EmptyYamlFileException(Exception): |
| pass |
| |
| |
| # |
| # |
| def yaml_load(filename): |
| """ |
| Safely load a YAML document |
| |
| Follows recommendations from |
| https://security.openstack.org/guidelines/dg_avoid-dangerous-input-parsing-libraries.html. |
| |
| :param str filename: filename to load |
| :raises yaml.scanner: On YAML scan issues |
| :raises: any other exception on file access errors |
| :return: dictionary representing the YAML document |
| """ |
| try: |
| with open(filename, 'r', encoding='utf-8') as f: |
| return yaml.load(f, Loader=SafeLoader) |
| except yaml.scanner.ScannerError as e: # For errors parsing schema.yaml |
| mark = e.problem_mark |
| cmark = e.context_mark |
| log.error("%s:%d:%d: error: %s (note %s context @%s:%d:%d %s)", |
| mark.name, mark.line, mark.column, e.problem, |
| e.note, cmark.name, cmark.line, cmark.column, e.context) |
| raise |
| |
| # If pykwalify is installed, then the validate function will work -- |
| # otherwise, it is a stub and we'd warn about it. |
| try: |
| import pykwalify.core |
| # Don't print error messages yourself, let us do it |
| logging.getLogger("pykwalify.core").setLevel(50) |
| |
| def _yaml_validate(data, schema): |
| if not schema: |
| return |
| c = pykwalify.core.Core(source_data=data, schema_data=schema) |
| c.validate(raise_exception=True) |
| |
| except ImportError as e: |
| log.warning("can't import pykwalify; won't validate YAML (%s)", e) |
| def _yaml_validate(data, schema): |
| pass |
| |
| def yaml_load_verify(filename, schema): |
| """ |
| Safely load a testcase/sample yaml document and validate it |
| against the YAML schema, returning in case of success the YAML data. |
| |
| :param str filename: name of the file to load and process |
| :param dict schema: loaded YAML schema (can load with :func:`yaml_load`) |
| |
| # 'document.yaml' contains a single YAML document. |
| :raises yaml.scanner.ScannerError: on YAML parsing error |
| :raises pykwalify.errors.SchemaError: on Schema violation error |
| """ |
| # 'document.yaml' contains a single YAML document. |
| y = yaml_load(filename) |
| if not y: |
| raise EmptyYamlFileException('No data in YAML file: %s' % filename) |
| _yaml_validate(y, schema) |
| return y |