8000 Suppress errors from semantic analysis in dynamic (unannotated) funct… · python/mypy@432f706 · GitHub
[go: up one dir, main page]

Skip to content

Commit 432f706

Browse files
gvanrossumddfisher
authored andcommitted
Suppress errors from semantic analysis in dynamic (unannotated) functions. (#1415)
* Suppress errors from semantic analysis in dynamic (unannotated) functions. Fix #1334. * Don't suppress 'continue/break' outside loop. * Rough and tumble fix to make tests pass. Not sure all these are right. Please review. * Clean up SemanticAnalyzer.__init__().
1 parent 2497413 commit 432f706

File tree

5 files changed

+44
-35
lines changed

5 files changed

+44
-35
lines changed

mypy/build.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,16 +368,18 @@ def __init__(self, data_dir: str,
368368
self.custom_typing_module = custom_typing_module
369369
self.source_set = source_set
370370
self.reports = reports
371+
check_untyped_defs = CHECK_UNTYPED_DEFS in self.flags
371372
self.semantic_analyzer = SemanticAnalyzer(lib_path, self.errors,
372-
pyversion=pyversion)
373+
pyversion=pyversion,
374+
check_untyped_defs=check_untyped_defs)
373375
self.modules = self.semantic_analyzer.modules
374376
self.semantic_analyzer_pass3 = ThirdPass(self.modules, self.errors)
375377
self.type_checker = TypeChecker(self.errors,
376378
self.modules,
377379
self.pyversion,
378380
DISALLOW_UNTYPED_CALLS in self.flags,
379381
DISALLOW_UNTYPED_DEFS in self.flags,
380-
CHECK_UNTYPED_DEFS in self.flags)
382+
check_untyped_defs)
381383
self.missing_modules = set() # type: Set[str]
382384

383385
def all_imported_modules_in_file(self,

mypy/semanal.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,11 @@ class SemanticAnalyzer(NodeVisitor):
190190
imports = None # type: Set[str] # Imported modules (during phase 2 analysis)
191191
errors = None # type: Errors # Keeps track of generated errors
192192

193-
def __init__(self, lib_path: List[str], errors: Errors,
194-
pyversion: Tuple[int, int] = defaults.PYTHON3_VERSION) -> None:
193+
def __init__(self,
194+
lib_path: List[str],
195+
errors: Errors,
196+
pyversion: Tuple[int, int],
197+
check_untyped_defs: bool) -> None:
195198
"""Construct semantic analyzer.
196199
197200
Use lib_path to search for modules, and report analysis errors
@@ -211,6 +214,7 @@ def __init__(self, lib_path: List[str], errors: Errors,
211214
self.errors = errors
212215
self.modules = {}
213216
self.pyversion = pyversion
217+
self.check_untyped_defs = check_untyped_defs
214218
self.postpone_nested_functions_stack = [FUNCTION_BOTH_PHASES]
215219
self.postponed_functions_stack = []
216220

@@ -244,10 +248,12 @@ def visit_file(self, file_node: MypyFile, fnam: str) -> None:
244248
def visit_func_def(self, defn: FuncDef) -> None:
245249
phase_info = self.postpone_nested_functions_stack[-1]
246250
if phase_info != FUNCTION_SECOND_PHASE:
251+
self.function_stack.append(defn)
247252
# First phase of analysis for function.
248253
self.errors.push_function(defn.name())
249254
self.update_function_type_variables(defn)
250255
self.errors.pop_function()
256+
self.function_stack.pop()
251257

252258
defn.is_conditional = self.block_depth[-1] > 0
253259

@@ -1630,11 +1636,11 @@ def visit_for_stmt(self, s: ForStmt) -> None:
16301636

16311637
def visit_break_stmt(self, s: BreakStmt) -> None:
16321638
if self.loop_depth == 0:
1633-
self.fail("'break' outside loop", s)
1639+
self.fail("'break' outside loop", s, True)
16341640

16351641
def visit_continue_stmt(self, s: ContinueStmt) -> None:
16361642
if self.loop_depth == 0:
1637-
self.fail("'continue' outside loop", s)
1643+
self.fail("'continue' outside loop", s, True)
16381644

16391645
def visit_if_stmt(self, s: IfStmt) -> None:
16401646
infer_reachability_of_if_statement(s, pyversion=self.pyversion)
@@ -2203,10 +2209,19 @@ def name_not_defined(self, name: str, ctx: Context) -> None:
22032209
def name_already_defined(self, name: str, ctx: Context) -> None:
22042210
self.fail("Name '{}' already defined".format(name), ctx)
22052211

2206-
def fail(self, msg: str, ctx: Context) -> None:
2212+
def fail(self, msg: str, ctx: Context, serious: bool = False) -> None:
2213+
if (not serious and
2214+
not self.check_untyped_defs and
2215+
self.function_stack and
2216+
self.function_stack[-1].is_dynamic()):
2217+
return
22072218
self.errors.report(ctx.get_line(), msg)
22082219

22092220
def note(self, msg: str, ctx: Context) -> None:
2221+
if (not self.check_untyped_defs and
2222+
self.function_stack and
2223+
self.function_stack[-1].is_dynamic()):
2224+
return
22102225
self.errors.report(ctx.get_line(), msg, severity='note')
22112226

22122227
def undefined_name_extra_info(self, fullname: str) -> Optional[str]:

mypy/test/data/check-weak-typing.test

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,6 @@ def f():
123123
1 + 'a' # E: Unsupported left operand type for + ("int")
124124
[out]
125125
main: note: In function "f":
126-
[case testNonWeakFunction]
127-
def f():
128-
if y: # E: Name 'y' is not defined
129-
x = 1
130-
else:
131-
x = 'a'
132-
[out]
133-
main: note: In function "f":
134126
[case testWeakFunctionCall]
135127
# mypy: weak=global
136128
def f(a: str) -> None: pass

mypy/test/data/semanal-errors.test

Lines changed: 19 additions & 19 deletions
< F438 div class="border position-relative rounded-bottom-2">
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ main:3: error: Name 'y' is not defined
1717

1818
[case testUndefinedVariableWithinFunctionContext]
1919
import typing
20-
def f():
20+
def f() -> None:
2121
x
2222
y
2323
[out]
@@ -39,7 +39,7 @@ import typing
3939
class A:
4040
def f(self): pass
4141
class B:
42-
def g(self):
42+
def g(self) -> None:
4343
f # error
4444
g # error
4545
[out]
@@ -178,7 +178,7 @@ main:4: error: Name 'x' already defined
178178
[case testLocalVarRedefinition]
179179
import typing
180180
class A: pass
181-
def f():
181+
def f() -> None:
182182
x = 0 # type: A
183183
x = 0 # type: A
184184
[out]
@@ -523,7 +523,7 @@ main:4: error: Invalid type "__main__.t"
523523
from typing import TypeVar, Generic
524524
t = TypeVar('t')
525525
class c(Generic[t]):
526-
def f(self): x = t
526+
def f(self) -> None: x = t
527527
def f(y: t): x = t
528528
[out]
529529
main: note: In function "f":
@@ -546,7 +546,7 @@ main:2: error: Name 'B' is not defined
546546
[case testSuperOutsideClass]
547547
class A: pass
548548
super().x
549-
def f(): super().y
549+
def f() -> None: super().y
550550
[out]
551551
main:2: error: "super" used outside class
552552
main: note: In function "f":
@@ -572,7 +572,7 @@ main:5: error: Name 'f' already defined
572572

573573
[case testInvalidGlobalDecl]
574574
import typing
575-
def f():
575+
def f() -> None:
576576
global x
577577
x = None
578578
[out]
@@ -582,7 +582,7 @@ main:4: error: Name 'x' is not defined
582582
[case testInvalidNonlocalDecl]
583583
import typing
584584
def f():
585-
def g():
585+
def g() -> None:
586586
nonlocal x
587587
x = None
588588
[out]
@@ -593,7 +593,7 @@ main:5: error: Name 'x' is not defined
593593
[case testNonlocalDeclNotMatchingGlobal]
594594
import typing
595595
x = None
596-
def f():
596+
def f() -> None:
597597
nonlocal x
598598
x = None
599599
[out]
@@ -605,7 +605,7 @@ main:5: error: Name 'x' is not defined
605605
import typing
606606
def g():
607607
x = None
608-
def f(x):
608+
def f(x) -> None:
609609
nonlocal x
610610
x = None
611611
[out]
@@ -623,7 +623,7 @@ import typing
623623
x = 1
624624
def f():
625625
x = 1
626-
def g():
626+
def g() -> None:
627627
global x
628628
nonlocal x
629629
x = None
@@ -636,7 +636,7 @@ import typing
636636
x = 1
637637
def f():
638638
x = 1
639-
def g():
639+
def g() -> None:
640640
nonlocal x
641641
global x
642642
x = None
@@ -646,7 +646,7 @@ main:7: error: Name 'x' is nonlocal and global
646646

647647
[case testNestedFunctionAndScoping]
648648
import typing
649-
def f(x):
649+
def f(x) -> None:
650650
def g(y):
651651
z = x
652652
z
@@ -659,7 +659,7 @@ main:6: error: Name 'y' is not defined
659659

660660
[case testMultipleNestedFunctionDef]
661661
import typing
662-
def f(x):
662+
def f(x) -> None:
663663
def g(): pass
664664
x = 1
665665
def g(): pass
@@ -669,7 +669,7 @@ main:5: error: Name 'g' already defined
669669

670670
[case testRedefinedOverloadedFunction]
671671
from typing import overload, Any
672-
def f():
672+
def f() -> None:
673673
@overload
674674
def p(o: object) -> None: pass # no error
675675
@overload
@@ -683,8 +683,8 @@ main:8: error: Name 'p' already defined
683683
[case testNestedFunctionInMethod]
684684
import typing
685685
class A:
686-
def f(self):
687-
def g():
686+
def f(self) -> None:
687+
def g() -> None:
688688
x
689689
y
690690
[out]
@@ -861,7 +861,7 @@ main:3: error: 'abstractmethod' used with a non-method
861861
[case testAbstractNestedFunction]
862862
import typing
863863
from abc import abstractmethod
864-
def g():
864+
def g() -> None:
865865
@abstractmethod
866866
def foo(): pass
867867
[out]
@@ -1133,7 +1133,7 @@ import typing
11331133
@staticmethod
11341134
def f(): pass
11351135
class A:
1136-
def g(self):
1136+
def g(self) -> None:
11371137
@staticmethod
11381138
def h(): pass
11391139
[builtins fixtures/staticmethod.py]
@@ -1147,7 +1147,7 @@ import typing
11471147
@classmethod
11481148
def f(): pass
11491149
class A:
1150-
def g(self):
1150+
def g(self) -> None:
11511151
@classmethod
11521152
def h(): pass
11531153
[builtins fixtures/classmethod.py]

mypy/test/data/semanal-statements.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ MypyFile:1(
534534
IntExpr(0)))))))
535535

536536
[case testDelMultipleThingsInvalid]
537-
def f(x, y):
537+
def f(x, y) -> None:
538538
del x, y + 1
539539
[out]
540540
main: note: In function "f":

0 commit comments

Comments
 (0)
0