Skip to content

Commit

Permalink
Use future import for type annotations
Browse files Browse the repository at this point in the history
Use of the `__future__` import of annotations allows several niceties,
in particular:
- parametrization of builtin types as generics
- `|` syntax for unions (including `| None` for optionals)

Update to use the future import wherever it improves or simplifies
annotations.

Avoid using new typing features outside of annotations (e.g. in
assignment), which fails on older pythons. This is an unfortunate
wart in the way that the future import works.
  • Loading branch information
sirosen committed Jan 3, 2022
1 parent 7ecc47d commit 215746f
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 19 deletions.
6 changes: 4 additions & 2 deletions jsonschema/_format.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from contextlib import suppress
from uuid import UUID
import datetime
Expand Down Expand Up @@ -34,9 +36,9 @@ class FormatChecker(object):
limit which formats will be used during validation.
"""

checkers: typing.Dict[
checkers: dict[
str,
typing.Tuple[_FormatCheckerFunc, _CheckerRaises],
tuple[_FormatCheckerFunc, _CheckerRaises],
] = {}

def __init__(self, formats=None):
Expand Down
7 changes: 4 additions & 3 deletions jsonschema/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
"""
Validation errors, and some surrounding helpers.
"""
from __future__ import annotations

from collections import defaultdict, deque
from pprint import pformat
from textwrap import dedent, indent
import itertools
import typing

import attr

from jsonschema import _utils

WEAK_MATCHES: typing.FrozenSet[str] = frozenset(["anyOf", "oneOf"])
STRONG_MATCHES: typing.FrozenSet[str] = frozenset()
WEAK_MATCHES: frozenset[str] = frozenset(["anyOf", "oneOf"])
STRONG_MATCHES: frozenset[str] = frozenset()

_unset = _utils.Unset()

Expand Down
12 changes: 7 additions & 5 deletions jsonschema/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# for reference material on Protocols, see
# https://www.python.org/dev/peps/pep-0544/

from typing import Any, ClassVar, Iterator, Optional, Union
from __future__ import annotations

from typing import Any, ClassVar, Iterator
import sys

# doing these imports with `try ... except ImportError` doesn't pass mypy
Expand Down Expand Up @@ -73,13 +75,13 @@ class Validator(Protocol):
TYPE_CHECKER: ClassVar[TypeChecker]

#: The schema that was passed in when initializing the object.
schema: Union[dict, bool]
schema: dict | bool

def __init__(
self,
schema: Union[dict, bool],
resolver: Optional[RefResolver] = None,
format_checker: Optional[FormatChecker] = None,
schema: dict | bool,
resolver: RefResolver | None = None,
format_checker: FormatChecker | None = None,
) -> None:
...

Expand Down
15 changes: 8 additions & 7 deletions jsonschema/tests/test_validators.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from collections import deque, namedtuple
from contextlib import contextmanager
from decimal import Decimal
Expand All @@ -8,7 +10,6 @@
import os
import sys
import tempfile
import typing
import unittest
import warnings

Expand Down Expand Up @@ -1663,7 +1664,7 @@ def test_False_is_not_a_schema_even_if_you_forget_to_check(self):

class TestDraft3Validator(AntiDraft6LeakMixin, ValidatorTestMixin, TestCase):
Validator = validators.Draft3Validator
valid: typing.Tuple[dict, dict] = ({}, {})
valid: tuple[dict, dict] = ({}, {})
invalid = {"type": "integer"}, "foo"

def test_any_type_is_valid_for_type_any(self):
Expand Down Expand Up @@ -1695,31 +1696,31 @@ def test_is_type_does_not_evade_bool_if_it_is_being_tested(self):

class TestDraft4Validator(AntiDraft6LeakMixin, ValidatorTestMixin, TestCase):
Validator = validators.Draft4Validator
valid: typing.Tuple[dict, dict] = ({}, {})
valid: tuple[dict, dict] = ({}, {})
invalid = {"type": "integer"}, "foo"


class TestDraft6Validator(ValidatorTestMixin, TestCase):
Validator = validators.Draft6Validator
valid: typing.Tuple[dict, dict] = ({}, {})
valid: tuple[dict, dict] = ({}, {})
invalid = {"type": "integer"}, "foo"


class TestDraft7Validator(ValidatorTestMixin, TestCase):
Validator = validators.Draft7Validator
valid: typing.Tuple[dict, dict] = ({}, {})
valid: tuple[dict, dict] = ({}, {})
invalid = {"type": "integer"}, "foo"


class TestDraft201909Validator(ValidatorTestMixin, TestCase):
Validator = validators.Draft201909Validator
valid: typing.Tuple[dict, dict] = ({}, {})
valid: tuple[dict, dict] = ({}, {})
invalid = {"type": "integer"}, "foo"


class TestDraft202012Validator(ValidatorTestMixin, TestCase):
Validator = validators.Draft202012Validator
valid: typing.Tuple[dict, dict] = ({}, {})
valid: tuple[dict, dict] = ({}, {})
invalid = {"type": "integer"}, "foo"


Expand Down
6 changes: 4 additions & 2 deletions jsonschema/validators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""
Creation and extension of validators, with implementations for existing drafts.
"""
from __future__ import annotations

from collections import deque
from collections.abc import Sequence
from functools import lru_cache
Expand All @@ -23,9 +25,9 @@
exceptions,
)

_VALIDATORS: typing.Dict[str, typing.Any] = {}
_VALIDATORS: dict[str, typing.Any] = {}
_META_SCHEMAS = _utils.URIDict()
_VOCABULARIES: typing.List[typing.Tuple[str, typing.Any]] = []
_VOCABULARIES: list[tuple[str, typing.Any]] = []


def __getattr__(name):
Expand Down

0 comments on commit 215746f

Please sign in to comment.