Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4c68d1b

Browse files
authored
Make --allow-redefinition mean --allow-redefinition-new (#21276)
Also now `--allow-redefinition` is the primary flag name for the previous `--allow-redefinition-new` flag, and the `--allow-redefinition-new` name is a (soft deprecated) alias. The original `--allow-redefinition` behavior is still available via `--allow-redefinition-old`. Also removed some now redundant `--local-partial-types` flags in tests.
1 parent 781f1e6 commit 4c68d1b

23 files changed

Lines changed: 209 additions & 217 deletions

docs/source/command_line.rst

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ of the above sections.
595595
This flag causes mypy to suppress errors caused by not being able to fully
596596
infer the types of global and class variables.
597597

598-
.. option:: --allow-redefinition-new
598+
.. option:: --allow-redefinition
599599

600600
By default, mypy won't allow a variable to be redefined with an
601601
unrelated type. This flag enables the redefinition of *unannotated*
@@ -613,7 +613,7 @@ of the above sections.
613613
# Type of "x" is "int | str" here.
614614
return x
615615
616-
Without the new flag, mypy only supports inferring optional types
616+
Without this flag, mypy only supports inferring optional types
617617
(``X | None``) from multiple assignments. With this option enabled,
618618
mypy can infer arbitrary union types.
619619

@@ -646,24 +646,21 @@ of the above sections.
646646
Note: We are planning to turn this flag on by default in a future mypy
647647
release.
648648

649-
.. option:: --allow-redefinition
649+
.. option:: --allow-redefinition-new
650650

651-
This is an alias to :option:`--allow-redefinition-old <mypy --allow-redefinition-old>`.
652-
In mypy v2.0 this will point to
653-
:option:`--allow-redefinition-new <mypy --allow-redefinition-new>`, and will
654-
eventually became the default.
651+
Deprecated alias for :option:`--allow-redefinition <mypy --allow-redefinition>`.
655652

656653
.. option:: --allow-redefinition-old
657654

658-
This is an older variant of
659-
:option:`--allow-redefinition-new <mypy --allow-redefinition-new>`.
655+
This is an older, more limited variant of
656+
:option:`--allow-redefinition <mypy --allow-redefinition>`.
660657
This flag enables redefinition of a variable with an
661658
arbitrary type *in some contexts*: only redefinitions within the
662659
same block and nesting depth as the original definition are allowed.
663660

664-
We have no plans to remove this flag, but we expect that
665-
:option:`--allow-redefinition-new <mypy --allow-redefinition-new>`
666-
will replace this flag for new use cases eventually.
661+
We have no plans to remove this flag, but
662+
:option:`--allow-redefinition <mypy --allow-redefinition>`
663+
is recommended for new use cases.
667664

668665
Example where this can be useful:
669666

docs/source/config_file.rst

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ section of the command line docs.
713713
Causes mypy to suppress errors caused by not being able to fully
714714
infer the types of global and class variables.
715715

716-
.. confval:: allow_redefinition_new
716+
.. confval:: allow_redefinition
717717

718718
:type: boolean
719719
:default: False
@@ -763,6 +763,13 @@ section of the command line docs.
763763
Note: We are planning to turn this flag on by default in a future mypy
764764
release.
765765

766+
.. confval:: allow_redefinition_new
767+
768+
:type: boolean
769+
:default: False
770+
771+
Deprecated alias for :confval:`allow_redefinition`.
772+
766773
.. confval:: allow_redefinition_old
767774

768775
:type: boolean
@@ -789,14 +796,6 @@ section of the command line docs.
789796
items = "100" # valid, items now has type str
790797
items = int(items) # valid, items now has type int
791798
792-
.. confval:: allow_redefinition
793-
794-
:type: boolean
795-
:default: False
796-
797-
An alias to :confval:`allow_redefinition_old`, in mypy v2.0 this will point to
798-
:confval:`allow_redefinition_new`, and will eventually became the default.
799-
800799
.. confval:: local_partial_types
801800

802801
:type: boolean

mypy/binder.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ def __init__(self, options: Options) -> None:
199199

200200
# If True, initial assignment to a simple variable (e.g. "x", but not "x.y")
201201
# is added to the binder. This allows more precise narrowing and more
202-
# flexible inference of variable types (--allow-redefinition-new).
203-
self.bind_all = options.allow_redefinition_new
202+
# flexible inference of variable types (--allow-redefinition).
203+
self.bind_all = options.allow_redefinition
204204

205205
# This tracks any externally visible changes in binder to invalidate
206206
# expression caches when needed.
@@ -339,7 +339,7 @@ def update_from_options(self, frames: list[Frame]) -> bool:
339339
continue
340340

341341
# Remove exact duplicates to save pointless work later, this is
342-
# a micro-optimization for --allow-redefinition-new.
342+
# a micro-optimization for --allow-redefinition.
343343
seen_types = set()
344344
resulting_types = []
345345
for rv in resulting_values:

mypy/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3250,7 +3250,7 @@ def semantic_analysis_pass1(self) -> None:
32503250
# TODO: Do this while constructing the AST?
32513251
self.tree.names = SymbolTable()
32523252
if not self.tree.is_stub:
3253-
if not self.options.allow_redefinition_new:
3253+
if not self.options.allow_redefinition:
32543254
# Perform some low-key variable renaming when assignments can't
32553255
# widen inferred types
32563256
self.tree.accept(LimitedVariableRenameVisitor())

mypy/checker.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,7 +1495,7 @@ def check_func_def(
14951495
new_frame.types[key] = narrowed_type
14961496
self.binder.declarations[key] = old_binder.declarations[key]
14971497

1498-
if self.options.allow_redefinition_new and not self.is_stub:
1498+
if self.options.allow_redefinition and not self.is_stub:
14991499
# Add formal argument types to the binder.
15001500
for arg in defn.arguments:
15011501
# TODO: Add these directly using a fast path (possibly "put")
@@ -3439,7 +3439,7 @@ def check_assignment(
34393439
# unpleasant, and a generalization of this would
34403440
# be an improvement!
34413441
if (
3442-
not self.options.allow_redefinition_new
3442+
not self.options.allow_redefinition
34433443
and is_literal_none(rvalue)
34443444
and isinstance(lvalue, NameExpr)
34453445
and lvalue.kind == LDEF
@@ -3499,7 +3499,7 @@ def check_assignment(
34993499
):
35003500
lvalue.node.type = remove_instance_last_known_values(lvalue_type)
35013501
elif (
3502-
self.options.allow_redefinition_new
3502+
self.options.allow_redefinition
35033503
and lvalue_type is not None
35043504
and not isinstance(lvalue_type, PartialType)
35053505
# Note that `inferred is not None` is not a reliable check here, because
@@ -4482,7 +4482,7 @@ def check_lvalue(
44824482
# When revisiting the initial assignment (for example in a loop),
44834483
# treat is as regular if redefinitions are allowed.
44844484
skip_definition = (
4485-
self.options.allow_redefinition_new
4485+
self.options.allow_redefinition
44864486
and isinstance(lvalue, NameExpr)
44874487
and isinstance(lvalue.node, Var)
44884488
and lvalue.node.is_inferred
@@ -4513,7 +4513,7 @@ def check_lvalue(
45134513
elif isinstance(lvalue, NameExpr):
45144514
lvalue_type = self.expr_checker.analyze_ref_expr(lvalue, lvalue=True)
45154515
if (
4516-
self.options.allow_redefinition_new
4516+
self.options.allow_redefinition
45174517
and isinstance(lvalue.node, Var)
45184518
# We allow redefinition for function arguments inside function body.
45194519
# Although we normally do this for variables without annotation, users
@@ -4601,15 +4601,15 @@ def infer_variable_type(
46014601
init_type = strip_type(init_type)
46024602

46034603
self.set_inferred_type(name, lvalue, init_type)
4604-
if self.options.allow_redefinition_new:
4604+
if self.options.allow_redefinition:
46054605
self.binder.assign_type(lvalue, init_type, init_type)
46064606

46074607
def infer_partial_type(self, name: Var, lvalue: Lvalue, init_type: Type) -> bool:
46084608
init_type = get_proper_type(init_type)
46094609
if isinstance(init_type, NoneType) and (
4610-
isinstance(lvalue, MemberExpr) or not self.options.allow_redefinition_new
4610+
isinstance(lvalue, MemberExpr) or not self.options.allow_redefinition
46114611
):
4612-
# When using --allow-redefinition-new, None types aren't special
4612+
# When using --allow-redefinition, None types aren't special
46134613
# when inferring simple variable types.
46144614
partial_type = PartialType(None, name)
46154615
elif isinstance(init_type, Instance):
@@ -4857,7 +4857,7 @@ def check_simple_assignment(
48574857
get_proper_type(lvalue_type), AnyType
48584858
)
48594859

4860-
# If redefinitions are allowed (i.e. we have --allow-redefinition-new
4860+
# If redefinitions are allowed (i.e. we have --allow-redefinition
48614861
# and a variable without annotation) or if a variable has union type we
48624862
# try inferring r.h.s. twice with a fallback type context. The only exception
48634863
# is TypedDicts, they are often useless without context.
@@ -5047,8 +5047,8 @@ def replace_partial_type(
50475047
# Updating a partial type should invalidate expression caches.
50485048
self.binder.version += 1
50495049
del partial_types[var]
5050-
if self.options.allow_redefinition_new:
5051-
# When using --allow-redefinition-new, binder tracks all types of
5050+
if self.options.allow_redefinition:
5051+
# When using --allow-redefinition, binder tracks all types of
50525052
# simple variables.
50535053
n = NameExpr(var.name)
50545054
n.node = var
@@ -5463,10 +5463,10 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None:
54635463
if isinstance(var.node, Var):
54645464
new_type = DeletedType(source=source)
54655465
var.node.type = new_type
5466-
if self.options.allow_redefinition_new:
5466+
if self.options.allow_redefinition:
54675467
# TODO: Should we use put() here?
54685468
self.binder.assign_type(var, new_type, new_type)
5469-
if not self.options.allow_redefinition_new:
5469+
if not self.options.allow_redefinition:
54705470
self.binder.cleanse(var)
54715471
if s.else_body:
54725472
self.accept(s.else_body)
@@ -8373,7 +8373,7 @@ def visit_nonlocal_decl(self, o: NonlocalDecl, /) -> None:
83738373
return None
83748374

83758375
def visit_global_decl(self, o: GlobalDecl, /) -> None:
8376-
if self.options.allow_redefinition_new:
8376+
if self.options.allow_redefinition:
83778377
# Add names to binder, since their types could be widened
83788378
for name in o.names:
83798379
sym = self.globals.get(name)
@@ -9199,7 +9199,7 @@ def is_valid_inferred_type(
91999199
# type could either be NoneType or an Optional type, depending on
92009200
# the context. This resolution happens in leave_partial_types when
92019201
# we pop a partial types scope.
9202-
return is_lvalue_final or (not is_lvalue_member and options.allow_redefinition_new)
9202+
return is_lvalue_final or (not is_lvalue_member and options.allow_redefinition)
92039203
elif isinstance(proper_type, UninhabitedType):
92049204
return False
92059205
return not typ.accept(InvalidInferredTypes())

mypy/config_parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -507,9 +507,9 @@ def parse_section(
507507
# Here we use `key` for original config section key, and `options_key` for
508508
# the corresponding Options attribute.
509509
options_key = key
510-
# Match aliasing for command line flag.
511-
if key.endswith("allow_redefinition"):
512-
options_key += "_old"
510+
# Match aliasing for deprecated config option name.
511+
if options_key == "allow_redefinition_new":
512+
options_key = "allow_redefinition"
513513
if key in config_types:
514514
ct = config_types[key]
515515
elif key in invalid_options:

mypy/main.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,16 @@ def main(
103103
if options.cache_dir == os.devnull:
104104
fail("error: cache must be enabled in parallel mode", stderr, options)
105105

106-
if options.allow_redefinition_new and not options.local_partial_types:
106+
if options.allow_redefinition and not options.local_partial_types:
107107
fail(
108-
"error: --local-partial-types must be enabled if using --allow-redefinition-new",
108+
"error: --local-partial-types must be enabled if using --allow-redefinition",
109109
stderr,
110110
options,
111111
)
112112

113-
if options.allow_redefinition_new and options.allow_redefinition_old:
113+
if options.allow_redefinition and options.allow_redefinition_old:
114114
fail(
115-
"--allow-redefinition-old and --allow-redefinition-new should not be used together",
115+
"--allow-redefinition-old and --allow-redefinition should not be used together",
116116
stderr,
117117
options,
118118
)
@@ -888,9 +888,8 @@ def add_invertible_flag(
888888
"--allow-redefinition",
889889
default=False,
890890
strict_flag=False,
891-
help="Alias to --allow-redefinition-old; will point to --allow-redefinition-new in v2.0",
891+
help="Allow flexible variable redefinition with a new type",
892892
group=strictness_group,
893-
dest="allow_redefinition_old",
894893
)
895894

896895
add_invertible_flag(
@@ -905,8 +904,9 @@ def add_invertible_flag(
905904
"--allow-redefinition-new",
906905
default=False,
907906
strict_flag=False,
908-
help="Allow more flexible variable redefinition semantics",
907+
help="Deprecated alias for --allow-redefinition",
909908
group=strictness_group,
909+
dest="allow_redefinition",
910910
)
911911

912912
add_invertible_flag(

mypy/nativeparse.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# mypy: allow-redefinition-new, local-partial-types
21
"""Python parser that directly constructs a native AST (when compiled).
32
43
Use a Rust extension to generate a serialized AST, and deserialize the AST directly

mypy/options.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class BuildType:
2424
PER_MODULE_OPTIONS: Final = {
2525
# Please keep this list sorted
2626
"allow_redefinition_old",
27-
"allow_redefinition_new",
27+
"allow_redefinition",
2828
"allow_untyped_globals",
2929
"always_false",
3030
"always_true",
@@ -235,7 +235,7 @@ def __init__(self) -> None:
235235

236236
# Allow flexible variable redefinition with an arbitrary type, in different
237237
# blocks and at different nesting levels
238-
self.allow_redefinition_new = False
238+
self.allow_redefinition = False
239239

240240
# Prohibit equality, identity, and container checks for non-overlapping types.
241241
# This makes 1 == '1', 1 in ['1'], and 1 is '1' errors.

mypy/semanal.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -706,23 +706,21 @@ def refresh_partial(
706706

707707
def refresh_top_level(self, file_node: MypyFile) -> None:
708708
"""Reanalyze a stale module top-level in fine-grained incremental mode."""
709-
if self.options.allow_redefinition_new and not self.options.local_partial_types:
709+
if self.options.allow_redefinition and not self.options.local_partial_types:
710710
n = TempNode(AnyType(TypeOfAny.special_form))
711711
n.line = 1
712712
n.column = 0
713713
n.end_line = 1
714714
n.end_column = 0
715-
self.fail("--local-partial-types must be enabled if using --allow-redefinition-new", n)
716-
if self.options.allow_redefinition_new and self.options.allow_redefinition_old:
715+
self.fail("--local-partial-types must be enabled if using --allow-redefinition", n)
716+
if self.options.allow_redefinition and self.options.allow_redefinition_old:
717717
n = TempNode(AnyType(TypeOfAny.special_form))
718718
n.line = 1
719719
n.column = 0
720720
n.end_line = 1
721721
n.end_column = 0
722722
self.fail(
723-
"--allow-redefinition-old and --allow-redefinition-new"
724-
" should not be used together",
725-
n,
723+
"--allow-redefinition-old and --allow-redefinition should not be used together", n
726724
)
727725
self.recurse_into_functions = False
728726
self.add_implicit_module_attrs(file_node)
@@ -4493,9 +4491,9 @@ def analyze_name_lvalue(
44934491
else:
44944492
lvalue.fullname = lvalue.name
44954493
if self.is_func_scope():
4496-
if unmangle(name) == "_" and not self.options.allow_redefinition_new:
4494+
if unmangle(name) == "_" and not self.options.allow_redefinition:
44974495
# Special case for assignment to local named '_': always infer 'Any'.
4498-
# This isn't needed with --allow-redefinition-new, since arbitrary
4496+
# This isn't needed with --allow-redefinition, since arbitrary
44994497
# types can be assigned to '_' anyway.
45004498
typ = AnyType(TypeOfAny.special_form)
45014499
self.store_declared_types(lvalue, typ)

0 commit comments

Comments
 (0)