blob: 2bfcd9be8d9dc5c3b365e648b71f27dfea4e2a87 [file] [log] [blame]
Georg Brandle5a32dc2007-12-21 08:16:54 +00001"""
2Define names for built-in types that aren't directly accessible as a builtin.
Guido van Rossume7b146f2000-02-04 15:28:42 +00003"""
Guido van Rossum85d89451994-06-23 11:53:27 +00004import sys
5
Tim Peters26991a72001-09-25 22:02:03 +00006# 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 Brandla18af4e2007-04-21 15:47:16 +00009# "__iter__" and "__next__" attributes instead.
Tim Peters26991a72001-09-25 22:02:03 +000010
Guido van Rossumadc940e1994-09-29 10:04:43 +000011def _f(): pass
12FunctionType = type(_f)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000013LambdaType = type(lambda: None) # Same as FunctionType
Guido van Rossuma8add0e2007-05-14 22:03:55 +000014CodeType = type(_f.__code__)
Victor Stinner0db176f2012-04-16 00:16:30 +020015MappingProxyType = type(type.__dict__)
Guido van Rossum85d89451994-06-23 11:53:27 +000016
Tim Peters264c6592004-07-18 00:08:11 +000017def _g():
Tim Peters3e7b1a02001-06-25 19:46:25 +000018 yield 1
Tim Peters264c6592004-07-18 00:08:11 +000019GeneratorType = type(_g())
Tim Peters3e7b1a02001-06-25 19:46:25 +000020
Guido van Rossumadc940e1994-09-29 10:04:43 +000021class _C:
Guido van Rossum898c9151997-09-04 22:12:34 +000022 def _m(self): pass
Guido van Rossum65810fe2006-05-26 19:12:38 +000023MethodType = type(_C()._m)
Guido van Rossum85d89451994-06-23 11:53:27 +000024
Guido van Rossumadc940e1994-09-29 10:04:43 +000025BuiltinFunctionType = type(len)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000026BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
Guido van Rossum85d89451994-06-23 11:53:27 +000027
28ModuleType = type(sys)
Guido van Rossum85d89451994-06-23 11:53:27 +000029
30try:
Guido van Rossum898c9151997-09-04 22:12:34 +000031 raise TypeError
Guido van Rossum85d89451994-06-23 11:53:27 +000032except TypeError:
Guido van Rossuma8add0e2007-05-14 22:03:55 +000033 tb = sys.exc_info()[2]
34 TracebackType = type(tb)
35 FrameType = type(tb.tb_frame)
Guido van Rossumf15d1591997-09-29 23:22:12 +000036 tb = None; del tb
Guido van Rossum85d89451994-06-23 11:53:27 +000037
Christian Heimes5e696852008-04-09 08:37:03 +000038# For Jython, the following two types are identical
39GetSetDescriptorType = type(FunctionType.__code__)
40MemberDescriptorType = type(FunctionType.__globals__)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000041
42del sys, _f, _g, _C, # Not for export
Nick Coghlan7fc570a2012-05-20 02:34:13 +100043
44
45# Provide a PEP 3115 compliant mechanism for class creation
46def 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
53def 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
85def _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