On 5 Oct 2021, at 18:39, Victor Stinner vstinner@python.org wrote:
Using Py_SET_TYPE() to change a type base class is not correct. You should set the __class__ attribute instead using PyObject_SetAttr(). The implementation is way more complex!
I agree that in general you should call PyObject_SetAttr().
That said, I think I’m fine here, other than a change in 3.9 where instances of heap types now own a reference to their type. The scenario where I do this are very specific, and because of that none of the guards in object_set_class would trigger. I won’t bore you with the details.
This is code that has worked without problems for way over a decade. I might change PyObjC anyway, the code in question should not be performance critical and I’m slowly cleaning up code that’s too magical for its own good.
The other instance of Py_SET_TYPE in PyObjC is more problematic and depends too much on implementation details of CPython. Annoyingly that’s also a use were calling PyObject_SetAttr won’t work. Coming up with a fix for that will be interesting :-).
One of these days I should write up where PyObjC peeks and pokes into non-public APIs, and what functionality would help to avoid that. I’d love to end up in a future where I could use the stable ABI for PyObjC, although that won’t be easy.
Ronald
Victor
On Tue, Oct 5, 2021 at 5:38 PM Ronald Oussoren ronaldoussoren@mac.com wrote:
On 5 Oct 2021, at 17:07, Victor Stinner vstinner@python.org wrote:
On Tue, Oct 5, 2021 at 2:26 PM Ronald Oussoren ronaldoussoren@mac.com wrote:
A problem with Py_SET_TYPE is that it has no way to report errors, which means it is not compatible with tagged pointers.
IMHO future proof API should always have a way to report errors (for example through a return value), even if the current CPython implementation will always succed.
Btw. I don’t particularly mind minor changes like the introduction of Py_SET_TYPE because adopting these is can almost be done mechanically.
Py_SET_TYPE() is weird workaround for limited C compilers (Windows MSC) which don't support referencing a base type using "&PyLong_Type" syntax when defining a type statically in C (".tp_base = &PyLong_Type,").
If you only define heap types, it's not needed.
Note quite ;-). I have some calls in PyObjC that dynamically change the type of an object. One changes the type of a python proxy for an Objective-C object when the type of that object change (which can happen in ObjC).
Another one looks a lot more dodgy as it changes the type of an instance of a builtin type, I’ve made a note to look into that. I guess that’s a clear argument in favour of the struct-hiding work you’ve been doing. You never know what strange things users do when they can poke directly into implementation details.
Py_SET_REFCNT() and Py_SET_TYPE() should not be part of the limited C API. I chose to add them anyway because it was possible to access directly PyObject.ob_refcnt and PyObject.ob_type in Python 3.9 and older. I'm not sure about Py_SET_SIZE() and the limited C API. Again, I added it since it was already possible to access PyVarObject.ob_size before.
I agree with adding those macros, I never particularly liked “Py_TYPE(obj) = value”. The new API looks cleaner to me, and adding APIs that lead to cleaner code, or are harder to misuse is likely a net positive.
Ronald
Victor
Night gathers, and now my watch begins. It shall not end until my death.
capi-sig mailing list -- capi-sig@python.org To unsubscribe send an email to capi-sig-leave@python.org https://mail.python.org/mailman3/lists/capi-sig.python.org/ Member address: ronaldoussoren@mac.com
—
Twitter / micro.blog: @ronaldoussoren Blog: https://blog.ronaldoussoren.net/
-- Night gathers, and now my watch begins. It shall not end until my death.
capi-sig mailing list -- capi-sig@python.org To unsubscribe send an email to capi-sig-leave@python.org https://mail.python.org/mailman3/lists/capi-sig.python.org/ Member address: ronaldoussoren@mac.com
—
Twitter / micro.blog: @ronaldoussoren Blog: https://blog.ronaldoussoren.net/