Do not allow arbitrary attributes to be set on SWIG-wrapped structs in Python
Description
By default, SWIG-wrapped structs in Python allow any arbitrary attribute to be set, regardless of whether it matches an underlying field of the C struct. This makes it easy to assign to the wrong field due to a trivial typo, e.g. setting s.foo
when you meant to set s.Foo
, which can then be very hard to debug in large code bases. (Where s.foo
is actually stored is a mystery -- it doesn't show up in s.__dict__
for example -- which makes it more difficult to debug whether you've set a non-C-struct attribute.)
This MR enables the SWIG %pythonnondynamic
feature (there is no equivalent for Octave) to prevent arbitrary attributes to be set on SWIG-wrapped structs. (For those who might worry such a feature is "non-Pythonic", note that C structs are very much "non-Pythonic", and sometimes their SWIG wrappers must behave accordingly. Also, disallowing new attributes is not a world away from the behaviour of a namedtuple
.)
I'm not aware of any use cases where people are setting non-C-struct fields in SWIG wrappers, given that the latter are only useful for passing to C functions. It's far more likely that people are creating new Python wrapper classes, which use SWIG wrappers internally together with Python wrapper code. So IMHO it's unlikely this change will break anything. Indeed it's more likely to uncover bugs where the wrong C struct field has been set.
API Changes and Justification
Backwards Compatible Changes
-
This change does not modify any class/function/struct/type definitions in a public C header file or any Python class/function definitions -
This change adds new classes/functions/structs/types to a public C header file or Python module
Backwards Incompatible Changes
-
This change modifies an existing class/function/struct/type definition in a public C header file or Python module -
This change removes an existing class/function/struct/type from a public C header file or Python module
Review Status
N/A