[Pyrex] Shadowing of C globals

Sam Rushing sam-pyrex at rushing.nightmare.com
Thu Jan 26 21:13:42 CET 2006


Several times I've been bitten by this problem:

----------
cdef int counter

def fun1():
  counter = counter + 1

def fun2():
  global counter
  counter = counter + 1

----------

fun1() will fail with "you can't add 1 to None", whereas in Python it
you would get UnboundLocalError...

fun2() tells Pyrex that it's a global value, and does the expected
thing.

The usual pattern for this is to write a function that reads a global
variable, and then at some much later time change it to also update that
variable.  Surprise!

Now, reasonable people could argue for hours about what is the 'right'
thing to do here.  The current behavior is correct, because it's what
Python does (or close, anyway).  And I would never be surprised by it in
Python code.  However, once I've defined a global C variable my brain
somehow expects it to behave more like a C variable than a Python one.

I've found the following warning to be helpful - it actually found
*another* instance of this bug in my project the first time I used it.

--- d1/Pyrex/Compiler/ExprNodes.py      Mon Jun 13 17:39:17 2005
+++ d2/Pyrex/Compiler/ExprNodes.py  Wed Jan 25 17:43:37 2006
@@ -659,6 +659,12 @@
     
     def analyse_target_declaration(self, env):
         self.entry = env.lookup_here(self.name)
+        maybe_shadowed = env.lookup (self.name)
+        if maybe_shadowed is not None:
+            if maybe_shadowed != self.entry and maybe_shadowed.is_cglobal:
+                print "Warning: local '%s' shadows C global: %s:%d:%d" % (
+                    self.name, self.pos[0], self.pos[1], self.pos[2]
+                    )
         if not self.entry:
             self.entry = env.declare_var(self.name, 
                 PyrexTypes.py_object_type, self.pos)

-Sam




More information about the Pyrex mailing list