aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/deprecated/python/enum34/patches/01-unknown.patch
blob: 4ed999b4e6e2b3b3c08784910670b86ad96846a9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
--- contrib/deprecated/python/enum34/enum/__init__.py	(index)
+++ contrib/deprecated/python/enum34/enum/__init__.py	(working tree)
@@ -8,6 +8,8 @@ version = 1, 1, 10
 
 pyver = float('%s.%s' % _sys.version_info[:2])
 
+ALLOW_SYNONYMS = '__allow_synonyms__'
+
 try:
     any
 except NameError:
@@ -161,6 +163,7 @@ class EnumMeta(type):
             for k, v in original_dict.items():
                 classdict[k] = v
 
+        allow_synonyms = classdict.get(ALLOW_SYNONYMS, True)
         member_type, first_enum = metacls._get_mixins_(bases)
         __new__, save_new, use_args = metacls._find_new_(classdict, member_type,
                                                         first_enum)
@@ -215,8 +218,18 @@ class EnumMeta(type):
         # auto-numbering ;)
         if __new__ is None:
             __new__ = enum_class.__new__
+
+        val2name = {}
         for member_name in _order_:
             value = members[member_name]
+            if not allow_synonyms:
+                if value in val2name:
+                    raise ValueError(
+                        'allow_synonyms=False forbids multiple names of the same value; '
+                        'Members {!r} and {!r} break this'.format(val2name[value], member_name)
+                    )
+                val2name[value] = member_name
+
             if not isinstance(value, tuple):
                 args = (value, )
             else:
@@ -237,7 +250,7 @@ class EnumMeta(type):
             enum_member.__init__(*args)
             # If another member with the same value was already defined, the
             # new member becomes an alias to the existing one.
-            for name, canonical_member in enum_class._member_map_.items():
+            for name, canonical_member in (enum_class._member_map_.items() if allow_synonyms else ()):
                 if canonical_member.value == enum_member._value_:
                     enum_member = canonical_member
                     break
@@ -328,7 +341,7 @@ class EnumMeta(type):
         """
         return True
 
-    def __call__(cls, value, names=None, module=None, type=None, start=1):
+    def __call__(cls, value, names=None, module=None, type=None, start=1, allow_synonyms=True):
         """Either returns an existing member, or creates a new enum class.
 
         This method is used both when an enum class is given a value to match
@@ -347,7 +360,7 @@ class EnumMeta(type):
         if names is None:  # simple value lookup
             return cls.__new__(cls, value)
         # otherwise, functional API: we're creating a new Enum type
-        return cls._create_(value, names, module=module, type=type, start=start)
+        return cls._create_(value, names, module=module, type=type, start=start, allow_synonyms=allow_synonyms)
 
     def __contains__(cls, member):
         return isinstance(member, cls) and member.name in cls._member_map_
@@ -420,7 +433,7 @@ class EnumMeta(type):
             raise AttributeError('Cannot reassign members.')
         super(EnumMeta, cls).__setattr__(name, value)
 
-    def _create_(cls, class_name, names=None, module=None, type=None, start=1):
+    def _create_(cls, class_name, names=None, module=None, type=None, start=1, allow_synonyms=True):
         """Convenience method to create a new Enum class.
 
         `names` can be:
@@ -465,6 +478,7 @@ class EnumMeta(type):
         # only set _order_ in classdict if name/value was not from a mapping
         if not isinstance(item, basestring):
             classdict['_order_'] = _order_
+        classdict[ALLOW_SYNONYMS] = getattr(cls, ALLOW_SYNONYMS, allow_synonyms)
         enum_class = metacls.__new__(metacls, class_name, bases, classdict)
 
         # TODO: replace the frame hack if a blessed way to know the calling