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.

Author rhettinger
Recipients rhettinger
Date 2011-01-21.23:49:23
SpamBayes Score 6.661338e-14
Marked as misclassified No
Message-id <1295653779.62.0.836506069174.issue10977@psf.upfronthosting.co.za>
In-reply-to
Content
Currently, the concrete object C API bypasses any methods defined on subclasses of builtin types.  

It has long been accepted that subclasses of builtin types need to override many methods rather than just a few because the type itself was implemented with direct internal calls.  This work-around requires extra work but still makes it possible to create a consistent subclass (a case-insensitive dictionary for example).

However, there is another problem with this workaround.  Any subclassed builtin may still be bypassed by other functions and methods using the concrete C API.

For example, the OrderedDict class overrides enough dict methods to make itself internally consistent and fully usable by all pure python code.  However, any builtin or extension using PyDict_SetItem() or PyDict_DelItem() will update the OrderedDict's internal unordered dict
and bypass all the logic keeping dict ordering invariants intact.  Note, this problem would still impact OrderedDict even if it were rewritten in C.  The concrete calls would directly access the original dict structure and ignore any of the logic implemented in the subclass (whether coded in pure python or in C).

Since OrderedDict is written in pure python, the consequence of having its invariants violated would result in disorganization, but not in a crash.  However if OrderedDict were rewritten in C, augmenting the inherited data structure with its own extra state, then this problem could result in seg-faulting.

Note this is only one example.  Pretty much any subclass of a builtin type that adds additional state is vulnerable to a concrete C API that updates only part of the state while leaving the extra state information in an inconsistent state.

Another example would be a list subclass that kept extra state tracking the number of None objects contained within.  There is no way to implement that subclass, either in C or pure python, even if every method were overridden, that wouldn't be rendered inconsistent by an external tool using PyList_SetItem().

My recommendation is to find all of the mutating methods for the concrete C API and add an alternate path for subclasses.  The alternate path should use the abstract API.

Pseudo-code for PyList_SetItem():

   if type(obj) is list:
      # proceed as currently implemented
   else:
      # use PyObject_SetItem() adapting the 
      # function parameters and return values if necessary
      # to match the API for PyList_SetItem().
   else:
      raise BadInternalCall('object should be a list')
History
Date User Action Args
2011-01-21 23:49:39rhettingersetrecipients: + rhettinger
2011-01-21 23:49:39rhettingersetmessageid: <1295653779.62.0.836506069174.issue10977@psf.upfronthosting.co.za>
2011-01-21 23:49:24rhettingerlinkissue10977 messages
2011-01-21 23:49:23rhettingercreate