Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"""Python Enumerations""" 

2 

3import sys as _sys 

4 

5__all__ = ['Enum', 'IntEnum', 'unique'] 

6 

7pyver = float('%s.%s' % _sys.version_info[:2]) 

8 

9try: 

10 any 

11except NameError: 

12 def any(iterable): 

13 for element in iterable: 

14 if element: 

15 return True 

16 return False 

17 

18 

19class _RouteClassAttributeToGetattr(object): 

20 """Route attribute access on a class to __getattr__. 

21 

22 This is a descriptor, used to define attributes that act differently when 

23 accessed through an instance and through a class. Instance access remains 

24 normal, but access to an attribute through a class will be routed to the 

25 class's __getattr__ method; this is done by raising AttributeError. 

26 

27 """ 

28 def __init__(self, fget=None): 

29 self.fget = fget 

30 

31 def __get__(self, instance, ownerclass=None): 

32 if instance is None: 32 ↛ 33line 32 didn't jump to line 33, because the condition on line 32 was never true

33 raise AttributeError() 

34 return self.fget(instance) 

35 

36 def __set__(self, instance, value): 

37 raise AttributeError("can't set attribute") 

38 

39 def __delete__(self, instance): 

40 raise AttributeError("can't delete attribute") 

41 

42 

43def _is_descriptor(obj): 

44 """Returns True if obj is a descriptor, False otherwise.""" 

45 return ( 

46 hasattr(obj, '__get__') or 

47 hasattr(obj, '__set__') or 

48 hasattr(obj, '__delete__')) 

49 

50 

51def _is_dunder(name): 

52 """Returns True if a __dunder__ name, False otherwise.""" 

53 return (name[:2] == name[-2:] == '__' and 

54 name[2:3] != '_' and 

55 name[-3:-2] != '_' and 

56 len(name) > 4) 

57 

58 

59def _is_sunder(name): 

60 """Returns True if a _sunder_ name, False otherwise.""" 

61 return (name[0] == name[-1] == '_' and 

62 name[1:2] != '_' and 

63 name[-2:-1] != '_' and 

64 len(name) > 2) 

65 

66 

67def _make_class_unpicklable(cls): 

68 """Make the given class un-picklable.""" 

69 def _break_on_call_reduce(self): 

70 raise TypeError('%r cannot be pickled' % self) 

71 cls.__reduce__ = _break_on_call_reduce 

72 cls.__module__ = '<unknown>' 

73 

74 

75class _EnumDict(dict): 

76 """Track enum member order and ensure member names are not reused. 

77 

78 EnumMeta will use the names found in self._member_names as the 

79 enumeration member names. 

80 

81 """ 

82 def __init__(self): 

83 super(_EnumDict, self).__init__() 

84 self._member_names = [] 

85 

86 def __setitem__(self, key, value): 

87 """Changes anything not dundered or not a descriptor. 

88 

89 If a descriptor is added with the same name as an enum member, the name 

90 is removed from _member_names (this may leave a hole in the numerical 

91 sequence of values). 

92 

93 If an enum member name is used twice, an error is raised; duplicate 

94 values are not checked for. 

95 

96 Single underscore (sunder) names are reserved. 

97 

98 Note: in 3.x __order__ is simply discarded as a not necessary piece 

99 leftover from 2.x 

100 

101 """ 

102 if pyver >= 3.0 and key == '__order__': 102 ↛ 103line 102 didn't jump to line 103, because the condition on line 102 was never true

103 return 

104 if _is_sunder(key): 104 ↛ 105line 104 didn't jump to line 105, because the condition on line 104 was never true

105 raise ValueError('_names_ are reserved for future Enum use') 

106 elif _is_dunder(key): 

107 pass 

108 elif key in self._member_names: 108 ↛ 110line 108 didn't jump to line 110, because the condition on line 108 was never true

109 # descriptor overwriting an enum? 

110 raise TypeError('Attempted to reuse key: %r' % key) 

111 elif not _is_descriptor(value): 

112 if key in self: 112 ↛ 114line 112 didn't jump to line 114, because the condition on line 112 was never true

113 # enum overwriting a descriptor? 

114 raise TypeError('Key already defined as: %r' % self[key]) 

115 self._member_names.append(key) 

116 super(_EnumDict, self).__setitem__(key, value) 

117 

118 

119# Dummy value for Enum as EnumMeta explicitly checks for it, but of course until 

120# EnumMeta finishes running the first time the Enum class doesn't exist. This 

121# is also why there are checks in EnumMeta like `if Enum is not None` 

122Enum = None 

123 

124 

125class EnumMeta(type): 

126 """Metaclass for Enum""" 

127 @classmethod 

128 def __prepare__(metacls, cls, bases): 

129 return _EnumDict() 

130 

131 def __new__(metacls, cls, bases, classdict): 

132 # an Enum class is final once enumeration items have been defined; it 

133 # cannot be mixed with other types (int, float, etc.) if it has an 

134 # inherited __new__ unless a new __new__ is defined (or the resulting 

135 # class will fail). 

136 if type(classdict) is dict: 

137 original_dict = classdict 

138 classdict = _EnumDict() 

139 for k, v in original_dict.items(): 

140 classdict[k] = v 

141 

142 member_type, first_enum = metacls._get_mixins_(bases) 

143 #if member_type is object: 

144 # use_args = False 

145 #else: 

146 # use_args = True 

147 __new__, save_new, use_args = metacls._find_new_(classdict, member_type, 

148 first_enum) 

149 # save enum items into separate mapping so they don't get baked into 

150 # the new class 

151 members = dict((k, classdict[k]) for k in classdict._member_names) 

152 for name in classdict._member_names: 

153 del classdict[name] 

154 

155 # py2 support for definition order 

156 __order__ = classdict.get('__order__') 

157 if __order__ is None: 157 ↛ 164line 157 didn't jump to line 164, because the condition on line 157 was never false

158 __order__ = classdict._member_names 

159 if pyver < 3.0: 159 ↛ 160line 159 didn't jump to line 160, because the condition on line 159 was never true

160 order_specified = False 

161 else: 

162 order_specified = True 

163 else: 

164 del classdict['__order__'] 

165 order_specified = True 

166 if pyver < 3.0: 

167 __order__ = __order__.replace(',', ' ').split() 

168 aliases = [name for name in members if name not in __order__] 

169 __order__ += aliases 

170 

171 # check for illegal enum names (any others?) 

172 invalid_names = set(members) & set(['mro']) 

173 if invalid_names: 173 ↛ 174line 173 didn't jump to line 174, because the condition on line 173 was never true

174 raise ValueError('Invalid enum member name(s): %s' % ( 

175 ', '.join(invalid_names), )) 

176 

177 # create our new Enum type 

178 enum_class = super(EnumMeta, metacls).__new__(metacls, cls, bases, classdict) 

179 enum_class._member_names_ = [] # names in random order 

180 enum_class._member_map_ = {} # name->value map 

181 enum_class._member_type_ = member_type 

182 

183 # Reverse value->name map for hashable values. 

184 enum_class._value2member_map_ = {} 

185 

186 # check for a __getnewargs__, and if not present sabotage 

187 # pickling, since it won't work anyway 

188 if (member_type is not object and 188 ↛ 191line 188 didn't jump to line 191, because the condition on line 188 was never true

189 member_type.__dict__.get('__getnewargs__') is None 

190 ): 

191 _make_class_unpicklable(enum_class) 

192 

193 # instantiate them, checking for duplicates as we go 

194 # we instantiate first instead of checking for duplicates first in case 

195 # a custom __new__ is doing something funky with the values -- such as 

196 # auto-numbering ;) 

197 if __new__ is None: 197 ↛ 198line 197 didn't jump to line 198, because the condition on line 197 was never true

198 __new__ = enum_class.__new__ 

199 for member_name in __order__: 

200 value = members[member_name] 

201 if not isinstance(value, tuple): 201 ↛ 204line 201 didn't jump to line 204, because the condition on line 201 was never false

202 args = (value, ) 

203 else: 

204 args = value 

205 if member_type is tuple: # special case for tuple enums 205 ↛ 206line 205 didn't jump to line 206, because the condition on line 205 was never true

206 args = (args, ) # wrap it one more time 

207 if not use_args or not args: 207 ↛ 212line 207 didn't jump to line 212, because the condition on line 207 was never false

208 enum_member = __new__(enum_class) 

209 if not hasattr(enum_member, '_value_'): 209 ↛ 215line 209 didn't jump to line 215, because the condition on line 209 was never false

210 enum_member._value_ = value 

211 else: 

212 enum_member = __new__(enum_class, *args) 

213 if not hasattr(enum_member, '_value_'): 

214 enum_member._value_ = member_type(*args) 

215 value = enum_member._value_ 

216 enum_member._name_ = member_name 

217 enum_member.__objclass__ = enum_class 

218 enum_member.__init__(*args) 

219 # If another member with the same value was already defined, the 

220 # new member becomes an alias to the existing one. 

221 for name, canonical_member in enum_class._member_map_.items(): 

222 if canonical_member.value == enum_member._value_: 

223 enum_member = canonical_member 

224 break 

225 else: 

226 # Aliases don't appear in member names (only in __members__). 

227 enum_class._member_names_.append(member_name) 

228 enum_class._member_map_[member_name] = enum_member 

229 try: 

230 # This may fail if value is not hashable. We can't add the value 

231 # to the map, and by-value lookups for this value will be 

232 # linear. 

233 enum_class._value2member_map_[value] = enum_member 

234 except TypeError: 

235 pass 

236 

237 # in Python2.x we cannot know definition order, so go with value order 

238 # unless __order__ was specified in the class definition 

239 if not order_specified: 239 ↛ 240line 239 didn't jump to line 240, because the condition on line 239 was never true

240 enum_class._member_names_ = [ 

241 e[0] for e in sorted( 

242 [(name, enum_class._member_map_[name]) for name in enum_class._member_names_], 

243 key=lambda t: t[1]._value_ 

244 )] 

245 

246 # double check that repr and friends are not the mixin's or various 

247 # things break (such as pickle) 

248 if Enum is not None: 

249 setattr(enum_class, '__getnewargs__', Enum.__getnewargs__) 

250 for name in ('__repr__', '__str__', '__format__'): 

251 class_method = getattr(enum_class, name) 

252 obj_method = getattr(member_type, name, None) 

253 enum_method = getattr(first_enum, name, None) 

254 if obj_method is not None and obj_method is class_method: 

255 setattr(enum_class, name, enum_method) 

256 

257 # method resolution and int's are not playing nice 

258 # Python's less than 2.6 use __cmp__ 

259 

260 if pyver < 2.6: 260 ↛ 262line 260 didn't jump to line 262, because the condition on line 260 was never true

261 

262 if issubclass(enum_class, int): 

263 setattr(enum_class, '__cmp__', getattr(int, '__cmp__')) 

264 

265 elif pyver < 3.0: 265 ↛ 267line 265 didn't jump to line 267, because the condition on line 265 was never true

266 

267 if issubclass(enum_class, int): 

268 for method in ( 

269 '__le__', 

270 '__lt__', 

271 '__gt__', 

272 '__ge__', 

273 '__eq__', 

274 '__ne__', 

275 '__hash__', 

276 ): 

277 setattr(enum_class, method, getattr(int, method)) 

278 

279 # replace any other __new__ with our own (as long as Enum is not None, 

280 # anyway) -- again, this is to support pickle 

281 if Enum is not None: 

282 # if the user defined their own __new__, save it before it gets 

283 # clobbered in case they subclass later 

284 if save_new: 284 ↛ 285line 284 didn't jump to line 285, because the condition on line 284 was never true

285 setattr(enum_class, '__member_new__', enum_class.__dict__['__new__']) 

286 setattr(enum_class, '__new__', Enum.__dict__['__new__']) 

287 return enum_class 

288 

289 def __call__(cls, value, names=None, module=None, type=None): 

290 """Either returns an existing member, or creates a new enum class. 

291 

292 This method is used both when an enum class is given a value to match 

293 to an enumeration member (i.e. Color(3)) and for the functional API 

294 (i.e. Color = Enum('Color', names='red green blue')). 

295 

296 When used for the functional API: `module`, if set, will be stored in 

297 the new class' __module__ attribute; `type`, if set, will be mixed in 

298 as the first base class. 

299 

300 Note: if `module` is not set this routine will attempt to discover the 

301 calling module by walking the frame stack; if this is unsuccessful 

302 the resulting class will not be pickleable. 

303 

304 """ 

305 if names is None: # simple value lookup 305 ↛ 308line 305 didn't jump to line 308, because the condition on line 305 was never false

306 return cls.__new__(cls, value) 

307 # otherwise, functional API: we're creating a new Enum type 

308 return cls._create_(value, names, module=module, type=type) 

309 

310 def __contains__(cls, member): 

311 return isinstance(member, cls) and member.name in cls._member_map_ 

312 

313 def __delattr__(cls, attr): 

314 # nicer error message when someone tries to delete an attribute 

315 # (see issue19025). 

316 if attr in cls._member_map_: 

317 raise AttributeError( 

318 "%s: cannot delete Enum member." % cls.__name__) 

319 super(EnumMeta, cls).__delattr__(attr) 

320 

321 def __dir__(self): 

322 return (['__class__', '__doc__', '__members__', '__module__'] + 

323 self._member_names_) 

324 

325 @property 

326 def __members__(cls): 

327 """Returns a mapping of member name->value. 

328 

329 This mapping lists all enum members, including aliases. Note that this 

330 is a copy of the internal mapping. 

331 

332 """ 

333 return cls._member_map_.copy() 

334 

335 def __getattr__(cls, name): 

336 """Return the enum member matching `name` 

337 

338 We use __getattr__ instead of descriptors or inserting into the enum 

339 class' __dict__ in order to support `name` and `value` being both 

340 properties for enum members (which live in the class' __dict__) and 

341 enum members themselves. 

342 

343 """ 

344 if _is_dunder(name): 

345 raise AttributeError(name) 

346 try: 

347 return cls._member_map_[name] 

348 except KeyError: 

349 raise AttributeError(name) 

350 

351 def __getitem__(cls, name): 

352 return cls._member_map_[name] 

353 

354 def __iter__(cls): 

355 return (cls._member_map_[name] for name in cls._member_names_) 

356 

357 def __reversed__(cls): 

358 return (cls._member_map_[name] for name in reversed(cls._member_names_)) 

359 

360 def __len__(cls): 

361 return len(cls._member_names_) 

362 

363 def __repr__(cls): 

364 return "<enum %r>" % cls.__name__ 

365 

366 def __setattr__(cls, name, value): 

367 """Block attempts to reassign Enum members. 

368 

369 A simple assignment to the class namespace only changes one of the 

370 several possible ways to get an Enum member from the Enum class, 

371 resulting in an inconsistent Enumeration. 

372 

373 """ 

374 member_map = cls.__dict__.get('_member_map_', {}) 

375 if name in member_map: 375 ↛ 376line 375 didn't jump to line 376, because the condition on line 375 was never true

376 raise AttributeError('Cannot reassign members.') 

377 super(EnumMeta, cls).__setattr__(name, value) 

378 

379 def _create_(cls, class_name, names=None, module=None, type=None): 

380 """Convenience method to create a new Enum class. 

381 

382 `names` can be: 

383 

384 * A string containing member names, separated either with spaces or 

385 commas. Values are auto-numbered from 1. 

386 * An iterable of member names. Values are auto-numbered from 1. 

387 * An iterable of (member name, value) pairs. 

388 * A mapping of member name -> value. 

389 

390 """ 

391 metacls = cls.__class__ 

392 if type is None: 

393 bases = (cls, ) 

394 else: 

395 bases = (type, cls) 

396 classdict = metacls.__prepare__(class_name, bases) 

397 __order__ = [] 

398 

399 # special processing needed for names? 

400 if isinstance(names, str): 

401 names = names.replace(',', ' ').split() 

402 if isinstance(names, (tuple, list)) and isinstance(names[0], str): 

403 names = [(e, i+1) for (i, e) in enumerate(names)] 

404 

405 # Here, names is either an iterable of (name, value) or a mapping. 

406 for item in names: 

407 if isinstance(item, str): 

408 member_name, member_value = item, names[item] 

409 else: 

410 member_name, member_value = item 

411 classdict[member_name] = member_value 

412 __order__.append(member_name) 

413 # only set __order__ in classdict if name/value was not from a mapping 

414 if not isinstance(item, str): 

415 classdict['__order__'] = ' '.join(__order__) 

416 enum_class = metacls.__new__(metacls, class_name, bases, classdict) 

417 

418 # TODO: replace the frame hack if a blessed way to know the calling 

419 # module is ever developed 

420 if module is None: 

421 try: 

422 module = _sys._getframe(2).f_globals['__name__'] 

423 except (AttributeError, ValueError): 

424 pass 

425 if module is None: 

426 _make_class_unpicklable(enum_class) 

427 else: 

428 enum_class.__module__ = module 

429 

430 return enum_class 

431 

432 @staticmethod 

433 def _get_mixins_(bases): 

434 """Returns the type for creating enum members, and the first inherited 

435 enum class. 

436 

437 bases: the tuple of bases that was given to __new__ 

438 

439 """ 

440 if not bases or Enum is None: 

441 return object, Enum 

442 

443 

444 # double check that we are not subclassing a class with existing 

445 # enumeration members; while we're at it, see if any other data 

446 # type has been mixed in so we can use the correct __new__ 

447 member_type = first_enum = None 

448 for base in bases: 

449 if (base is not Enum and 449 ↛ 452line 449 didn't jump to line 452, because the condition on line 449 was never true

450 issubclass(base, Enum) and 

451 base._member_names_): 

452 raise TypeError("Cannot extend enumerations") 

453 # base is now the last base in bases 

454 if not issubclass(base, Enum): 454 ↛ 455line 454 didn't jump to line 455, because the condition on line 454 was never true

455 raise TypeError("new enumerations must be created as " 

456 "`ClassName([mixin_type,] enum_type)`") 

457 

458 # get correct mix-in type (either mix-in type of Enum subclass, or 

459 # first base if last base is Enum) 

460 if not issubclass(bases[0], Enum): 

461 member_type = bases[0] # first data type 

462 first_enum = bases[-1] # enum type 

463 else: 

464 for base in bases[0].__mro__: 

465 # most common: (IntEnum, int, Enum, object) 

466 # possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>, 

467 # <class 'int'>, <Enum 'Enum'>, 

468 # <class 'object'>) 

469 if issubclass(base, Enum): 

470 if first_enum is None: 470 ↛ 464line 470 didn't jump to line 464, because the condition on line 470 was never false

471 first_enum = base 

472 else: 

473 if member_type is None: 473 ↛ 464line 473 didn't jump to line 464, because the condition on line 473 was never false

474 member_type = base 

475 

476 return member_type, first_enum 

477 

478 if pyver < 3.0: 478 ↛ 479line 478 didn't jump to line 479, because the condition on line 478 was never true

479 @staticmethod 

480 def _find_new_(classdict, member_type, first_enum): 

481 """Returns the __new__ to be used for creating the enum members. 

482 

483 classdict: the class dictionary given to __new__ 

484 member_type: the data type whose __new__ will be used by default 

485 first_enum: enumeration to check for an overriding __new__ 

486 

487 """ 

488 # now find the correct __new__, checking to see of one was defined 

489 # by the user; also check earlier enum classes in case a __new__ was 

490 # saved as __member_new__ 

491 __new__ = classdict.get('__new__', None) 

492 if __new__: 

493 return None, True, True # __new__, save_new, use_args 

494 

495 N__new__ = getattr(None, '__new__') 

496 O__new__ = getattr(object, '__new__') 

497 if Enum is None: 

498 E__new__ = N__new__ 

499 else: 

500 E__new__ = Enum.__dict__['__new__'] 

501 # check all possibles for __member_new__ before falling back to 

502 # __new__ 

503 for method in ('__member_new__', '__new__'): 

504 for possible in (member_type, first_enum): 

505 try: 

506 target = possible.__dict__[method] 

507 except (AttributeError, KeyError): 

508 target = getattr(possible, method, None) 

509 if target not in [ 

510 None, 

511 N__new__, 

512 O__new__, 

513 E__new__, 

514 ]: 

515 if method == '__member_new__': 

516 classdict['__new__'] = target 

517 return None, False, True 

518 if isinstance(target, staticmethod): 

519 target = target.__get__(member_type) 

520 __new__ = target 

521 break 

522 if __new__ is not None: 

523 break 

524 else: 

525 __new__ = object.__new__ 

526 

527 # if a non-object.__new__ is used then whatever value/tuple was 

528 # assigned to the enum member name will be passed to __new__ and to the 

529 # new enum member's __init__ 

530 if __new__ is object.__new__: 

531 use_args = False 

532 else: 

533 use_args = True 

534 

535 return __new__, False, use_args 

536 else: 

537 @staticmethod 

538 def _find_new_(classdict, member_type, first_enum): 

539 """Returns the __new__ to be used for creating the enum members. 

540 

541 classdict: the class dictionary given to __new__ 

542 member_type: the data type whose __new__ will be used by default 

543 first_enum: enumeration to check for an overriding __new__ 

544 

545 """ 

546 # now find the correct __new__, checking to see of one was defined 

547 # by the user; also check earlier enum classes in case a __new__ was 

548 # saved as __member_new__ 

549 __new__ = classdict.get('__new__', None) 

550 

551 # should __new__ be saved as __member_new__ later? 

552 save_new = __new__ is not None 

553 

554 if __new__ is None: 

555 # check all possibles for __member_new__ before falling back to 

556 # __new__ 

557 for method in ('__member_new__', '__new__'): 

558 for possible in (member_type, first_enum): 

559 target = getattr(possible, method, None) 

560 if target not in ( 

561 None, 

562 None.__new__, 

563 object.__new__, 

564 Enum.__new__, 

565 ): 

566 __new__ = target 

567 break 

568 if __new__ is not None: 

569 break 

570 else: 

571 __new__ = object.__new__ 

572 

573 # if a non-object.__new__ is used then whatever value/tuple was 

574 # assigned to the enum member name will be passed to __new__ and to the 

575 # new enum member's __init__ 

576 if __new__ is object.__new__: 

577 use_args = False 

578 else: 

579 use_args = True 

580 

581 return __new__, save_new, use_args 

582 

583 

584######################################################## 

585# In order to support Python 2 and 3 with a single 

586# codebase we have to create the Enum methods separately 

587# and then use the `type(name, bases, dict)` method to 

588# create the class. 

589######################################################## 

590temp_enum_dict = {} 

591temp_enum_dict['__doc__'] = "Generic enumeration.\n\n Derive from this class to define new enumerations.\n\n" 

592 

593def __new__(cls, value): 

594 # all enum instances are actually created during class construction 

595 # without calling this method; this method is called by the metaclass' 

596 # __call__ (i.e. Color(3) ), and by pickle 

597 if type(value) is cls: 597 ↛ 599line 597 didn't jump to line 599, because the condition on line 597 was never true

598 # For lookups like Color(Color.red) 

599 value = value.value 

600 #return value 

601 # by-value search for a matching enum member 

602 # see if it's in the reverse mapping (for hashable values) 

603 try: 

604 if value in cls._value2member_map_: 

605 return cls._value2member_map_[value] 

606 except TypeError: 

607 # not there, now do long search -- O(n) behavior 

608 for member in cls._member_map_.values(): 

609 if member.value == value: 

610 return member 

611 raise ValueError("%s is not a valid %s" % (value, cls.__name__)) 

612temp_enum_dict['__new__'] = __new__ 

613del __new__ 

614 

615def __repr__(self): 

616 return "<%s.%s: %r>" % ( 

617 self.__class__.__name__, self._name_, self._value_) 

618temp_enum_dict['__repr__'] = __repr__ 

619del __repr__ 

620 

621def __str__(self): 

622 return "%s.%s" % (self.__class__.__name__, self._name_) 

623temp_enum_dict['__str__'] = __str__ 

624del __str__ 

625 

626def __dir__(self): 

627 added_behavior = [m for m in self.__class__.__dict__ if m[0] != '_'] 

628 return (['__class__', '__doc__', '__module__', 'name', 'value'] + added_behavior) 

629temp_enum_dict['__dir__'] = __dir__ 

630del __dir__ 

631 

632def __format__(self, format_spec): 

633 # mixed-in Enums should use the mixed-in type's __format__, otherwise 

634 # we can get strange results with the Enum name showing up instead of 

635 # the value 

636 

637 # pure Enum branch 

638 if self._member_type_ is object: 

639 cls = str 

640 val = str(self) 

641 # mix-in branch 

642 else: 

643 cls = self._member_type_ 

644 val = self.value 

645 return cls.__format__(val, format_spec) 

646temp_enum_dict['__format__'] = __format__ 

647del __format__ 

648 

649 

650#################################### 

651# Python's less than 2.6 use __cmp__ 

652 

653if pyver < 2.6: 653 ↛ 655line 653 didn't jump to line 655, because the condition on line 653 was never true

654 

655 def __cmp__(self, other): 

656 if type(other) is self.__class__: 

657 if self is other: 

658 return 0 

659 return -1 

660 return NotImplemented 

661 raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__)) 

662 temp_enum_dict['__cmp__'] = __cmp__ 

663 del __cmp__ 

664 

665else: 

666 

667 def __le__(self, other): 

668 raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__)) 

669 temp_enum_dict['__le__'] = __le__ 

670 del __le__ 

671 

672 def __lt__(self, other): 

673 raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__)) 

674 temp_enum_dict['__lt__'] = __lt__ 

675 del __lt__ 

676 

677 def __ge__(self, other): 

678 raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__)) 

679 temp_enum_dict['__ge__'] = __ge__ 

680 del __ge__ 

681 

682 def __gt__(self, other): 

683 raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__)) 

684 temp_enum_dict['__gt__'] = __gt__ 

685 del __gt__ 

686 

687 

688def __eq__(self, other): 

689 if type(other) is self.__class__: 

690 return self is other 

691 return NotImplemented 

692temp_enum_dict['__eq__'] = __eq__ 

693del __eq__ 

694 

695def __ne__(self, other): 

696 if type(other) is self.__class__: 

697 return self is not other 

698 return NotImplemented 

699temp_enum_dict['__ne__'] = __ne__ 

700del __ne__ 

701 

702def __getnewargs__(self): 

703 return (self._value_, ) 

704temp_enum_dict['__getnewargs__'] = __getnewargs__ 

705del __getnewargs__ 

706 

707def __hash__(self): 

708 return hash(self._name_) 

709temp_enum_dict['__hash__'] = __hash__ 

710del __hash__ 

711 

712# _RouteClassAttributeToGetattr is used to provide access to the `name` 

713# and `value` properties of enum members while keeping some measure of 

714# protection from modification, while still allowing for an enumeration 

715# to have members named `name` and `value`. This works because enumeration 

716# members are not set directly on the enum class -- __getattr__ is 

717# used to look them up. 

718 

719@_RouteClassAttributeToGetattr 

720def name(self): 

721 return self._name_ 

722temp_enum_dict['name'] = name 

723del name 

724 

725@_RouteClassAttributeToGetattr 

726def value(self): 

727 return self._value_ 

728temp_enum_dict['value'] = value 

729del value 

730 

731Enum = EnumMeta('Enum', (object, ), temp_enum_dict) 

732del temp_enum_dict 

733 

734# Enum has now been created 

735########################### 

736 

737class IntEnum(int, Enum): 

738 """Enum where members are also (and must be) ints""" 

739 

740 

741def unique(enumeration): 

742 """Class decorator that ensures only unique members exist in an enumeration.""" 

743 duplicates = [] 

744 for name, member in enumeration.__members__.items(): 

745 if name != member.name: 

746 duplicates.append((name, member.name)) 

747 if duplicates: 

748 duplicate_names = ', '.join( 

749 ["%s -> %s" % (alias, name) for (alias, name) in duplicates] 

750 ) 

751 raise ValueError('duplicate names found in %r: %s' % 

752 (enumeration, duplicate_names) 

753 ) 

754 return enumeration