From 1d1e9beb4d57727961853068b6b68b6a324384e1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Wed, 7 Jun 2017 17:09:28 -0700 Subject: [PATCH 1/4] Rename --disallow-untyped-defs to --disallow-any=unannotated --- docs/source/command_line.rst | 6 ++--- docs/source/config_file.rst | 12 +++------ mypy/checker.py | 2 +- mypy/main.py | 37 ++++++++++++++++++++++----- mypy/options.py | 4 --- test-data/unit/check-flags.test | 16 ++++++------ test-data/unit/check-incremental.test | 2 +- test-data/unit/cmdline.test | 8 +++--- 8 files changed, 51 insertions(+), 36 deletions(-) diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 0ea5981c31d18..3b31ffc2c87cc 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -11,7 +11,8 @@ flag (or its long form ``--help``):: usage: mypy [-h] [-v] [-V] [--python-version x.y] [--platform PLATFORM] [-2] [--ignore-missing-imports] [--follow-imports {normal,silent,skip,error}] - [--disallow-untyped-calls] [--disallow-untyped-defs] + [--disallow-any {unimported, unannotated}] + [--disallow-untyped-calls] [--check-untyped-defs] [--disallow-subclassing-any] [--warn-incomplete-stub] [--warn-redundant-casts] [--no-warn-no-return] [--warn-return-any] [--warn-unused-ignores] @@ -274,9 +275,6 @@ Here are some more useful flags: re-check your code without ``--strict-optional`` to ensure new type errors are not introduced. -- ``--disallow-untyped-defs`` reports an error whenever it encounters - a function definition without type annotations. - - ``--check-untyped-defs`` is less severe than the previous option -- it type checks the body of every function, regardless of whether it has type annotations. (By default the bodies of functions without diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 6fe139b1bb8c8..5056363cbc5dc 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -151,10 +151,6 @@ overridden by the pattern sections matching the module name. calling functions without type annotations from functions with type annotations. -- ``disallow_untyped_defs`` (Boolean, default False) disallows - defining functions without type annotations or with incomplete type - annotations. - - ``check_untyped_defs`` (Boolean, default False) type-checks the interior of functions without type annotations. @@ -191,13 +187,13 @@ You might put this in your ``mypy.ini`` file at the root of your repo: [mypy] python_version = 2.7 [mypy-foo.*] - disallow_untyped_defs = True + disallow_untyped_calls = True This automatically sets ``--python-version 2.7`` (a.k.a. ``--py2``) for all mypy runs in this tree, and also selectively turns on the -``--disallow-untyped-defs`` flag for all modules in the ``foo`` -package. This issues an error for function definitions without -type annotations in that subdirectory only. +``--disallow-untyped-calls`` flag for all modules in the ``foo`` +package. This issues an error for calls to functions without +type annotations from functions with type annotations. .. note:: diff --git a/mypy/checker.py b/mypy/checker.py index 9cde2c54cbf66..91783f8e3e069 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -606,7 +606,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None: item) show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub - if self.options.disallow_untyped_defs and show_untyped: + if 'unannotated' in self.options.disallow_any and show_untyped: # Check for functions with unspecified/not fully specified types. def is_implicit_any(t: Type) -> bool: return isinstance(t, AnyType) and t.implicit diff --git a/mypy/main.py b/mypy/main.py index 422ca3ccec033..9e4eb2a14c2fd 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -97,7 +97,8 @@ def type_check_only(sources: List[BuildSource], bin_dir: str, options: Options) options=options) -disallow_any_options = ['unimported'] +disallow_any_options = ['unimported', 'unannotated'] +disallow_any_strict = ['unannotated'] def disallow_any_argument_type(raw_options: str) -> List[str]: @@ -201,7 +202,8 @@ def process_options(args: List[str], strict_flag_names = [] # type: List[str] strict_flag_assignments = [] # type: List[Tuple[str, bool]] - disallow_any_options = ['unimported'] + + strict_flag_names.append('--disallow-any={}'.format(','.join(disallow_any_strict))) def add_invertible_flag(flag: str, *, @@ -252,9 +254,6 @@ def add_invertible_flag(flag: str, add_invertible_flag('--disallow-untyped-calls', default=False, strict_flag=True, help="disallow calling functions without type annotations" " from functions with type annotations") - add_invertible_flag('--disallow-untyped-defs', default=False, strict_flag=True, - help="disallow defining functions without type annotations" - " or with incomplete type annotations") add_invertible_flag('--check-untyped-defs', default=False, strict_flag=True, help="type check the interior of functions without type annotations") add_invertible_flag('--disallow-subclassing-any', default=False, strict_flag=True, @@ -349,6 +348,9 @@ def add_invertible_flag(flag: str, parser.add_argument('--no-fast-parser', action='store_true', dest='special-opts:no_fast_parser', help=argparse.SUPPRESS) + add_invertible_flag('--disallow-untyped-defs', default=False, strict_flag=True, + dest='special-opts:disallow_untyped_defs', + help=argparse.SUPPRESS) report_group = parser.add_argument_group( title='report generation', @@ -390,6 +392,8 @@ def add_invertible_flag(flag: str, if getattr(dummy, 'special-opts:strict'): for dest, value in strict_flag_assignments: setattr(options, dest, value) + options.disallow_any.extend(o for o in disallow_any_strict + if o not in options.disallow_any) # Parse command line for real, using a split namespace. special_opts = argparse.Namespace() @@ -427,6 +431,11 @@ def add_invertible_flag(flag: str, if special_opts.no_fast_parser: print("Warning: --no-fast-parser no longer has any effect. The fast parser " "is now mypy's default and only parser.") + if special_opts.disallow_untyped_defs: + print("Warning: --disallow-untyped-defs has been deprecated. " + "Please use --disallow-any=unannotated.") + if 'unannotated' not in options.disallow_any: + options.disallow_any.append('unannotated') # Check for invalid argument combinations. if require_targets: @@ -610,9 +619,11 @@ def get_init_file(dir: str) -> Optional[str]: 'mypy_path': lambda s: [p.strip() for p in re.split('[,:]', s)], 'junit_xml': str, 'disallow_any': disallow_any_argument_type, - # These two are for backwards compatibility + + # These are for backwards compatibility 'silent_imports': bool, 'almost_silent': bool, + 'disallow_untyped_defs': bool, } SHARED_CONFIG_FILES = ('setup.cfg',) @@ -724,6 +735,20 @@ def parse_section(prefix: str, template: Options, except ValueError as err: print("%s: %s: %s" % (prefix, key, err), file=sys.stderr) continue + if key == 'disallow_untyped_defs': + print("%s: disallow_untyped_defs has been deprecated. " + "Please use disallow_any=unannotated." % prefix, v) + if v: + disallow_any_opts = results['disallow_any'] if 'disallow_any' in results else None + if (disallow_any_opts + and isinstance(disallow_any_opts, List) + and 'unannotated' not in disallow_any_opts): + disallow_any_opts.append('unannotated') + else: + results['disallow_any'] = ['unannotated'] + else: + results['disallow_any'] = [] + if key == 'silent_imports': print("%s: silent_imports has been replaced by " "ignore_missing_imports=True; follow_imports=skip" % prefix, file=sys.stderr) diff --git a/mypy/options.py b/mypy/options.py index 69f99cce9501d..8f80bace9d6c1 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -21,7 +21,6 @@ class Options: "follow_imports", "disallow_any", "disallow_untyped_calls", - "disallow_untyped_defs", "check_untyped_defs", "debug_cache", "strict_optional_whitelist", @@ -51,9 +50,6 @@ def __init__(self) -> None: # Disallow calling untyped functions from typed ones self.disallow_untyped_calls = False - # Disallow defining untyped (or incompletely typed) functions - self.disallow_untyped_defs = False - # Type check unannotated functions self.check_untyped_defs = False diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 6f8dcdd4a94b3..191e65c1d0ec3 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -1,45 +1,45 @@ [case testUnannotatedFunction] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated def f(x): pass [out] main:2: error: Function is missing a type annotation [case testUnannotatedArgument] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated def f(x) -> int: pass [out] main:2: error: Function is missing a type annotation for one or more arguments [case testUnannotatedArgumentWithFastParser] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated def f(x) -> int: pass [out] main:2: error: Function is missing a type annotation for one or more arguments [case testNoArgumentFunction] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated def f() -> int: pass [out] [case testUnannotatedReturn] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated def f(x: int): pass [out] main:2: error: Function is missing a return type annotation [case testUnannotatedReturnWithFastParser] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated def f(x: int): pass [out] main:2: error: Function is missing a return type annotation [case testLambda] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated lambda x: x [out] [case testUntypedDef] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unannotated def f(): 1 + "str" [out] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index d28cb1acf512c..bc976847010b8 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -2700,7 +2700,7 @@ a = A() [builtins fixtures/property.pyi] [case testSerializeAbstractPropertyDisallowUntypedIncremental] -# flags: --disallow-untyped-defs +# flags: --disallow-any=unimported from abc import abstractmethod import typing class A: diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 118a7c0f54526..78b9e3f8a4985 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -151,9 +151,9 @@ def f(): # cmd: mypy x.py y.py z.py [file mypy.ini] [[mypy] -disallow_untyped_defs = True +disallow_any = unannotated [[mypy-y*] -disallow_untyped_defs = False +disallow_any = [[mypy-z*] disallow_untyped_calls = True [file x.py] @@ -181,7 +181,7 @@ x.py:1: error: Function is missing a type annotation [file mypy.ini] [[mypy] [[mypy-*x*] -disallow_untyped_defs = True +disallow_any = unannotated [[mypy-*y*] disallow_untyped_calls = True [file xx.py] @@ -209,7 +209,7 @@ xx.py:1: error: Function is missing a type annotation [file mypy.ini] [[mypy] [[mypy-x*,z*] -disallow_untyped_defs = True +disallow_any = unannotated [file x.py] def f(a): pass [file y.py] From f1f0a7c47f214c6dcbf14ea9ed83c756281c48fe Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Fri, 9 Jun 2017 14:43:55 -0700 Subject: [PATCH 2/4] Allow both --disallow-untyped-defs and --disallow-any=unannotated --- docs/source/command_line.rst | 6 +++-- docs/source/config_file.rst | 12 ++++++--- mypy/checker.py | 2 +- mypy/main.py | 39 +++++++-------------------- mypy/options.py | 4 +++ test-data/unit/check-flags.test | 20 +++++++++----- test-data/unit/check-incremental.test | 2 +- test-data/unit/cmdline.test | 33 +++++++++++++++++++++-- 8 files changed, 71 insertions(+), 47 deletions(-) diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 3b31ffc2c87cc..0ea5981c31d18 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -11,8 +11,7 @@ flag (or its long form ``--help``):: usage: mypy [-h] [-v] [-V] [--python-version x.y] [--platform PLATFORM] [-2] [--ignore-missing-imports] [--follow-imports {normal,silent,skip,error}] - [--disallow-any {unimported, unannotated}] - [--disallow-untyped-calls] + [--disallow-untyped-calls] [--disallow-untyped-defs] [--check-untyped-defs] [--disallow-subclassing-any] [--warn-incomplete-stub] [--warn-redundant-casts] [--no-warn-no-return] [--warn-return-any] [--warn-unused-ignores] @@ -275,6 +274,9 @@ Here are some more useful flags: re-check your code without ``--strict-optional`` to ensure new type errors are not introduced. +- ``--disallow-untyped-defs`` reports an error whenever it encounters + a function definition without type annotations. + - ``--check-untyped-defs`` is less severe than the previous option -- it type checks the body of every function, regardless of whether it has type annotations. (By default the bodies of functions without diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 5056363cbc5dc..6fe139b1bb8c8 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -151,6 +151,10 @@ overridden by the pattern sections matching the module name. calling functions without type annotations from functions with type annotations. +- ``disallow_untyped_defs`` (Boolean, default False) disallows + defining functions without type annotations or with incomplete type + annotations. + - ``check_untyped_defs`` (Boolean, default False) type-checks the interior of functions without type annotations. @@ -187,13 +191,13 @@ You might put this in your ``mypy.ini`` file at the root of your repo: [mypy] python_version = 2.7 [mypy-foo.*] - disallow_untyped_calls = True + disallow_untyped_defs = True This automatically sets ``--python-version 2.7`` (a.k.a. ``--py2``) for all mypy runs in this tree, and also selectively turns on the -``--disallow-untyped-calls`` flag for all modules in the ``foo`` -package. This issues an error for calls to functions without -type annotations from functions with type annotations. +``--disallow-untyped-defs`` flag for all modules in the ``foo`` +package. This issues an error for function definitions without +type annotations in that subdirectory only. .. note:: diff --git a/mypy/checker.py b/mypy/checker.py index 91783f8e3e069..9cde2c54cbf66 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -606,7 +606,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None: item) show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub - if 'unannotated' in self.options.disallow_any and show_untyped: + if self.options.disallow_untyped_defs and show_untyped: # Check for functions with unspecified/not fully specified types. def is_implicit_any(t: Type) -> bool: return isinstance(t, AnyType) and t.implicit diff --git a/mypy/main.py b/mypy/main.py index 9e4eb2a14c2fd..eb28b7e3bdb44 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -98,7 +98,6 @@ def type_check_only(sources: List[BuildSource], bin_dir: str, options: Options) disallow_any_options = ['unimported', 'unannotated'] -disallow_any_strict = ['unannotated'] def disallow_any_argument_type(raw_options: str) -> List[str]: @@ -203,8 +202,6 @@ def process_options(args: List[str], strict_flag_names = [] # type: List[str] strict_flag_assignments = [] # type: List[Tuple[str, bool]] - strict_flag_names.append('--disallow-any={}'.format(','.join(disallow_any_strict))) - def add_invertible_flag(flag: str, *, inverse: str = None, @@ -254,6 +251,9 @@ def add_invertible_flag(flag: str, add_invertible_flag('--disallow-untyped-calls', default=False, strict_flag=True, help="disallow calling functions without type annotations" " from functions with type annotations") + add_invertible_flag('--disallow-untyped-defs', default=False, strict_flag=True, + help="disallow defining functions without type annotations" + " or with incomplete type annotations") add_invertible_flag('--check-untyped-defs', default=False, strict_flag=True, help="type check the interior of functions without type annotations") add_invertible_flag('--disallow-subclassing-any', default=False, strict_flag=True, @@ -348,9 +348,6 @@ def add_invertible_flag(flag: str, parser.add_argument('--no-fast-parser', action='store_true', dest='special-opts:no_fast_parser', help=argparse.SUPPRESS) - add_invertible_flag('--disallow-untyped-defs', default=False, strict_flag=True, - dest='special-opts:disallow_untyped_defs', - help=argparse.SUPPRESS) report_group = parser.add_argument_group( title='report generation', @@ -392,8 +389,6 @@ def add_invertible_flag(flag: str, if getattr(dummy, 'special-opts:strict'): for dest, value in strict_flag_assignments: setattr(options, dest, value) - options.disallow_any.extend(o for o in disallow_any_strict - if o not in options.disallow_any) # Parse command line for real, using a split namespace. special_opts = argparse.Namespace() @@ -431,11 +426,9 @@ def add_invertible_flag(flag: str, if special_opts.no_fast_parser: print("Warning: --no-fast-parser no longer has any effect. The fast parser " "is now mypy's default and only parser.") - if special_opts.disallow_untyped_defs: - print("Warning: --disallow-untyped-defs has been deprecated. " - "Please use --disallow-any=unannotated.") - if 'unannotated' not in options.disallow_any: - options.disallow_any.append('unannotated') + + if 'unannotated' in options.disallow_any: + options.disallow_untyped_defs = True # Check for invalid argument combinations. if require_targets: @@ -619,11 +612,9 @@ def get_init_file(dir: str) -> Optional[str]: 'mypy_path': lambda s: [p.strip() for p in re.split('[,:]', s)], 'junit_xml': str, 'disallow_any': disallow_any_argument_type, - - # These are for backwards compatibility + # These two are for backwards compatibility 'silent_imports': bool, 'almost_silent': bool, - 'disallow_untyped_defs': bool, } SHARED_CONFIG_FILES = ('setup.cfg',) @@ -735,20 +726,8 @@ def parse_section(prefix: str, template: Options, except ValueError as err: print("%s: %s: %s" % (prefix, key, err), file=sys.stderr) continue - if key == 'disallow_untyped_defs': - print("%s: disallow_untyped_defs has been deprecated. " - "Please use disallow_any=unannotated." % prefix, v) - if v: - disallow_any_opts = results['disallow_any'] if 'disallow_any' in results else None - if (disallow_any_opts - and isinstance(disallow_any_opts, List) - and 'unannotated' not in disallow_any_opts): - disallow_any_opts.append('unannotated') - else: - results['disallow_any'] = ['unannotated'] - else: - results['disallow_any'] = [] - + if key == 'disallow_any': + results['disallow_untyped_defs'] = v and 'unannotated' in v if key == 'silent_imports': print("%s: silent_imports has been replaced by " "ignore_missing_imports=True; follow_imports=skip" % prefix, file=sys.stderr) diff --git a/mypy/options.py b/mypy/options.py index 8f80bace9d6c1..69f99cce9501d 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -21,6 +21,7 @@ class Options: "follow_imports", "disallow_any", "disallow_untyped_calls", + "disallow_untyped_defs", "check_untyped_defs", "debug_cache", "strict_optional_whitelist", @@ -50,6 +51,9 @@ def __init__(self) -> None: # Disallow calling untyped functions from typed ones self.disallow_untyped_calls = False + # Disallow defining untyped (or incompletely typed) functions + self.disallow_untyped_defs = False + # Type check unannotated functions self.check_untyped_defs = False diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 191e65c1d0ec3..6ee0247c9bf48 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -1,44 +1,50 @@ [case testUnannotatedFunction] -# flags: --disallow-any=unannotated +# flags: --disallow-untyped-defs def f(x): pass [out] main:2: error: Function is missing a type annotation [case testUnannotatedArgument] -# flags: --disallow-any=unannotated +# flags: --disallow-untyped-defs def f(x) -> int: pass [out] main:2: error: Function is missing a type annotation for one or more arguments [case testUnannotatedArgumentWithFastParser] -# flags: --disallow-any=unannotated +# flags: --disallow-untyped-defs def f(x) -> int: pass [out] main:2: error: Function is missing a type annotation for one or more arguments [case testNoArgumentFunction] -# flags: --disallow-any=unannotated +# flags: --disallow-untyped-defs def f() -> int: pass [out] [case testUnannotatedReturn] -# flags: --disallow-any=unannotated +# flags: --disallow-untyped-defs def f(x: int): pass [out] main:2: error: Function is missing a return type annotation [case testUnannotatedReturnWithFastParser] -# flags: --disallow-any=unannotated +# flags: --disallow-untyped-defs def f(x: int): pass [out] main:2: error: Function is missing a return type annotation [case testLambda] -# flags: --disallow-any=unannotated +# flags: --disallow-untyped-defs lambda x: x [out] [case testUntypedDef] +# flags: --disallow-untyped-defs +def f(): + 1 + "str" +[out] +main:2: error: Function is missing a type annotation +[case testUntypedDefDisallowUnannotated] # flags: --disallow-any=unannotated def f(): 1 + "str" diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index bc976847010b8..d28cb1acf512c 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -2700,7 +2700,7 @@ a = A() [builtins fixtures/property.pyi] [case testSerializeAbstractPropertyDisallowUntypedIncremental] -# flags: --disallow-any=unimported +# flags: --disallow-untyped-defs from abc import abstractmethod import typing class A: diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 78b9e3f8a4985..8f0e2ff54be07 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -151,6 +151,35 @@ def f(): # cmd: mypy x.py y.py z.py [file mypy.ini] [[mypy] +disallow_untyped_defs = True +[[mypy-y*] +disallow_untyped_defs = False +[[mypy-z*] +disallow_untyped_calls = True +[file x.py] +def f(a): + pass +def g(a: int) -> int: + return f(a) +[file y.py] +def f(a): + pass +def g(a: int) -> int: + return f(a) +[file z.py] +def f(a): + pass +def g(a: int) -> int: + return f(a) +[out] +z.py:1: error: Function is missing a type annotation +z.py:4: error: Call to untyped function "f" in typed context +x.py:1: error: Function is missing a type annotation + +[case testPerFileConfigSectionDisallowUnannotated] +# cmd: mypy x.py y.py z.py +[file mypy.ini] +[[mypy] disallow_any = unannotated [[mypy-y*] disallow_any = @@ -181,7 +210,7 @@ x.py:1: error: Function is missing a type annotation [file mypy.ini] [[mypy] [[mypy-*x*] -disallow_any = unannotated +disallow_untyped_defs = True [[mypy-*y*] disallow_untyped_calls = True [file xx.py] @@ -209,7 +238,7 @@ xx.py:1: error: Function is missing a type annotation [file mypy.ini] [[mypy] [[mypy-x*,z*] -disallow_any = unannotated +disallow_untyped_defs = True [file x.py] def f(a): pass [file y.py] From 921040b98299f0ba47a914705825979bc28c112b Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Fri, 9 Jun 2017 15:50:26 -0700 Subject: [PATCH 3/4] Add tests for interaction of unnanotated and --disallow-untyped-defs --- test-data/unit/cmdline.test | 61 +++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 8f0e2ff54be07..cfc50f819a36c 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -176,33 +176,74 @@ z.py:1: error: Function is missing a type annotation z.py:4: error: Call to untyped function "f" in typed context x.py:1: error: Function is missing a type annotation -[case testPerFileConfigSectionDisallowUnannotated] -# cmd: mypy x.py y.py z.py +[case testPerFileConfigSectionUntypedWithDisallowUnannotated] +# cmd: mypy w.py x.py y.py z.py [file mypy.ini] [[mypy] disallow_any = unannotated [[mypy-y*] disallow_any = [[mypy-z*] -disallow_untyped_calls = True +disallow_untyped_defs = True +[[mypy-w*] +disallow_untyped_defs = False +[file x.py] +def f(a): + pass +[file y.py] +def f(a): + pass +[file z.py] +def f(a): + pass +[file w.py] +def f(a): + pass +[out] +z.py:1: error: Function is missing a type annotation +x.py:1: error: Function is missing a type annotation + +[case testPerFileConfigSectionDisallowUnannotatedWithUntyped] +# cmd: mypy x.py y.py z.py +[file mypy.ini] +[[mypy] +disallow_untyped_defs = True +[[mypy-y*] +disallow_any = +[[mypy-z*] +disallow_any = unannotated +[file x.py] +def f(a): + pass +[file y.py] +def f(a): + pass +[file z.py] +def f(a): + pass +[out] +z.py:1: error: Function is missing a type annotation +x.py:1: error: Function is missing a type annotation + +[case testPerFileConfigSectionDisallowUnannotatedNoOverride] +# cmd: mypy x.py y.py z.py +[file mypy.ini] +[[mypy] +[[mypy-x*] +disallow_untyped_defs = True +[[mypy-z*] +disallow_any = unannotated [file x.py] def f(a): pass -def g(a: int) -> int: - return f(a) [file y.py] def f(a): pass -def g(a: int) -> int: - return f(a) [file z.py] def f(a): pass -def g(a: int) -> int: - return f(a) [out] z.py:1: error: Function is missing a type annotation -z.py:4: error: Call to untyped function "f" in typed context x.py:1: error: Function is missing a type annotation [case testPerFileConfigSectionMultipleMatches] From 7be7e49b1e75365b6f67f9b8b708673165ff324d Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Fri, 9 Jun 2017 16:41:41 -0700 Subject: [PATCH 4/4] Add Documentation --- docs/source/command_line.rst | 16 ++++++++++++++++ docs/source/config_file.rst | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 0ea5981c31d18..ad7555bb2759d 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -274,6 +274,22 @@ Here are some more useful flags: re-check your code without ``--strict-optional`` to ensure new type errors are not introduced. +.. _disallow-any: + +- ``--disallow-any`` disallows various types of ``Any`` in a module. + The option takes a comma-separated list of the following values: + ``unimported``, ``unannotated``. + + ``unimported`` disallows usage of types that come from unfollowed imports + (such types become aliases for ``Any``). Unfollowed imports occur either + when the imported module does not exist or when ``--follow-imports=skip`` + is set. + + ``unannotated`` disallows function definitions that are not fully + typed (i.e. that are missing an explicit type annotation for any + of the parameters or the return type). ``unannotated`` option is + interchangeable with ``--disallow-untyped-defs``. + - ``--disallow-untyped-defs`` reports an error whenever it encounters a function definition without type annotations. diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 6fe139b1bb8c8..07db822df8a1f 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -147,6 +147,12 @@ overridden by the pattern sections matching the module name. - ``almost_silent`` (Boolean, deprecated) equivalent to ``follow_imports=skip``. +- ``disallow_any`` (Comma-separated list, default empty) is an option to + disallow various types of ``Any`` in a module. The flag takes a + comma-separated list of the following arguments: ``unimported``, + ``unannotated``. For explanations see the discussion for the + :ref:`--disallow-any ` option. + - ``disallow_untyped_calls`` (Boolean, default False) disallows calling functions without type annotations from functions with type annotations.