mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	gh-116040: [Enum] fix by-value calls when second value is falsey; e.g. Cardinal(1, 0) (GH-116072)
This commit is contained in:
		
							parent
							
								
									b2d74cdbcd
								
							
						
					
					
						commit
						13ffd4bd9f
					
				
					 3 changed files with 35 additions and 4 deletions
				
			
		
							
								
								
									
										15
									
								
								Lib/enum.py
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								Lib/enum.py
									
										
									
									
									
								
							|  | @ -162,6 +162,13 @@ def _dedent(text): | ||||||
|         lines[j] = l[i:] |         lines[j] = l[i:] | ||||||
|     return '\n'.join(lines) |     return '\n'.join(lines) | ||||||
| 
 | 
 | ||||||
|  | class _not_given: | ||||||
|  |     def __repr__(self): | ||||||
|  |         return('<not given>') | ||||||
|  |     def __bool__(self): | ||||||
|  |         return False | ||||||
|  | _not_given = _not_given() | ||||||
|  | 
 | ||||||
| class _auto_null: | class _auto_null: | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return '_auto_null' |         return '_auto_null' | ||||||
|  | @ -680,7 +687,7 @@ def __bool__(cls): | ||||||
|         """ |         """ | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
|     def __call__(cls, value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None): |     def __call__(cls, value, names=_not_given, *values, module=None, qualname=None, type=None, start=1, boundary=None): | ||||||
|         """ |         """ | ||||||
|         Either returns an existing member, or creates a new enum class. |         Either returns an existing member, or creates a new enum class. | ||||||
| 
 | 
 | ||||||
|  | @ -709,18 +716,18 @@ def __call__(cls, value, names=None, *values, module=None, qualname=None, type=N | ||||||
|         """ |         """ | ||||||
|         if cls._member_map_: |         if cls._member_map_: | ||||||
|             # simple value lookup if members exist |             # simple value lookup if members exist | ||||||
|             if names: |             if names is not _not_given: | ||||||
|                 value = (value, names) + values |                 value = (value, names) + values | ||||||
|             return cls.__new__(cls, value) |             return cls.__new__(cls, value) | ||||||
|         # otherwise, functional API: we're creating a new Enum type |         # otherwise, functional API: we're creating a new Enum type | ||||||
|         if names is None and type is None: |         if names is _not_given and type is None: | ||||||
|             # no body? no data-type? possibly wrong usage |             # no body? no data-type? possibly wrong usage | ||||||
|             raise TypeError( |             raise TypeError( | ||||||
|                     f"{cls} has no members; specify `names=()` if you meant to create a new, empty, enum" |                     f"{cls} has no members; specify `names=()` if you meant to create a new, empty, enum" | ||||||
|                     ) |                     ) | ||||||
|         return cls._create_( |         return cls._create_( | ||||||
|                 class_name=value, |                 class_name=value, | ||||||
|                 names=names, |                 names=names or None, | ||||||
|                 module=module, |                 module=module, | ||||||
|                 qualname=qualname, |                 qualname=qualname, | ||||||
|                 type=type, |                 type=type, | ||||||
|  |  | ||||||
|  | @ -3409,6 +3409,15 @@ def __new__(cls, int_value, *value_aliases): | ||||||
|         self.assertIs(Types(2), Types.NetList) |         self.assertIs(Types(2), Types.NetList) | ||||||
|         self.assertIs(Types('nl'), Types.NetList) |         self.assertIs(Types('nl'), Types.NetList) | ||||||
| 
 | 
 | ||||||
|  |     def test_second_tuple_item_is_falsey(self): | ||||||
|  |         class Cardinal(Enum): | ||||||
|  |             RIGHT = (1, 0) | ||||||
|  |             UP = (0, 1) | ||||||
|  |             LEFT = (-1, 0) | ||||||
|  |             DOWN = (0, -1) | ||||||
|  |         self.assertIs(Cardinal(1, 0), Cardinal.RIGHT) | ||||||
|  |         self.assertIs(Cardinal(-1, 0), Cardinal.LEFT) | ||||||
|  | 
 | ||||||
|     def test_no_members(self): |     def test_no_members(self): | ||||||
|         with self.assertRaisesRegex( |         with self.assertRaisesRegex( | ||||||
|                 TypeError, |                 TypeError, | ||||||
|  | @ -3421,6 +3430,20 @@ def test_no_members(self): | ||||||
|             ): |             ): | ||||||
|             Flag(7) |             Flag(7) | ||||||
| 
 | 
 | ||||||
|  |     def test_empty_names(self): | ||||||
|  |         for nothing, e_type in ( | ||||||
|  |                 ('', None), | ||||||
|  |                 ('', int), | ||||||
|  |                 ([], None), | ||||||
|  |                 ([], int), | ||||||
|  |                 ({}, None), | ||||||
|  |                 ({}, int), | ||||||
|  |             ): | ||||||
|  |             empty_enum = Enum('empty_enum', nothing, type=e_type) | ||||||
|  |             self.assertEqual(len(empty_enum), 0) | ||||||
|  |             self.assertRaises(TypeError, 'has no members', empty_enum, 0) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class TestOrder(unittest.TestCase): | class TestOrder(unittest.TestCase): | ||||||
|     "test usage of the `_order_` attribute" |     "test usage of the `_order_` attribute" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | [Enum] fix by-value calls when second value is falsey; e.g. Cardinal(1, 0) | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ethan Furman
						Ethan Furman