Skip to content

Commit

Permalink
fixes from merge
Browse files Browse the repository at this point in the history
  • Loading branch information
KotlinIsland committed Dec 6, 2023
1 parent 3cf9713 commit 1b1c43a
Show file tree
Hide file tree
Showing 33 changed files with 1,703 additions and 893 deletions.
2,252 changes: 1,457 additions & 795 deletions .mypy/baseline.json

Large diffs are not rendered by default.

26 changes: 22 additions & 4 deletions mypy/binder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from collections import defaultdict
from contextlib import contextmanager
from typing import DefaultDict, Iterator, List, Optional, Tuple, Union, cast
from typing import DefaultDict, Iterator, List, Optional, Tuple, Union, cast, Iterable, Container
from typing_extensions import TypeAlias as _TypeAlias

from mypy.erasetype import remove_instance_last_known_values
Expand Down Expand Up @@ -121,6 +121,18 @@ def __init__(self) -> None:
self.try_frames: set[int] = set()
self.break_frames: list[int] = []
self.continue_frames: list[int] = []
self.artificial_values: set[Key]
self._collect_artificial_keys = False

@contextmanager
def collect_artificial_keys(self):
collect_artificial_keys = self._collect_artificial_keys
self._collect_artificial_keys = True
self.artificial_values = set()
try:
yield
finally:
self._collect_artificial_keys = collect_artificial_keys

def _get_id(self) -> int:
self.next_id += 1
Expand All @@ -142,6 +154,8 @@ def push_frame(self, conditional_frame: bool = False) -> Frame:
return f

def _put(self, key: Key, type: Type, index: int = -1) -> None:
if self._collect_artificial_keys:
self.artificial_values.add(key)
self.frames[index].types[key] = type

def _get(self, key: Key, index: int = -1) -> Type | None:
Expand Down Expand Up @@ -203,7 +217,8 @@ def update_from_options(self, frames: list[Frame]) -> bool:
options are the same.
"""

frames = [f for f in frames if f.unreachable == 0]
artificial = any([f.unreachable == 2 for f in frames])
frames = [f for f in frames if not f.unreachable]
changed = False
keys = {key for f in frames for key in f.types}

Expand Down Expand Up @@ -246,7 +261,10 @@ def update_from_options(self, frames: list[Frame]) -> bool:
if simplified == self.declarations[key]:
type = simplified
if current_value is None or not is_same_type(type, current_value):
self._put(key, type)
if not (artificial and key in self.artificial_values):
# if any frames were artificially unreachable,
# we don't want to narrow any types
self._put(key, type)
changed = True

self.frames[-1].unreachable = not frames
Expand Down Expand Up @@ -396,7 +414,7 @@ def allow_jump(self, index: int) -> None:
for f in self.frames[index + 1 :]:
frame.types.update(f.types)
if f.unreachable:
frame.unreachable = True
frame.unreachable = f.unreachable
self.options_on_return[index].append(frame)

def handle_break(self) -> None:
Expand Down
5 changes: 3 additions & 2 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7414,8 +7414,9 @@ def push_type_map(self, type_map: TypeMap) -> None:
if type_map is None:
self.binder.unreachable()
else:
for expr, type in type_map.items():
self.binder.put(expr, type)
with self.binder.collect_artificial_keys():
for expr, type in type_map.items():
self.binder.put(expr, type)

def infer_issubclass_maps(self, node: CallExpr, expr: Expression) -> tuple[TypeMap, TypeMap]:
"""Infer type restrictions for an expression in issubclass call."""
Expand Down
14 changes: 10 additions & 4 deletions mypy/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,15 @@ def _infer_constraints(
# T :> U2", but they are not equivalent to the constraint solver,
# which never introduces new Union types (it uses join() instead).
if isinstance(template, TypeVarType):
return _infer_constraints(template.upper_bound, actual, direction, skip_neg_op) + [
Constraint(template, direction, actual)
]
if not isinstance(get_proper_type(template.upper_bound), CallableType):
generic_bound = _infer_constraints(
template.upper_bound, actual, direction, skip_neg_op
)
else:
# HACK: Disregard CallableType because `(*Any, **Any) -> object`
# will produce unwanted constraints
generic_bound = []
return generic_bound + [Constraint(template, direction, actual)]

if (
isinstance(actual, TypeVarType)
Expand All @@ -360,7 +366,7 @@ def _infer_constraints(
):
# Unless template is also a type variable (or a union that contains one), using the upper
# bound for inference will usually give better result for actual that is a type variable.
if not isinstance(template, UnionType) or not any(
if not isinstance(template, (UnionType, IntersectionType)) or not any(
isinstance(t, TypeVarType) for t in template.items
):
actual = get_proper_type(actual.upper_bound)
Expand Down
1 change: 1 addition & 0 deletions mypy/dmypy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ def serve(self) -> None:
data = receive(server)
sys.stdout = WriteToConn(server, "stdout") # type: ignore[assignment]
sys.stderr = WriteToConn(server, "stderr") # type: ignore[assignment]
self.options.color_output = False # needed so that initialize_unix_colors doesn't try to get the `fileno` of the WriteToConn
resp: dict[str, Any] = {}
if "command" not in data:
resp = {"error": "No command found in request"}
Expand Down
8 changes: 4 additions & 4 deletions mypy/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,20 +242,20 @@ def filtered_errors(self) -> list[ErrorInfo]:
class StoredBaselineError(TypedDict):
"""Structure of an error while stored in a baseline file"""

code: Optional[str]
code: str | None
column: int
message: str
offset: int
target: Optional[str]
target: str | None
src: str


class BaselineError(TypedDict):
code: Optional[str]
code: str | None
column: int
line: int
message: str
target: Optional[str]
target: str | None
src: str


Expand Down
6 changes: 4 additions & 2 deletions mypy/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -1371,7 +1371,7 @@ def return_type_incompatible_with_supertype(
):
self.note(f'Consider declaring "{name}" in {target} without "async"', context)
self.note(
"See https://mypy.readthedocs.io/en/stable/more_types.html#asynchronous-iterators",
"See https://kotlinisland.github.io/basedmypy/more_types.html#asynchronous-iterators",
context,
)

Expand Down Expand Up @@ -2470,7 +2470,9 @@ def quote_type_string(type_string: str) -> str:
"""Quotes a type representation for use in messages."""
no_quote_regex = r"^<(tuple|union): \d+ items>$"
if (
type_string in ["Module", "overloaded function", "Never", "<deleted>"]
# erm, "Never" should "Never" be unquoted!
type_string in ["Module", "overloaded function", "<deleted>"]
# type_string in ["Module", "overloaded function", "Never", "<deleted>"]
or type_string.startswith("Module ")
or re.match(no_quote_regex, type_string) is not None
or type_string.endswith("?")
Expand Down
2 changes: 1 addition & 1 deletion mypy/stubdoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def format_sig(
args.append(arg_def)

retfield = ""
ret_type = self.ret_type if self.ret_type else any_val
ret_type = self.ret_type or any_val
if ret_type is not None:
retfield = " -> " + ret_type

Expand Down
15 changes: 8 additions & 7 deletions mypy/stubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ def __init__(
include_docstrings: bool = False,
legacy: bool = False,
) -> None:
super().__init__(_all_, include_private, export_less, include_docstrings)
super().__init__(_all_, include_private, export_less, include_docstrings, legacy=legacy)
self._decorators: list[str] = []
# Stack of defined variables (per scope).
self._vars: list[list[str]] = [[]]
Expand All @@ -431,8 +431,6 @@ def __init__(
self._current_class: ClassDef | None = None
# Was the tree semantically analysed before?
self.analyzed = analyzed
# Don't use based features?
self.legacy = legacy
# Short names of methods defined in the body of the current class
self.method_names: set[str] = set()
self.processing_dataclass = False
Expand Down Expand Up @@ -539,10 +537,10 @@ def _get_func_return(self, o: FuncDef, ctx: FunctionContext) -> str | None:
if o.abstract_status == IS_ABSTRACT or o.name in METHODS_WITH_RETURN_VALUE:
# Always assume abstract methods return Any unless explicitly annotated. Also
# some dunder methods should not have a None return type.
return None # implicit Any
return None if self.legacy else self.add_name("_typeshed.Incomplete") # implicit Any
retname = infer_method_ret_type(o.name)
if not self.legacy and retname == "None":
retname = ""
return None
if retname is not None:
return retname
if has_yield_expression(o) or has_yield_from_expression(o):
Expand All @@ -561,9 +559,12 @@ def _get_func_return(self, o: FuncDef, ctx: FunctionContext) -> str | None:
if has_return_statement(o):
return_name = self.add_name("_typeshed.Incomplete")
return f"{generator_name}[{yield_name}, {send_name}, {return_name}]"
if o.is_property:
return None

if not has_return_statement(o) and o.abstract_status == NOT_ABSTRACT:
return "None"
return None
return "None" if self.legacy else None
return None if self.legacy else self.add_name("_typeshed.Incomplete")

def _get_func_docstring(self, node: FuncDef) -> str | None:
if not node.body.body:
Expand Down
6 changes: 4 additions & 2 deletions mypy/stubgenc.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ def __init__(
export_less: bool = False,
include_docstrings: bool = False,
module: ModuleType | None = None,
legacy=False,
) -> None:
self.doc_dir = doc_dir
if module is None:
Expand All @@ -235,7 +236,7 @@ def __init__(
self.is_c_module = is_c_module(self.module)
self.known_modules = known_modules
self.resort_members = self.is_c_module
super().__init__(_all_, include_private, export_less, include_docstrings)
super().__init__(_all_, include_private, export_less, include_docstrings, legacy=legacy)
self.module_name = module_name

def get_default_function_sig(self, func: object, ctx: FunctionContext) -> FunctionSig:
Expand Down Expand Up @@ -686,7 +687,8 @@ def generate_property_stub(

def get_type_fullname(self, typ: type) -> str:
"""Given a type, return a string representation"""
if typ is Any:
# typ is a TypeForm, not a type
if typ is Any: # type: ignore[comparison-overlap, unused-ignore]
return "Any"
typename = getattr(typ, "__qualname__", typ.__name__)
module_name = self.get_obj_module(typ)
Expand Down
6 changes: 6 additions & 0 deletions mypy/stubutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,10 @@ def __init__(
include_private: bool = False,
export_less: bool = False,
include_docstrings: bool = False,
legacy=False,
):
self.legacy = legacy

# Best known value of __all__.
self._all_ = _all_
self._include_private = include_private
Expand Down Expand Up @@ -594,6 +597,9 @@ def add_name(self, fullname: str, require: bool = True) -> str:
The import will be internal to the stub (i.e don't reexport).
"""

if fullname == "_typeshed.Incomplete" and not self.legacy:
fullname = "basedtyping.Untyped"
module, name = fullname.rsplit(".", 1)
alias = "_" + name if name in self.defined_names else None
self.import_tracker.add_import_from(module, [(name, alias)], require=require)
Expand Down
7 changes: 6 additions & 1 deletion mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1635,7 +1635,12 @@ def are_parameters_compatible(
# (*Any) a supertype of all callables with positional arguments. This is needed in
# particular because we often refuse to try type inference if actual type is not
# a subtype of erased template type.
if all(k.is_positional() for k in left.arg_kinds) and ignore_pos_arg_names:
# HACK: working around upstream issues:
# https://github.com/python/mypy/issues/16567
# https://github.com/python/mypy/issues/16568
# https://github.com/python/mypy/issues/16569
# if all(k.is_positional() for k in left.arg_kinds) and ignore_pos_arg_names:
if all(k.is_positional() for k in left.arg_kinds):
return True

# Match up corresponding arguments and check them for compatibility. In
Expand Down
Loading

0 comments on commit 1b1c43a

Please sign in to comment.