@@ -11,6 +11,8 @@ from gssapi.raw.oids cimport OID
11
11
12
12
from gssapi.raw.types import MechType
13
13
14
+ from enum import EnumMeta, Enum
15
+
14
16
15
17
cdef extern from " python_gssapi.h" :
16
18
OM_uint32 gss_display_status(OM_uint32 * minor_status,
@@ -329,3 +331,64 @@ class GSSError(Exception):
329
331
maj_str = maj_str,
330
332
min_stat = self .min_code,
331
333
min_str = min_str)
334
+
335
+
336
+ # WARNING: FOR YOUR OWN PERSONAL SANITY, DO NOT TRY THIS AT HOME
337
+ # This allows things like extensions declaring their own RequirementFlags
338
+ # without having to worry about import order. There *might* be a cleaner
339
+ # way to do this, but most of the ways probably exploit the interals of Enum
340
+ class _EnumExtension (EnumMeta ):
341
+ def __new__ (metacls , name , bases , classdict ):
342
+ # find the base class that this overrides
343
+
344
+ base_attr = classdict.get(' __base__' , None )
345
+
346
+ if len (bases) != 1 or bases[0 ] is not object or base_attr is None :
347
+ raise TypeError (" Enumeration extensions must be created as "
348
+ " `ClassName(object)` and must contain the "
349
+ " `__base__` attribute" )
350
+
351
+ adds_to = base_attr
352
+ del classdict[' __base__' ]
353
+
354
+ bases = adds_to.__bases__
355
+
356
+ # we need to have the same Enum type
357
+ if not issubclass (adds_to, Enum):
358
+ raise TypeError (" Enumeration extensions must extend a subtype "
359
+ " of Enum or directly sublcass object" )
360
+
361
+ # roughly preserve insertion order in Python 3.4+
362
+ # (actually preserving order would require using parts of the Enum
363
+ # implementation that aren't part of the spec)
364
+ old_classdict = classdict
365
+ classdict = metacls.__prepare__(name, bases)
366
+
367
+ # NB(directxman12): we can't use update, because that doesn't
368
+ # trigger __setitem__, which thus won't update the _EnumDict correctly
369
+ base_members = adds_to.__members__
370
+ for k, v in base_members.items():
371
+ classdict[k] = v.value
372
+
373
+ for k, v in old_classdict.items():
374
+ if k in base_members:
375
+ raise AttributeError (" Enumeration extensions cannot override "
376
+ " existing enumeration members" )
377
+
378
+ classdict[k] = v
379
+
380
+ res = super (_EnumExtension, metacls).__new__(metacls, name,
381
+ bases, classdict)
382
+
383
+ # replace the old with the new
384
+ for k, v in res.__dict__ .items():
385
+ if (k not in (' __module__' , ' __qualname__' , ' __doc__' ) and
386
+ k in adds_to.__dict__ ):
387
+ setattr (adds_to, k, v)
388
+
389
+ # preserve enum semantics
390
+ for member in adds_to.__members__ .values():
391
+ member.__class__ = adds_to
392
+
393
+ # always return the original
394
+ return adds_to
0 commit comments