Georg Brandl | e5a32dc | 2007-12-21 08:16:54 +0000 | [diff] [blame] | 1 | """ |
| 2 | Define names for built-in types that aren't directly accessible as a builtin. |
Guido van Rossum | e7b146f | 2000-02-04 15:28:42 +0000 | [diff] [blame] | 3 | """ |
Guido van Rossum | 85d8945 | 1994-06-23 11:53:27 +0000 | [diff] [blame] | 4 | import sys |
| 5 | |
Tim Peters | 26991a7 | 2001-09-25 22:02:03 +0000 | [diff] [blame] | 6 | # Iterators in Python aren't a matter of type but of protocol. A large |
| 7 | # and changing number of builtin types implement *some* flavor of |
| 8 | # iterator. Don't check the type! Use hasattr to check for both |
Georg Brandl | a18af4e | 2007-04-21 15:47:16 +0000 | [diff] [blame] | 9 | # "__iter__" and "__next__" attributes instead. |
Tim Peters | 26991a7 | 2001-09-25 22:02:03 +0000 | [diff] [blame] | 10 | |
Guido van Rossum | adc940e | 1994-09-29 10:04:43 +0000 | [diff] [blame] | 11 | def _f(): pass |
| 12 | FunctionType = type(_f) |
Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 13 | LambdaType = type(lambda: None) # Same as FunctionType |
Guido van Rossum | a8add0e | 2007-05-14 22:03:55 +0000 | [diff] [blame] | 14 | CodeType = type(_f.__code__) |
Victor Stinner | 0db176f | 2012-04-16 00:16:30 +0200 | [diff] [blame] | 15 | MappingProxyType = type(type.__dict__) |
Guido van Rossum | 85d8945 | 1994-06-23 11:53:27 +0000 | [diff] [blame] | 16 | |
Tim Peters | 264c659 | 2004-07-18 00:08:11 +0000 | [diff] [blame] | 17 | def _g(): |
Tim Peters | 3e7b1a0 | 2001-06-25 19:46:25 +0000 | [diff] [blame] | 18 | yield 1 |
Tim Peters | 264c659 | 2004-07-18 00:08:11 +0000 | [diff] [blame] | 19 | GeneratorType = type(_g()) |
Tim Peters | 3e7b1a0 | 2001-06-25 19:46:25 +0000 | [diff] [blame] | 20 | |
Guido van Rossum | adc940e | 1994-09-29 10:04:43 +0000 | [diff] [blame] | 21 | class _C: |
Guido van Rossum | 898c915 | 1997-09-04 22:12:34 +0000 | [diff] [blame] | 22 | def _m(self): pass |
Guido van Rossum | 65810fe | 2006-05-26 19:12:38 +0000 | [diff] [blame] | 23 | MethodType = type(_C()._m) |
Guido van Rossum | 85d8945 | 1994-06-23 11:53:27 +0000 | [diff] [blame] | 24 | |
Guido van Rossum | adc940e | 1994-09-29 10:04:43 +0000 | [diff] [blame] | 25 | BuiltinFunctionType = type(len) |
Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 26 | BuiltinMethodType = type([].append) # Same as BuiltinFunctionType |
Guido van Rossum | 85d8945 | 1994-06-23 11:53:27 +0000 | [diff] [blame] | 27 | |
| 28 | ModuleType = type(sys) |
Guido van Rossum | 85d8945 | 1994-06-23 11:53:27 +0000 | [diff] [blame] | 29 | |
| 30 | try: |
Guido van Rossum | 898c915 | 1997-09-04 22:12:34 +0000 | [diff] [blame] | 31 | raise TypeError |
Guido van Rossum | 85d8945 | 1994-06-23 11:53:27 +0000 | [diff] [blame] | 32 | except TypeError: |
Guido van Rossum | a8add0e | 2007-05-14 22:03:55 +0000 | [diff] [blame] | 33 | tb = sys.exc_info()[2] |
| 34 | TracebackType = type(tb) |
| 35 | FrameType = type(tb.tb_frame) |
Guido van Rossum | f15d159 | 1997-09-29 23:22:12 +0000 | [diff] [blame] | 36 | tb = None; del tb |
Guido van Rossum | 85d8945 | 1994-06-23 11:53:27 +0000 | [diff] [blame] | 37 | |
Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 38 | # For Jython, the following two types are identical |
| 39 | GetSetDescriptorType = type(FunctionType.__code__) |
| 40 | MemberDescriptorType = type(FunctionType.__globals__) |
Thomas Wouters | 0e3f591 | 2006-08-11 14:57:12 +0000 | [diff] [blame] | 41 | |
| 42 | del sys, _f, _g, _C, # Not for export |
Nick Coghlan | 7fc570a | 2012-05-20 02:34:13 +1000 | [diff] [blame^] | 43 | |
| 44 | |
| 45 | # Provide a PEP 3115 compliant mechanism for class creation |
| 46 | def new_class(name, bases=(), kwds=None, exec_body=None): |
| 47 | """Create a class object dynamically using the appropriate metaclass.""" |
| 48 | meta, ns, kwds = prepare_class(name, bases, kwds) |
| 49 | if exec_body is not None: |
| 50 | exec_body(ns) |
| 51 | return meta(name, bases, ns, **kwds) |
| 52 | |
| 53 | def prepare_class(name, bases=(), kwds=None): |
| 54 | """Call the __prepare__ method of the appropriate metaclass. |
| 55 | |
| 56 | Returns (metaclass, namespace, kwds) as a 3-tuple |
| 57 | |
| 58 | *metaclass* is the appropriate metaclass |
| 59 | *namespace* is the prepared class namespace |
| 60 | *kwds* is an updated copy of the passed in kwds argument with any |
| 61 | 'metaclass' entry removed. If no kwds argument is passed in, this will |
| 62 | be an empty dict. |
| 63 | """ |
| 64 | if kwds is None: |
| 65 | kwds = {} |
| 66 | else: |
| 67 | kwds = dict(kwds) # Don't alter the provided mapping |
| 68 | if 'metaclass' in kwds: |
| 69 | meta = kwds.pop('metaclass') |
| 70 | else: |
| 71 | if bases: |
| 72 | meta = type(bases[0]) |
| 73 | else: |
| 74 | meta = type |
| 75 | if isinstance(meta, type): |
| 76 | # when meta is a type, we first determine the most-derived metaclass |
| 77 | # instead of invoking the initial candidate directly |
| 78 | meta = _calculate_meta(meta, bases) |
| 79 | if hasattr(meta, '__prepare__'): |
| 80 | ns = meta.__prepare__(name, bases, **kwds) |
| 81 | else: |
| 82 | ns = {} |
| 83 | return meta, ns, kwds |
| 84 | |
| 85 | def _calculate_meta(meta, bases): |
| 86 | """Calculate the most derived metaclass.""" |
| 87 | winner = meta |
| 88 | for base in bases: |
| 89 | base_meta = type(base) |
| 90 | if issubclass(winner, base_meta): |
| 91 | continue |
| 92 | if issubclass(base_meta, winner): |
| 93 | winner = base_meta |
| 94 | continue |
| 95 | # else: |
| 96 | raise TypeError("metaclass conflict: " |
| 97 | "the metaclass of a derived class " |
| 98 | "must be a (non-strict) subclass " |
| 99 | "of the metaclasses of all its bases") |
| 100 | return winner |