Skip to content

Commit

Permalink
various cleanup (#341)
Browse files Browse the repository at this point in the history
- Drop unnecessary dependencies
- Add another resource on overloads
- Remove some unused imports
- Fix false positive on implicit classmethods
  • Loading branch information
JelleZijlstra authored Dec 15, 2021
1 parent f8146bb commit ba5343a
Show file tree
Hide file tree
Showing 12 changed files with 22 additions and 15 deletions.
3 changes: 3 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

- The first argument to `__new__` and `__init_subclass`
does not need to be `self` (#342)
- Drop dependencies on `attrs` and `mypy_extensions` (#341)
- Correct location of error for incompatible parameter (#339)

## Version 0.5.0 (December 12, 2021)
Expand Down
1 change: 0 additions & 1 deletion pyanalyze/annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
from typed_ast import ast3
import builtins
from collections.abc import Callable, Iterable
from typed_ast import ast3
from typing import (
Any,
Container,
Expand Down
9 changes: 6 additions & 3 deletions pyanalyze/name_check_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
ExceptionOrNone = ExceptionValue | KnownNone
FunctionNode = Union[ast.FunctionDef, ast.AsyncFunctionDef, ast.Lambda]

IMPLICIT_CLASSMETHODS = ("__init_subclass__", "__new__")

BINARY_OPERATION_TO_DESCRIPTION_AND_METHOD = {
ast.Add: ("addition", "__add__", "__iadd__", "__radd__"),
Expand Down Expand Up @@ -1750,9 +1751,9 @@ def _visit_function_args(
)
elif is_self:
assert self.current_class is not None
if function_info.is_classmethod or getattr(node, "name", None) in (
"__init_subclass__",
"__new__",
if (
function_info.is_classmethod
or getattr(node, "name", None) in IMPLICIT_CLASSMETHODS
):
value = SubclassValue(TypedValue(self.current_class))
else:
Expand Down Expand Up @@ -1831,6 +1832,8 @@ def _check_method_first_arg(
# try to confirm that it's actually a method
if not hasattr(node, "name") or not hasattr(self.current_class, node.name):
return
if node.name in IMPLICIT_CLASSMETHODS:
return
first_must_be = "cls" if function_info.is_classmethod else "self"

if len(node.args.args) < 1 or len(node.args.defaults) == len(node.args.args):
Expand Down
8 changes: 7 additions & 1 deletion pyanalyze/safe.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
from typing import Any, Dict, Sequence, Tuple, Union, Container, NewType, Type, TypeVar
import typing
import typing_extensions
import mypy_extensions

try:
import mypy_extensions
except ImportError:
mypy_extensions = None

T = TypeVar("T")

Expand Down Expand Up @@ -138,6 +142,8 @@ def _fill_typing_name_cache(name: str) -> Tuple[Tuple[Any, ...], Tuple[str, ...]
objs = []
names = []
for mod in (typing, typing_extensions, mypy_extensions):
if mod is None:
continue
try:
objs.append(getattr(mod, name))
names.append(f"{mod}.{name}")
Expand Down
2 changes: 2 additions & 0 deletions pyanalyze/signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,8 @@ def check_call(
of mypy's behavior.
- Eric Traut's `discussion <https://github.com/microsoft/pyright/issues/2521#issuecomment-956823577>`_
of pyright's behavior.
- The `documentation <https://github.com/microsoft/pyright/blob/main/docs/type-concepts.md#overloads>`_
for pyright's behavior.
Our behavior is closer to mypy. The general rule is to pick the first overload that matches
and return an error otherwise, but there are two twists: ``Any`` and unions.
Expand Down
2 changes: 1 addition & 1 deletion pyanalyze/test_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ def capybara():

@assert_passes()
def test_callable_compatibility(self):
from typing import TypeVar, Callable, Union, Iterable, Any
from typing import TypeVar, Callable, Union, Iterable
from typing_extensions import Protocol

AnyStr = TypeVar("AnyStr", bytes, str)
Expand Down
1 change: 0 additions & 1 deletion pyanalyze/test_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ def capybara():
@assert_passes()
def test_module_annotations(self):
from pyanalyze import test_attributes
from pyanalyze.type_object import TypeObject
from typing import Optional

annotated_global: Optional[str] = None
Expand Down
5 changes: 1 addition & 4 deletions pyanalyze/test_name_check_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,12 +504,9 @@ def __init_subclass__(cls):
def __new__(cls):
assert_is_value(cls, SubclassValue(TypedValue(OldStyle)))

@assert_passes()
def test_cls_type_inference(self):
class OldStyle:
@classmethod
def capybara(cls):
pass
assert_is_value(cls, SubclassValue(TypedValue(OldStyle)))

@assert_passes()
def test_display_type_inference(self):
Expand Down
2 changes: 1 addition & 1 deletion pyanalyze/test_signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,7 @@ def capybara(
@assert_passes()
def test_any_and_union(self):
from pyanalyze.extensions import overload
from typing import List, Any, Union
from typing import Any, Union
from typing_extensions import Literal

@overload
Expand Down
2 changes: 0 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
# Needed for ReadTheDocs
attrs
asynq
dataclasses; python_version < '3.7'
qcore>=0.5.1
ast_decompiler>=0.4.0
typeshed_client>=1.0.0
typing_inspect>=0.5.0
typing_extensions
mypy_extensions
aenum>=2.2.3
codemod
myst-parser==0.15.1
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
keywords="quora static analysis",
packages=["pyanalyze"],
install_requires=[
"attrs",
"asynq",
"dataclasses; python_version < '3.7'",
"qcore>=0.5.1",
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ skip_missing_interpreters = True
[testenv]
deps =
pytest
mypy_extensions

commands =
pytest pyanalyze/
Expand Down

0 comments on commit ba5343a

Please sign in to comment.