1 2cimport cython 3 4class Base(type): 5 def __new__(cls, name, bases, attrs): 6 attrs['metaclass_was_here'] = True 7 return type.__new__(cls, name, bases, attrs) 8 9@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode") 10class Foo(object): 11 """ 12 >>> obj = Foo() 13 >>> obj.metaclass_was_here 14 True 15 """ 16 __metaclass__ = Base 17 18 19def non_type_metaclass(name, bases, namespace): 20 namespace['BASES'] = [b.__name__ for b in bases] 21 namespace['NAME'] = name 22 return type(name, bases, namespace) 23 24class FunctionAsPy2Metaclass(object): 25 """ 26 >>> obj = FunctionAsPy2Metaclass() 27 >>> obj.NAME 28 'FunctionAsPy2Metaclass' 29 >>> obj.BASES 30 ['object'] 31 >>> obj.x 32 1 33 """ 34 __metaclass__ = non_type_metaclass 35 x = 1 36 37 38class ODict(dict): 39 def __init__(self): 40 dict.__init__(self) 41 self._order = [] 42 dict.__setitem__(self, '_order', self._order) 43 44 def __setitem__(self, key, value): 45 dict.__setitem__(self, key, value) 46 self._order.append(key) 47 48class Py3MetaclassPlusAttr(type): 49 def __new__(cls, name, bases, attrs, **kwargs): 50 assert isinstance(attrs, ODict), str(type(attrs)) 51 for key, value in kwargs.items(): 52 attrs[key] = value 53 attrs['metaclass_was_here'] = True 54 return type.__new__(cls, name, bases, attrs) 55 56 def __init__(self, cls, attrs, obj, **kwargs): 57 pass 58 59 @staticmethod 60 def __prepare__(*args, **kwargs): 61 return ODict() 62 63@cython.test_fail_if_path_exists("//PyClassMetaclassNode") 64@cython.test_assert_path_exists("//Py3ClassNode") 65class Py3ClassMCOnly(object, metaclass=Py3MetaclassPlusAttr): 66 """ 67 >>> obj = Py3ClassMCOnly() 68 >>> obj.bar 69 321 70 >>> obj.metaclass_was_here 71 True 72 >>> obj._order 73 ['__module__', '__qualname__', '__doc__', 'bar', 'metaclass_was_here'] 74 """ 75 bar = 321 76 77class Py3InheritedMetaclass(Py3ClassMCOnly): 78 """ 79 >>> obj = Py3InheritedMetaclass() 80 >>> obj.bar 81 345 82 >>> obj.metaclass_was_here 83 True 84 >>> obj._order 85 ['__module__', '__qualname__', '__doc__', 'bar', 'metaclass_was_here'] 86 """ 87 bar = 345 88 89class Py3Base(type): 90 def __new__(cls, name, bases, attrs, **kwargs): 91 assert isinstance(attrs, ODict), str(type(attrs)) 92 for key, value in kwargs.items(): 93 attrs[key] = value 94 return type.__new__(cls, name, bases, attrs) 95 96 def __init__(self, cls, attrs, obj, **kwargs): 97 pass 98 99 @staticmethod 100 def __prepare__(*args, **kwargs): 101 return ODict() 102 103@cython.test_fail_if_path_exists("//PyClassMetaclassNode") 104@cython.test_assert_path_exists("//Py3ClassNode") 105class Py3Foo(object, metaclass=Py3Base, foo=123): 106 """ 107 >>> obj = Py3Foo() 108 >>> obj.foo 109 123 110 >>> obj.bar 111 321 112 >>> obj._order 113 ['__module__', '__qualname__', '__doc__', 'bar', 'foo'] 114 """ 115 bar = 321 116 117@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode") 118class Py3FooInherited(Py3Foo, foo=567): 119 """ 120 >>> obj = Py3FooInherited() 121 >>> obj.foo 122 567 123 >>> obj.bar 124 321 125 >>> obj._order 126 ['__module__', '__qualname__', '__doc__', 'bar', 'foo'] 127 """ 128 bar = 321 129 130kwargs = {'foo': 123, 'bar': 456} 131 132@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode") 133class Py3Mixed(metaclass=Py3Base, **kwargs): 134 """ 135 >>> Py3Mixed.foo 136 123 137 >>> Py3Mixed.bar 138 456 139 """ 140 141kwargs['metaclass'] = Py3Base 142 143@cython.test_assert_path_exists("//PyClassMetaclassNode") 144class Py3Kwargs(**kwargs): 145 """ 146 >>> Py3Kwargs.foo 147 123 148 >>> Py3Kwargs.bar 149 456 150 """ 151 152class Base3(type): 153 def __new__(cls, name, bases, attrs, **kwargs): 154 kwargs['b'] = 2 155 return type.__new__(cls, name, bases, attrs) 156 157 def __init__(self, *args, **kwargs): 158 self.kwargs = kwargs 159 160 @staticmethod 161 def __prepare__(*args, **kwargs): 162 kwargs['a'] = 1 163 return {} 164 165kwargs = {'c': 0} 166 167@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode") 168class Foo3(metaclass=Base3, a=0, b=0, **kwargs): 169 """ 170 >>> sorted(Foo3.kwargs.items()) 171 [('a', 0), ('b', 0), ('c', 0)] 172 """ 173 174class PyClassWithNew(object): 175 """ 176 >>> PyClassWithNew(389) 177 389 178 """ 179 def __new__(self, arg): 180 return arg 181