Skip to content

Commit ca58524

Browse files
committed
tests/basics: Add skip detection for metaclass and enum tests.
Adds feature detection to skip tests when required features are not available (e.g. in minimal/standard build variants). - class_metaclass_init.py: Skip if MICROPY_PY_METACLASS_INIT disabled - class_metaclass_property.py: Skip if MICROPY_PY_METACLASS_PROPERTIES disabled - class_metaclass_prepare.py: Already had skip for __prepare__ - enum_auto.py: Add enum import check before __prepare__ check - enum_flag.py: Skip if enum or __prepare__ not available - enum_strenum.py: Skip if enum module not available - metaclass.py: Skip if MICROPY_PY_METACLASS_INIT disabled This fixes CI failures on build variants where these features are disabled by config. Signed-off-by: Andrew Leech <[email protected]>
1 parent cc4d559 commit ca58524

File tree

7 files changed

+188
-63
lines changed

7 files changed

+188
-63
lines changed

tests/basics/class_metaclass_init.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
# Test metaclass __init__ support (requires MICROPY_PY_METACLASS_INIT)
2+
3+
# Skip test if metaclass __init__ is not supported
4+
_init_test = []
5+
6+
class _TestMeta(type):
7+
def __init__(cls, name, bases, attrs):
8+
super().__init__(name, bases, attrs)
9+
_init_test.append(1)
10+
11+
class _Test(metaclass=_TestMeta):
12+
pass
13+
14+
if not _init_test:
15+
print("SKIP")
16+
raise SystemExit
17+
118
# Test 1: Basic metaclass __init__ call
219
init_called = []
320

tests/basics/class_metaclass_prepare.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
# Test metaclass __prepare__ method (PEP 3115)
22

3+
# Skip test if classmethod builtin is not available
4+
try:
5+
classmethod
6+
except NameError:
7+
print("SKIP")
8+
raise SystemExit
9+
310
# Skip test if __prepare__ is not supported
411
_prepare_test = []
5-
class _TestMeta(type):
6-
@classmethod
7-
def __prepare__(mcs, name, bases):
8-
_prepare_test.append(1)
9-
return {}
1012

11-
class _Test(metaclass=_TestMeta):
13+
try:
14+
class _TestMeta(type):
15+
@classmethod
16+
def __prepare__(mcs, name, bases):
17+
_prepare_test.append(1)
18+
return {}
19+
20+
class _Test(metaclass=_TestMeta):
21+
pass
22+
except:
1223
pass
1324

1425
if not _prepare_test:
@@ -22,7 +33,7 @@ class _Test(metaclass=_TestMeta):
2233
class Meta1(type):
2334
@classmethod
2435
def __prepare__(mcs, name, bases):
25-
prepare_log.append(f"__prepare__({name})")
36+
prepare_log.append("__prepare__(%s)" % (name,))
2637
return {}
2738

2839
class Test1(metaclass=Meta1):
@@ -37,7 +48,7 @@ class Test1(metaclass=Meta1):
3748
class Meta2(type):
3849
@classmethod
3950
def __prepare__(mcs, name, bases):
40-
print(f"mcs={mcs.__name__}, name={name}, bases={bases}")
51+
print("mcs=%s, name=%s, bases=%s" % (mcs.__name__, name, bases))
4152
return {}
4253

4354
class Base2:
@@ -58,7 +69,7 @@ def __prepare__(mcs, name, bases):
5869
class Test3(metaclass=Meta3):
5970
pass
6071

61-
print(f"Test3.injected = {Test3.injected}")
72+
print("Test3.injected = %s" % (Test3.injected))
6273
print("PASS" if Test3.injected == 42 else "FAIL")
6374

6475
# Test 4: __prepare__ can access namespace in __new__
@@ -82,7 +93,7 @@ def __new__(mcs, name, bases, namespace):
8293
class Test4(metaclass=Meta4):
8394
x = 1
8495

85-
print(f"Was prepared: {Test4._was_prepared}")
96+
print("Was prepared: %s" % (Test4._was_prepared))
8697
print("PASS" if Test4._was_prepared else "FAIL")
8798

8899
# Test 5: __prepare__ inheritance
@@ -91,7 +102,7 @@ class Test4(metaclass=Meta4):
91102
class BaseMeta(type):
92103
@classmethod
93104
def __prepare__(mcs, name, bases):
94-
print(f"BaseMeta.__prepare__({name})")
105+
print("BaseMeta.__prepare__(%s)" % (name))
95106
return {}
96107

97108
class DerivedMeta(BaseMeta):
@@ -109,7 +120,7 @@ class Meta6(type):
109120
class Test6(metaclass=Meta6):
110121
x = 1
111122

112-
print(f"Test6.x = {Test6.x}")
123+
print("Test6.x = %s" % (Test6.x))
113124
print("PASS")
114125

115126
print("\nAll __prepare__ tests completed!")

tests/basics/class_metaclass_property.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
# Test metaclass property/method support (requires MICROPY_PY_METACLASS_PROPERTIES)
2+
3+
# Skip test if property builtin is not available
4+
try:
5+
property
6+
except NameError:
7+
print("SKIP")
8+
raise SystemExit
9+
10+
# Skip test if metaclass property access is not supported
11+
_property_test = None
12+
13+
try:
14+
class _TestMeta(type):
15+
@property
16+
def test_prop(cls):
17+
return "works"
18+
19+
class _Test(metaclass=_TestMeta):
20+
pass
21+
22+
_property_test = _Test.test_prop
23+
except (AttributeError, TypeError):
24+
pass
25+
26+
if _property_test != "works":
27+
print("SKIP")
28+
raise SystemExit
29+
130
# Test 1: Metaclass property access
231
class Meta(type):
332
@property

tests/basics/enum_auto.py

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,48 @@
11
# Test enum.auto() support (requires MICROPY_PY_METACLASS_PREPARE)
22

3+
# Skip test if enum module is not available
4+
try:
5+
from enum import Enum, IntEnum, auto
6+
except ImportError:
7+
print("SKIP")
8+
raise SystemExit
9+
10+
# Skip test if classmethod builtin is not available
11+
try:
12+
classmethod
13+
except NameError:
14+
print("SKIP")
15+
raise SystemExit
16+
317
# Skip test if __prepare__ is not supported
418
_prepare_test = []
5-
class _TestMeta(type):
6-
@classmethod
7-
def __prepare__(mcs, name, bases):
8-
_prepare_test.append(1)
9-
return {}
1019

11-
class _Test(metaclass=_TestMeta):
20+
try:
21+
class _TestMeta(type):
22+
@classmethod
23+
def __prepare__(mcs, name, bases):
24+
_prepare_test.append(1)
25+
return {}
26+
27+
class _Test(metaclass=_TestMeta):
28+
pass
29+
except:
1230
pass
1331

1432
if not _prepare_test:
1533
print("SKIP")
1634
raise SystemExit
1735

18-
# Now run the actual tests
19-
from enum import Enum, IntEnum, auto
20-
2136
# Test 1: Basic auto() usage - sequential values starting from 1
2237
print("Test 1: Basic auto() usage")
2338
class Color(Enum):
2439
RED = auto()
2540
GREEN = auto()
2641
BLUE = auto()
2742

28-
print(f"RED.value = {Color.RED.value}")
29-
print(f"GREEN.value = {Color.GREEN.value}")
30-
print(f"BLUE.value = {Color.BLUE.value}")
43+
print("RED.value = %s" % (Color.RED.value))
44+
print("GREEN.value = %s" % (Color.GREEN.value))
45+
print("BLUE.value = %s" % (Color.BLUE.value))
3146
print("PASS" if (Color.RED.value == 1 and Color.GREEN.value == 2 and Color.BLUE.value == 3) else "FAIL")
3247

3348
# Test 2: Mixed auto() and explicit values
@@ -39,10 +54,10 @@ class Status(Enum):
3954
PAUSED = auto()
4055
STOPPED = auto()
4156

42-
print(f"PENDING.value = {Status.PENDING.value}")
43-
print(f"ACTIVE.value = {Status.ACTIVE.value}")
44-
print(f"PAUSED.value = {Status.PAUSED.value}")
45-
print(f"STOPPED.value = {Status.STOPPED.value}")
57+
print("PENDING.value = %s" % (Status.PENDING.value))
58+
print("ACTIVE.value = %s" % (Status.ACTIVE.value))
59+
print("PAUSED.value = %s" % (Status.PAUSED.value))
60+
print("STOPPED.value = %s" % (Status.STOPPED.value))
4661
# In MicroPython, auto() starts at max(explicit) + 1, then assigns in creation order
4762
# PENDING, PAUSED, STOPPED were created in that order, so they get 11, 12, 13
4863
print("PASS" if (Status.ACTIVE.value == 10 and
@@ -56,17 +71,17 @@ class Priority(IntEnum):
5671
MEDIUM = auto()
5772
HIGH = auto()
5873

59-
print(f"LOW.value = {Priority.LOW.value}")
60-
print(f"MEDIUM.value = {Priority.MEDIUM.value}")
61-
print(f"HIGH.value = {Priority.HIGH.value}")
74+
print("LOW.value = %s" % (Priority.LOW.value))
75+
print("MEDIUM.value = %s" % (Priority.MEDIUM.value))
76+
print("HIGH.value = %s" % (Priority.HIGH.value))
6277
print("PASS" if (Priority.LOW.value == 1 and Priority.MEDIUM.value == 2 and Priority.HIGH.value == 3) else "FAIL")
6378

6479
# Test 4: auto() with single member
6580
print("\nTest 4: auto() with single member")
6681
class Single(Enum):
6782
ONLY = auto()
6883

69-
print(f"ONLY.value = {Single.ONLY.value}")
84+
print("ONLY.value = %s" % (Single.ONLY.value))
7085
print("PASS" if Single.ONLY.value == 1 else "FAIL")
7186

7287
# Test 5: All auto() values
@@ -79,7 +94,7 @@ class AllAuto(Enum):
7994
E = auto()
8095

8196
values = [AllAuto.A.value, AllAuto.B.value, AllAuto.C.value, AllAuto.D.value, AllAuto.E.value]
82-
print(f"Values: {values}")
97+
print("Values: %s" % (values))
8398
print("PASS" if values == [1, 2, 3, 4, 5] else "FAIL")
8499

85100
# Test 6: auto() after explicit value 0
@@ -89,9 +104,9 @@ class StartZero(Enum):
89104
ONE = auto()
90105
TWO = auto()
91106

92-
print(f"ZERO.value = {StartZero.ZERO.value}")
93-
print(f"ONE.value = {StartZero.ONE.value}")
94-
print(f"TWO.value = {StartZero.TWO.value}")
107+
print("ZERO.value = %s" % (StartZero.ZERO.value))
108+
print("ONE.value = %s" % (StartZero.ONE.value))
109+
print("TWO.value = %s" % (StartZero.TWO.value))
95110
print("PASS" if (StartZero.ZERO.value == 0 and StartZero.ONE.value == 1 and StartZero.TWO.value == 2) else "FAIL")
96111

97112
# Test 7: auto() continues from highest explicit value
@@ -103,11 +118,11 @@ class Complex(Enum):
103118
D = 50
104119
E = auto()
105120

106-
print(f"A.value = {Complex.A.value}")
107-
print(f"B.value = {Complex.B.value}")
108-
print(f"C.value = {Complex.C.value}")
109-
print(f"D.value = {Complex.D.value}")
110-
print(f"E.value = {Complex.E.value}")
121+
print("A.value = %s" % (Complex.A.value))
122+
print("B.value = %s" % (Complex.B.value))
123+
print("C.value = %s" % (Complex.C.value))
124+
print("D.value = %s" % (Complex.D.value))
125+
print("E.value = %s" % (Complex.E.value))
111126
# In MicroPython: auto() starts at max(100, 50) + 1 = 101
112127
# A, C, E created in that order get 101, 102, 103
113128
print("PASS" if (Complex.B.value == 100 and Complex.D.value == 50 and
@@ -123,21 +138,21 @@ class Direction(Enum):
123138

124139
# Test iteration
125140
directions = [d for d in Direction]
126-
print(f"Member count: {len(directions)}")
141+
print("Member count: %s" % (len(directions)))
127142
print("PASS" if len(directions) == 4 else "FAIL")
128143

129144
# Test value lookup
130145
try:
131146
north = Direction(1)
132-
print(f"Direction(1) = {north.name}")
147+
print("Direction(1) = %s" % (north.name))
133148
print("PASS" if north == Direction.NORTH else "FAIL")
134149
except ValueError:
135150
print("FAIL - value lookup failed")
136151

137152
# Test 9: auto() repr
138153
print("\nTest 9: auto() repr")
139154
a = auto()
140-
print(f"repr(auto()) = {repr(a)}")
155+
print("repr(auto()) = %s" % (repr(a)))
141156
print("PASS" if repr(a) == "auto()" else "FAIL")
142157

143158
print("\nAll enum.auto() tests completed!")

0 commit comments

Comments
 (0)