Skip to content

Commit

Permalink
Merge pull request #243 from 23andMe/feature/ruff-codebase
Browse files Browse the repository at this point in the history
Feature/ruff codebase
  • Loading branch information
cblakkan authored Mar 20, 2024
2 parents 3a8594b + 06547bf commit 7d4ee06
Show file tree
Hide file tree
Showing 27 changed files with 631 additions and 703 deletions.
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Run ruff on codebase
9fc3c943c87fc876da6e0a75f621e15a2201cbdd
2 changes: 2 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
line-length = 121
indent-width = 4
50 changes: 25 additions & 25 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
#!/usr/bin/env python
from setuptools import setup, find_packages

readme = open('README.md', encoding='utf-8').read()
license = open('LICENSE', encoding='utf-8').read()
version = open('yamale/VERSION', encoding='utf-8').read().strip()
readme = open("README.md", encoding="utf-8").read()
license = open("LICENSE", encoding="utf-8").read()
version = open("yamale/VERSION", encoding="utf-8").read().strip()

setup(
name='yamale',
name="yamale",
version=version,
url='https://github.com/23andMe/Yamale',
author='Bo Lopker',
author_email='[email protected]',
description='A schema and validator for YAML.',
url="https://github.com/23andMe/Yamale",
author="Bo Lopker",
author_email="[email protected]",
description="A schema and validator for YAML.",
long_description=readme,
long_description_content_type='text/markdown',
license='MIT',
long_description_content_type="text/markdown",
license="MIT",
packages=find_packages(),
include_package_data=True,
install_requires=['pyyaml'],
python_requires='>=3.8',
install_requires=["pyyaml"],
python_requires=">=3.8",
entry_points={
'console_scripts': ['yamale=yamale.command_line:main'],
"console_scripts": ["yamale=yamale.command_line:main"],
},
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
]
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Operating System :: OS Independent",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
)
2 changes: 1 addition & 1 deletion yamale/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.0.0
5.1.0
73 changes: 37 additions & 36 deletions yamale/command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# -*- coding: utf-8 -*-

"""
Validate yaml files and check them against their schemas. Designed to be used outside of Vagrant.
Validate yaml files and check them against their schemas. Designed to be used outside of Vagrant.
Just install Yamale:
pip install yamale
Just install Yamale:
pip install yamale
"""

import argparse
Expand Down Expand Up @@ -37,9 +37,9 @@ def _validate(schema_path, data_path, parser, 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 == '.':
"""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))
Expand All @@ -49,8 +49,8 @@ def _find_data_path_schema(data_path, schema_name):


def _find_schema(data_path, schema_name):
""" Checks if `schema_name` is a valid file, if not
searches in `data_path` for it. """
"""Checks if `schema_name` is a valid file, if not
searches in `data_path` for it."""

if os.path.isfile(schema_name):
return schema_name
Expand All @@ -65,7 +65,7 @@ def _find_schema(data_path, schema_name):


def _validate_single(yaml_path, schema_name, parser, strict):
print('Validating %s...' % yaml_path)
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))
Expand All @@ -76,29 +76,26 @@ def _validate_dir(root, schema_name, cpus, parser, strict):
pool = Pool(processes=cpus)
res = []
error_messages = []
print('Finding yaml files...')
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:
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)))
res.append(pool.apply_async(_validate, (s, d, parser, strict, False)))
else:
print('No schema found for: %s' % d)
print("No schema found for: %s" % d)

print('Found %s yaml files.' % len(res))
print('Validating...')
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()])
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)))
raise ValueError("\n----\n".join(set(error_messages)))


def _router(root, schema_name, cpus, parser, strict=True):
Expand All @@ -110,29 +107,33 @@ def _router(root, schema_name, cpus, parser, strict=True):


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.')
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))
print("Validation failed!\n%s" % str(e))
exit(1)
try:
print('Validation success! 👍')
print("Validation success! 👍")
except UnicodeEncodeError:
print('Validation success!')
print("Validation success!")


if __name__ == '__main__':
if __name__ == "__main__":
main()
6 changes: 3 additions & 3 deletions yamale/readers/tests/test_bad_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from pytest import raises
from .. import parse_yaml

parsers = ['pyyaml', 'PyYAML', 'ruamel']
parsers = ["pyyaml", "PyYAML", "ruamel"]


@pytest.mark.parametrize('parser', parsers)
@pytest.mark.parametrize("parser", parsers)
def test_reader_error(parser):
with raises(IOError):
parse_yaml('wat', parser)
parse_yaml("wat", parser)
34 changes: 17 additions & 17 deletions yamale/readers/tests/test_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
from .. import yaml_reader
from yamale.tests import get_fixture

parsers = ['pyyaml', 'PyYAML', 'ruamel']
TYPES = get_fixture('types.yaml')
NESTED = get_fixture('nested.yaml')
KEYWORDS = get_fixture('keywords.yaml')
parsers = ["pyyaml", "PyYAML", "ruamel"]
TYPES = get_fixture("types.yaml")
NESTED = get_fixture("nested.yaml")
KEYWORDS = get_fixture("keywords.yaml")


@pytest.mark.parametrize('parser', parsers)
@pytest.mark.parametrize('use_string', [True, False])
@pytest.mark.parametrize("parser", parsers)
@pytest.mark.parametrize("use_string", [True, False])
def test_parse(parser, use_string):
if use_string:
with io.open(TYPES, encoding='utf-8') as f:
with io.open(TYPES, encoding="utf-8") as f:
content = f.read()
a = yaml_reader.parse_yaml(parser=parser, content=content)[0]
else:
a = yaml_reader.parse_yaml(TYPES, parser)[0]
assert a['string'] == 'str()'
assert a["string"] == "str()"


def test_parse_validates_arguments():
Expand All @@ -28,22 +28,22 @@ def test_parse_validates_arguments():
yaml_reader.parse_yaml(path=None, content=None)


@pytest.mark.parametrize('parser', parsers)
@pytest.mark.parametrize("parser", parsers)
def test_types(parser):
t = yaml_reader.parse_yaml(TYPES, parser)[0]
assert t['string'] == 'str()'
assert t['number'] == 'num()'
assert t['boolean'] == 'bool()'
assert t['integer'] == 'int()'
assert t["string"] == "str()"
assert t["number"] == "num()"
assert t["boolean"] == "bool()"
assert t["integer"] == "int()"


@pytest.mark.parametrize('parser', parsers)
@pytest.mark.parametrize("parser", parsers)
def test_keywords(parser):
t = yaml_reader.parse_yaml(KEYWORDS, parser)[0]
assert t['optional_min'] == 'int(min=1, required=False)'
assert t["optional_min"] == "int(min=1, required=False)"


@pytest.mark.parametrize('parser', parsers)
@pytest.mark.parametrize("parser", parsers)
def test_nested(parser):
t = yaml_reader.parse_yaml(NESTED, parser)[0]
assert t['list'][-1]['string'] == 'str()'
assert t["list"][-1]["string"] == "str()"
11 changes: 5 additions & 6 deletions yamale/readers/yaml_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

def _pyyaml(f):
import yaml

try:
Loader = yaml.CSafeLoader
except AttributeError: # System does not have libyaml
Expand All @@ -13,17 +14,15 @@ def _pyyaml(f):

def _ruamel(f):
from ruamel.yaml import YAML
yaml = YAML(typ='safe')

yaml = YAML(typ="safe")
return list(yaml.load_all(f))


_parsers = {
'pyyaml': _pyyaml,
'ruamel': _ruamel
}
_parsers = {"pyyaml": _pyyaml, "ruamel": _ruamel}


def parse_yaml(path=None, parser='pyyaml', content=None):
def parse_yaml(path=None, parser="pyyaml", content=None):
try:
parse = _parsers[parser.lower()]
except KeyError:
Expand Down
5 changes: 2 additions & 3 deletions yamale/schema/datapath.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
class DataPath(object):

def __init__(self, *path):
self._path = path

Expand All @@ -9,7 +8,7 @@ def __add__(self, other):
return dp

def __str__(self):
return '.'.join(map(str, (self._path)))
return ".".join(map(str, (self._path)))

def __repr__(self):
return 'DataPath({})'.format(repr(self._path))
return "DataPath({})".format(repr(self._path))
Loading

0 comments on commit 7d4ee06

Please sign in to comment.