Skip to content

Commit 5f310f2

Browse files
committed
Test that illustrates sympy metaclass problem
1 parent 840a310 commit 5f310f2

File tree

1 file changed

+37
-4
lines changed

1 file changed

+37
-4
lines changed

test-data/unit/check-classes.test

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4351,7 +4351,7 @@ class C(B):
43514351
class X(type): pass
43524352
class Y(type): pass
43534353
class A(metaclass=X): pass
4354-
class B(A, metaclass=Y): pass # E: Inconsistent metaclass structure for "B"
4354+
class B(A, metaclass=Y): pass # E: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
43554355

43564356
[case testMetaclassNoTypeReveal]
43574357
class M:
@@ -5213,8 +5213,8 @@ class CD(six.with_metaclass(M)): pass # E: Multiple metaclass definitions
52135213
class M1(type): pass
52145214
class Q1(metaclass=M1): pass
52155215
@six.add_metaclass(M)
5216-
class CQA(Q1): pass # E: Inconsistent metaclass structure for "CQA"
5217-
class CQW(six.with_metaclass(M, Q1)): pass # E: Inconsistent metaclass structure for "CQW"
5216+
class CQA(Q1): pass # E: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
5217+
class CQW(six.with_metaclass(M, Q1)): pass # E: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
52185218
[builtins fixtures/tuple.pyi]
52195219

52205220
[case testSixMetaclassAny]
@@ -5319,7 +5319,7 @@ class C5(future.utils.with_metaclass(f())): pass # E: Dynamic metaclass not sup
53195319

53205320
class M1(type): pass
53215321
class Q1(metaclass=M1): pass
5322-
class CQW(future.utils.with_metaclass(M, Q1)): pass # E: Inconsistent metaclass structure for "CQW"
5322+
class CQW(future.utils.with_metaclass(M, Q1)): pass # E: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
53235323
[builtins fixtures/tuple.pyi]
53245324

53255325
[case testFutureMetaclassAny]
@@ -6663,6 +6663,39 @@ class MyMetaClass(type):
66636663
class MyClass(metaclass=MyMetaClass):
66646664
pass
66656665

6666+
6667+
[case testMetaclassPlaceholderNode]
6668+
from sympy.assumptions import ManagedProperties
6669+
from sympy.ops import AssocOp
6670+
reveal_type(AssocOp.x) # N: Revealed type is "sympy.basic.Basic"
6671+
reveal_type(AssocOp.y) # N: Revealed type is "builtins.int"
6672+
6673+
[file sympy/__init__.py]
6674+
6675+
[file sympy/assumptions.py]
6676+
from .basic import Basic
6677+
class ManagedProperties(type):
6678+
x: Basic
6679+
y: int
6680+
# The problem is with the next line,
6681+
# it creates the following order (classname, metaclass):
6682+
# 1. Basic NameExpr(ManagedProperties)
6683+
# 2. AssocOp None
6684+
# 3. ManagedProperties None
6685+
# 4. Basic NameExpr(ManagedProperties [sympy.assumptions.ManagedProperties])
6686+
# So, `AssocOp` will still have `metaclass_type` as `None`
6687+
# and all its `mro` types will have `declared_metaclass` as `None`.
6688+
from sympy.ops import AssocOp
6689+
6690+
[file sympy/basic.py]
6691+
from .assumptions import ManagedProperties
6692+
class Basic(metaclass=ManagedProperties): ...
6693+
6694+
[file sympy/ops.py]
6695+
from sympy.basic import Basic
6696+
class AssocOp(Basic): ...
6697+
6698+
66666699
[case testGenericOverride]
66676700
from typing import Generic, TypeVar, Any
66686701

0 commit comments

Comments
 (0)