Skip to content

Commit

Permalink
flake8 -> ruff, a mostly painless affair.
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian committed Mar 15, 2023
1 parent 61bd0b1 commit db1e185
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 67 deletions.
13 changes: 0 additions & 13 deletions .flake8

This file was deleted.

18 changes: 17 additions & 1 deletion jsonschema/__init__.py
@@ -1,5 +1,5 @@
"""
An implementation of JSON Schema for Python
An implementation of JSON Schema for Python.
The main functionality is provided by the validator classes for each of the
supported JSON Schema versions.
Expand Down Expand Up @@ -98,3 +98,19 @@ def __getattr__(name):
return ValidatorForFormat.FORMAT_CHECKER

raise AttributeError(f"module {__name__} has no attribute {name}")


__all__ = [
"Draft201909Validator",
"Draft202012Validator",
"Draft3Validator",
"Draft4Validator",
"Draft6Validator",
"Draft7Validator",
"FormatChecker",
"SchemaError",
"TypeChecker",
"ValidationError",
"Validator",
"validate",
]
3 changes: 3 additions & 0 deletions jsonschema/__main__.py
@@ -1,3 +1,6 @@
"""
The jsonschema CLI is now deprecated in favor of check-jsonschema.
"""
from jsonschema.cli import main

main()
8 changes: 3 additions & 5 deletions jsonschema/_format.py
Expand Up @@ -51,9 +51,9 @@ def __init__(self, formats: typing.Iterable[str] | None = None):
self.checkers = {k: self.checkers[k] for k in formats}

def __repr__(self):
return "<FormatChecker checkers={}>".format(sorted(self.checkers))
return f"<FormatChecker checkers={sorted(self.checkers)}>"

def checks(
def checks( # noqa: D417,D214,D405 (charliermarsh/ruff#3547)
self, format: str, raises: _RaisesType = (),
) -> typing.Callable[[_F], _F]:
"""
Expand All @@ -73,7 +73,7 @@ def checks(
The exception object will be accessible as the
`jsonschema.exceptions.ValidationError.cause` attribute of the
resulting validation error.
"""
""" # noqa: D417,D214,D405 (charliermarsh/ruff#3547)

def _checks(func: _F) -> _F:
self.checkers[format] = (func, raises)
Expand Down Expand Up @@ -126,7 +126,6 @@ def check(self, instance: object, format: str) -> None:
if the instance does not conform to ``format``
"""

if format not in self.checkers:
return

Expand Down Expand Up @@ -157,7 +156,6 @@ def conforms(self, instance: object, format: str) -> bool:
bool: whether it conformed
"""

try:
self.check(instance, format)
except FormatError:
Expand Down
2 changes: 1 addition & 1 deletion jsonschema/_legacy_validators.py
Expand Up @@ -222,7 +222,7 @@ def recursiveRef(validator, recursiveRef, instance, schema):

def find_evaluated_item_indexes_by_schema(validator, instance, schema):
"""
Get all indexes of items that get evaluated under the current schema
Get all indexes of items that get evaluated under the current schema.
Covers all keywords related to unevaluatedItems: items, prefixItems, if,
then, else, contains, unevaluatedItems, allOf, oneOf, anyOf
Expand Down
13 changes: 6 additions & 7 deletions jsonschema/_types.py
Expand Up @@ -14,8 +14,8 @@
# the concrete type of a type checker mapping
# this "do nothing" wrapper presents the correct information to mypy
def _typed_map_converter(
init_val: Mapping[str, Callable[["TypeChecker", Any], bool]],
) -> HashTrieMap[str, Callable[["TypeChecker", Any], bool]]:
init_val: Mapping[str, Callable[[TypeChecker, Any], bool]],
) -> HashTrieMap[str, Callable[[TypeChecker, Any], bool]]:
return HashTrieMap.convert(init_val)


Expand Down Expand Up @@ -79,7 +79,7 @@ class TypeChecker:
"""

_type_checkers: HashTrieMap[
str, Callable[["TypeChecker", Any], bool],
str, Callable[[TypeChecker, Any], bool],
] = attr.ib(
default=HashTrieMap(),
converter=_typed_map_converter,
Expand Down Expand Up @@ -116,7 +116,7 @@ def is_type(self, instance, type: str) -> bool:

return fn(self, instance)

def redefine(self, type: str, fn) -> "TypeChecker":
def redefine(self, type: str, fn) -> TypeChecker:
"""
Produce a new checker with the given type redefined.
Expand All @@ -135,7 +135,7 @@ def redefine(self, type: str, fn) -> "TypeChecker":
"""
return self.redefine_many({type: fn})

def redefine_many(self, definitions=()) -> "TypeChecker":
def redefine_many(self, definitions=()) -> TypeChecker:
"""
Produce a new checker with the given types redefined.
Expand All @@ -148,7 +148,7 @@ def redefine_many(self, definitions=()) -> "TypeChecker":
type_checkers = self._type_checkers.update(definitions)
return attr.evolve(self, type_checkers=type_checkers)

def remove(self, *types) -> "TypeChecker":
def remove(self, *types) -> TypeChecker:
"""
Produce a new checker with the given types forgotten.
Expand All @@ -164,7 +164,6 @@ def remove(self, *types) -> "TypeChecker":
if any given type is unknown to this object
"""

type_checkers = self._type_checkers
for each in types:
try:
Expand Down
8 changes: 2 additions & 6 deletions jsonschema/exceptions.py
Expand Up @@ -51,7 +51,7 @@ def __init__(
parent=None,
type_checker=_unset,
):
super(_Error, self).__init__(
super().__init__(
message,
validator,
path,
Expand Down Expand Up @@ -252,7 +252,7 @@ class FormatError(Exception):
"""

def __init__(self, message, cause=None):
super(FormatError, self).__init__(message, cause)
super().__init__(message, cause)
self.message = message
self.cause = self.__cause__ = cause

Expand Down Expand Up @@ -283,7 +283,6 @@ def __contains__(self, index):
"""
Check whether ``instance[index]`` has any errors.
"""

return index in self._contents

def __getitem__(self, index):
Expand All @@ -295,7 +294,6 @@ def __getitem__(self, index):
by ``instance.__getitem__`` will be propagated (usually this is
some subclass of `LookupError`.
"""

if self._instance is not _unset and index not in self:
self._instance[index]
return self._contents[index]
Expand All @@ -310,7 +308,6 @@ def __iter__(self):
"""
Iterate (non-recursively) over the indices in the instance with errors.
"""

return iter(self._contents)

def __len__(self):
Expand All @@ -329,7 +326,6 @@ def total_errors(self):
"""
The total number of errors in the entire tree, including children.
"""

child_errors = sum(len(tree) for _, tree in self._contents.items())
return len(self.errors) + child_errors

Expand Down
2 changes: 1 addition & 1 deletion jsonschema/protocols.py
Expand Up @@ -206,7 +206,7 @@ def validate(self, instance: Any) -> None:
ValidationError: [2, 3, 4] is too long
"""

def evolve(self, **kwargs) -> "Validator":
def evolve(self, **kwargs) -> Validator:
"""
Create a new validator like this one, but with given changes.
Expand Down
2 changes: 1 addition & 1 deletion jsonschema/tests/test_jsonschema_test_suite.py
Expand Up @@ -39,7 +39,7 @@ def missing_format(test): # pragma: no cover
):
return

return "Format checker {0!r} not found.".format(schema["format"])
return f"Format checker {schema['format']!r} not found."
return missing_format


Expand Down
6 changes: 3 additions & 3 deletions jsonschema/tests/test_validators.py
Expand Up @@ -1522,7 +1522,7 @@ def test_schema_with_invalid_regex_with_disabled_format_validation(self):
)


class ValidatorTestMixin(MetaSchemaTestsMixin, object):
class ValidatorTestMixin(MetaSchemaTestsMixin):
def test_it_implements_the_validator_protocol(self):
self.assertIsInstance(self.Validator({}), protocols.Validator)

Expand Down Expand Up @@ -1632,7 +1632,7 @@ def check(value):
elif value == "bad":
raise bad
else: # pragma: no cover
self.fail("What is {}? [Baby Don't Hurt Me]".format(value))
self.fail(f"What is {value}? [Baby Don't Hurt Me]")

validator = self.Validator(
{"format": "foo"}, format_checker=checker,
Expand Down Expand Up @@ -2201,7 +2201,7 @@ def test_it_retrieves_local_refs_via_urlopen(self):
self.addCleanup(os.remove, tempf.name)
json.dump({"foo": "bar"}, tempf)

ref = "file://{}#foo".format(pathname2url(tempf.name))
ref = f"file://{pathname2url(tempf.name)}#foo"
with self.resolver.resolving(ref) as resolved:
self.assertEqual(resolved, "bar")

Expand Down
13 changes: 4 additions & 9 deletions jsonschema/validators.py
Expand Up @@ -518,7 +518,6 @@ def extend(
likely be made before modifying it, in order to not affect the
old validator.
"""

all_validators = dict(validator.VALIDATORS)
all_validators.update(validators)

Expand Down Expand Up @@ -892,7 +891,7 @@ def __init__(
self._remote_cache = remote_cache

@classmethod
def from_schema(
def from_schema( # noqa: D417
cls,
schema,
id_of=referencing.jsonschema.DRAFT202012.id_of,
Expand All @@ -912,7 +911,6 @@ def from_schema(
`_RefResolver`
"""

return cls(base_uri=id_of(schema) or "", referrer=schema, *args, **kwargs) # noqa: B026, E501

def push_scope(self, scope):
Expand Down Expand Up @@ -992,7 +990,6 @@ def resolving(self, ref):
The reference to resolve
"""

url, resolved = self.resolve(ref)
self.push_scope(url)
try:
Expand All @@ -1003,7 +1000,7 @@ def resolving(self, ref):
def _find_in_referrer(self, key):
return self._get_subschemas_cache()[key]

@lru_cache() # noqa: B019
@lru_cache # noqa: B019
def _get_subschemas_cache(self):
cache = {key: [] for key in _SUBSCHEMAS_KEYWORDS}
for keyword, subschema in _search_schema(
Expand All @@ -1012,7 +1009,7 @@ def _get_subschemas_cache(self):
cache[keyword].append(subschema)
return cache

@lru_cache() # noqa: B019
@lru_cache # noqa: B019
def _find_in_subschemas(self, url):
subschemas = self._get_subschemas_cache()["$id"]
if not subschemas:
Expand Down Expand Up @@ -1073,7 +1070,6 @@ def resolve_fragment(self, document, fragment):
a URI fragment to resolve within it
"""

fragment = fragment.lstrip("/")

if not fragment:
Expand Down Expand Up @@ -1196,7 +1192,7 @@ def _search_schema(schema, matcher):
values.extendleft(value.values())


def validate(instance, schema, cls=None, *args, **kwargs):
def validate(instance, schema, cls=None, *args, **kwargs): # noqa: D417
"""
Validate an instance under the given schema.
Expand Down Expand Up @@ -1323,7 +1319,6 @@ class is returned:
recommended.
"""

DefaultValidator = _LATEST_VERSION if default is _UNSET else default

if schema is True or schema is False or "$schema" not in schema:
Expand Down
53 changes: 42 additions & 11 deletions pyproject.toml
Expand Up @@ -111,15 +111,46 @@ multi_line_output = 3
ignore_missing_imports = true
show_error_codes = true

[tool.pydocstyle]
match = "(?!(test_|_|compat|cli)).*\\.py" # see PyCQA/pydocstyle#323
add-select = [
"D410", # Trailing whitespace plz
]
add-ignore = [
"D107", # Hah, no
"D200", # 1-line docstrings don't need to be on one line
"D202", # One line is fine.
"D412", # Trailing whitespace plz
"D413", # No trailing whitespace plz
[tool.ruff]
line-length = 79
target-version = "py38"
select = ["B", "D", "D204", "E", "F", "Q", "UP", "W"]
ignore = [
# It's totally OK to call functions for default arguments.
"B008",
# raise SomeException(...) is fine.
"B904",
# It's fine to not have docstrings for magic methods.
"D105",
# __init__ especially doesn't need a docstring
"D107",
# This rule makes diffs uglier when expanding docstrings (and it's uglier)
"D200",
# No blank lines before docstrings.
"D203",
# Start docstrings on the second line.
"D212",
# This rule misses sassy docstrings ending with ! or ?.
"D400",
# Section headers should end with a colon not a newline
"D406",
# Underlines aren't needed
"D407",
# Plz spaces after section headers
"D412",
]
extend-exclude = ["json"]

[tool.ruff.flake8-quotes]
docstring-quotes = "double"

[tool.ruff.per-file-ignores]
"docs/*" = ["D"]
"jsonschema/cli.py" = ["D", "UP"]
"jsonschema/_utils.py" = ["D"]
"jsonschema/benchmarks/*" = ["D"]
"jsonschema/tests/*" = ["D"]

[tool.ruff.pyupgrade]
# We support 3.8 + 3.9
keep-runtime-typing = true
11 changes: 2 additions & 9 deletions tox.ini
Expand Up @@ -76,15 +76,8 @@ deps = detect-secrets
commands = {envbindir}/detect-secrets scan {toxinidir}

[testenv:style]
deps =
flake8
flake8-broken-line
flake8-bugbear
flake8-commas
flake8-quotes
flake8-tidy-imports
commands =
{envpython} -m flake8 {posargs} {toxinidir}/jsonschema {toxinidir}/docs
deps = ruff
commands = {envpython} -m ruff check {toxinidir}

[testenv:typing]
skip_install = true
Expand Down

0 comments on commit db1e185

Please sign in to comment.