On Mon, Jun 4, 2012 at 10:43 PM, Eric Snow <ericsnowcurrently@gmail.com>wrote:
On Mon, Jun 4, 2012 at 6:10 PM, PJ Eby <pje@telecommunity.com> wrote:
I mean that class-level __metaclass__ is no longer supported as of PEP 3115, so I can't use that as a way to non-invasively obtain the enclosing class at class creation time.
Depends on what you mean by non-invasive:
Non-invasive meaning, "not requiring the user of the descriptor or decorator to make extra declarations-at-a-distance, especially ones that increase the likelihood of clashing machinery if multiple frameworks require the same functionality." ;-) That means class decorators, mixins, and explicit metaclasses don't work. The class decorator adds yak shaving, and the others lead to functional clashing. Currently, my choices for porting these libraries (and their dependents) to Python 3 are (in roughly descending order of preference): 1. Replace __builtins__.__build_class__ and hope PyPy et al follow CPython's lead, 2. Abuse sys.set_trace() and __class__ to get a callback at the right moment (because set_trace() *is* supported on other implementations in practice right now, at least for 2.x), or 3. Write a class decorator like "@py3_is_less_dynamic_than_py2", put it in a common library, and ask everybody and their dog to use it on any class whose body contains any decorator or descriptor from any of my libraries (or which someone else *derived* from any of my libraries, etc. ad nauseam), oh and good luck finding which ones all of them are, and yeah, if you miss it, stuff might not work. (Note, by the way, that this goes against the advice of not changing APIs while migrating to Python 3... and let's not forget all the documentation that has to be changed, each piece of which must explain and motivate this new and apparently-pointless decorator to the library's user.) I would prefer to have an option 4 or 5 (where there's a standard Python way to get a class creation callback from a class body), but #1 is honestly the most attractive at the moment, as I might only need to implement it in *one* library, with no changes to clients, including people who've built stuff based on that library or any of its clients, recursively. (#2 would also do it, but I was *really* hoping to get rid of that hack in Python 3.) Given these choices, I hope it's more understandable why I'd want to lobby for at least documenting __build_class__ and its replaceability, and perhaps encouraging other Python 3 implementations to offer the same feature. Given that implementing PEP 3115 and types.new_class() mean the same functionality has to be present, and given that class creation is generally not a performance-critical function, there's little reason for a sufficiently dynamic Python implementation (by which I basically mean Jython, IronPython, and PyPy) to support it. (More-static implementations don't always even support metaclasses to begin with, so they're not going to lose anything important by not supporting dynamic __build_class__.)