Re: [Python-Dev] PEP487: Simpler customization of class creation
On 28 July 2016 at 13:55, Joao S. O. Bueno wrote: > Actually, as documented on the PEP (and I just confirmed at a Python > 3.5 prompt), > you actually can't use custom keywords for class defintions. This PEP > fixes that, but at the same time makes any other class reserved > keyword impossible in the future - that is, unless a single line > warning against reserved name patterns is added. We don't warn against people defining new dunder-protocols as methods, why would we warn against a similar breach of convention in this case? I'm also wondering how you would want such a warning to work if we ever claimed a parameter name for a base class in the standard library, but didn't claim it as a name supported by type/object. Note that I'm not denying that it *may* be annoying *if* we define a new universal class parameter at some point in the future *and* it collides with a custom parameter in a pre-existing API *and* the authors of that API miss the related PEP. However, given that we've come up with exactly one named class parameter to date (metaclass), and explicitly decided against adding another (namespace, replaced with PEP 520's simpler option of just making the standard namespace provide attribute ordering data), the odds of actually encountering the posited problematic scenario seem pretty remote. Regards, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia ___ Python-Dev mailing list [email protected] https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP487: Simpler customization of class creation
On 28 July 2016 at 04:26, Nick Coghlan wrote: > On 28 July 2016 at 13:55, Joao S. O. Bueno wrote: >> Actually, as documented on the PEP (and I just confirmed at a Python >> 3.5 prompt), >> you actually can't use custom keywords for class defintions. This PEP >> fixes that, but at the same time makes any other class reserved >> keyword impossible in the future - that is, unless a single line >> warning against reserved name patterns is added. > > We don't warn against people defining new dunder-protocols as methods, > why would we warn against a similar breach of convention in this case? > I'm also wondering how you would want such a warning to work if we > ever claimed a parameter name for a base class in the standard > library, but didn't claim it as a name supported by type/object. > > Note that I'm not denying that it *may* be annoying *if* we define a > new universal class parameter at some point in the future *and* it > collides with a custom parameter in a pre-existing API *and* the > authors of that API miss the related PEP. > > However, given that we've come up with exactly one named class > parameter to date (metaclass), and explicitly decided against adding > another (namespace, replaced with PEP 520's simpler option of just > making the standard namespace provide attribute ordering data), the > odds of actually encountering the posited problematic scenario seem > pretty remote. That is alright. (Even though, I think somewhere around there are remarks against one putting forth his own dunder methods) . But that elaves another issue open: the "metaclass" parameter get in to a very odd position, in which it has nothing distinctive about it, still is the only parameter that will be swallowed and won't reach "__init_subclass__". Although I know it is not straightforward to implement (as the "metaclass" parameter is not passed to the metaclass __new__ or __init__), wouldn't it make sense to make it be passed to __init_subclass__ just like all other keywords? (the default __init_subclass__ then could swallow it, if it reaches there). I am putting the question now, because it is a matter of "now" or "never" - I can see it can does make sense if it is not passed down. Anyway, do you have any remarks on the first issue I raised? About __init_subclass__ being called in the class it is defined in, not just on it's descendant subclasses? > > Regards, > Nick. > > -- > Nick Coghlan | [email protected] | Brisbane, Australia ___ Python-Dev mailing list [email protected] https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP487: Simpler customization of class creation
On 28 July 2016 at 23:12, Joao S. O. Bueno wrote:
> Although I know it is not straightforward to implement (as the
> "metaclass" parameter is not passed to the metaclass __new__ or
> __init__), wouldn't it make sense to make it be passed to
> __init_subclass__ just like all other keywords? (the default
> __init_subclass__ then could swallow it, if it reaches there).
>
> I am putting the question now, because it is a matter of "now" or
> "never" - I can see it can does make sense if it is not passed down.
It would complicate the implementation, and has the potential to be
confusing (since the explicit metaclass hint and the actual metaclass
aren't guaranteed to be the same), so I don't think it makes sense to
pass it down. I'll make sure we note it in the documentation for the
new protocol method, though.
> Anyway, do you have any remarks on the first issue I raised? About
> __init_subclass__ being called in the class it is defined in, not just
> on it's descendant subclasses?
That's already covered in the PEP:
https://www.python.org/dev/peps/pep-0487/#calling-the-hook-on-the-class-itself
We want to make it easy for mixin classes to use __init_subclass__ to
define "required attributes" on subclasses, and that's straightforward
with the current definition:
class MyMixin:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if not hasattr(cls, "mixin_required_attribute"):
raise TypeError(f"Subclasses of {__class__} must
define a 'mixin_required_attribute' attribute")
If you actually do want the init_subclass__ method to also run on the
"base" class, then you'll need to tweak the class hierarchy a bit to
look like:
class _PrivateInitBase:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
...
def MyOriginalClass(_PrivateInitBase):
...
(You don't want to call __init_subclass__ from a class decorator, as
that would call any parent __init_subclass__ implementations a second
time)
By contrast, when we had the default the other way around, opting
*out* of self-application required boilerplate inside of
__init_subclass__ to special case the situation where "cls is
__class__":
class MyMixin:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if cls is __class__:
return # Don't init the base class
if not getattr(cls, "mixin_required_attribute", None) is None:
raise TypeError(f"Subclasses of {__class__} must
define a non-None 'mixin_required_attribute' attribute")
This raises exciting new opportunities for subtle bugs, like bailing
out *before* calling the parent __init_subclass__ method, and then
figure out that a later error from an apparently unrelated method is
because your __init_subclass__ implementation is buggy.
There's still an opportunity for bugs with the current design decision
(folks expecting __init_subclass__ to be called on the class defining
it when that isn't the case), but they should be relatively shallow
ones, and once people learn the rule that __init_subclass__ is only
called on *strict* subclasses, it's a pretty easy behaviour to
remember.
Cheers,
Nick.
--
Nick Coghlan | [email protected] | Brisbane, Australia
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP487: Simpler customization of class creation
On 28 July 2016 at 10:53, Nick Coghlan wrote:
> On 28 July 2016 at 23:12, Joao S. O. Bueno wrote:
>> Although I know it is not straightforward to implement (as the
>> "metaclass" parameter is not passed to the metaclass __new__ or
>> __init__), wouldn't it make sense to make it be passed to
>> __init_subclass__ just like all other keywords? (the default
>> __init_subclass__ then could swallow it, if it reaches there).
>>
>> I am putting the question now, because it is a matter of "now" or
>> "never" - I can see it can does make sense if it is not passed down.
>
> It would complicate the implementation, and has the potential to be
> confusing (since the explicit metaclass hint and the actual metaclass
> aren't guaranteed to be the same), so I don't think it makes sense to
> pass it down. I'll make sure we note it in the documentation for the
> new protocol method, though.
>
>> Anyway, do you have any remarks on the first issue I raised? About
>> __init_subclass__ being called in the class it is defined in, not just
>> on it's descendant subclasses?
>
> That's already covered in the PEP:
> https://www.python.org/dev/peps/pep-0487/#calling-the-hook-on-the-class-itself
>
> We want to make it easy for mixin classes to use __init_subclass__ to
> define "required attributes" on subclasses, and that's straightforward
> with the current definition:
>
> class MyMixin:
> def __init_subclass__(cls, **kwargs):
> super().__init_subclass__(**kwargs)
> if not hasattr(cls, "mixin_required_attribute"):
> raise TypeError(f"Subclasses of {__class__} must
> define a 'mixin_required_attribute' attribute")
>
> If you actually do want the init_subclass__ method to also run on the
> "base" class, then you'll need to tweak the class hierarchy a bit to
> look like:
>
> class _PrivateInitBase:
> def __init_subclass__(cls, **kwargs):
> super().__init_subclass__(**kwargs)
> ...
>
> def MyOriginalClass(_PrivateInitBase):
> ...
>
> (You don't want to call __init_subclass__ from a class decorator, as
> that would call any parent __init_subclass__ implementations a second
> time)
>
> By contrast, when we had the default the other way around, opting
> *out* of self-application required boilerplate inside of
> __init_subclass__ to special case the situation where "cls is
> __class__":
>
> class MyMixin:
> def __init_subclass__(cls, **kwargs):
> super().__init_subclass__(**kwargs)
> if cls is __class__:
> return # Don't init the base class
> if not getattr(cls, "mixin_required_attribute", None) is None:
> raise TypeError(f"Subclasses of {__class__} must
> define a non-None 'mixin_required_attribute' attribute")
>
> This raises exciting new opportunities for subtle bugs, like bailing
> out *before* calling the parent __init_subclass__ method, and then
> figure out that a later error from an apparently unrelated method is
> because your __init_subclass__ implementation is buggy.
>
> There's still an opportunity for bugs with the current design decision
> (folks expecting __init_subclass__ to be called on the class defining
> it when that isn't the case), but they should be relatively shallow
> ones, and once people learn the rule that __init_subclass__ is only
> called on *strict* subclasses, it's a pretty easy behaviour to
> remember.
Thanks for the extensive reasoning.
Maybe then adding a `run_init_subclass` class decorator on the stdlib
to go along with the pep?
It should be a two liner that would avoid boiler plate done wrong -
but more important than thatm is that it being documented alog with
the __init_sublass__ method will make it more obvious it is not run
where it is defined. (I had missed it in the PEP text and just
understood that part when re-reading the PEP after being surprised)
js
-><-
>
> Cheers,
> Nick.
>
> --
> Nick Coghlan | [email protected] | Brisbane, Australia
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP487: Simpler customization of class creation
On 29 July 2016 at 00:06, Joao S. O. Bueno wrote: > Maybe then adding a `run_init_subclass` class decorator on the stdlib > to go along with the pep? > It should be a two liner that would avoid boiler plate done wrong - > but more important than thatm is that it being documented alog with > the __init_sublass__ method will make it more obvious it is not run > where it is defined. (I had missed it in the PEP text and just > understood that part when re-reading the PEP after being surprised) The class decorator approach looks like this: def run_init_subclass(cls, **kwds): cls.__init_subclass__(**kwds) However, it's not the right way to do it, as it means super(cls, cls).__init_subclass__(**kwds) will get called a second time (since the class machinery will have already done it implicitly before invoking the class decorators). If the parent class methods are idempotent then calling them again won't matter, but if you're supplying extra keyword arguments, you'd need to specify them in both the decorator call *and* the class header. (I didn't actually realise this problem until writing the earlier email, so I'll probably tweak that part of the PEP to be more explicit about this aspect) So the simplest approach if you want "this class *and* all its descendants" behaviour is to adhere to the "strict subclasses only" requirement, and put the __init_subclass__ implementation in a base class, even if that means creating an additional mixin just to hold it. If that recommended approach isn't acceptable for some reason, then the decorator-centric alternative would be to instead write it this way: def decorate_class(cls, **kwds): ... @decorate_class class MyClass: def __init_subclass__(cls, **kwds): super().__init_subclass__(**kwds) decorate_class(cls) So the decorator gets defined outside the class, applied explicitly to the base class, and then the __init_subclass__ hook applies it implicitly to all subclasses. Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia ___ Python-Dev mailing list [email protected] https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 514: Python registration in the Windows registry
Why do you need SysArchitecture? Surely the 32bit pythons are registered in the 32bit registry and the 64 bit pythons in the 64 bit registry. you can side by side install python 3.4 but only if you install 64 bit first then 32 bit second. Barry > On 15 Jul 2016, at 23:20, Steve Dower wrote: > > Hi all > > I'd like to get this PEP approved (status changed to Active, IIUC). > > So far (to my knowledge), Anaconda is writing out the new metadata and Visual > Studio is reading it. Any changes to the schema now will require somewhat > public review anyway, so I don't see any harm in approving the PEP right now. > > To reiterate, this doesn't require changing anything about CPython at all and > has no backwards compatibility impact on official releases (but hopefully it > will stop alternative distros from overwriting our essential metadata and > causing problems). > > I suppose I look to Guido first, unless he wants to delegate to one of the > other Windows contributors? > > Cheers, > Steve > > URL: https://www.python.org/dev/peps/pep-0514/ > > Full text > --- > > PEP: 514 > Title: Python registration in the Windows registry > Version: $Revision$ > Last-Modified: $Date$ > Author: Steve Dower > Status: Draft > Type: Informational > Content-Type: text/x-rst > Created: 02-Feb-2016 > Post-History: 02-Feb-2016, 01-Mar-2016 > > Abstract > > > This PEP defines a schema for the Python registry key to allow third-party > installers to register their installation, and to allow applications to detect > and correctly display all Python environments on a user's machine. No > implementation changes to Python are proposed with this PEP. > > Python environments are not required to be registered unless they want to be > automatically discoverable by external tools. > > The schema matches the registry values that have been used by the official > installer since at least Python 2.5, and the resolution behaviour matches the > behaviour of the official Python releases. > > Motivation > == > > When installed on Windows, the official Python installer creates a registry > key > for discovery and detection by other applications. This allows tools such as > installers or IDEs to automatically detect and display a user's Python > installations. > > Third-party installers, such as those used by distributions, typically create > identical keys for the same purpose. Most tools that use the registry to > detect > Python installations only inspect the keys used by the official installer. As > a > result, third-party installations that wish to be discoverable will overwrite > these values, resulting in users "losing" their Python installation. > > By describing a layout for registry keys that allows third-party installations > to register themselves uniquely, as well as providing tool developers guidance > for discovering all available Python installations, these collisions should be > prevented. > > Definitions > === > > A "registry key" is the equivalent of a file-system path into the registry. > Each > key may contain "subkeys" (keys nested within keys) and "values" (named and > typed attributes attached to a key). > > ``HKEY_CURRENT_USER`` is the root of settings for the currently logged-in > user, > and this user can generally read and write all settings under this root. > > ``HKEY_LOCAL_MACHINE`` is the root of settings for all users. Generally, any > user can read these settings but only administrators can modify them. It is > typical for values under ``HKEY_CURRENT_USER`` to take precedence over those > in > ``HKEY_LOCAL_MACHINE``. > > On 64-bit Windows, ``HKEY_LOCAL_MACHINE\Software\Wow6432Node`` is a special > key > that 32-bit processes transparently read and write to rather than accessing > the > ``Software`` key directly. > > Structure > = > > We consider there to be a single collection of Python environments on a > machine, > where the collection may be different for each user of the machine. There are > three potential registry locations where the collection may be stored based on > the installation options of each environment:: > >HKEY_CURRENT_USER\Software\Python\\ >HKEY_LOCAL_MACHINE\Software\Python\\ >HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\\ > > Environments are uniquely identified by their Company-Tag pair, with two > options > for conflict resolution: include everything, or give priority to user > preferences. > > Tools that include every installed environment, even where the Company-Tag > pairs > match, should ensure users can easily identify whether the registration was > per-user or per-machine. > > When tools are selecting a single installed environment from all registered > environments, the intent is that user preferences from ``HKEY_CURRENT_USER`` > will override matching Company-Tag pairs in ``HKEY_LOCAL_MACHINE``. > > Official Python releases use ``PythonCore`` for Company, and the value of > ``sys.winver`
Re: [Python-Dev] Supporting native backup facility of SQLite
Lele Gaifax writes: > Paul Moore writes: > >> If you were interested in doing that, I'd suggest opening a tracker issue >> with a patch. > > Excellent, will do that, thank you for the encouragement! See http://bugs.python.org/issue27645 Thank you in advance for any feedback! ciao, lele. -- nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia. [email protected] | -- Fortunato Depero, 1929. ___ Python-Dev mailing list [email protected] https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 514: Python registration in the Windows registry
On 28 July 2016 at 17:51, Barry Scott wrote: > Why do you need SysArchitecture? Surely the 32bit pythons are registered in > the 32bit registry and the 64 bit pythons in the 64 bit registry. Per-user installs go in HKEY_CURRENT_USER, which is not architecture-specific. So you either need SysArchitecture, or you have to leave it as "unknown". Paul ___ Python-Dev mailing list [email protected] https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 514: Python registration in the Windows registry
The 3.4 issue where ordering matters is a bug in the MSI, incidentally (there's an extra upgrade code in one of them). Python 3.5 does not have the issue and side by side works correctly for both per-user and all-user installs. Top-posted from my Windows Phone -Original Message- From: "Barry Scott" Sent: 7/28/2016 10:19 To: "Steve Dower" Cc: "Python Dev" Subject: Re: [Python-Dev] PEP 514: Python registration in the Windows registry Why do you need SysArchitecture? Surely the 32bit pythons are registered in the 32bit registry and the 64 bit pythons in the 64 bit registry. you can side by side install python 3.4 but only if you install 64 bit first then 32 bit second. Barry > On 15 Jul 2016, at 23:20, Steve Dower wrote: > > Hi all > > I'd like to get this PEP approved (status changed to Active, IIUC). > > So far (to my knowledge), Anaconda is writing out the new metadata and Visual > Studio is reading it. Any changes to the schema now will require somewhat > public review anyway, so I don't see any harm in approving the PEP right now. > > To reiterate, this doesn't require changing anything about CPython at all and > has no backwards compatibility impact on official releases (but hopefully it > will stop alternative distros from overwriting our essential metadata and > causing problems). > > I suppose I look to Guido first, unless he wants to delegate to one of the > other Windows contributors? > > Cheers, > Steve > > URL: https://www.python.org/dev/peps/pep-0514/ > > Full text > --- > > PEP: 514 > Title: Python registration in the Windows registry > Version: $Revision$ > Last-Modified: $Date$ > Author: Steve Dower > Status: Draft > Type: Informational > Content-Type: text/x-rst > Created: 02-Feb-2016 > Post-History: 02-Feb-2016, 01-Mar-2016 > > Abstract > > > This PEP defines a schema for the Python registry key to allow third-party > installers to register their installation, and to allow applications to detect > and correctly display all Python environments on a user's machine. No > implementation changes to Python are proposed with this PEP. > > Python environments are not required to be registered unless they want to be > automatically discoverable by external tools. > > The schema matches the registry values that have been used by the official > installer since at least Python 2.5, and the resolution behaviour matches the > behaviour of the official Python releases. > > Motivation > == > > When installed on Windows, the official Python installer creates a registry > key > for discovery and detection by other applications. This allows tools such as > installers or IDEs to automatically detect and display a user's Python > installations. > > Third-party installers, such as those used by distributions, typically create > identical keys for the same purpose. Most tools that use the registry to > detect > Python installations only inspect the keys used by the official installer. As > a > result, third-party installations that wish to be discoverable will overwrite > these values, resulting in users "losing" their Python installation. > > By describing a layout for registry keys that allows third-party installations > to register themselves uniquely, as well as providing tool developers guidance > for discovering all available Python installations, these collisions should be > prevented. > > Definitions > === > > A "registry key" is the equivalent of a file-system path into the registry. > Each > key may contain "subkeys" (keys nested within keys) and "values" (named and > typed attributes attached to a key). > > ``HKEY_CURRENT_USER`` is the root of settings for the currently logged-in > user, > and this user can generally read and write all settings under this root. > > ``HKEY_LOCAL_MACHINE`` is the root of settings for all users. Generally, any > user can read these settings but only administrators can modify them. It is > typical for values under ``HKEY_CURRENT_USER`` to take precedence over those > in > ``HKEY_LOCAL_MACHINE``. > > On 64-bit Windows, ``HKEY_LOCAL_MACHINE\Software\Wow6432Node`` is a special > key > that 32-bit processes transparently read and write to rather than accessing > the > ``Software`` key directly. > > Structure > = > > We consider there to be a single collection of Python environments on a > machine, > where the collection may be different for each user of the machine. There are > three potential registry locations where the collection may be stored based on > the installation options of each environment:: > >HKEY_CURRENT_USER\Software\Python\\ >HKEY_LOCAL_MACHINE\Software\Python\\ >HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\\ > > Environments are uniquely identified by their Company-Tag pair, with two > options > for conflict resolution: include everything, or give priority to user > preferences. > > Tools that include every installed environment, even whe
