Commit d17e481c authored by Robert Bradshaw's avatar Robert Bradshaw

Better error when using non-existant attributes from cimported modules.

When not imported, this caused was a runtime NameError.  Now an error
is given at compile time.
parent 71383c16
...@@ -1858,6 +1858,9 @@ class NameNode(AtomicExprNode): ...@@ -1858,6 +1858,9 @@ class NameNode(AtomicExprNode):
self.entry = env.declare_var(self.name, type, self.pos) self.entry = env.declare_var(self.name, type, self.pos)
if self.entry.is_declared_generic: if self.entry.is_declared_generic:
self.result_ctype = py_object_type self.result_ctype = py_object_type
if self.entry.as_module:
# cimported modules namespace can shadow actual variables
self.entry.is_variable = 1
def analyse_types(self, env): def analyse_types(self, env):
self.initialized_check = env.directives['initializedcheck'] self.initialized_check = env.directives['initializedcheck']
...@@ -1963,10 +1966,16 @@ class NameNode(AtomicExprNode): ...@@ -1963,10 +1966,16 @@ class NameNode(AtomicExprNode):
or entry.is_cpp_class): or entry.is_cpp_class):
if self.entry.as_variable: if self.entry.as_variable:
self.entry = self.entry.as_variable self.entry = self.entry.as_variable
else: elif not self.is_cython_module:
error(self.pos, error(self.pos,
"'%s' is not a constant, variable or function identifier" % self.name) "'%s' is not a constant, variable or function identifier" % self.name)
def is_cimported_module_without_shadow(self, env):
if self.is_cython_module or self.cython_attribute:
return False
entry = self.entry or env.lookup(self.name)
return entry.as_module and not entry.is_variable
def is_simple(self): def is_simple(self):
# If it's not a C variable, it'll be in a temp. # If it's not a C variable, it'll be in a temp.
return 1 return 1
...@@ -6374,6 +6383,9 @@ class AttributeNode(ExprNode): ...@@ -6374,6 +6383,9 @@ class AttributeNode(ExprNode):
entry.is_cglobal or entry.is_cfunction entry.is_cglobal or entry.is_cfunction
or entry.is_type or entry.is_const): or entry.is_type or entry.is_const):
return self.as_name_node(env, entry, target) return self.as_name_node(env, entry, target)
if self.is_cimported_module_without_shadow(env):
error(self.pos, "cimported module has no attribute '%s'" % self.attribute)
return self
return None return None
def analyse_as_type_attribute(self, env): def analyse_as_type_attribute(self, env):
...@@ -6610,6 +6622,9 @@ class AttributeNode(ExprNode): ...@@ -6610,6 +6622,9 @@ class AttributeNode(ExprNode):
gil_message = "Accessing Python attribute" gil_message = "Accessing Python attribute"
def is_cimported_module_without_shadow(self, env):
return self.obj.is_cimported_module_without_shadow(env)
def is_simple(self): def is_simple(self):
if self.obj: if self.obj:
return self.result_in_temp() or self.obj.is_simple() return self.result_in_temp() or self.obj.is_simple()
......
...@@ -1255,6 +1255,7 @@ class ModuleScope(Scope): ...@@ -1255,6 +1255,7 @@ class ModuleScope(Scope):
return entry return entry
else: else:
entry = self.declare_var(name, py_object_type, pos) entry = self.declare_var(name, py_object_type, pos)
entry.is_variable = 0
entry.as_module = scope entry.as_module = scope
self.add_imported_module(scope) self.add_imported_module(scope)
return entry return entry
......
# mode: compile # mode: compile
cimport libc cimport libc.stdio
from libc cimport stdio from libc cimport stdio
from libc.stdio cimport printf, puts, fputs, putchar, fputc, putc, stdout from libc.stdio cimport printf, puts, fputs, putchar, fputc, putc, stdout
libc.stdio.printf("hello %s\n", b"world") with nogil:
stdio.printf("hello %s\n", b"world") libc.stdio.printf("hello %s\n", b"world")
printf("hello %s\n", b"world") stdio.printf("hello %s\n", b"world")
printf("printf_output %d %d\n", 1, 2) printf("hello %s\n", b"world")
puts("puts_output") printf("printf_output %d %d\n", 1, 2)
fputs("fputs_output", stdout) puts("puts_output")
putchar(b'z') fputs("fputs_output", stdout)
fputc(b'x', stdout) putchar(b'z')
putc(b'c', stdout) fputc(b'x', stdout)
putc(b'c', stdout)
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