From 60bf01b9bd2c71c17c4a63265421751ea31b949a Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sat, 20 Nov 2010 17:38:38 +0100 Subject: [PATCH] optimise Py3-style metaclass also when other keywords are provided --- Cython/Compiler/Nodes.py | 25 +++++++++++++++---------- tests/run/metaclass.pyx | 3 ++- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index a25033ce..c56fab70 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -2959,22 +2959,27 @@ class PyClassDefNode(ClassDefNode): self.py3_style_class = True self.bases = 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: + if keyword_args and not starstar_arg: + for i, item in list(enumerate(keyword_args.key_value_pairs))[::-1]: + if item.key.value == 'metaclass': + if self.metaclass is not None: + error(item.pos, "keyword argument 'metaclass' passed multiple times") + # special case: we already know the metaclass, + # so we don't need to do the "build kwargs, + # find metaclass" dance at runtime + self.metaclass = item.value + del keyword_args.key_value_pairs[i] + if starstar_arg or (keyword_args and keyword_args.key_value_pairs): self.mkw = ExprNodes.KeywordArgsNode( pos, keyword_args = keyword_args, starstar_arg = starstar_arg) + else: + self.mkw = ExprNodes.NullNode(pos) + if self.metaclass is None: 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, ) + mkw = self.mkw) self.classobj = ExprNodes.Py3ClassNode(pos, name = name, bases = self.bases, dict = self.dict, doc = doc_node, metaclass = self.metaclass, mkw = self.mkw) diff --git a/tests/run/metaclass.pyx b/tests/run/metaclass.pyx index 764c37fb..6e2fe0a8 100644 --- a/tests/run/metaclass.pyx +++ b/tests/run/metaclass.pyx @@ -66,7 +66,8 @@ class Py3Base(type): def __prepare__(*args, **kwargs): return ODict() -@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode") +@cython.test_fail_if_path_exists("//PyClassMetaclassNode") +@cython.test_assert_path_exists("//Py3ClassNode") class Py3Foo(object, metaclass=Py3Base, foo=123): """ >>> obj = Py3Foo() -- 2.26.2