Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into 2023-04-13-attrs-ev…
Browse files Browse the repository at this point in the history
…olve-union
  • Loading branch information
ikonst committed Apr 20, 2023
2 parents b6233fb + 0845818 commit 10d9e91
Show file tree
Hide file tree
Showing 113 changed files with 1,333 additions and 603 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/psf/black
rev: 22.12.0 # must match test-requirements.txt
rev: 23.3.0 # must match test-requirements.txt
hooks:
- id: black
- repo: https://github.com/pycqa/isort
Expand Down
2 changes: 1 addition & 1 deletion misc/analyze_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def load_json(data_path: str, meta_path: str) -> CacheData:


def get_files(root: str) -> Iterable[CacheData]:
for (dirpath, dirnames, filenames) in os.walk(root):
for dirpath, dirnames, filenames in os.walk(root):
for filename in filenames:
if filename.endswith(".data.json"):
meta_filename = filename.replace(".data.json", ".meta.json")
Expand Down
1 change: 0 additions & 1 deletion misc/fix_annotate.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ def foo(self, bar, baz=12):


class FixAnnotate(BaseFix):

# This fixer is compatible with the bottom matcher.
BM_compatible = True

Expand Down
1 change: 0 additions & 1 deletion mypy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@


def _run(main_wrapper: Callable[[TextIO, TextIO], None]) -> tuple[str, str, int]:

stdout = StringIO()
stderr = StringIO()

Expand Down
12 changes: 1 addition & 11 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,7 @@ def _build(

source_set = BuildSourceSet(sources)
cached_read = fscache.read
errors = Errors(
options.show_error_context,
options.show_column_numbers,
options.hide_error_codes,
options.pretty,
options.show_error_end,
lambda path: read_py_file(path, cached_read),
options.show_absolute_path,
options.many_errors_threshold,
options,
)
errors = Errors(options, read_source=lambda path: read_py_file(path, cached_read))
plugin, snapshot = load_plugins(options, errors, stdout, extra_plugins)

# Add catch-all .gitignore to cache dir if we created it
Expand Down
67 changes: 45 additions & 22 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ def __init__(
self.expr_checker = mypy.checkexpr.ExpressionChecker(
self, self.msg, self.plugin, per_line_checking_time_ns
)
self.pattern_checker = PatternChecker(self, self.msg, self.plugin)
self.pattern_checker = PatternChecker(self, self.msg, self.plugin, options)

@property
def type_context(self) -> list[Type | None]:
Expand Down Expand Up @@ -483,7 +483,9 @@ def check_first_pass(self) -> None:
"typing.Sequence", [self.named_type("builtins.str")]
)
if not is_subtype(all_.type, seq_str):
str_seq_s, all_s = format_type_distinctly(seq_str, all_.type)
str_seq_s, all_s = format_type_distinctly(
seq_str, all_.type, options=self.options
)
self.fail(
message_registry.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s), all_node
)
Expand Down Expand Up @@ -1178,7 +1180,8 @@ def check_func_def(
msg = None
elif typ.arg_names[i] in {"self", "cls"}:
msg = message_registry.ERASED_SELF_TYPE_NOT_SUPERTYPE.format(
erased, ref_type
erased.str_with_options(self.options),
ref_type.str_with_options(self.options),
)
else:
msg = message_registry.MISSING_OR_INVALID_SELF_TYPE
Expand Down Expand Up @@ -1323,7 +1326,7 @@ def check_unbound_return_typevar(self, typ: CallableType) -> None:
):
self.note(
"Consider using the upper bound "
f"{format_type(typ.ret_type.upper_bound)} instead",
f"{format_type(typ.ret_type.upper_bound, self.options)} instead",
context=typ.ret_type,
)

Expand Down Expand Up @@ -1430,7 +1433,9 @@ def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None:
get_proper_type(bound_type.ret_type), (AnyType, Instance, TupleType, UninhabitedType)
):
self.fail(
message_registry.NON_INSTANCE_NEW_TYPE.format(format_type(bound_type.ret_type)),
message_registry.NON_INSTANCE_NEW_TYPE.format(
format_type(bound_type.ret_type, self.options)
),
fdef,
)
else:
Expand Down Expand Up @@ -1954,11 +1959,15 @@ def bind_and_map_method(
# If we have an overload, filter to overloads that match the self type.
# This avoids false positives for concrete subclasses of generic classes,
# see testSelfTypeOverrideCompatibility for an example.
filtered_items = [
item
for item in mapped_typ.items
if not item.arg_types or is_subtype(active_self_type, item.arg_types[0])
]
filtered_items = []
for item in mapped_typ.items:
if not item.arg_types:
filtered_items.append(item)
item_arg = item.arg_types[0]
if isinstance(item_arg, TypeVarType):
item_arg = item_arg.upper_bound
if is_subtype(active_self_type, item_arg):
filtered_items.append(item)
# If we don't have any filtered_items, maybe it's always a valid override
# of the superclass? However if you get to that point you're in murky type
# territory anyway, so we just preserve the type and have the behaviour match
Expand Down Expand Up @@ -2068,7 +2077,6 @@ def erase_override(t: Type) -> Type:
if not is_subtype(
original.arg_types[i], erase_override(override.arg_types[i])
):

arg_type_in_super = original.arg_types[i]

if isinstance(node, FuncDef):
Expand Down Expand Up @@ -2348,7 +2356,10 @@ class Baz(int, Foo, Bar, enum.Flag): ...
enum_base = base
continue
elif enum_base is not None and not base.type.is_enum:
self.fail(f'No non-enum mixin classes are allowed after "{enum_base}"', defn)
self.fail(
f'No non-enum mixin classes are allowed after "{enum_base.str_with_options(self.options)}"',
defn,
)
break

def check_enum_new(self, defn: ClassDef) -> None:
Expand All @@ -2373,7 +2384,7 @@ def has_new_method(info: TypeInfo) -> bool:
if candidate and has_new:
self.fail(
"Only a single data type mixin is allowed for Enum subtypes, "
'found extra "{}"'.format(base),
'found extra "{}"'.format(base.str_with_options(self.options)),
defn,
)
elif candidate:
Expand Down Expand Up @@ -2954,7 +2965,6 @@ def check_compatibility_all_supers(
and lvalue.kind in (MDEF, None)
and len(lvalue_node.info.bases) > 0 # None for Vars defined via self
):

for base in lvalue_node.info.mro[1:]:
tnode = base.names.get(lvalue_node.name)
if tnode is not None:
Expand Down Expand Up @@ -3976,7 +3986,12 @@ def check_member_assignment(

dunder_set = attribute_type.type.get_method("__set__")
if dunder_set is None:
self.fail(message_registry.DESCRIPTOR_SET_NOT_CALLABLE.format(attribute_type), context)
self.fail(
message_registry.DESCRIPTOR_SET_NOT_CALLABLE.format(
attribute_type.str_with_options(self.options)
),
context,
)
return AnyType(TypeOfAny.from_error), get_type, False

bound_method = analyze_decorator_or_funcbase_access(
Expand Down Expand Up @@ -4130,7 +4145,9 @@ def visit_expression_stmt(self, s: ExpressionStmt) -> None:
if error_note_and_code:
error_note, code = error_note_and_code
self.fail(
message_registry.TYPE_MUST_BE_USED.format(format_type(expr_type)), s, code=code
message_registry.TYPE_MUST_BE_USED.format(format_type(expr_type, self.options)),
s,
code=code,
)
self.note(error_note, s, code=code)

Expand Down Expand Up @@ -4960,7 +4977,9 @@ def _make_fake_typeinfo_and_full_name(
# We use the pretty_names_list for error messages but can't
# use it for the real name that goes into the symbol table
# because it can have dots in it.
pretty_names_list = pretty_seq(format_type_distinctly(*base_classes, bare=True), "and")
pretty_names_list = pretty_seq(
format_type_distinctly(*base_classes, options=self.options, bare=True), "and"
)
try:
info, full_name = _make_fake_typeinfo_and_full_name(base_classes, curr_module)
with self.msg.filter_errors() as local_errors:
Expand Down Expand Up @@ -4997,7 +5016,7 @@ def intersect_instance_callable(self, typ: Instance, callable_type: CallableType
gen_name = gen_unique_name(f"<callable subtype of {typ.type.name}>", cur_module.names)

# Synthesize a fake TypeInfo
short_name = format_type_bare(typ)
short_name = format_type_bare(typ, self.options)
cdef, info = self.make_fake_typeinfo(cur_module.fullname, gen_name, short_name, [typ])

# Build up a fake FuncDef so we can populate the symbol table.
Expand Down Expand Up @@ -5203,7 +5222,7 @@ def _check_for_truthy_type(self, t: Type, expr: Expression) -> None:
return

def format_expr_type() -> str:
typ = format_type(t)
typ = format_type(t, self.options)
if isinstance(expr, MemberExpr):
return f'Member "{expr.name}" has type {typ}'
elif isinstance(expr, RefExpr) and expr.fullname:
Expand All @@ -5218,14 +5237,16 @@ def format_expr_type() -> str:
return f"Expression has type {typ}"

if isinstance(t, FunctionLike):
self.fail(message_registry.FUNCTION_ALWAYS_TRUE.format(format_type(t)), expr)
self.fail(
message_registry.FUNCTION_ALWAYS_TRUE.format(format_type(t, self.options)), expr
)
elif isinstance(t, UnionType):
self.fail(message_registry.TYPE_ALWAYS_TRUE_UNIONTYPE.format(format_expr_type()), expr)
elif isinstance(t, Instance) and t.type.fullname == "typing.Iterable":
_, info = self.make_fake_typeinfo("typing", "Collection", "Collection", [])
self.fail(
message_registry.ITERABLE_ALWAYS_TRUE.format(
format_expr_type(), format_type(Instance(info, t.args))
format_expr_type(), format_type(Instance(info, t.args), self.options)
),
expr,
)
Expand Down Expand Up @@ -6010,7 +6031,9 @@ def check_subtype(
note_msg = ""
notes = notes or []
if subtype_label is not None or supertype_label is not None:
subtype_str, supertype_str = format_type_distinctly(orig_subtype, orig_supertype)
subtype_str, supertype_str = format_type_distinctly(
orig_subtype, orig_supertype, options=self.options
)
if subtype_label is not None:
extra_info.append(subtype_label + " " + subtype_str)
if supertype_label is not None:
Expand Down
32 changes: 24 additions & 8 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
# Type of callback user for checking individual function arguments. See
# check_args() below for details.
ArgChecker: _TypeAlias = Callable[
[Type, Type, ArgKind, Type, int, int, CallableType, Optional[Type], Context, Context], None,
[Type, Type, ArgKind, Type, int, int, CallableType, Optional[Type], Context, Context], None
]

# Maximum nesting level for math union in overloads, setting this to large values
Expand Down Expand Up @@ -845,7 +845,7 @@ def check_typeddict_call_with_kwargs(
# this may give a better error message.
ret_type = callee

for (item_name, item_expected_type) in ret_type.items.items():
for item_name, item_expected_type in ret_type.items.items():
if item_name in kwargs:
item_value = kwargs[item_name]
self.chk.check_simple_assignment(
Expand Down Expand Up @@ -2126,7 +2126,9 @@ def check_argument_types(
if actual_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(
actual_type
):
is_mapping = is_subtype(actual_type, self.chk.named_type("typing.Mapping"))
is_mapping = is_subtype(
actual_type, self.chk.named_type("_typeshed.SupportsKeysAndGetItem")
)
self.msg.invalid_keyword_var_arg(actual_type, is_mapping, context)
expanded_actual = mapper.expand_actual_type(
actual_type, actual_kind, callee.arg_names[i], callee_arg_kind
Expand Down Expand Up @@ -3965,7 +3967,12 @@ def visit_type_application(self, tapp: TypeApplication) -> Type:
if isinstance(tapp.expr, RefExpr) and isinstance(tapp.expr.node, TypeAlias):
# Subscription of a (generic) alias in runtime context, expand the alias.
item = expand_type_alias(
tapp.expr.node, tapp.types, self.chk.fail, tapp.expr.node.no_args, tapp
tapp.expr.node,
tapp.types,
self.chk.fail,
tapp.expr.node.no_args,
tapp,
self.chk.options,
)
item = get_proper_type(item)
if isinstance(item, Instance):
Expand Down Expand Up @@ -4030,7 +4037,12 @@ class LongName(Generic[T]): ...
disallow_any = self.chk.options.disallow_any_generics and self.is_callee
item = get_proper_type(
set_any_tvars(
alias, ctx.line, ctx.column, disallow_any=disallow_any, fail=self.msg.fail
alias,
ctx.line,
ctx.column,
self.chk.options,
disallow_any=disallow_any,
fail=self.msg.fail,
)
)
if isinstance(item, Instance):
Expand Down Expand Up @@ -4346,7 +4358,11 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
for arg in stargs:
if rv is None:
constructor = CallableType(
[self.chk.named_generic_type("typing.Mapping", [kt, vt])],
[
self.chk.named_generic_type(
"_typeshed.SupportsKeysAndGetItem", [kt, vt]
)
],
[nodes.ARG_POS],
[None],
self.chk.named_generic_type("builtins.dict", [kt, vt]),
Expand Down Expand Up @@ -4936,14 +4952,14 @@ def is_valid_keyword_var_arg(self, typ: Type) -> bool:
is_subtype(
typ,
self.chk.named_generic_type(
"typing.Mapping",
"_typeshed.SupportsKeysAndGetItem",
[self.named_type("builtins.str"), AnyType(TypeOfAny.special_form)],
),
)
or is_subtype(
typ,
self.chk.named_generic_type(
"typing.Mapping", [UninhabitedType(), UninhabitedType()]
"_typeshed.SupportsKeysAndGetItem", [UninhabitedType(), UninhabitedType()]
),
)
or isinstance(typ, ParamSpecType)
Expand Down
10 changes: 8 additions & 2 deletions mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,10 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type:
dunder_get = descriptor_type.type.get_method("__get__")
if dunder_get is None:
mx.msg.fail(
message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), mx.context
message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(
descriptor_type.str_with_options(mx.msg.options)
),
mx.context,
)
return AnyType(TypeOfAny.from_error)

Expand Down Expand Up @@ -694,7 +697,10 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type:

if not isinstance(inferred_dunder_get_type, CallableType):
mx.msg.fail(
message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), mx.context
message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(
descriptor_type.str_with_options(mx.msg.options)
),
mx.context,
)
return AnyType(TypeOfAny.from_error)

Expand Down
Loading

0 comments on commit 10d9e91

Please sign in to comment.