This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: gotcha: _fields_ is final but accepts lists
Type: behavior Stage:
Components: ctypes Versions: Python 2.5
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: theller Nosy List: amaury.forgeotdarc, cscheid, theller
Priority: normal Keywords:

Created on 2008-04-24 16:29 by cscheid, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (4)
msg65728 - (view) Author: Carlos Scheidegger (cscheid) Date: 2008-04-24 16:29
When creating ctypes.Structure classes dynamically, there's a gotcha.
_fields_ is final, but it takes a list that can be appended to. I'm not
sure this is a bug, but I would argue it is a lot more surprising than
it could be:

Python 2.5.2 (r252:60911, Apr 21 2008, 11:17:30) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> class Foo(ctypes.Structure):
...  _fields_ = [('dim', ctypes.c_int)]
... 
>>> x = Foo()
>>> x.dim = 1
>>> x.dim = '123' # This is ok, and expected
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> 
>>> 
>>> class Bar(ctypes.Structure):
...  pass
... 
>>> x._fields_ = []
>>> x._fields_.append(('dim', ctypes.c_int))
>>> x = Bar()
>>> x.dim = '123' # This, however, is strange
>>>

This was somewhat foreseen, since _fields_ is final:

>>> class Baz(ctypes.Structure):
...  pass
... 
>>> Baz._fields_ = []
>>> Baz._fields_ = [('dim', ctypes.c_int)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: _fields_ is final

Would it not make sense for _fields_ to require a tuple, so that it
cannot be mutated? I realize this is a big change. Currently, ctypes
accepts tuples as the input to _fields_. Maybe a warning should be
issued when a list is assigned to _fields_?
msg65730 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-04-24 17:42
The __slots__ member of a class object has the same behavior.
You may mutate it (even replace it) but this has no effect: only the
value available when the "class" statement was executed is relevant.
msg65731 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2008-04-24 17:54
> The __slots__ member of a class object has the same behavior.
> You may mutate it (even replace it) but this has no effect: only the
> value available when the "class" statement was executed is relevant.

The rules in ctypes are a little bit more complicated (but thanks for the
__slots__ example, Amaury):

The _fields_ sequence is used when the class statement is executed (if
_fields_ are given), or when _fields_ are assigned to the class.
The third case appears when an instance of a structure class without _fields_
is actually *used*: by creating an instance of the class, by using the
class in another structure _fields_ definition; in this case the structure class
is built with an empty _fields_ list.

To answer the OP quetsions:  Yes, disallowing lists as _fields_ would break
too much code.  Also, I think tuples in lists are easier to read than nested tuples.
msg65732 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2008-04-24 17:54
Closing as won't fix.
History
Date User Action Args
2022-04-11 14:56:33adminsetgithub: 46932
2008-04-24 17:54:48thellersetstatus: open -> closed
resolution: wont fix
messages: + msg65732
2008-04-24 17:54:07thellersetmessages: + msg65731
2008-04-24 17:42:56amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg65730
2008-04-24 16:29:57cscheidcreate