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: Extended storage in new-style classes
Type: enhancement Stage: test needed
Components: Interpreter Core Versions:
process
Status: closed Resolution: works for me
Dependencies: Superseder:
Assigned To: Nosy List: BreamoreBoy, ajaksu2, amaury.forgeotdarc, dabrahams, david_abrahams, ethan.furman, loewis
Priority: low Keywords:

Created on 2002-02-09 00:51 by david_abrahams, last changed 2022-04-10 16:04 by admin. This issue is now closed.

Messages (9)
msg61081 - (view) Author: David Abrahams (david_abrahams) Date: 2002-02-09 00:51
I want to be able to reserve some storage in my own 
new-style class objects. Ideally the storage would 
fall before the variable-length section so I didn't 
have to worry about alignment issues.

-Dave
msg61082 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2002-02-17 00:10
Logged In: YES 
user_id=21627

I cannot fully understand the requirement. Are you talking
about a type implemented in C, or a class in Python?

Assuming it is a C type: Are you defining a type that
inherits from a builtin, or one that doesn't.

Assuming does not inherit: what is the problem with just
setting tp_basicsize correctly?

If it is a C type and it does inherit from a variable-length
builtin, this won't be possible: the API for the base type
won't know about the extra fields. In that case, extend the
type so that it has an __dict__ and put everything into the
dict.
msg61083 - (view) Author: David Abrahams (david_abrahams) Date: 2002-02-17 01:05
Logged In: YES 
user_id=52572

It's a C subtype of PyBaseObjectType, and you can't just 
set tp_basicsize correctly because the base type has its 
own idea of where the variable length section starts and 
doesn't respect a difference in tp_basicsize. I've spoken 
with Guido about this; he understands all the details. I 
entered this feature request in the tracker at his request 
(the weakref subclassing was entered at Fred's request).
msg81811 - (view) Author: Daniel Diniz (ajaksu2) * (Python triager) Date: 2009-02-12 19:58
Seems very out of date.
msg114177 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-08-17 21:46
I'll close this unless there's a positive response within a couple of weeks.
msg114180 - (view) Author: Dave Abrahams (dabrahams) Date: 2010-08-17 21:56
I can't imagine what kind of "positive response" you'd want from me.  I responded to the last question asked.  I certainly don't know whether this is still an issue, though.
msg189495 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2013-05-18 03:54
David, is this still a need?  Or, put another way, has Python change enough in the last 11 years that you can now do what you wanted?
msg189496 - (view) Author: Dave Abrahams (dabrahams) Date: 2013-05-18 04:34
I have no idea. I don't work with low-level python much anymore. Sorry

Sent from my moss-covered three-handled family gradunza

On May 17, 2013, at 8:54 PM, Ethan Furman <report@bugs.python.org> wrote:

> 
> Ethan Furman added the comment:
> 
> David, is this still a need?  Or, put another way, has Python change enough in the last 11 years that you can now do what you wanted?
> 
> ----------
> nosy: +ethan.furman
> 
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue515074>
> _______________________________________
msg191022 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2013-06-12 12:28
Most concrete variable-sized types don't use tp_basicsize to know where the data lives. For example, PyBytesObject has a "char ob_sval[1];" member, and PyBytes_AsString() looks at this fixed offset.
For this reason, additional data cannot be stored before the variable-length section, only after.

It is possible to store data after the variable section, and CPython does it already for the __dict__ slot of user-defined classes::
    >>> bytes.__basicsize__
    33
    >>> class B(bytes): pass
    ...
    >>> B.__basicsize__
    41
    >>> B.__dictoffset__
    -8

Note that tp_basicsize was increased by the size of the additional data (here a PyObject*).
To access your data, the logic is something like::
    tp->tp_basicsize + (obj->ob_size * tp->tp_itemsize) - sizeof(MyData)
The function _PyObject_GetDictPtr() has similar code, and already aligns to the pointer size.

Of course, at the end of one object you cannot have *both* a __dict__ slot and custom data.
The custom type needs to either disallow subclassing, or provide a (negative) tp_dictoffset.
Also, some care may be required if the base class uses a custom allocator.

Overall, I think it's a bit involved, but doable.
I close the issue as "works for me", someone can reopen if there is something wrong in the base types.
History
Date User Action Args
2022-04-10 16:04:58adminsetgithub: 36073
2013-06-12 12:28:22amaury.forgeotdarcsetstatus: open -> closed

nosy: + amaury.forgeotdarc
messages: + msg191022

resolution: works for me
2013-05-18 04:34:58dabrahamssetmessages: + msg189496
2013-05-18 03:54:44ethan.furmansetnosy: + ethan.furman
messages: + msg189495
2010-08-17 21:56:44dabrahamssetstatus: pending -> open
nosy: + dabrahams
messages: + msg114180

2010-08-17 21:46:38BreamoreBoysetstatus: open -> pending
nosy: + BreamoreBoy
messages: + msg114177

2009-02-12 19:58:46ajaksu2setpriority: normal -> low
nosy: + ajaksu2
messages: + msg81811
stage: test needed
2002-02-09 00:51:52david_abrahamscreate