On 29 September 2017 at 08:04, Ivan Levkivskyi <email@example.com> wrote:
>> How would you feel about calling it "__mro_entry__", as a mnemonic for
>> "the substitute entry to use instead of this object when calculating a
>> subclass MRO"?
> I don't have any preferences for the name, __mro_entry__ sounds equally OK
> to me.
I'd propose changing it then, as searching for "Python mro entry" is
likely to get people to the right place faster than searching for
"Python subclass base".
> I propose to update
> ``type.__new__`` to just give
> a better error message explaining this.
+1 from me, since that avoids ever resolving the list of bases twice.
> 3) Do we need to update types.new_class and types.prepare_class?
> Here I am not sure. These functions are rather utility functions and are
> designed to
> mimic in Python what __build_class__ does in C. I think we might add
> that does the same as its C counterpart. Then we can update types.new_class
> and types.prepare_class
> like you proposed, this will preserve their current API while
> types.new_class will match behaviour of __build_class__
Your suggestion for `types.__new__` gave me a different idea: what if
`types.prepare_class` *also* just raised an error when given a
non-class as a nominal base class?
Then if we added `types.resolve_bases` as a public API, a full
reimplementation of `types.new_class` would now look like:
resolved_bases = types.resolve_bases(bases)
mcl, ns, updated_kwds = types.prepare_class(name, resolved_bases, kwds)
ns["__orig_bases__"] = bases
mcl(name, resolved_bases, ns, **updated_kwds)
That way, `types.new_class` would transparently switch to the new
behaviour, while clients of any other dynamic type creation API could
do their own base class resolution, even if the type creation API they
were using didn't implicitly support MRO entry resolution.