Skip to content

Commit d65b903

Browse files
authored
bpo-43162: [Enum] deprecate enum member.member access (GH-24486)
In 3.5 (?) a speed optimization made it possible to access members as attributes of other members, i.e. ``Color.RED.BLUE``. This was always discouraged in the docs, and other recent optimizations has made that one no longer necessary. Because some may be relying on it anyway, it is being deprecated in 3.10, and will be removed in 3.11.
1 parent e1f7769 commit d65b903

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

Lib/enum.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,28 +139,38 @@ def __get__(self, instance, ownerclass=None):
139139
return ownerclass._member_map_[self.name]
140140
except KeyError:
141141
raise AttributeError(
142-
'%s: no attribute %r' % (ownerclass.__name__, self.name)
142+
'%s: no class attribute %r' % (ownerclass.__name__, self.name)
143143
)
144144
else:
145145
if self.fget is None:
146+
# check for member
147+
if self.name in ownerclass._member_map_:
148+
import warnings
149+
warnings.warn(
150+
"accessing one member from another is not supported, "
151+
" and will be disabled in 3.11",
152+
DeprecationWarning,
153+
stacklevel=2,
154+
)
155+
return ownerclass._member_map_[self.name]
146156
raise AttributeError(
147-
'%s: no attribute %r' % (ownerclass.__name__, self.name)
157+
'%s: no instance attribute %r' % (ownerclass.__name__, self.name)
148158
)
149159
else:
150160
return self.fget(instance)
151161

152162
def __set__(self, instance, value):
153163
if self.fset is None:
154164
raise AttributeError(
155-
"%s: cannot set attribute %r" % (self.clsname, self.name)
165+
"%s: cannot set instance attribute %r" % (self.clsname, self.name)
156166
)
157167
else:
158168
return self.fset(instance, value)
159169

160170
def __delete__(self, instance):
161171
if self.fdel is None:
162172
raise AttributeError(
163-
"%s: cannot delete attribute %r" % (self.clsname, self.name)
173+
"%s: cannot delete instance attribute %r" % (self.clsname, self.name)
164174
)
165175
else:
166176
return self.fdel(instance)

Lib/test/test_enum.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,6 +2185,29 @@ class Private(Enum):
21852185
self.assertEqual(Private._Private__corporal, 'Radar')
21862186
self.assertEqual(Private._Private__major_, 'Hoolihan')
21872187

2188+
@unittest.skipUnless(
2189+
sys.version_info[:2] == (3, 10),
2190+
'member-member access now raises an exception',
2191+
)
2192+
def test_warning_for_member_from_member_access(self):
2193+
with self.assertWarns(DeprecationWarning):
2194+
class Di(Enum):
2195+
YES = 1
2196+
NO = 0
2197+
nope = Di.YES.NO
2198+
self.assertIs(Di.NO, nope)
2199+
2200+
@unittest.skipUnless(
2201+
sys.version_info[:2] > (3, 10),
2202+
'member-member access currently issues a warning',
2203+
)
2204+
def test_exception_for_member_from_member_access(self):
2205+
with self.assertRaisesRegex(AttributeError, "Di: no instance attribute .NO."):
2206+
class Di(Enum):
2207+
YES = 1
2208+
NO = 0
2209+
nope = Di.YES.NO
2210+
21882211
def test_strenum_auto(self):
21892212
class Strings(StrEnum):
21902213
ONE = auto()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
deprecate unsupported ability to access enum members as attributes of other
2+
enum members

0 commit comments

Comments
 (0)