import ExprNodes
if self.doc and Options.docstrings:
doc = embed_position(self.pos, self.doc)
- # FIXME: correct string node?
doc_node = ExprNodes.StringNode(pos, value = doc)
else:
doc_node = None
if keyword_args or starstar_arg:
self.py3_style_class = True
self.bases = bases
- self.mkw = ExprNodes.KeywordArgsNode(pos,
- keyword_args = keyword_args, starstar_arg = starstar_arg)
- self.metaclass = ExprNodes.PyClassMetaclassNode(pos, mkw = self.mkw, bases = self.bases)
+ self.metaclass = None
+ if keyword_args and not starstar_arg and len(keyword_args.key_value_pairs) == 1:
+ item = keyword_args.key_value_pairs[0]
+ if item.key.value == 'metaclass':
+ # special case: we already know the metaclass and
+ # it's the only kwarg, so we don't need to do the
+ # "build kwargs, find metaclass" dance at runtime
+ self.metaclass = item.value
+ self.mkw = ExprNodes.NullNode(pos)
+ if self.metaclass is None:
+ self.mkw = ExprNodes.KeywordArgsNode(
+ pos, keyword_args = keyword_args, starstar_arg = starstar_arg)
+ self.metaclass = ExprNodes.PyClassMetaclassNode(
+ pos, mkw = self.mkw, bases = self.bases)
self.dict = ExprNodes.PyClassNamespaceNode(pos, name = name,
doc = doc_node, metaclass = self.metaclass, bases = self.bases,
mkw = self.mkw, )
'autotestdict' : ('module',),
'autotestdict.all' : ('module',),
'autotestdict.cdef' : ('module',),
- 'test_assert_path_exists' : ('function',),
- 'test_fail_if_path_exists' : ('function',),
+ 'test_assert_path_exists' : ('function', 'class', 'cclass'),
+ 'test_fail_if_path_exists' : ('function', 'class', 'cclass'),
}
def parse_directive_value(name, value, relaxed_bool=False):
+cimport cython
+
class Base(type):
def __new__(cls, name, bases, attrs):
attrs['metaclass_was_here'] = True
return type.__new__(cls, name, bases, attrs)
+@cython.test_fail_if_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Foo(object):
"""
>>> obj = Foo()
dict.__setitem__(self, key, value)
self._order.append(key)
+class Py3MetaclassPlusAttr(type):
+ def __new__(cls, name, bases, attrs, **kwargs):
+ for key, value in kwargs.items():
+ attrs[key] = value
+ attrs['metaclass_was_here'] = True
+ return type.__new__(cls, name, bases, attrs)
+
+ def __init__(self, cls, attrs, obj, **kwargs):
+ pass
+
+ @staticmethod
+ def __prepare__(*args, **kwargs):
+ return ODict()
+
+@cython.test_fail_if_path_exists("//PyClassMetaclassNode")
+@cython.test_assert_path_exists("//Py3ClassNode")
+class Py3ClassMCOnly(object, metaclass=Py3MetaclassPlusAttr):
+ """
+ >>> obj = Py3ClassMCOnly()
+ >>> obj.bar
+ 321
+ >>> obj.metaclass_was_here
+ True
+ >>> obj._order
+ ['__module__', '__doc__', 'bar', 'metaclass_was_here']
+ """
+ bar = 321
+
class Py3Base(type):
def __new__(cls, name, bases, attrs, **kwargs):
for key, value in kwargs.items():
def __prepare__(*args, **kwargs):
return ODict()
+@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Py3Foo(object, metaclass=Py3Base, foo=123):
"""
>>> obj = Py3Foo()
kwargs = {'foo': 123, 'bar': 456}
+@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Py3Mixed(metaclass=Py3Base, **kwargs):
"""
>>> Py3Mixed.foo
kwargs['metaclass'] = Py3Base
+@cython.test_assert_path_exists("//PyClassMetaclassNode")
class Py3Kwargs(**kwargs):
"""
>>> Py3Kwargs.foo
return {}
kwargs = {'c': 0}
+
+@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Foo3(metaclass=Base3, a=0, b=0, **kwargs):
"""
>>> Foo3.kwargs