@@ -126,6 +126,29 @@ def __init__(self, prog: Optional[str]) -> None:
126
126
super ().__init__ (prog = prog , max_help_position = 28 )
127
127
128
128
129
+ # Define pairs of flag prefixes with inverse meaning.
130
+ flag_prefix_pairs = [
131
+ ('allow' , 'disallow' ),
132
+ ('show' , 'hide' ),
133
+ ]
134
+ flag_prefix_map = {} # type: Dict[str, str]
135
+ for a , b in flag_prefix_pairs :
136
+ flag_prefix_map [a ] = b
137
+ flag_prefix_map [b ] = a
138
+
139
+
140
+ def invert_flag_name (flag : str ) -> str :
141
+ split = flag [2 :].split ('-' , 1 )
142
+ if len (split ) == 2 :
143
+ prefix , rest = split
144
+ if prefix in flag_prefix_map :
145
+ return '--{}-{}' .format (flag_prefix_map [prefix ], rest )
146
+ elif prefix == 'no' :
147
+ return '--{}' .format (rest )
148
+
149
+ return '--no-{}' .format (flag [2 :])
150
+
151
+
129
152
def process_options (args : List [str ],
130
153
require_targets : bool = True
131
154
) -> Tuple [List [BuildSource ], Options ]:
@@ -135,6 +158,32 @@ def process_options(args: List[str],
135
158
fromfile_prefix_chars = '@' ,
136
159
formatter_class = AugmentedHelpFormatter )
137
160
161
+ strict_flag_names = [] # type: List[str]
162
+ strict_flag_assignments = [] # type: List[Tuple[str, bool]]
163
+
164
+ def add_invertible_flag (flag : str ,
165
+ * ,
166
+ inverse : str = None ,
167
+ default : bool ,
168
+ dest : str = None ,
169
+ help : str ,
170
+ strict_flag : bool = False
171
+ ) -> None :
172
+ if inverse is None :
173
+ inverse = invert_flag_name (flag )
174
+ arg = parser .add_argument (flag , # type: ignore # incorrect stub for add_argument
175
+ action = 'store_false' if default else 'store_true' ,
176
+ dest = dest ,
177
+ help = help + " (inverse: {})" .format (inverse ))
178
+ dest = arg .dest
179
+ arg = parser .add_argument (inverse , # type: ignore # incorrect stub for add_argument
180
+ action = 'store_true' if default else 'store_false' ,
181
+ dest = dest ,
182
+ help = argparse .SUPPRESS )
183
+ if strict_flag :
184
+ strict_flag_names .append (flag )
185
+ strict_flag_assignments .append ((dest , not default ))
186
+
138
187
# Unless otherwise specified, arguments will be parsed directly onto an
139
188
# Options object. Options that require further processing should have
140
189
# their `dest` prefixed with `special-opts:`, which will cause them to be
@@ -154,37 +203,36 @@ def process_options(args: List[str],
154
203
help = "silently ignore imports of missing modules" )
155
204
parser .add_argument ('--follow-imports' , choices = ['normal' , 'silent' , 'skip' , 'error' ],
156
205
default = 'normal' , help = "how to treat imports (default normal)" )
157
- parser . add_argument ('--disallow-untyped-calls' , action = 'store_true' ,
206
+ add_invertible_flag ('--disallow-untyped-calls' , default = False , strict_flag = True ,
158
207
help = "disallow calling functions without type annotations"
159
208
" from functions with type annotations" )
160
- parser . add_argument ('--disallow-untyped-defs' , action = 'store_true' ,
209
+ add_invertible_flag ('--disallow-untyped-defs' , default = False , strict_flag = True ,
161
210
help = "disallow defining functions without type annotations"
162
211
" or with incomplete type annotations" )
163
- parser . add_argument ('--check-untyped-defs' , action = 'store_true' ,
212
+ add_invertible_flag ('--check-untyped-defs' , default = False , strict_flag = True ,
164
213
help = "type check the interior of functions without type annotations" )
165
- parser . add_argument ('--disallow-subclassing-any' , action = 'store_true' ,
214
+ add_invertible_flag ('--disallow-subclassing-any' , default = False , strict_flag = True ,
166
215
help = "disallow subclassing values of type 'Any' when defining classes" )
167
- parser . add_argument ('--warn-incomplete-stub' , action = 'store_true' ,
216
+ add_invertible_flag ('--warn-incomplete-stub' , default = False ,
168
217
help = "warn if missing type annotation in typeshed, only relevant with"
169
218
" --check-untyped-defs enabled" )
170
- parser . add_argument ('--warn-redundant-casts' , action = 'store_true' ,
219
+ add_invertible_flag ('--warn-redundant-casts' , default = False , strict_flag = True ,
171
220
help = "warn about casting an expression to its inferred type" )
172
- parser . add_argument ('--warn-no-return' , action = 'store_true' ,
221
+ add_invertible_flag ('--warn-no-return' , default = False ,
173
222
help = "warn about functions that end without returning" )
174
- parser . add_argument ('--warn-unused-ignores' , action = 'store_true' ,
223
+ add_invertible_flag ('--warn-unused-ignores' , default = False , strict_flag = True ,
175
224
help = "warn about unneeded '# type: ignore' comments" )
176
- parser . add_argument ('--show-error-context' , action = 'store_false' ,
225
+ add_invertible_flag ('--show-error-context' , default = True ,
177
226
dest = 'hide_error_context' ,
178
227
help = 'Precede errors with "note:" messages explaining context' )
179
- parser . add_argument ('--fast-parser' , action = 'store_true' ,
180
- help = "enable fast parser (recommended except on Windows )" )
228
+ add_invertible_flag ('--fast-parser' , default = False ,
229
+ help = "enable fast parser (recommended)" )
181
230
parser .add_argument ('-i' , '--incremental' , action = 'store_true' ,
182
231
help = "enable experimental module cache" )
183
232
parser .add_argument ('--cache-dir' , action = 'store' , metavar = 'DIR' ,
184
233
help = "store module cache info in the given folder in incremental mode "
185
234
"(defaults to '{}')" .format (defaults .CACHE_DIR ))
186
- parser .add_argument ('--strict-optional' , action = 'store_true' ,
187
- dest = 'strict_optional' ,
235
+ add_invertible_flag ('--strict-optional' , default = False , strict_flag = True ,
188
236
help = "enable experimental strict Optional checks" )
189
237
parser .add_argument ('--strict-optional-whitelist' , metavar = 'GLOB' , nargs = '*' ,
190
238
help = "suppress strict Optional errors in all but the provided files "
@@ -207,15 +255,17 @@ def process_options(args: List[str],
207
255
parser .add_argument ('--config-file' ,
208
256
help = "Configuration file, must have a [mypy] section "
209
257
"(defaults to {})" .format (defaults .CONFIG_FILE ))
210
- parser .add_argument ('--show-column-numbers' , action = 'store_true' ,
211
- dest = 'show_column_numbers' ,
258
+ add_invertible_flag ('--show-column-numbers' , default = False ,
212
259
help = "Show column numbers in error messages" )
213
260
parser .add_argument ('--find-occurrences' , metavar = 'CLASS.MEMBER' ,
214
261
dest = 'special-opts:find_occurrences' ,
215
262
help = "print out all usages of a class member (experimental)" )
216
- parser .add_argument ('--strict-boolean' , action = 'store_true' ,
217
- dest = 'strict_boolean' ,
263
+ add_invertible_flag ('--strict-boolean' , default = False , strict_flag = True ,
218
264
help = 'enable strict boolean checks in conditions' )
265
+ strict_help = "Strict mode. Enables the following flags: {}" .format (
266
+ ", " .join (strict_flag_names ))
267
+ parser .add_argument ('--strict' , action = 'store_true' , dest = 'special-opts:strict' ,
268
+ help = strict_help )
219
269
# hidden options
220
270
# --shadow-file a.py tmp.py will typecheck tmp.py in place of a.py.
221
271
# Useful for tools to make transformations to a file to get more
@@ -229,9 +279,6 @@ def process_options(args: List[str],
229
279
parser .add_argument ('--debug-cache' , action = 'store_true' , help = argparse .SUPPRESS )
230
280
# --dump-graph will dump the contents of the graph of SCCs and exit.
231
281
parser .add_argument ('--dump-graph' , action = 'store_true' , help = argparse .SUPPRESS )
232
- parser .add_argument ('--hide-error-context' , action = 'store_true' ,
233
- dest = 'hide_error_context' ,
234
- help = argparse .SUPPRESS )
235
282
# deprecated options
236
283
parser .add_argument ('-f' , '--dirty-stubs' , action = 'store_true' ,
237
284
dest = 'special-opts:dirty_stubs' ,
@@ -270,7 +317,7 @@ def process_options(args: List[str],
270
317
help = "type-check given files or directories" )
271
318
272
319
# Parse arguments once into a dummy namespace so we can get the
273
- # filename for the config file.
320
+ # filename for the config file and know if the user requested all strict options .
274
321
dummy = argparse .Namespace ()
275
322
parser .parse_args (args , dummy )
276
323
config_file = defaults .CONFIG_FILE
@@ -284,6 +331,12 @@ def process_options(args: List[str],
284
331
if config_file and os .path .exists (config_file ):
285
332
parse_config_file (options , config_file )
286
333
334
+ # Set strict flags before parsing (if strict mode enabled), so other command
335
+ # line options can override.
336
+ if getattr (dummy , 'special-opts:strict' ):
337
+ for dest , value in strict_flag_assignments :
338
+ setattr (options , dest , value )
339
+
287
340
# Parse command line for real, using a split namespace.
288
341
special_opts = argparse .Namespace ()
289
342
parser .parse_args (args , SplitNamespace (options , special_opts , 'special-opts:' ))
0 commit comments