Shofel2_T124_python/venv/lib/python3.10/site-packages/yamale/command_line.py

136 lines
4.6 KiB
Python
Raw Normal View History

2024-05-25 16:45:07 +00:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Validate yaml files and check them against their schemas. Designed to be used outside of Vagrant.
Just install Yamale:
pip install yamale
"""
import argparse
import glob
import os
from multiprocessing import Pool
from .yamale_error import YamaleError
from .schema.validationresults import Result
from .version import __version__
import yamale
schemas = {}
def _validate(schema_path, data_path, parser, strict, _raise_error):
schema = schemas.get(schema_path)
try:
if not schema:
schema = yamale.make_schema(schema_path, parser)
schemas[schema_path] = schema
except (SyntaxError, ValueError) as e:
results = [Result([str(e)])]
if not _raise_error:
return results
raise YamaleError(results)
data = yamale.make_data(data_path, parser)
return yamale.validate(schema, data, strict, _raise_error)
def _find_data_path_schema(data_path, schema_name):
""" Starts in the data file folder and recursively looks
in parents for `schema_name` """
if not data_path or data_path == os.path.abspath(os.sep) or data_path == '.':
return None
directory = os.path.dirname(data_path)
path = glob.glob(os.path.join(directory, schema_name))
if not path:
return _find_schema(directory, schema_name)
return path[0]
def _find_schema(data_path, schema_name):
""" Checks if `schema_name` is a valid file, if not
searches in `data_path` for it. """
directory = os.path.dirname(data_path)
path = glob.glob(os.path.join(directory, schema_name))
for p in path:
if os.path.isfile(p):
return p
return _find_data_path_schema(data_path, schema_name)
def _validate_single(yaml_path, schema_name, parser, strict):
print('Validating %s...' % yaml_path)
s = _find_schema(yaml_path, schema_name)
if not s:
raise ValueError("Invalid schema name for '{}' or schema not found.".format(schema_name))
_validate(s, yaml_path, parser, strict, True)
def _validate_dir(root, schema_name, cpus, parser, strict):
pool = Pool(processes=cpus)
res = []
error_messages = []
print('Finding yaml files...')
for root, dirs, files in os.walk(root):
for f in files:
if (f.endswith('.yaml') or f.endswith('.yml')) and f != schema_name:
d = os.path.join(root, f)
s = _find_schema(d, schema_name)
if s:
res.append(pool.apply_async(_validate,
(s, d, parser, strict, False)))
else:
print('No schema found for: %s' % d)
print('Found %s yaml files.' % len(res))
print('Validating...')
for r in res:
sub_results = r.get(timeout=300)
error_messages.extend([str(sub_result)
for sub_result in sub_results
if not sub_result.isValid()])
pool.close()
pool.join()
if error_messages:
raise ValueError('\n----\n'.join(set(error_messages)))
def _router(root, schema_name, cpus, parser, strict=True):
root = os.path.abspath(root)
if os.path.isfile(root):
_validate_single(root, schema_name, parser, strict)
else:
_validate_dir(root, schema_name, cpus, parser, strict)
def main():
parser = argparse.ArgumentParser(description='Validate yaml files.')
parser.add_argument('path', metavar='PATH', default='./', nargs='?',
help='folder to validate. Default is current directory.')
parser.add_argument('-V', '--version', action='version', version=__version__)
parser.add_argument('-s', '--schema', default='schema.yaml',
help='filename of schema. Default is schema.yaml.')
parser.add_argument('-n', '--cpu-num', default=4, type=int,
help='number of CPUs to use. Default is 4.')
parser.add_argument('-p', '--parser', default='pyyaml',
help='YAML library to load files. Choices are "ruamel" or "pyyaml" (default).')
parser.add_argument('--no-strict', action='store_true',
help='Disable strict mode, unexpected elements in the data will be accepted.')
args = parser.parse_args()
try:
_router(args.path, args.schema, args.cpu_num, args.parser, not args.no_strict)
except (SyntaxError, NameError, TypeError, ValueError) as e:
print('Validation failed!\n%s' % str(e))
exit(1)
try:
print('Validation success! 👍')
except UnicodeEncodeError:
print('Validation success!')
if __name__ == '__main__':
main()