[Python-Dev] PEP487: Simpler customization of class creation
Hi list, so this is the next round for PEP 487. During the last round, most of the comments were in the direction that a two step approach for integrating into Python, first in pure Python, later in C, was not a great idea and everything should be in C directly. So I implemented it in C, put it onto the issue tracker here: http://bugs.python.org/issue27366, and also modified the PEP accordingly. For those who had not been in the discussion, PEP 487 proposes to add two hooks, __init_subclass__ which is a classmethod called whenever a class is subclassed, and __set_owner__, a hook in descriptors which gets called once the class the descriptor is part of is created. While implementing PEP 487 I realized that there is and oddity in the type base class: type.__init__ forbids to use keyword arguments, even for the usual three arguments it has (name, base and dict), while type.__new__ allows for keyword arguments. As I plan to forward any keyword arguments to the new __init_subclass__, I stumbled over that. As I write in the PEP, I think it would be a good idea to forbid using keyword arguments for type.__new__ as well. But if people think this would be to big of a change, it would be possible to do it differently. Hoping for good comments Greetings Martin The PEP follows: PEP: 487 Title: Simpler customisation of class creation Version: $Revision$ Last-Modified: $Date$ Author: Martin Teichmann , Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 27-Feb-2015 Python-Version: 3.6 Post-History: 27-Feb-2015, 5-Feb-2016, 24-Jun-2016, 2-Jul-2016 Replaces: 422 Abstract Currently, customising class creation requires the use of a custom metaclass. This custom metaclass then persists for the entire lifecycle of the class, creating the potential for spurious metaclass conflicts. This PEP proposes to instead support a wide range of customisation scenarios through a new ``__init_subclass__`` hook in the class body, and a hook to initialize attributes. The new mechanism should be easier to understand and use than implementing a custom metaclass, and thus should provide a gentler introduction to the full power Python's metaclass machinery. Background == Metaclasses are a powerful tool to customize class creation. They have, however, the problem that there is no automatic way to combine metaclasses. If one wants to use two metaclasses for a class, a new metaclass combining those two needs to be created, typically manually. This need often occurs as a surprise to a user: inheriting from two base classes coming from two different libraries suddenly raises the necessity to manually create a combined metaclass, where typically one is not interested in those details about the libraries at all. This becomes even worse if one library starts to make use of a metaclass which it has not done before. While the library itself continues to work perfectly, suddenly every code combining those classes with classes from another library fails. Proposal While there are many possible ways to use a metaclass, the vast majority of use cases falls into just three categories: some initialization code running after class creation, the initalization of descriptors and keeping the order in which class attributes were defined. The first two categories can easily be achieved by having simple hooks into the class creation: 1. An ``__init_subclass__`` hook that initializes all subclasses of a given class. 2. upon class creation, a ``__set_owner__`` hook is called on all the attribute (descriptors) defined in the class, and The third category is the topic of another PEP 520. As an example, the first use case looks as follows:: >>> class SpamBase: ...# this is implicitly a @classmethod ...def __init_subclass__(cls, **kwargs): ...cls.class_args = kwargs ...super().__init_subclass__(cls, **kwargs) >>> class Spam(SpamBase, a=1, b="b"): ...pass >>> Spam.class_args {'a': 1, 'b': 'b'} The base class ``object`` contains an empty ``__init_subclass__`` method which serves as an endpoint for cooperative multiple inheritance. Note that this method has no keyword arguments, meaning that all methods which are more specialized have to process all keyword arguments. This general proposal is not a new idea (it was first suggested for inclusion in the language definition `more than 10 years ago`_, and a similar mechanism has long been supported by `Zope's ExtensionClass`_), but the situation has changed sufficiently in recent years that the idea is worth reconsidering for inclusion. The second part of the proposal adds an ``__set_owner__`` initializer for class attributes, especially if they are descriptors. Descriptors are defined in the body of a class, but they do not know anything about that class, they do not even know the name they are accessed with. They do get to know their owner once ``__get__`` is called, but still they do not know thei
Re: [Python-Dev] Request for CPython 3.5.3 release
Hi everybody, I fully understand that AsyncIO is a drop in the ocean of CPython, you're working to prepare the entire 3.5.3 release for December, not yet ready. However, you might create a 3.5.2.1 release with only this AsyncIO fix ? PEP 440 doesn't seem to forbid that even if I see only 3 digits examples in PEP, I only find an example with 4 digits: https://www.python.org/dev/peps/pep-0440/#version-specifiers If 3.5.2.1 or 3.5.3 are impossible to release before december, what are the alternative solutions for AsyncIO users ? 1. Use 3.5.1 and hope that Linux distributions won't use 3.5.2 ? 2. Patch by hand asyncio source code ? 3. Remove asyncio folder in CPython, and install asyncio via github repository ? 4. Anything else ? To be honest, I'm migrating an AsyncIO application from 3.4.3 to 3.5.1 with more than 10 000 lines of code, I'm really interested in to know if it's better to keep 3.4.3 for now, or if 3.5 branch is enough stable ? Have a nice week-end. -- Ludovic Gasc (GMLudo) http://www.gmludo.eu/ 2016-06-30 9:41 GMT+02:00 Larry Hastings : > On 06/28/2016 02:51 PM, Larry Hastings wrote: > > > On 06/28/2016 02:05 PM, Yury Selivanov wrote: > > Larry and the release team: would it be possible to make an > "emergency" 3.5.3 release? > > > I'd like to hear from the other asyncio reviewers: is this bug bad enough > to merit such an "emergency" release? > > > Thanks, > > > */arry* > > > There has been a distinct lack of "dear god yes Larry" emails so far. > This absence suggests that, no, it is not a bad enough bug to merit such a > release. > > If we stay to our usual schedule, I expect 3.5.3 to ship December-ish. > > > */arry* > > ___ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/gmludo%40gmail.com > > ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Request for CPython 3.5.3 release
On 2 July 2016 at 16:17, Ludovic Gasc wrote: > Hi everybody, > > I fully understand that AsyncIO is a drop in the ocean of CPython, you're > working to prepare the entire 3.5.3 release for December, not yet ready. > However, you might create a 3.5.2.1 release with only this AsyncIO fix ? That would be more work than just doing a 3.5.3 release, though - the problem isn't with the version number bump, it's with asking the release team to do additional work without clearly explaining the rationale for the request (more on that below). While some parts of the release process are automated, there's still a lot of steps to run through by a number of different people: https://www.python.org/dev/peps/pep-0101/. The first key question to answer in this kind of situation is: "Is there code that will run correctly on 3.5.1 that will now fail on 3.5.2?" (i.e. it's a regression introduced by the asyncio and coroutine changes in the point release rather than something that was already broken in 3.5.0 and 3.5.1). If the answer is "No", then it doesn't inhibit the 3.5.2 rollout in any way, and folks can wait until 3.5.3 for the fix. However, if the answer is "Yes, it's a new regression in 3.5.2" (as in this case), then the next question becomes "Is there an agreed resolution for the regression?" The answer to that is currently "No" - Yury's PR against the asyncio repo is still being discussed. Once the answer to that question is "Yes", *then* the question of releasing a high priority fix in a Python 3.5.3 release can be properly considered by answering the question "Of the folks using asyncio, what proportion of them are likely to encounter problems in upgrading to Python 3.5.2, and is there a workaround they can apply or alternate approach they can use to avoid the problem?". At the moment, Yury's explanation of the fix in the PR is (understandably) addressed at getting the problem resolved within the context of asyncio, and hence just describes the particular APIs affected, and the details of the incorrect behaviour. While that's an important step in the process, it doesn't provide a clear assessment of the *consequences* of the bug aimed at folks that aren't themselves deeply immersed in using asyncio, so we can't tell if the problem is "Some idiomatic code frequently recommended in user facing examples and used in third party asyncio based libraries may hang client processes" (which would weigh in favour of an early 3.5.3 release before people start encountering the regression in practice) or "Some low level API's not recommended for general use may hang if used in a particular non-idiomatic combination only likely to be encountered by event loop implementors" (which would suggest it may be OK to stick with the normal maintenance release cadence). > If 3.5.2.1 or 3.5.3 are impossible to release before december, Early maintenance releases are definitely possible, but the consequences of particular regressions need to be put into terms that make sense to the release team, which generally means stepping up from "APIs X, Y, and Z broke in this way" to "Users doing A, B, and C will be affected in this way". As an example of a case where an early maintenance release took place: several years ago, Python 2.6.3 happened to break both "from logging import *" (due to a missing entry in test___all__ letting an error in logging.__all__ through) and building extension modules with setuptools (due to a change in a private API that setuptools was monkeypatching). Those were considered significant enough for the 2.6.4 release to happen early. > what are the > alternative solutions for AsyncIO users ? > 1. Use 3.5.1 and hope that Linux distributions won't use 3.5.2 ? Linux distributions have mechanisms to carry patches (indeed, selective application of patches is one of the main benefits of using system packages over upstream ones), so any distro that rebases on 3.5.2 can be encouraged to add the fix once it lands regardless of whether or not Larry approves an additional maintenance release outside the normal cadence. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com