[Python-checkins] [3.9] bpo-42517: [Enum] deprecate private name members (GH-23722) (GH-23748)
ethanfurman
webhook-mailer at python.org
Mon Dec 14 18:57:12 EST 2020
https://github.com/python/cpython/commit/aba12b67c18b17bb727a0d50dd0653e38cb64dc8
commit: aba12b67c18b17bb727a0d50dd0653e38cb64dc8
branch: 3.9
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: ethanfurman <ethan at stoneleaf.us>
date: 2020-12-14T15:56:58-08:00
summary:
[3.9] bpo-42517: [Enum] deprecate private name members (GH-23722) (GH-23748)
private names will raise a DeprecationWarning; in 3.10 they will become normal attributes
files:
A Misc/NEWS.d/next/Library/2020-12-09-10-59-16.bpo-42517.FKEVcZ.rst
M Doc/library/enum.rst
M Lib/enum.py
M Lib/test/test_enum.py
diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst
index a3c51655576ba..4ecca209d87b3 100644
--- a/Doc/library/enum.rst
+++ b/Doc/library/enum.rst
@@ -1121,6 +1121,15 @@ and raise an error if the two do not match::
In Python 2 code the :attr:`_order_` attribute is necessary as definition
order is lost before it can be recorded.
+
+_Private__names
+"""""""""""""""
+
+Private names will be normal attributes in Python 3.10 instead of either an error
+or a member (depending on if the name ends with an underscore). Using these names
+in 3.9 will issue a :exc:`DeprecationWarning`.
+
+
``Enum`` member type
""""""""""""""""""""
diff --git a/Lib/enum.py b/Lib/enum.py
index 35210c993325d..46b5435b7c8e0 100644
--- a/Lib/enum.py
+++ b/Lib/enum.py
@@ -41,6 +41,19 @@ def _is_sunder(name):
name[-2:-1] != '_'
)
+def _is_private(cls_name, name):
+ # do not use `re` as `re` imports `enum`
+ pattern = '_%s__' % (cls_name, )
+ if (
+ len(name) >= 5
+ and name.startswith(pattern)
+ and name[len(pattern)] != '_'
+ and (name[-1] != '_' or name[-2] != '_')
+ ):
+ return True
+ else:
+ return False
+
def _make_class_unpicklable(cls):
"""
Make the given class un-picklable.
@@ -81,6 +94,14 @@ def __setitem__(self, key, value):
Single underscore (sunder) names are reserved.
"""
+ if _is_private(self._cls_name, key):
+ import warnings
+ warnings.warn(
+ "private variables, such as %r, will be normal attributes in 3.10"
+ % (key, ),
+ DeprecationWarning,
+ stacklevel=2,
+ )
if _is_sunder(key):
if key not in (
'_order_', '_create_pseudo_member_',
@@ -146,6 +167,7 @@ def __prepare__(metacls, cls, bases):
metacls._check_for_existing_members(cls, bases)
# create the namespace dict
enum_dict = _EnumDict()
+ enum_dict._cls_name = cls
# inherit previous flags and _generate_next_value_ function
member_type, first_enum = metacls._get_mixins_(cls, bases)
if first_enum is not None:
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
index dca668a9046f3..f7f8522bda4f3 100644
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -1147,6 +1147,7 @@ def test_multiple_mixin_mro(self):
class auto_enum(type(Enum)):
def __new__(metacls, cls, bases, classdict):
temp = type(classdict)()
+ temp._cls_name = cls
names = set(classdict._member_names)
i = 0
for k in classdict._member_names:
@@ -2049,6 +2050,23 @@ def test_empty_globals(self):
exec(code, global_ns, local_ls)
+ @unittest.skipUnless(
+ sys.version_info[:2] == (3, 9),
+ 'private variables are now normal attributes',
+ )
+ def test_warning_for_private_variables(self):
+ with self.assertWarns(DeprecationWarning):
+ class Private(Enum):
+ __corporal = 'Radar'
+ self.assertEqual(Private._Private__corporal.value, 'Radar')
+ try:
+ with self.assertWarns(DeprecationWarning):
+ class Private(Enum):
+ __major_ = 'Hoolihan'
+ except ValueError:
+ pass
+
+
class TestOrder(unittest.TestCase):
def test_same_members(self):
diff --git a/Misc/NEWS.d/next/Library/2020-12-09-10-59-16.bpo-42517.FKEVcZ.rst b/Misc/NEWS.d/next/Library/2020-12-09-10-59-16.bpo-42517.FKEVcZ.rst
new file mode 100644
index 0000000000000..e99294d9430d1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-12-09-10-59-16.bpo-42517.FKEVcZ.rst
@@ -0,0 +1,2 @@
+Enum: private names will raise a DeprecationWarning; in 3.10 they will
+become normal attributes
More information about the Python-checkins
mailing list