Skip to content

Commit b7976e9

Browse files
authored
Support __new__ in fine grained mode (python#4763)
This is a straightforward PR that essentially adds same dependencies on `__new__` as we have on `__init__` for a class as a callable. Just in case I add few dedicated tests.
1 parent 8aa4a5c commit b7976e9

File tree

8 files changed

+220
-4
lines changed

8 files changed

+220
-4
lines changed

mypy/server/deps.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ def process_type_info(self, info: TypeInfo) -> None:
247247
target=make_trigger(info.fullname() + '.' + name))
248248
self.add_dependency(make_trigger(base_info.fullname() + '.__init__'),
249249
target=make_trigger(info.fullname() + '.__init__'))
250+
self.add_dependency(make_trigger(base_info.fullname() + '.__new__'),
251+
target=make_trigger(info.fullname() + '.__new__'))
250252

251253
def visit_import(self, o: Import) -> None:
252254
for id, as_id in o.ids:
@@ -314,6 +316,7 @@ def visit_assignment_stmt(self, o: AssignmentStmt) -> None:
314316
if isinstance(typ, FunctionLike) and typ.is_type_obj():
315317
class_name = typ.type_object().fullname()
316318
self.add_dependency(make_trigger(class_name + '.__init__'))
319+
self.add_dependency(make_trigger(class_name + '.__new__'))
317320
if isinstance(rvalue, IndexExpr) and isinstance(rvalue.analyzed, TypeAliasExpr):
318321
self.add_type_dependencies(rvalue.analyzed.type)
319322
else:
@@ -438,6 +441,7 @@ def process_global_ref_expr(self, o: RefExpr) -> None:
438441
if isinstance(typ, FunctionLike) and typ.is_type_obj():
439442
class_name = typ.type_object().fullname()
440443
self.add_dependency(make_trigger(class_name + '.__init__'))
444+
self.add_dependency(make_trigger(class_name + '.__new__'))
441445

442446
def visit_name_expr(self, o: NameExpr) -> None:
443447
if o.kind == LDEF:

test-data/unit/deps-classes.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def f(a: Any) -> None:
1818
class A: pass
1919
[out]
2020
<m.N.__init__> -> m.f
21+
<m.N.__new__> -> m.f
2122
<m.N.a> -> m.f
2223
<m.N> -> m.f
2324
<a.A> -> <m.N.a>, <m.N>, m
@@ -35,6 +36,7 @@ class A: pass
3536
class B: pass
3637
[out]
3738
<m.N.__init__> -> m.f
39+
<m.N.__new__> -> m.f
3840
<m.N.a> -> m.f
3941
<m.N> -> m.f
4042
<a.A> -> <m.N.a>, <m.N>, m
@@ -48,8 +50,10 @@ M = NamedTuple('M', [('z', 'N')])
4850
y = M(x)
4951
[out]
5052
<m.M.__init__> -> m
53+
<m.M.__new__> -> m
5154
<m.M> -> <m.y>, m
5255
<m.N.__init__> -> m
56+
<m.N.__new__> -> m
5357
<m.N> -> <m.M.z>, <m.M>, <m.x>, <m.y>, m
5458
<m.x> -> m
5559
<m.y> -> m
@@ -67,6 +71,7 @@ def f(a: Any) -> None:
6771
class A: pass
6872
[out]
6973
<m.N.__init__> -> m.f
74+
<m.N.__new__> -> m.f
7075
<m.N.a> -> m.f
7176
<m.N> -> m.N, m.f
7277
<a.A> -> <m.N.a>, <m.N>, m, m.N
@@ -111,6 +116,7 @@ class D:
111116
[out]
112117
-- TODO: Is it okay to have targets like m.S1@4.__init__?
113118
<m.C.__init__> -> <m.S1@4.__init__>, <m.S2@8.__init__>
119+
<m.C.__new__> -> <m.S1@4.__new__>, <m.S2@8.__new__>
114120
<m.C> -> m.C, m.D.g, m.f
115121
<m.D.g> -> m.D.g
116122
<m.D> -> m.D
@@ -127,6 +133,7 @@ class D(C):
127133
super().foo()
128134
[out]
129135
<m.C.__init__> -> <m.D.__init__>, m.D.__init__
136+
<m.C.__new__> -> <m.D.__new__>
130137
<m.C.foo> -> <m.D.foo>
131138
<m.C> -> m, m.C, m.D
132139
<m.D.__init__> -> m.D.__init__
@@ -144,8 +151,10 @@ def foo() -> None:
144151
D(6)
145152
[out]
146153
<m.C.__init__> -> <m.D.__init__>
154+
<m.C.__new__> -> <m.D.__new__>
147155
<m.C> -> m, m.C, m.D
148156
<m.D.__init__> -> m.foo
157+
<m.D.__new__> -> m.foo
149158
<m.D> -> m.D, m.foo
150159

151160
[case testClassBasedEnum]
@@ -165,7 +174,9 @@ class B: pass
165174
<m.A.X> -> m.g
166175
-- The __init__ is superfluous but benign
167176
<m.A.__init__> -> m.g
177+
<m.A.__new__> -> m.g
168178
<m.A> -> <m.f>, m.A, m.f, m.g
169179
<m.B.__init__> -> m
180+
<m.B.__new__> -> m
170181
-- The <m.A.X> dependecy target is superfluous but benign
171182
<m.B> -> <m.A.X>, m

test-data/unit/deps-expressions.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def g() -> None:
5454
[out]
5555
<m.A.__init__> -> m.g
5656
<m.A.__iter__> -> m.g
57+
<m.A.__new__> -> m.g
5758
<m.A> -> m.A, m.g
5859
<m.f1> -> m.g
5960
<m.f2> -> m.g
@@ -86,6 +87,7 @@ def g() -> None:
8687
[out]
8788
<m.A.__init__> -> m.g
8889
<m.A.__iter__> -> m.g
90+
<m.A.__new__> -> m.g
8991
<m.A> -> m.A, m.g
9092
<m.f1> -> m.g
9193
<m.f2> -> m.g
@@ -136,6 +138,7 @@ def g() -> None:
136138
[out]
137139
<m.A.__init__> -> m.g
138140
<m.A.__iter__> -> m.g
141+
<m.A.__new__> -> m.g
139142
<m.A> -> m.A, m.g
140143

141144
[case testCast]
@@ -165,6 +168,7 @@ def g() -> None:
165168
x = A[B, C](f())
166169
[out]
167170
<m.A.__init__> -> m.g
171+
<m.A.__new__> -> m.g
168172
<m.A> -> m.A, m.g
169173
<m.B> -> m.B, m.g
170174
<m.C> -> m.C, m.g
@@ -271,9 +275,11 @@ def f() -> int:
271275
[out]
272276
<m.A.__init__> -> m.f
273277
<m.A.__lt__> -> m.f
278+
<m.A.__new__> -> m.f
274279
<m.A> -> m.A, m.f
275280
<m.B.__gt__> -> m.f
276281
<m.B.__init__> -> m.f
282+
<m.B.__new__> -> m.f
277283
<m.B> -> <m.A.__lt__>, m.A.__lt__, m.B, m.f
278284

279285
[case testIsOp-skip]
@@ -286,8 +292,10 @@ def f() -> bool:
286292
[out]
287293
-- fails because of https://github.com/python/mypy/issues/4055
288294
<m.A.__init__> -> m.f
295+
<m.A.__new__> -> m.f
289296
<m.A> -> m.A, m.f
290297
<m.B.__init__> -> m.f
298+
<m.B.__new__> -> m.f
291299
<m.B> -> m.B, m.f
292300

293301
[case testInOp]
@@ -300,8 +308,10 @@ def f() -> int:
300308
[out]
301309
<m.A.__contains__> -> m.f
302310
<m.A.__init__> -> m.f
311+
<m.A.__new__> -> m.f
303312
<m.A> -> m.A, m.f
304313
<m.B.__init__> -> m.f
314+
<m.B.__new__> -> m.f
305315
<m.B> -> <m.A.__contains__>, m.A.__contains__, m.B, m.f
306316

307317
[case testComparisonExprWithMultipleOperands]
@@ -316,13 +326,16 @@ def f() -> int:
316326
[out]
317327
<m.A.__init__> -> m.f
318328
<m.A.__lt__> -> m.f
329+
<m.A.__new__> -> m.f
319330
<m.A> -> m.A, m.f
320331
<m.B.__gt__> -> m.f
321332
<m.B.__init__> -> m.f
322333
<m.B.__le__> -> m.f
334+
<m.B.__new__> -> m.f
323335
<m.B> -> <m.A.__lt__>, <m.C.__ge__>, m.A.__lt__, m.B, m.C.__ge__, m.f
324336
<m.C.__ge__> -> m.f
325337
<m.C.__init__> -> m.f
338+
<m.C.__new__> -> m.f
326339
<m.C> -> m.C, m.f
327340

328341
[case testOperatorWithTupleOperand]

test-data/unit/deps-generics.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ def f() -> None:
6464
a = A(B())
6565
[out]
6666
<m.A.__init__> -> m.f
67+
<m.A.__new__> -> m.f
6768
<m.A.x> -> m.A.__init__
6869
<m.A> -> m.A, m.f
6970
<m.B.__init__> -> m.f
71+
<m.B.__new__> -> m.f
7072
<m.B> -> m.B, m.f
7173
<m.T> -> <m.A.__init__>, <m.A.x>, m.A, m.A.__init__
7274

@@ -92,6 +94,7 @@ class B(A[C]): pass
9294
class C: pass
9395
[out]
9496
<m.A.__init__> -> <m.B.__init__>
97+
<m.A.__new__> -> <m.B.__new__>
9598
<m.A> -> m.A, m.B
9699
<m.B> -> m.B
97100
<m.C> -> m.B, m.C
@@ -106,6 +109,7 @@ class A(Generic[T]): pass
106109
class B(A[T]): pass
107110
[out]
108111
<m.A.__init__> -> <m.B.__init__>
112+
<m.A.__new__> -> <m.B.__new__>
109113
<m.A> -> m.A, m.B
110114
<m.B> -> m.B
111115
<m.T> -> m.A, m.B

test-data/unit/deps-statements.test

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,12 @@ def g() -> None:
173173
f3()
174174
[builtins fixtures/exception.pyi]
175175
[out]
176-
-- The dependency on the ctor is basically spurious but not a problem
176+
-- The dependencies on the ctor are basically spurious but not a problem
177177
<m.A.__init__> -> m.g
178+
<m.A.__new__> -> m.g
178179
<m.A> -> m.A, m.g
179180
<m.B.__init__> -> m.g
181+
<m.B.__new__> -> m.g
180182
<m.B.f> -> m.g
181183
<m.B> -> m.B, m.g
182184
<m.f1> -> m.g
@@ -198,10 +200,12 @@ def g() -> None:
198200
f2()
199201
[builtins fixtures/exception.pyi]
200202
[out]
201-
-- The dependency on the ctor is basically spurious but not a problem
203+
-- The dependencies on the ctor are basically spurious but not a problem
202204
<m.A.__init__> -> m.g
205+
<m.A.__new__> -> m.g
203206
<m.A> -> m.A, m.g
204207
<m.B.__init__> -> m.g
208+
<m.B.__new__> -> m.g
205209
<m.B> -> m.B, m.g
206210
<m.f1> -> m.g
207211
<m.f2> -> m.g
@@ -496,6 +500,7 @@ def f() -> Iterator[int]:
496500
[out]
497501
<m.A.__init__> -> m.f
498502
<m.A.__iter__> -> m.f
503+
<m.A.__new__> -> m.f
499504
<m.A> -> m.A, m.f
500505

501506
[case testFunctionDecorator]
@@ -577,6 +582,7 @@ def g() -> None: pass
577582
[builtins fixtures/isinstancelist.pyi]
578583
[out]
579584
<m.A.__init__> -> <m.B.__init__>
585+
<m.A.__new__> -> <m.B.__new__>
580586
<m.A> -> <m.f>, m, m.A, m.B, m.f
581587
<m.B> -> <m.f>, m.B, m.f
582588
<m.f> -> m
@@ -602,6 +608,7 @@ class C:
602608
[builtins fixtures/isinstancelist.pyi]
603609
[out]
604610
<m.A.__init__> -> <m.B.__init__>
611+
<m.A.__new__> -> <m.B.__new__>
605612
<m.A> -> <m.C.f>, m, m.A, m.B, m.C.f
606613
<m.B> -> <m.C.f>, m.B, m.C.f
607614
<m.C.f> -> m
@@ -670,5 +677,6 @@ class C:
670677
[out]
671678
<m.N> -> <m.f>, m, m.f
672679
<m.C.__init__> -> <m.N.__init__>
680+
<m.C.__new__> -> <m.N.__new__>
673681
<m.C.x> -> <m.N.x>
674682
<m.C> -> m, m.N

0 commit comments

Comments
 (0)