[Python-Dev] buglet in interaction between pygame, Numeric & copy in Python 2.3

Alex Martelli aleaxit@yahoo.com
Thu, 31 Jul 2003 18:06:12 +0200

I'm sending this buglet-report to the discussion lists for each of pygame, 
Numeric, and Python-Dev, because it ends with a recommendation for changes 
(at least to docs) in each of the two extension packages and Python 2.3.1.

I'm not a regular user of pygame [I am one of Numeric].  I helped some pygame 
users find out why their program was breaking (in just one point) when 
migrating Python 2.2 -> 2.3 (Numeric 23.0, pygame 1.5.6 from cvs snapshot).

The problem can be narrowed down the following little buglet.py script:

import copy, pygame.display, pygame.surfarray

screen = pygame.display.set_mode((640,480),0,24)
surf = pygame.surfarray.pixels3d(screen)
xx = copy.copy(surf[10:20,30])

With python 2.2, this runs without errors.  With 2.3:

Traceback (most recent call last):
  File "buglet.py", line 6, in ?
    xx = copy.copy(surf[10:20,30])
  File "/usr/local/lib/python2.3/copy.py", line 101, in copy
    raise Error("un(shallow)copyable object of type %s" % cls)
copy.Error: un(shallow)copyable object of type <type 'array'>

Workaround for the problem: add an "import Numeric" at the top of buglet.py.

Reason for the problem: copy.copy uses different mechanisms in 2.3 vs 2.2 for 
shallow copies of Numeric.array instances.  In 2.2, it looked for a method 
__copy__ on the instance, found it, and happily used it.  In 2.3, it relies 
on getting a 'reductor' function from the copy_reg.dispatch_table.  Module
Numeric installs such a reductor *WHEN IMPORTED* -- but pygame never 
imports it even though functions such as the above-used pixels3d do return
instances of Numeric.array.  So, Numeric.py doesn't run, and therefore cannot 
install its pickle_array function with the copy_reg module.

Suggested fix in pygame: I would suggest making sure Numeric has been
imported when Numeric.array instances are to be returned.  That's up to the
pygame maintainers, of course; at the very least, I think this issue should
be mentioned in pygame's docs (asking the user to make sure "import Numeric" 
happens in any pygame-using program that manipulates such instances).

Suggested fix in Numeric: Numeric cannot DO anything much about this issue, I 
think, but it should probably *mention* (in the docs regarding interfacing to 
Numeric from other C-coded extensions) that other extensions should make sure 
Numeric is _imported_ (from a Python POV), if said extensions return 
instances of Numeric.array, to ensure such instances have full functionality 
(and in particular shallow copyability).

Suggested fix in Python: a mention in the "what's new" document, section 
"porting to Python 2.3", is probably warranted -- not so much about Numeric 
and/or pygame extensions per se, though these are both popular 3rd party 
extensions, but rather the excellent changes in the shallow copy mechanics, 
which may indeed require code changes on the part of extension authors.