mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	bpo-41517: do not allow Enums to be extended (GH-22271)
fix bug that let Enums be extended via multiple inheritance
(cherry picked from commit 3064dbf5df)
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
			
			
This commit is contained in:
		
							parent
							
								
									6a39888c2c
								
							
						
					
					
						commit
						48f99250ff
					
				
					 3 changed files with 18 additions and 5 deletions
				
			
		
							
								
								
									
										19
									
								
								Lib/enum.py
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								Lib/enum.py
									
										
									
									
									
								
							|  | @ -123,10 +123,12 @@ class EnumMeta(type): | |||
|     """Metaclass for Enum""" | ||||
|     @classmethod | ||||
|     def __prepare__(metacls, cls, bases): | ||||
|         # check that previous enum members do not exist | ||||
|         metacls._check_for_existing_members(cls, bases) | ||||
|         # create the namespace dict | ||||
|         enum_dict = _EnumDict() | ||||
|         # inherit previous flags and _generate_next_value_ function | ||||
|         member_type, first_enum = metacls._get_mixins_(bases) | ||||
|         member_type, first_enum = metacls._get_mixins_(cls, bases) | ||||
|         if first_enum is not None: | ||||
|             enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None) | ||||
|         return enum_dict | ||||
|  | @ -142,7 +144,7 @@ def __new__(metacls, cls, bases, classdict): | |||
|         ignore = classdict['_ignore_'] | ||||
|         for key in ignore: | ||||
|             classdict.pop(key, None) | ||||
|         member_type, first_enum = metacls._get_mixins_(bases) | ||||
|         member_type, first_enum = metacls._get_mixins_(cls, bases) | ||||
|         __new__, save_new, use_args = metacls._find_new_(classdict, member_type, | ||||
|                                                         first_enum) | ||||
| 
 | ||||
|  | @ -401,7 +403,7 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s | |||
|         """ | ||||
|         metacls = cls.__class__ | ||||
|         bases = (cls, ) if type is None else (type, cls) | ||||
|         _, first_enum = cls._get_mixins_(bases) | ||||
|         _, first_enum = cls._get_mixins_(cls, bases) | ||||
|         classdict = metacls.__prepare__(class_name, bases) | ||||
| 
 | ||||
|         # special processing needed for names? | ||||
|  | @ -474,7 +476,14 @@ def _convert_(cls, name, module, filter, source=None): | |||
|         return cls | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _get_mixins_(bases): | ||||
|     def _check_for_existing_members(class_name, bases): | ||||
|         for chain in bases: | ||||
|             for base in chain.__mro__: | ||||
|                 if issubclass(base, Enum) and base._member_names_: | ||||
|                     raise TypeError("%s: cannot extend enumeration %r" % (class_name, base.__name__)) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _get_mixins_(class_name, bases): | ||||
|         """Returns the type for creating enum members, and the first inherited | ||||
|         enum class. | ||||
| 
 | ||||
|  | @ -499,7 +508,7 @@ def _find_data_type(bases): | |||
|                     elif not issubclass(base, Enum): | ||||
|                         candidate = base | ||||
|             if len(data_types) > 1: | ||||
|                 raise TypeError('too many data types: %r' % data_types) | ||||
|                 raise TypeError('%r: too many data types: %r' % (class_name, data_types)) | ||||
|             elif data_types: | ||||
|                 return data_types[0] | ||||
|             else: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Miss Islington (bot)
						Miss Islington (bot)