
Hi Nick, hi List, thanks for the good comments! I'll update the PEP and the implementation soon, as discussed at the end, I'll do it in C this time. For now just some quick responses:
This part isn't entirely clear to me, so you may want to give some Python pseudo-code that:
I will actually give the actual code, it's just 10 lines, that should be understandable.
- is explicit regarding exactly when this new code runs in the type creation process - whether the __set_owner__ hooks are called before or after __init_subclass__ runs, or only when the subclass calls up to super().__init_subclass__, and the implications of each choice (either descriptors see a partially initialised class object, or init_subclass sees partially initialised descriptor objects, or that choice is delegated to individual subclasses) - how the list of objects to be checked for "__set_owner__" methods is retrieved (presumably via "ns.items()" on the class definition namespace, but the PEP should be explicit)
For the second point, my personal preference would be for descriptors to have their owner set first and independently of __init_subclass__ super calls (as it seems more likely that __init_subclass__ will depend on having access to fully initialised descriptors than the other way around).
I intuitively programmed it the other way around, but I get your point and will change it. I agree that it should not be done in super().__init_subclass__ as people often forget to call it, or do weird things.
Honestly though, I'm not sure this additional user-visible complexity is worth it - "The default type metaclass has this new behaviour" is a lot easier to document and explain than "We added a new opt-in alternate metaclass that you can use if you want, and in the next version that will just become an alias for the builtin types again". We'd also end up being stuck with types.Type and types.Object as aliases for the type and object builtins forever (with the associated "How does 'class name:' or 'class name(object)' differ from 'class name(types.Object)'?" question and "It doesn't, unless you're using Python 3.6" answer for folks learning the language for the first time).
My idea with a stepped approach was to have a chance to look how people use the feature, so that when we make it standard eventually we actually get it right. In the end, this is a maintainability question. I am fully OK with following experienced core developers here, so if the general idea here is that a two-step approach is not needed, then no problem, let's do it in the Python core directly! Greetings Martin