From ac2dac9e99568a7582b00d091afaffde7ed79681 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 2 May 2008 04:22:48 -0400 Subject: First stage of __getattribute__ special method support. Works with test cases for a single class, have not dealt with subclass issues yet. --- Cython/Compiler/ModuleNode.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'Cython/Compiler/ModuleNode.py') diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index ade6af228..2b63c919f 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -666,7 +666,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): self.generate_ass_subscript_function(scope, code) if scope.defines_any(["__setslice__", "__delslice__"]): self.generate_ass_slice_function(scope, code) - if scope.defines_any(["__getattr__"]): + if scope.defines_any(["__getattr__","__getattribute__"]): self.generate_getattro_function(scope, code) if scope.defines_any(["__setattr__", "__delattr__"]): self.generate_setattro_function(scope, code) @@ -1030,27 +1030,36 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): "}") def generate_getattro_function(self, scope, code): - # First try to get the attribute using PyObject_GenericGetAttr. + # First try to get the attribute using __getattribute__, if defined, or + # PyObject_GenericGetAttr. + # # If that raises an AttributeError, call the user's __getattr__ - # method. - entry = scope.lookup_here("__getattr__") + # method, if defined. + getattr_entry = scope.lookup_here("__getattr__") + getattribute_entry = scope.lookup_here("__getattribute__") code.putln("") code.putln( "static PyObject *%s(PyObject *o, PyObject *n) {" % scope.mangle_internal("tp_getattro")) - code.putln( + if getattribute_entry is not None: + code.putln( + "PyObject *v = %s(o, n);" % + getattribute_entry.func_cname) + else: + code.putln( "PyObject *v = PyObject_GenericGetAttr(o, n);") - code.putln( + if getattr_entry is not None: + code.putln( "if (!v && PyErr_ExceptionMatches(PyExc_AttributeError)) {") - code.putln( - "PyErr_Clear();") - code.putln( - "v = %s(o, n);" % - entry.func_cname) - code.putln( + code.putln( + "PyErr_Clear();") + code.putln( + "v = %s(o, n);" % + getattr_entry.func_cname) + code.putln( "}") code.putln( - "return v;") + "return v;") code.putln( "}") -- cgit v1.2.1 From 6b56ec7391dba17f9b8fd02d0b94f4f753e30893 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Sun, 4 May 2008 23:28:40 -0400 Subject: __getattr(ibute)__ special methods now work with subclasses. --- Cython/Compiler/ModuleNode.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'Cython/Compiler/ModuleNode.py') diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 2b63c919f..eead6a445 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -1033,10 +1033,21 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): # First try to get the attribute using __getattribute__, if defined, or # PyObject_GenericGetAttr. # - # If that raises an AttributeError, call the user's __getattr__ - # method, if defined. - getattr_entry = scope.lookup_here("__getattr__") - getattribute_entry = scope.lookup_here("__getattribute__") + # If that raises an AttributeError, call the __getattr__ if defined. + # + # In both cases, defined can be in this class, or any base class. + def lookup_here_or_base(n,type=None): + # Recursive lookup + if type is None: + type = scope.parent_type + r = type.scope.lookup_here(n) + if r is None and \ + type.base_type is not None: + return lookup_here_or_base(n,type.base_type) + else: + return r + getattr_entry = lookup_here_or_base("__getattr__") + getattribute_entry = lookup_here_or_base("__getattribute__") code.putln("") code.putln( "static PyObject *%s(PyObject *o, PyObject *n) {" -- cgit v1.2.1 From 0aea8272512c851c48f4851e5883d16a27fbafac Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 9 May 2008 08:57:37 +0200 Subject: support enabling source annotation via CompilerOptions --- Cython/Compiler/ModuleNode.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Cython/Compiler/ModuleNode.py') diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index eead6a445..f7d1d3fbb 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -209,7 +209,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): def generate_c_code(self, env, options, result): modules = self.referenced_modules - if Options.annotate: + if Options.annotate or options.annotate: code = Annotate.AnnotationCCodeWriter(StringIO()) else: code = Code.CCodeWriter(StringIO()) @@ -239,14 +239,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): self.generate_declarations_for_modules(env, modules, code.h) - f = open_new_file(result.c_file) f.write(code.h.f.getvalue()) f.write("\n") f.write(code.f.getvalue()) f.close() result.c_file_generated = 1 - if Options.annotate: + if Options.annotate or options.annotate: self.annotate(code) code.save_annotation(result.c_file[:-1] + "pyx") # change? -- cgit v1.2.1 From bb72b52d5b6a5c5660182390d2110570cb8f74ac Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 9 May 2008 09:28:36 +0200 Subject: put the annotated .html file next to the .c file to fix annotation when the .c file is not in the same directory as the .pyx file --- Cython/Compiler/ModuleNode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Cython/Compiler/ModuleNode.py') diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index f7d1d3fbb..2acb1016b 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -247,7 +247,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): result.c_file_generated = 1 if Options.annotate or options.annotate: self.annotate(code) - code.save_annotation(result.c_file[:-1] + "pyx") # change? + code.save_annotation(result.main_source_file, result.c_file) def find_referenced_modules(self, env, module_list, modules_seen): if env not in modules_seen: -- cgit v1.2.1