Commit b363f41b authored by Stefan Behnel's avatar Stefan Behnel

optimisation: do not build and test metaclass kwargs if we know the metaclass at compile time

parent c9ff1344
......@@ -2952,16 +2952,26 @@ class PyClassDefNode(ClassDefNode):
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, )
......
......@@ -102,8 +102,8 @@ directive_scopes = { # defaults to available everywhere
'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()
......@@ -22,6 +25,34 @@ class ODict(dict):
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():
......@@ -35,6 +66,7 @@ class Py3Base(type):
def __prepare__(*args, **kwargs):
return ODict()
@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Py3Foo(object, metaclass=Py3Base, foo=123):
"""
>>> obj = Py3Foo()
......@@ -49,6 +81,7 @@ class Py3Foo(object, metaclass=Py3Base, foo=123):
kwargs = {'foo': 123, 'bar': 456}
@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Py3Mixed(metaclass=Py3Base, **kwargs):
"""
>>> Py3Mixed.foo
......@@ -59,6 +92,7 @@ class Py3Mixed(metaclass=Py3Base, **kwargs):
kwargs['metaclass'] = Py3Base
@cython.test_assert_path_exists("//PyClassMetaclassNode")
class Py3Kwargs(**kwargs):
"""
>>> Py3Kwargs.foo
......@@ -81,6 +115,8 @@ class Base3(type):
return {}
kwargs = {'c': 0}
@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Foo3(metaclass=Base3, a=0, b=0, **kwargs):
"""
>>> Foo3.kwargs
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment