From e30bea614c2431db7f95ecf79ffae43f61e8450b Mon Sep 17 00:00:00 2001 From: Coronon Date: Sun, 13 Oct 2019 22:04:32 +0400 Subject: [PATCH 01/10] Add recommendation to use string literal escaping --- mypy/message_registry.py | 3 +++ mypy/typeanal.py | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 195807216a2b..78a4b459429c 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -89,6 +89,9 @@ GENERIC_INSTANCE_VAR_CLASS_ACCESS = \ 'Access to generic instance variables via class is ambiguous' # type: Final BARE_GENERIC = 'Missing type parameters for generic type {}' # type: Final +BARE_GENERIC_STRING_LITERAL_ESCAPE = \ + 'Missing type parameters for generic type {}, ' \ + 'also consider using string literal escaping' # type: Final IMPLICIT_GENERIC_ANY_BUILTIN = \ 'Implicit generic "Any". Use "{}" and specify generic parameters' # type: Final diff --git a/mypy/typeanal.py b/mypy/typeanal.py index ca300d125cb8..73708590cb1a 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -55,6 +55,10 @@ 'mypy_extensions.KwArg': ARG_STAR2, } # type: Final +GENERIC_STUB_NOT_AT_RUNTIME_TYPES = { + 'OrderedDict' +} # type: Final + def analyze_type_alias(node: Expression, api: SemanticAnalyzerCoreInterface, @@ -907,8 +911,12 @@ def get_omitted_any(disallow_any: bool, fail: FailCallback, typ = unexpanded_type or typ type_str = typ.name if isinstance(typ, UnboundType) else format_type_bare(typ) - fail(message_registry.BARE_GENERIC.format(quote_type_string(type_str)), typ, - code=codes.TYPE_ARG) + if type_str in GENERIC_STUB_NOT_AT_RUNTIME_TYPES: + #Recommend to put type in quotes (string literal escaping) + fail(message_registry.BARE_GENERIC_STRING_LITERAL_ESCAPE.format(quote_type_string(type_str)), typ, code=codes.TYPE_ARG) + else: + fail(message_registry.BARE_GENERIC.format(quote_type_string(type_str)), typ, + code=codes.TYPE_ARG) any_type = AnyType(TypeOfAny.from_error, line=typ.line, column=typ.column) else: any_type = AnyType(TypeOfAny.from_omitted_generics, line=typ.line, column=typ.column) From 3983f50194ce483beac1c67a655a9c8af985b464 Mon Sep 17 00:00:00 2001 From: Coronon Date: Sun, 13 Oct 2019 22:22:19 +0400 Subject: [PATCH 02/10] PEP8 compliant --- mypy/typeanal.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 73708590cb1a..ab991174a4b9 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -912,11 +912,12 @@ def get_omitted_any(disallow_any: bool, fail: FailCallback, type_str = typ.name if isinstance(typ, UnboundType) else format_type_bare(typ) if type_str in GENERIC_STUB_NOT_AT_RUNTIME_TYPES: - #Recommend to put type in quotes (string literal escaping) - fail(message_registry.BARE_GENERIC_STRING_LITERAL_ESCAPE.format(quote_type_string(type_str)), typ, code=codes.TYPE_ARG) + # Recommend to put type in quotes (string literal escaping) + fail(message_registry.BARE_GENERIC_STRING_LITERAL_ESCAPE.format( + quote_type_string(type_str)), typ, code=codes.TYPE_ARG) else: fail(message_registry.BARE_GENERIC.format(quote_type_string(type_str)), typ, - code=codes.TYPE_ARG) + code=codes.TYPE_ARG) any_type = AnyType(TypeOfAny.from_error, line=typ.line, column=typ.column) else: any_type = AnyType(TypeOfAny.from_omitted_generics, line=typ.line, column=typ.column) From 56de035e2406d2040b340c7b141f92f546e28727 Mon Sep 17 00:00:00 2001 From: Coronon Date: Sun, 13 Oct 2019 22:28:02 +0400 Subject: [PATCH 03/10] PEP8 compliant2 --- mypy/message_registry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 78a4b459429c..74202c6d26da 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -91,7 +91,7 @@ BARE_GENERIC = 'Missing type parameters for generic type {}' # type: Final BARE_GENERIC_STRING_LITERAL_ESCAPE = \ 'Missing type parameters for generic type {}, ' \ - 'also consider using string literal escaping' # type: Final + 'also consider using string literal escaping' # type: Final IMPLICIT_GENERIC_ANY_BUILTIN = \ 'Implicit generic "Any". Use "{}" and specify generic parameters' # type: Final From 5455ea41f39c01d1e494969c93f2cc47edb06ed3 Mon Sep 17 00:00:00 2001 From: Coronon Date: Mon, 14 Oct 2019 23:22:40 +0400 Subject: [PATCH 04/10] Changed recom to note and added shorter doc anchor --- docs/source/common_issues.rst | 1 + mypy/message_registry.py | 3 --- mypy/semanal.py | 6 ++--- mypy/typeanal.py | 51 ++++++++++++++++++++++------------- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index 22c2a2a45820..e35e450df568 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -533,6 +533,7 @@ Here's the above example modified to use ``MYPY``: def listify(arg: 'bar.BarClass') -> 'List[bar.BarClass]': return [arg] +.. _not-generic-runtime: Using classes that are generic in stubs but not at runtime ---------------------------------------------------------- diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 74202c6d26da..195807216a2b 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -89,9 +89,6 @@ GENERIC_INSTANCE_VAR_CLASS_ACCESS = \ 'Access to generic instance variables via class is ambiguous' # type: Final BARE_GENERIC = 'Missing type parameters for generic type {}' # type: Final -BARE_GENERIC_STRING_LITERAL_ESCAPE = \ - 'Missing type parameters for generic type {}, ' \ - 'also consider using string literal escaping' # type: Final IMPLICIT_GENERIC_ANY_BUILTIN = \ 'Implicit generic "Any". Use "{}" and specify generic parameters' # type: Final diff --git a/mypy/semanal.py b/mypy/semanal.py index cf3e491da26a..4e262386f270 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -449,7 +449,7 @@ def add_builtin_aliases(self, tree: MypyFile) -> None: target = self.named_type_or_none(target_name, []) assert target is not None # Transform List to List[Any], etc. - fix_instance_types(target, self.fail) + fix_instance_types(target, self.fail, self.note) alias_node = TypeAlias(target, alias, line=-1, column=-1, # there is no context no_args=True, normalized=True) @@ -607,7 +607,7 @@ def analyze_func_def(self, defn: FuncDef) -> None: # has external return type `Coroutine[Any, Any, T]`. any_type = AnyType(TypeOfAny.special_form) ret_type = self.named_type_or_none('typing.Coroutine', - [any_type, any_type, defn.type.ret_type]) + [any_type, any_type, defn.type.ret_type]) assert ret_type is not None, "Internal error: typing.Coroutine not found" defn.type = defn.type.copy_modified(ret_type=ret_type) @@ -2489,7 +2489,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: # so we need to replace it with non-explicit Anys. res = make_any_non_explicit(res) no_args = isinstance(res, Instance) and not res.args # type: ignore - fix_instance_types(res, self.fail) + fix_instance_types(res, self.fail, self.note) if isinstance(s.rvalue, (IndexExpr, CallExpr)): # CallExpr is for `void = type(None)` s.rvalue.analyzed = TypeAliasExpr(res, alias_tvars, no_args) s.rvalue.analyzed.line = s.line diff --git a/mypy/typeanal.py b/mypy/typeanal.py index ab991174a4b9..50f6b0d775fb 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -56,7 +56,7 @@ } # type: Final GENERIC_STUB_NOT_AT_RUNTIME_TYPES = { - 'OrderedDict' + 'Queue' } # type: Final @@ -225,8 +225,14 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) res = get_proper_type(res) if (isinstance(res, Instance) and len(res.args) != len(res.type.type_vars) and not self.defining_alias): - fix_instance(res, self.fail, disallow_any=disallow_any, use_generic_error=True, - unexpanded_type=t) + fix_instance( + res, + self.fail, + self.note, + disallow_any=disallow_any, + use_generic_error=True, + unexpanded_type=t, + note=self.note) return res elif isinstance(node, TypeInfo): return self.analyze_type_with_type_info(node, t.args, t) @@ -323,13 +329,14 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt def get_omitted_any(self, typ: Type, fullname: Optional[str] = None) -> AnyType: disallow_any = not self.is_typeshed_stub and self.options.disallow_any_generics - return get_omitted_any(disallow_any, self.fail, typ, fullname) + return get_omitted_any(disallow_any, self.fail, self.note, typ, fullname) def analyze_type_with_type_info(self, info: TypeInfo, args: List[Type], ctx: Context) -> Type: """Bind unbound type when were able to find target TypeInfo. This handles simple cases like 'int', 'modname.UserClass[str]', etc. """ + if len(args) > 0 and info.fullname() == 'builtins.tuple': fallback = Instance(info, [AnyType(TypeOfAny.special_form)], ctx.line) return TupleType(self.anal_array(args), fallback, ctx.line) @@ -341,7 +348,7 @@ def analyze_type_with_type_info(self, info: TypeInfo, args: List[Type], ctx: Con instance = Instance(info, self.anal_array(args), ctx.line, ctx.column) # Check type argument count. if len(instance.args) != len(info.type_vars) and not self.defining_alias: - fix_instance(instance, self.fail, + fix_instance(instance, self.fail, self.note, disallow_any=self.options.disallow_any_generics and not self.is_typeshed_stub) @@ -896,9 +903,10 @@ def tuple_type(self, items: List[Type]) -> TupleType: # Mypyc doesn't support callback protocols yet. FailCallback = Callable[[str, Context, DefaultNamedArg(Optional[ErrorCode], 'code')], None] +NoteCallback = Callable[[str, Context, DefaultNamedArg(Optional[ErrorCode], 'code')], None] -def get_omitted_any(disallow_any: bool, fail: FailCallback, +def get_omitted_any(disallow_any: bool, fail: FailCallback, note: NoteCallback, typ: Type, fullname: Optional[str] = None, unexpanded_type: Optional[Type] = None) -> AnyType: if disallow_any: @@ -911,22 +919,28 @@ def get_omitted_any(disallow_any: bool, fail: FailCallback, typ = unexpanded_type or typ type_str = typ.name if isinstance(typ, UnboundType) else format_type_bare(typ) + fail( + message_registry.BARE_GENERIC.format( + quote_type_string(type_str)), + typ, + code=codes.TYPE_ARG) + if type_str in GENERIC_STUB_NOT_AT_RUNTIME_TYPES: # Recommend to put type in quotes (string literal escaping) - fail(message_registry.BARE_GENERIC_STRING_LITERAL_ESCAPE.format( - quote_type_string(type_str)), typ, code=codes.TYPE_ARG) - else: - fail(message_registry.BARE_GENERIC.format(quote_type_string(type_str)), typ, - code=codes.TYPE_ARG) + note( + "Subscripting classes that are not generic at runtime may require escaping, see https://mypy.readthedocs.io/en/latest/common_issues.html#not-generic-runtime", + typ, + code=codes.TYPE_ARG) + any_type = AnyType(TypeOfAny.from_error, line=typ.line, column=typ.column) else: any_type = AnyType(TypeOfAny.from_omitted_generics, line=typ.line, column=typ.column) return any_type -def fix_instance(t: Instance, fail: FailCallback, +def fix_instance(t: Instance, fail: FailCallback, note: NoteCallback, disallow_any: bool, use_generic_error: bool = False, - unexpanded_type: Optional[Type] = None) -> None: + unexpanded_type: Optional[Type] = None,) -> None: """Fix a malformed instance by replacing all type arguments with Any. Also emit a suitable error if this is not due to implicit Any's. @@ -936,7 +950,7 @@ def fix_instance(t: Instance, fail: FailCallback, fullname = None # type: Optional[str] else: fullname = t.type.fullname() - any_type = get_omitted_any(disallow_any, fail, t, fullname, unexpanded_type) + any_type = get_omitted_any(disallow_any, fail, note, t, fullname, unexpanded_type) t.args = [any_type] * len(t.type.type_vars) return # Invalid number of type parameters. @@ -1190,20 +1204,21 @@ def make_optional_type(t: Type) -> Type: return UnionType([t, NoneType()], t.line, t.column) -def fix_instance_types(t: Type, fail: FailCallback) -> None: +def fix_instance_types(t: Type, fail: FailCallback, note: NoteCallback) -> None: """Recursively fix all instance types (type argument count) in a given type. For example 'Union[Dict, List[str, int]]' will be transformed into 'Union[Dict[Any, Any], List[Any]]' in place. """ - t.accept(InstanceFixer(fail)) + t.accept(InstanceFixer(fail, note)) class InstanceFixer(TypeTraverserVisitor): - def __init__(self, fail: FailCallback) -> None: + def __init__(self, fail: FailCallback, note: NoteCallback) -> None: self.fail = fail + self.note = note def visit_instance(self, typ: Instance) -> None: super().visit_instance(typ) if len(typ.args) != len(typ.type.type_vars): - fix_instance(typ, self.fail, disallow_any=False, use_generic_error=True) + fix_instance(typ, self.fail, self.note, disallow_any=False, use_generic_error=True) From 75ff95d1444aec7f594839cd344203245da08f0a Mon Sep 17 00:00:00 2001 From: Coronon Date: Mon, 14 Oct 2019 23:52:44 +0400 Subject: [PATCH 05/10] fixed `multiple values for argument 'note'` + PEP8 --- mypy/typeanal.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 50f6b0d775fb..9565bc851e8e 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -231,8 +231,7 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) self.note, disallow_any=disallow_any, use_generic_error=True, - unexpanded_type=t, - note=self.note) + unexpanded_type=t) return res elif isinstance(node, TypeInfo): return self.analyze_type_with_type_info(node, t.args, t) @@ -928,7 +927,9 @@ def get_omitted_any(disallow_any: bool, fail: FailCallback, note: NoteCallback, if type_str in GENERIC_STUB_NOT_AT_RUNTIME_TYPES: # Recommend to put type in quotes (string literal escaping) note( - "Subscripting classes that are not generic at runtime may require escaping, see https://mypy.readthedocs.io/en/latest/common_issues.html#not-generic-runtime", + "Subscripting classes that are not generic at runtime may require " + "escaping, see https://mypy.readthedocs.io/" + "en/latest/common_issues.html#not-generic-runtime", typ, code=codes.TYPE_ARG) From 45e12fbd9a59fdfb2f7a5d79e11b5ff8eea3094d Mon Sep 17 00:00:00 2001 From: Coronon Date: Wed, 16 Oct 2019 20:41:14 +0400 Subject: [PATCH 06/10] annotations, MsgCallback, os.Pathlike, fullname --- mypy/typeanal.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 9565bc851e8e..c28b2cf7ae98 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -56,7 +56,8 @@ } # type: Final GENERIC_STUB_NOT_AT_RUNTIME_TYPES = { - 'Queue' + 'queue.Queue', + 'os.Pathlike', } # type: Final @@ -901,11 +902,10 @@ def tuple_type(self, items: List[Type]) -> TupleType: TypeVarList = List[Tuple[str, TypeVarExpr]] # Mypyc doesn't support callback protocols yet. -FailCallback = Callable[[str, Context, DefaultNamedArg(Optional[ErrorCode], 'code')], None] -NoteCallback = Callable[[str, Context, DefaultNamedArg(Optional[ErrorCode], 'code')], None] +MsgCallback = Callable[[str, Context, DefaultNamedArg(Optional[ErrorCode], 'code')], None] -def get_omitted_any(disallow_any: bool, fail: FailCallback, note: NoteCallback, +def get_omitted_any(disallow_any: bool, fail: MsgCallback, note: MsgCallback, typ: Type, fullname: Optional[str] = None, unexpanded_type: Optional[Type] = None) -> AnyType: if disallow_any: @@ -924,11 +924,14 @@ def get_omitted_any(disallow_any: bool, fail: FailCallback, note: NoteCallback, typ, code=codes.TYPE_ARG) - if type_str in GENERIC_STUB_NOT_AT_RUNTIME_TYPES: - # Recommend to put type in quotes (string literal escaping) + if fullname in GENERIC_STUB_NOT_AT_RUNTIME_TYPES: + # Recommend `from __future__ import annotations` or to put type in quotes + # (string literal escaping) for classes not generic at runtime note( "Subscripting classes that are not generic at runtime may require " - "escaping, see https://mypy.readthedocs.io/" + "escaping. If you are running Python 3.7+ you can simply use " + "`from __future__ import annotations`, otherwise please " + "see https://mypy.readthedocs.io/" "en/latest/common_issues.html#not-generic-runtime", typ, code=codes.TYPE_ARG) @@ -939,7 +942,7 @@ def get_omitted_any(disallow_any: bool, fail: FailCallback, note: NoteCallback, return any_type -def fix_instance(t: Instance, fail: FailCallback, note: NoteCallback, +def fix_instance(t: Instance, fail: MsgCallback, note: MsgCallback, disallow_any: bool, use_generic_error: bool = False, unexpanded_type: Optional[Type] = None,) -> None: """Fix a malformed instance by replacing all type arguments with Any. @@ -974,7 +977,7 @@ def fix_instance(t: Instance, fail: FailCallback, note: NoteCallback, def expand_type_alias(target: Type, alias_tvars: List[str], args: List[Type], - fail: FailCallback, no_args: bool, ctx: Context, *, + fail: MsgCallback, no_args: bool, ctx: Context, *, unexpanded_type: Optional[Type] = None, disallow_any: bool = False) -> Type: """Expand a (generic) type alias target following the rules outlined in TypeAlias docstring. @@ -1022,7 +1025,7 @@ def set_any_tvars(tp: Type, vars: List[str], newline: int, newcolumn: int, *, from_error: bool = False, disallow_any: bool = False, - fail: Optional[FailCallback] = None, + fail: Optional[MsgCallback] = None, unexpanded_type: Optional[Type] = None) -> ProperType: if from_error or disallow_any: type_of_any = TypeOfAny.from_error @@ -1205,7 +1208,7 @@ def make_optional_type(t: Type) -> Type: return UnionType([t, NoneType()], t.line, t.column) -def fix_instance_types(t: Type, fail: FailCallback, note: NoteCallback) -> None: +def fix_instance_types(t: Type, fail: MsgCallback, note: MsgCallback) -> None: """Recursively fix all instance types (type argument count) in a given type. For example 'Union[Dict, List[str, int]]' will be transformed into @@ -1215,7 +1218,7 @@ def fix_instance_types(t: Type, fail: FailCallback, note: NoteCallback) -> None: class InstanceFixer(TypeTraverserVisitor): - def __init__(self, fail: FailCallback, note: NoteCallback) -> None: + def __init__(self, fail: MsgCallback, note: MsgCallback) -> None: self.fail = fail self.note = note From 3ededa1e871c59e86bc0b7df68e8284234655018 Mon Sep 17 00:00:00 2001 From: Coronon Date: Thu, 17 Oct 2019 12:08:53 +0200 Subject: [PATCH 07/10] moved annotations to docs --- docs/source/common_issues.rst | 5 +++++ mypy/typeanal.py | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index e35e450df568..3cef1b8ade5e 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -569,6 +569,11 @@ string literal types or :py:data:`~typing.TYPE_CHECKING`: results: 'Queue[int]' = Queue() # OK +If you are running Python 3.7+ simply activate annotations. Read more about them in `PEP563 `_. + +.. code-block:: python + + from __future__ import annotations .. _silencing-linters: diff --git a/mypy/typeanal.py b/mypy/typeanal.py index c28b2cf7ae98..7f7347f95c41 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -929,9 +929,7 @@ def get_omitted_any(disallow_any: bool, fail: MsgCallback, note: MsgCallback, # (string literal escaping) for classes not generic at runtime note( "Subscripting classes that are not generic at runtime may require " - "escaping. If you are running Python 3.7+ you can simply use " - "`from __future__ import annotations`, otherwise please " - "see https://mypy.readthedocs.io/" + "escaping, see https://mypy.readthedocs.io/" "en/latest/common_issues.html#not-generic-runtime", typ, code=codes.TYPE_ARG) From 98697b859b719fc171680c117a9b03e283bb8a64 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 21 Oct 2019 12:20:45 +0100 Subject: [PATCH 08/10] Tweak docs --- docs/source/common_issues.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index 3cef1b8ade5e..ee4a83a63f6a 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -569,11 +569,15 @@ string literal types or :py:data:`~typing.TYPE_CHECKING`: results: 'Queue[int]' = Queue() # OK -If you are running Python 3.7+ simply activate annotations. Read more about them in `PEP563 `_. +If you are running Python 3.7+ you can use ``from __future__ import annotations`` +as a (nicer) alternative to string quotes, read more in :pep:`563`. For example: .. code-block:: python from __future__ import annotations + from queue import Queue + + results: Queue[int] = Queue() # This works at runtime .. _silencing-linters: From e7ea063398bd7d214c23bbc5873aad8e3b5642d9 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 21 Oct 2019 14:06:34 +0100 Subject: [PATCH 09/10] Add test (and fix it) --- mypy/typeanal.py | 2 +- test-data/unit/cmdline.test | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 7f7347f95c41..10004f17b357 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -57,7 +57,7 @@ GENERIC_STUB_NOT_AT_RUNTIME_TYPES = { 'queue.Queue', - 'os.Pathlike', + 'builtins._PathLike', } # type: Final diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index f4e8b684cb15..508458940375 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1444,3 +1444,17 @@ some_file.py:1: error: invalid syntax [syntax] ...ooks_like_we_started_typing_something_but_then. = did_not_notice(an_ex... ^ == Return code: 2 + +[case testSpecialTypeshedGenericNote] +# cmd: mypy --disallow-any-generics test.py +[file test.py] +from os import PathLike +from queue import Queue + +p: PathLike +q: Queue +[out] +test.py:4: error: Missing type parameters for generic type "_PathLike" +test.py:4: note: Subscripting classes that are not generic at runtime may require escaping, see https://mypy.readthedocs.io/en/latest/common_issues.html#not-generic-runtime +test.py:5: error: Missing type parameters for generic type "Queue" +test.py:5: note: Subscripting classes that are not generic at runtime may require escaping, see https://mypy.readthedocs.io/en/latest/common_issues.html#not-generic-runtime From 5a1245d8b8a8877ae35ff62598ca9bdfc18f50c9 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 21 Oct 2019 14:37:50 +0100 Subject: [PATCH 10/10] Fix test on Python 3.5 --- test-data/unit/cmdline.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 508458940375..63bc6e2f0bbe 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1446,7 +1446,7 @@ some_file.py:1: error: invalid syntax [syntax] == Return code: 2 [case testSpecialTypeshedGenericNote] -# cmd: mypy --disallow-any-generics test.py +# cmd: mypy --disallow-any-generics --python-version=3.6 test.py [file test.py] from os import PathLike from queue import Queue