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

Update typing for Python 3.7 (1) #1555

Merged
merged 4 commits into from
May 12, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions astroid/_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

from __future__ import annotations

import ast
import sys
import types
from functools import partial
from typing import Dict, List, NamedTuple, Optional, Type
from typing import NamedTuple

from astroid.const import PY38_PLUS, Context

if sys.version_info >= (3, 8):
# On Python 3.8, typed_ast was merged back into `ast`
_ast_py3: Optional[types.ModuleType] = ast
_ast_py3: types.ModuleType | None = ast
else:
try:
import typed_ast.ast3 as _ast_py3
Expand All @@ -21,17 +23,17 @@


class FunctionType(NamedTuple):
argtypes: List[ast.expr]
argtypes: list[ast.expr]
returns: ast.expr


class ParserModule(NamedTuple):
module: types.ModuleType
unary_op_classes: Dict[Type[ast.unaryop], str]
cmp_op_classes: Dict[Type[ast.cmpop], str]
bool_op_classes: Dict[Type[ast.boolop], str]
bin_op_classes: Dict[Type[ast.operator], str]
context_classes: Dict[Type[ast.expr_context], Context]
unary_op_classes: dict[type[ast.unaryop], str]
cmp_op_classes: dict[type[ast.cmpop], str]
bool_op_classes: dict[type[ast.boolop], str]
bin_op_classes: dict[type[ast.operator], str]
context_classes: dict[type[ast.expr_context], Context]

def parse(self, string: str, type_comments: bool = True) -> ast.Module:
if self.module is _ast_py3:
Expand All @@ -46,7 +48,7 @@ def parse(self, string: str, type_comments: bool = True) -> ast.Module:
return parse_func(string)


def parse_function_type_comment(type_comment: str) -> Optional[FunctionType]:
def parse_function_type_comment(type_comment: str) -> FunctionType | None:
"""Given a correct type comment, obtain a FunctionType object"""
if _ast_py3 is None:
return None
Expand Down Expand Up @@ -78,13 +80,13 @@ def get_parser_module(type_comments: bool = True) -> ParserModule:

def _unary_operators_from_module(
module: types.ModuleType,
) -> Dict[Type[ast.unaryop], str]:
) -> dict[type[ast.unaryop], str]:
return {module.UAdd: "+", module.USub: "-", module.Not: "not", module.Invert: "~"}


def _binary_operators_from_module(
module: types.ModuleType,
) -> Dict[Type[ast.operator], str]:
) -> dict[type[ast.operator], str]:
binary_operators = {
module.Add: "+",
module.BitAnd: "&",
Expand All @@ -105,13 +107,13 @@ def _binary_operators_from_module(

def _bool_operators_from_module(
module: types.ModuleType,
) -> Dict[Type[ast.boolop], str]:
) -> dict[type[ast.boolop], str]:
return {module.And: "and", module.Or: "or"}


def _compare_operators_from_module(
module: types.ModuleType,
) -> Dict[Type[ast.cmpop], str]:
) -> dict[type[ast.cmpop], str]:
return {
module.Eq: "==",
module.Gt: ">",
Expand All @@ -128,7 +130,7 @@ def _compare_operators_from_module(

def _contexts_from_module(
module: types.ModuleType,
) -> Dict[Type[ast.expr_context], Context]:
) -> dict[type[ast.expr_context], Context]:
return {
module.Load: Context.Load,
module.Store: Context.Store,
Expand Down
6 changes: 3 additions & 3 deletions astroid/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

from typing import Optional, Set
from __future__ import annotations

from astroid import nodes
from astroid.bases import Instance
Expand Down Expand Up @@ -36,7 +36,7 @@ def __init__(
self.argument_context_map = argument_context_map
args = callcontext.args
keywords = callcontext.keywords
self.duplicated_keywords: Set[str] = set()
self.duplicated_keywords: set[str] = set()
self._unpacked_args = self._unpack_args(args, context=context)
self._unpacked_kwargs = self._unpack_keywords(keywords, context=context)

Expand All @@ -50,7 +50,7 @@ def __init__(
}

@classmethod
def from_call(cls, call_node, context: Optional[InferenceContext] = None):
def from_call(cls, call_node, context: InferenceContext | None = None):
"""Get a CallSite object from the given Call node.

context will be used to force a single inference path.
Expand Down
7 changes: 4 additions & 3 deletions astroid/brain/brain_builtin_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

"""Astroid hooks for various builtins."""
from __future__ import annotations
cdce8p marked this conversation as resolved.
Show resolved Hide resolved

import itertools
from functools import partial
from typing import Iterator, Optional
from typing import Iterator

from astroid import arguments, helpers, inference_tip, nodes, objects, util
from astroid.builder import AstroidBuilder
Expand Down Expand Up @@ -534,7 +535,7 @@ def infer_callable(node, context=None):


def infer_property(
node: nodes.Call, context: Optional[InferenceContext] = None
node: nodes.Call, context: InferenceContext | None = None
) -> objects.Property:
"""Understand `property` class

Expand Down Expand Up @@ -894,7 +895,7 @@ def _build_dict_with_elements(elements):


def _infer_copy_method(
node: nodes.Call, context: Optional[InferenceContext] = None
node: nodes.Call, context: InferenceContext | None = None
) -> Iterator[nodes.NodeNG]:
assert isinstance(node.func, nodes.Attribute)
inferred_orig, inferred_copy = itertools.tee(node.func.expr.infer(context=context))
Expand Down
14 changes: 8 additions & 6 deletions astroid/brain/brain_dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
- https://lovasoa.github.io/marshmallow_dataclass/

"""
from __future__ import annotations

import sys
from typing import FrozenSet, Generator, List, Optional, Tuple, Union
from typing import Generator, Tuple, Union

from astroid import context, inference_tip
from astroid.builder import parse
Expand Down Expand Up @@ -179,7 +181,7 @@ def _check_generate_dataclass_init(node: ClassDef) -> bool:
)


def _generate_dataclass_init(assigns: List[AnnAssign]) -> str:
def _generate_dataclass_init(assigns: list[AnnAssign]) -> str:
"""Return an init method for a dataclass given the targets."""
target_names = []
params = []
Expand Down Expand Up @@ -234,7 +236,7 @@ def _generate_dataclass_init(assigns: List[AnnAssign]) -> str:


def infer_dataclass_attribute(
node: Unknown, ctx: Optional[context.InferenceContext] = None
node: Unknown, ctx: context.InferenceContext | None = None
) -> Generator:
"""Inference tip for an Unknown node that was dynamically generated to
represent a dataclass attribute.
Expand All @@ -257,7 +259,7 @@ def infer_dataclass_attribute(


def infer_dataclass_field_call(
node: Call, ctx: Optional[context.InferenceContext] = None
node: Call, ctx: context.InferenceContext | None = None
) -> Generator:
"""Inference tip for dataclass field calls."""
if not isinstance(node.parent, (AnnAssign, Assign)):
Expand All @@ -276,7 +278,7 @@ def infer_dataclass_field_call(


def _looks_like_dataclass_decorator(
node: NodeNG, decorator_names: FrozenSet[str] = DATACLASSES_DECORATORS
node: NodeNG, decorator_names: frozenset[str] = DATACLASSES_DECORATORS
) -> bool:
"""Return True if node looks like a dataclass decorator.

Expand Down Expand Up @@ -423,7 +425,7 @@ def _is_init_var(node: NodeNG) -> bool:


def _infer_instance_from_annotation(
node: NodeNG, ctx: Optional[context.InferenceContext] = None
node: NodeNG, ctx: context.InferenceContext | None = None
) -> Generator:
"""Infer an instance corresponding to the type annotation represented by node.

Expand Down
6 changes: 4 additions & 2 deletions astroid/brain/brain_functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

"""Astroid hooks for understanding functools library module."""
from __future__ import annotations

from functools import partial
from itertools import chain
from typing import Iterator, Optional
from typing import Iterator

from astroid import BoundMethod, arguments, extract_node, helpers, nodes, objects
from astroid.context import InferenceContext
Expand Down Expand Up @@ -63,7 +65,7 @@ def _transform_lru_cache(node, context=None) -> None:


def _functools_partial_inference(
node: nodes.Call, context: Optional[InferenceContext] = None
node: nodes.Call, context: InferenceContext | None = None
) -> Iterator[objects.PartialFunction]:
call = arguments.CallSite.from_call(node, context=context)
number_of_positional = len(call.positional_arguments)
Expand Down
11 changes: 6 additions & 5 deletions astroid/brain/brain_namedtuple_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

"""Astroid hooks for the Python standard library."""
from __future__ import annotations
cdce8p marked this conversation as resolved.
Show resolved Hide resolved

import functools
import keyword
from textwrap import dedent
from typing import Iterator, List, Optional, Tuple
from typing import Iterator

import astroid
from astroid import arguments, inference_tip, nodes, util
Expand Down Expand Up @@ -71,9 +72,9 @@ def _extract_namedtuple_arg_or_keyword( # pylint: disable=inconsistent-return-s
def infer_func_form(
node: nodes.Call,
base_type: nodes.NodeNG,
context: Optional[InferenceContext] = None,
context: InferenceContext | None = None,
enum: bool = False,
) -> Tuple[nodes.ClassDef, str, List[str]]:
) -> tuple[nodes.ClassDef, str, list[str]]:
"""Specific inference function for namedtuple or Python 3 enum."""
# node is a Call node, class name as first argument and generated class
# attributes as second argument
Expand Down Expand Up @@ -177,7 +178,7 @@ def _looks_like(node, name):


def infer_named_tuple(
node: nodes.Call, context: Optional[InferenceContext] = None
node: nodes.Call, context: InferenceContext | None = None
) -> Iterator[nodes.ClassDef]:
"""Specific inference function for namedtuple Call node"""
tuple_base_name = nodes.Name(name="tuple", parent=node.root())
Expand Down Expand Up @@ -503,7 +504,7 @@ def infer_typing_namedtuple_function(node, context=None):


def infer_typing_namedtuple(
node: nodes.Call, context: Optional[InferenceContext] = None
node: nodes.Call, context: InferenceContext | None = None
) -> Iterator[nodes.ClassDef]:
"""Infer a typing.NamedTuple(...) call."""
# This is essentially a namedtuple with different arguments
Expand Down
4 changes: 2 additions & 2 deletions astroid/brain/brain_numpy_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

"""Different utilities for the numpy brains"""
from typing import Tuple
from __future__ import annotations

from astroid.builder import extract_node
from astroid.nodes.node_classes import Attribute, Import, Name, NodeNG
Expand All @@ -20,7 +20,7 @@ def numpy_supports_type_hints() -> bool:
return np_ver and np_ver > NUMPY_VERSION_TYPE_HINTS_SUPPORT


def _get_numpy_version() -> Tuple[str, str, str]:
def _get_numpy_version() -> tuple[str, str, str]:
"""
Return the numpy version number if numpy can be imported. Otherwise returns
('0', '0', '0')
Expand Down
6 changes: 2 additions & 4 deletions astroid/brain/brain_re.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

from typing import Optional
from __future__ import annotations

from astroid import context, inference_tip, nodes
from astroid.brain.helpers import register_module_extender
Expand Down Expand Up @@ -74,9 +74,7 @@ def _looks_like_pattern_or_match(node: nodes.Call) -> bool:
)


def infer_pattern_match(
node: nodes.Call, ctx: Optional[context.InferenceContext] = None
):
def infer_pattern_match(node: nodes.Call, ctx: context.InferenceContext | None = None):
"""Infer re.Pattern and re.Match as classes. For PY39+ add `__class_getitem__`."""
class_def = nodes.ClassDef(
name=node.parent.targets[0].name,
Expand Down
16 changes: 9 additions & 7 deletions astroid/brain/brain_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

"""Astroid hooks for typing.py support."""
from __future__ import annotations

import typing
from functools import partial

Expand Down Expand Up @@ -140,7 +142,7 @@ def _looks_like_typing_subscript(node):


def infer_typing_attr(
node: Subscript, ctx: typing.Optional[context.InferenceContext] = None
node: Subscript, ctx: context.InferenceContext | None = None
) -> typing.Iterator[ClassDef]:
"""Infer a typing.X[...] subscript"""
try:
Expand Down Expand Up @@ -179,22 +181,22 @@ def infer_typing_attr(


def _looks_like_typedDict( # pylint: disable=invalid-name
node: typing.Union[FunctionDef, ClassDef],
node: FunctionDef | ClassDef,
) -> bool:
"""Check if node is TypedDict FunctionDef."""
return node.qname() in {"typing.TypedDict", "typing_extensions.TypedDict"}


def infer_old_typedDict( # pylint: disable=invalid-name
node: ClassDef, ctx: typing.Optional[context.InferenceContext] = None
node: ClassDef, ctx: context.InferenceContext | None = None
) -> typing.Iterator[ClassDef]:
func_to_add = _extract_single_node("dict")
node.locals["__call__"] = [func_to_add]
return iter([node])


def infer_typedDict( # pylint: disable=invalid-name
node: FunctionDef, ctx: typing.Optional[context.InferenceContext] = None
node: FunctionDef, ctx: context.InferenceContext | None = None
) -> typing.Iterator[ClassDef]:
"""Replace TypedDict FunctionDef with ClassDef."""
class_def = ClassDef(
Expand Down Expand Up @@ -254,7 +256,7 @@ def full_raiser(origin_func, attr, *args, **kwargs):


def infer_typing_alias(
node: Call, ctx: typing.Optional[context.InferenceContext] = None
node: Call, ctx: context.InferenceContext | None = None
) -> typing.Iterator[ClassDef]:
"""
Infers the call to _alias function
Expand Down Expand Up @@ -342,7 +344,7 @@ def _looks_like_special_alias(node: Call) -> bool:


def infer_special_alias(
node: Call, ctx: typing.Optional[context.InferenceContext] = None
node: Call, ctx: context.InferenceContext | None = None
) -> typing.Iterator[ClassDef]:
"""Infer call to tuple alias as new subscriptable class typing.Tuple."""
if not (
Expand Down Expand Up @@ -377,7 +379,7 @@ def _looks_like_typing_cast(node: Call) -> bool:


def infer_typing_cast(
node: Call, ctx: typing.Optional[context.InferenceContext] = None
node: Call, ctx: context.InferenceContext | None = None
) -> typing.Iterator[NodeNG]:
"""Infer call to cast() returning same type as casted-from var"""
if not isinstance(node.func, (Name, Attribute)):
Expand Down
Loading