Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use strict mypy checking #3222

Merged
merged 11 commits into from Aug 31, 2022
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Expand Up @@ -49,6 +49,8 @@ repos:
- types-typed-ast >= 1.4.1
- click >= 8.1.0
- platformdirs >= 2.1.0
- pytest
- hypothesis

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
Expand Down
45 changes: 26 additions & 19 deletions mypy.ini
Expand Up @@ -7,33 +7,40 @@ python_version=3.6
mypy_path=src

show_column_numbers=True

# show error messages from unrelated files
follow_imports=normal

# suppress errors about unsatisfied imports
ignore_missing_imports=True
show_error_codes=True

# be strict
disallow_untyped_calls=True
warn_return_any=True
strict_optional=True
warn_no_return=True
warn_redundant_casts=True
warn_unused_ignores=True
disallow_any_generics=True
no_implicit_optional=True
strict=True

# except for...
no_implicit_reexport = False

# Unreachable blocks have been an issue when compiling mypyc, let's try
# to avoid 'em in the first place.
warn_unreachable=True

# The following are off by default. Flip them on if you feel
# adventurous.
disallow_untyped_defs=True
check_untyped_defs=True

[mypy-black]
# The following is because of `patch_click()`. Remove when
# we drop Python 3.6 support.
warn_unused_ignores=False

[mypy-blib2to3.driver.*]
ignore_missing_imports = True

[mypy-IPython.*]
ignore_missing_imports = True

[mypy-colorama.*]
ignore_missing_imports = True

[mypy-pathspec.*]
ignore_missing_imports = True

[mypy-tokenize_rt.*]
ignore_missing_imports = True

[mypy-uvloop.*]
ignore_missing_imports = True

[mypy-_black_version.*]
ignore_missing_imports = True
5 changes: 4 additions & 1 deletion scripts/fuzz.py
Expand Up @@ -85,5 +85,8 @@ def test_idempotent_any_syntatically_valid_python(
pass
else:
test = test_idempotent_any_syntatically_valid_python
atheris.Setup(sys.argv, test.hypothesis.fuzz_one_input)
atheris.Setup(
sys.argv,
test.hypothesis.fuzz_one_input, # type: ignore[attr-defined]
)
atheris.Fuzz()
4 changes: 2 additions & 2 deletions src/blackd/middlewares.py
Expand Up @@ -9,7 +9,7 @@


def cors(allow_headers: Iterable[str]) -> Middleware:
@middleware
@middleware # type: ignore[misc]
async def impl(request: Request, handler: Handler) -> StreamResponse:
is_options = request.method == "OPTIONS"
is_preflight = is_options and "Access-Control-Request-Method" in request.headers
Expand All @@ -32,4 +32,4 @@ async def impl(request: Request, handler: Handler) -> StreamResponse:

return resp

return impl # type: ignore
return impl # type: ignore[no-any-return]
18 changes: 9 additions & 9 deletions src/blib2to3/pytree.py
Expand Up @@ -10,7 +10,7 @@
There's also a pattern matching implementation here.
"""

# mypy: allow-untyped-defs
# mypy: allow-untyped-defs, allow-incomplete-defs

from typing import (
Any,
Expand Down Expand Up @@ -291,7 +291,7 @@ def __str__(self) -> Text:
"""
return "".join(map(str, self.children))

def _eq(self, other) -> bool:
def _eq(self, other: Base) -> bool:
"""Compare two nodes for equality."""
return (self.type, self.children) == (other.type, other.children)

Expand Down Expand Up @@ -326,7 +326,7 @@ def prefix(self) -> Text:
return self.children[0].prefix

@prefix.setter
def prefix(self, prefix) -> None:
def prefix(self, prefix: Text) -> None:
if self.children:
self.children[0].prefix = prefix

Expand Down Expand Up @@ -439,7 +439,7 @@ def __str__(self) -> Text:
"""
return self._prefix + str(self.value)

def _eq(self, other) -> bool:
def _eq(self, other: "Leaf") -> bool:
"""Compare two nodes for equality."""
return (self.type, self.value) == (other.type, other.value)

Expand Down Expand Up @@ -472,7 +472,7 @@ def prefix(self) -> Text:
return self._prefix

@prefix.setter
def prefix(self, prefix) -> None:
def prefix(self, prefix: Text) -> None:
self.changed()
self._prefix = prefix

Expand Down Expand Up @@ -618,7 +618,7 @@ def __init__(
self.content = content
self.name = name

def match(self, node: NL, results=None):
def match(self, node: NL, results=None) -> bool:
"""Override match() to insist on a leaf node."""
if not isinstance(node, Leaf):
return False
Expand Down Expand Up @@ -678,7 +678,7 @@ def __init__(
if isinstance(item, WildcardPattern): # type: ignore[unreachable]
self.wildcards = True # type: ignore[unreachable]
self.type = type
self.content = newcontent
self.content = newcontent # TODO: this is unbound when content is None
self.name = name

def _submatch(self, node, results=None) -> bool:
Expand Down Expand Up @@ -920,7 +920,7 @@ def _recursive_matches(self, nodes, count) -> Iterator[Tuple[int, _Results]]:


class NegatedPattern(BasePattern):
def __init__(self, content: Optional[Any] = None) -> None:
def __init__(self, content: Optional[BasePattern] = None) -> None:
"""
Initializer.

Expand All @@ -941,7 +941,7 @@ def match_seq(self, nodes, results=None) -> bool:
# We only match an empty sequence of nodes in its entirety
return len(nodes) == 0

def generate_matches(self, nodes) -> Iterator[Tuple[int, _Results]]:
def generate_matches(self, nodes: List[NL]) -> Iterator[Tuple[int, _Results]]:
if self.content is None:
# Return a match if there is an empty sequence
if len(nodes) == 0:
Expand Down
2 changes: 1 addition & 1 deletion tests/optional.py
Expand Up @@ -26,7 +26,7 @@
from pytest import StashKey
except ImportError:
# pytest < 7
from _pytest.store import StoreKey as StashKey
from _pytest.store import StoreKey as StashKey # type: ignore[no-redef]

log = logging.getLogger(__name__)

Expand Down
24 changes: 15 additions & 9 deletions tests/test_blackd.py
@@ -1,6 +1,6 @@
import re
import sys
from typing import Any
from typing import TYPE_CHECKING, Any, Callable, TypeVar
from unittest.mock import patch

import pytest
Expand All @@ -19,16 +19,22 @@
except ImportError as e:
raise RuntimeError("Please install Black with the 'd' extra") from e

try:
from aiohttp.test_utils import unittest_run_loop
except ImportError:
# unittest_run_loop is unnecessary and a no-op since aiohttp 3.8, and aiohttp 4
# removed it. To maintain compatibility we can make our own no-op decorator.
def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any:
return func
if TYPE_CHECKING:
F = TypeVar("F", bound=Callable[..., Any])

unittest_run_loop: Callable[[F], F] = lambda x: x
else:
try:
from aiohttp.test_utils import unittest_run_loop
except ImportError:
# unittest_run_loop is unnecessary and a no-op since aiohttp 3.8, and
# aiohttp 4 removed it. To maintain compatibility we can make our own
# no-op decorator.
def unittest_run_loop(func, *args, **kwargs):
return func

@pytest.mark.blackd
class BlackDTestCase(AioHTTPTestCase):
class BlackDTestCase(AioHTTPTestCase): # type: ignore[misc]
def test_blackd_main(self) -> None:
with patch("blackd.web.run_app"):
result = CliRunner().invoke(blackd.main, [])
Expand Down