I'll let Paul pronounce. But you should probably have a BDFL-Delegate: ... header.
On Sat, Jul 23, 2016 at 12:16 PM, Steve Dower <steve.do...@python.org> wrote: > PEP 514 is now ready for pronouncement, so this is the last chance for any > feedback (BDFL-delegate Paul has been active on the github PR, so I don't > expect he has a lot of feedback left). > > The most major change from the previous post is the addition of some code > examples at the end. Honestly, I don't expect many tools written in Python > to be scanning the registry (since once you're in Python you probably don't > need to find it), but hopefully they'll help clarify the PEP for people who > prefer code. > > Full text below. > > Cheers, > Steve > > ---------- > > PEP: 514 > Title: Python registration in the Windows registry > Version: $Revision$ > Last-Modified: $Date$ > Author: Steve Dower <steve.do...@python.org> > Status: Draft > Type: Informational > Content-Type: text/x-rst > Created: 02-Feb-2016 > Post-History: 02-Feb-2016, 01-Mar-2016, 18-Jul-2016 > > Abstract > ======== > > This PEP defines a schema for the Python registry key to allow third-party > installers to register their installation, and to allow tools and > 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. As this relates to Windows > only, > these tools are expected to be predominantly GUI applications. However, > console > applications may also make use of the registered information. This PEP > covers > the information that may be made available, but the actual presentation and > use > of this information is left to the tool designers. > > 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. Some backwards compatibility > rules > are provided to ensure tools can correctly detect versions of CPython that > do > not register full information. > > 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. For example, the PEP 397 ``py.exe`` launcher and editors such > as > PyCharm and Visual Studio already make use of this information. > > 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, often causing users to "lose" their original 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. We also take the opportunity to add some well-known metadata so > that > more information can be presented to users. > > 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). These are used on Windows to store > settings > in much the same way that directories containing configuration files would > work. > > ``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. > > Further documentation regarding registry redirection on Windows is available > from the MSDN Library [1]_. > > 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\<Company>\<Tag> > HKEY_LOCAL_MACHINE\Software\Python\<Company>\<Tag> > HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\<Company>\<Tag> > > Official Python releases use ``PythonCore`` for Company, and the value of > ``sys.winver`` for Tag. The Company ``PyLauncher`` is reserved. Other > registered > environments may use any values for Company and Tag. Recommendations are > made > later in this document. > > Company-Tag pairs are case-insensitive, and uniquely identify each > environment. > Depending on the purpose and intended use of a tool, there are two suggested > approaches for resolving conflicts between Company-Tag pairs. > > Tools that list every installed environment may choose to include those > even where the Company-Tag pairs match. They should ensure users can easily > identify whether the registration was per-user or per-machine, and which > registration has the higher priority. > > Tools that aim to select a single installed environment from all registered > environments based on the Company-Tag pair, such as the ``py.exe`` launcher, > should always select the environment registered in ``HKEY_CURRENT_USER`` > when > than the matching one in ``HKEY_LOCAL_MACHINE``. > > Conflicts between ``HKEY_LOCAL_MACHINE\Software\Python`` and > ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python`` should only occur when > both > 64-bit and 32-bit versions of an interpreter have the same Tag. In this > case, > the tool should select whichever is more appropriate for its use. > > If a tool is able to determine from the provided information (or lack > thereof) > that it cannot use a registered environment, there is no obligation to > present > it to users. > > Except as discussed in the section on backwards compatibility, Company and > Tag > values are considered opaque to tools, and no information about the > interpreter > should be inferred from the text. However, some tools may display the > Company > and Tag values to users, so ideally the Tag will be able to help users > identify > the associated environment. > > Python environments are not required to register themselves unless they want > to > be automatically discoverable by external tools. > > Backwards Compatibility > ----------------------- > > Python 3.4 and earlier did not distinguish between 32-bit and 64-bit builds > in > ``sys.winver``. As a result, it is not possible to have valid side-by-side > installations of both 32-bit and 64-bit interpreters under this scheme since > it > would result in duplicate Tags. > > To ensure backwards compatibility, applications should treat environments > listed > under the following two registry keys as distinct, even when the Tag > matches:: > > HKEY_LOCAL_MACHINE\Software\Python\PythonCore\<Tag> > HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\PythonCore\<Tag> > > Environments listed under ``HKEY_CURRENT_USER`` may be treated as distinct > from > both of the above keys, potentially resulting in three environments > discovered > using the same Tag. Alternatively, a tool may determine whether the per-user > environment is 64-bit or 32-bit and give it priority over the per-machine > environment, resulting in a maximum of two discovered environments. > > It is not possible to detect side-by-side installations of both 64-bit and > 32-bit versions of Python prior to 3.5 when they have been installed for the > current user. Python 3.5 and later always uses different Tags for 64-bit and > 32-bit versions. > > The following section describe user-visible information that may be > registered. > For Python 3.5 and earlier, none of this information is available, but > alternative defaults are specified for the ``PythonCore`` key. > > Environments registered under other Company names have no backward > compatibility > requirements and must use distinct Tags to support side-by-side > installations. > Tools consuming these registrations are not required to disambiguate tags > other > than by preferring the user's setting. > > Company > ------- > > The Company part of the key is intended to group related environments and to > ensure that Tags are namespaced appropriately. The key name should be > alphanumeric without spaces and likely to be unique. For example, a > trademarked > name (preferred), a hostname, or as a last resort, a UUID would be > appropriate:: > > HKEY_CURRENT_USER\Software\Python\ExampleCorp > HKEY_CURRENT_USER\Software\Python\www.example.com > HKEY_CURRENT_USER\Software\Python\6C465E66-5A8C-4942-9E6A-D29159480C60 > > The company name ``PyLauncher`` is reserved for the PEP 397 launcher > (``py.exe``). It does not follow this convention and should be ignored by > tools. > > If a string value named ``DisplayName`` exists, it should be used to > identify > the environment manufacturer/developer/destributor to users. Otherwise, the > name > of the key should be used. (For ``PythonCore``, the default display name is > "Python Software Foundation".) > > If a string value named ``SupportUrl`` exists, it may be displayed or > otherwise > used to direct users to a web site related to the environment. (For > ``PythonCore``, the default support URL is "http://www.python.org/".) > > A complete example may look like:: > > HKEY_CURRENT_USER\Software\Python\ExampleCorp > (Default) = (value not set) > DisplayName = "Example Corp" > SupportUrl = "http://www.example.com" > > Tag > --- > > The Tag part of the key is intended to uniquely identify an environment > within > those provided by a single company. The key name should be alphanumeric > without > spaces and stable across installations. For example, the Python language > version, a UUID or a partial/complete hash would be appropriate, while a Tag > based on the install directory or some aspect of the current machine may > not. > For example:: > > HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy > HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6 > HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66 > > It is expected that some tools will require users to type the Tag into a > command > line, and that the Company may be optional provided the Tag is unique across > all > Python installations. Short, human-readable and easy to type Tags are > recommended, and if possible, select a value likely to be unique across all > other Companies. > > If a string value named ``DisplayName`` exists, it should be used to > identify > the environment to users. Otherwise, the name of the key should be used. > (For > ``PythonCore``, the default is "Python " followed by the Tag.) > > If a string value named ``SupportUrl`` exists, it may be displayed or > otherwise > used to direct users to a web site related to the environment. (For > ``PythonCore``, the default is "http://www.python.org/".) > > If a string value named ``Version`` exists, it should be used to identify > the > version of the environment. This is independent from the version of Python > implemented by the environment. (For ``PythonCore``, the default is the > first > three characters of the Tag.) > > If a string value named ``SysVersion`` exists, it must be in ``x.y`` or > ``x.y.z`` format matching the version returned by ``sys.version_info`` in > the > interpreter. If omitted, the Python version is unknown. (For ``PythonCore``, > the default is the first three characters of the Tag.) > > If a string value named ``SysArchitecture`` exists, it must match the first > element of the tuple returned by ``platform.architecture()``. Typically, > this > will be "32bit" or "64bit". If omitted, the architecture is unknown. (For > ``PythonCore``, the architecture is "32bit" when registered under > ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python`` *or* anywhere on a 32-bit > operating system, "64bit" when registered under > ``HKEY_LOCAL_MACHINE\Software\Python`` on a 64-bit machine, and unknown when > registered under ``HKEY_CURRENT_USER``.) > > Note that each of these values is recommended, but optional. Omitting > ``SysVersion`` or ``SysArchitecture`` may prevent some tools from correctly > supporting the environment. A complete example may look like this:: > > HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy > (Default) = (value not set) > DisplayName = "Example Py Distro 3" > SupportUrl = "http://www.example.com/distro-3" > Version = "3.0.12345.0" > SysVersion = "3.6.0" > SysArchitecture = "64bit" > > InstallPath > ----------- > > Beneath the environment key, an ``InstallPath`` key must be created. This > key is > always named ``InstallPath``, and the default value must match > ``sys.prefix``:: > > HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6\InstallPath > (Default) = "C:\ExampleCorpPy36" > > If a string value named ``ExecutablePath`` exists, it must be the full path > to > the ``python.exe`` (or equivalent) executable. If omitted, the environment > is > not executable. (For ``PythonCore``, the default is the ``python.exe`` file > in > the directory referenced by the ``(Default)`` value.) > > If a string value named ``ExecutableArguments`` exists, tools should use the > value as the first arguments when executing ``ExecutablePath``. Tools may > add > other arguments following these, and will reasonably expect standard Python > command line options to be available. > > If a string value named ``WindowedExecutablePath`` exists, it must be a path > to > the ``pythonw.exe`` (or equivalent) executable. If omitted, the default is > the > value of ``ExecutablePath``, and if that is omitted the environment is not > executable. (For ``PythonCore``, the default is the ``pythonw.exe`` file in > the > directory referenced by the ``(Default)`` value.) > > If a string value named ``WindowedExecutableArguments`` exists, tools should > use > the value as the first arguments when executing ``WindowedExecutablePath``. > Tools may add other arguments following these, and will reasonably expect > standard Python command line options to be available. > > A complete example may look like:: > > HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy\InstallPath > (Default) = "C:\ExampleDistro30" > ExecutablePath = "C:\ExampleDistro30\ex_python.exe" > ExecutableArguments = "--arg1" > WindowedExecutablePath = "C:\ExampleDistro30\ex_pythonw.exe" > WindowedExecutableArguments = "--arg1" > > Help > ---- > > Beneath the environment key, a ``Help`` key may be created. This key is > always > named ``Help`` if present and has no default value. > > Each subkey of ``Help`` specifies a documentation file, tool, or URL > associated > with the environment. The subkey may have any name, and the default value is > a > string appropriate for passing to ``os.startfile`` or equivalent. > > If a string value named ``DisplayName`` exists, it should be used to > identify > the help file to users. Otherwise, the key name should be used. > > A complete example may look like:: > > HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66\Help > Python\ > (Default) = "C:\ExampleDistro30\python36.chm" > DisplayName = "Python Documentation" > Extras\ > (Default) = "http://www.example.com/tutorial" > DisplayName = "Example Distro Online Tutorial" > > Other Keys > ---------- > > All other subkeys under a Company-Tag pair are available for private use. > > Official CPython releases have traditionally used certain keys in this space > to > determine the location of the Python standard library and other installed > modules. This behaviour is retained primarily for backward compatibility. > However, as the code that reads these values is embedded into the > interpreter, > third-party distributions may be affected by values written into > ``PythonCore`` > if using an unmodified interpreter. > > Sample Code > =========== > > This sample code enumerates the registry and displays the available > Company-Tag > pairs that could be used to launch an environment and the target executable. > It > only shows the most-preferred target for the tag. Backwards-compatible > handling > of ``PythonCore`` is omitted but shown in a later example:: > > # Display most-preferred environments. > # Assumes a 64-bit operating system > # Does not correctly handle PythonCore compatibility > > import winreg > > def enum_keys(key): > i = 0 > while True: > try: > yield winreg.EnumKey(key, i) > except OSError: > break > i += 1 > > def get_value(key, value_name): > try: > return winreg.QueryValue(key, value_name) > except FileNotFoundError: > return None > > seen = set() > for hive, key, flags in [ > (winreg.HKEY_CURRENT_USER, r'Software\Python', 0), > (winreg.HKEY_LOCAL_MACHINE, r'Software\Python', > winreg.KEY_WOW64_64KEY), > (winreg.HKEY_LOCAL_MACHINE, r'Software\Python', > winreg.KEY_WOW64_32KEY), > ]: > with winreg.OpenKeyEx(hive, key, access=winreg.KEY_READ | flags) as > root_key: > for comany in enum_keys(root_key): > if company == 'PyLauncher': > continue > > with winreg.OpenKey(root_key, company) as company_key: > for tag in enum_keys(company_key): > if (company, tag) in seen: > if company == 'PythonCore': > # TODO: Backwards compatibility handling > pass > continue > seen.add((company, tag)) > > try: > with winreg.OpenKey(company_key, tag + > r'\InstallPath') as ip_key: > exec_path = get_value(ip_key, > 'ExecutablePath') > exec_args = get_value(ip_key, > 'ExecutableArguments') > if company == 'PythonCore' and not > exec_path: > # TODO: Backwards compatibility handling > pass > except OSError: > exec_path, exec_args = None, None > > if exec_path: > print('{}\\{} - {} {}'.format(company, tag, > exec_path, exec_args or '')) > else: > print('{}\\{} - (not > executable)'.format(company, tag)) > > This example only scans ``PythonCore`` entries for the current user. Where > data > is missing, the defaults as described earlier in the PEP are substituted. > Note > that these defaults are only for use under ``PythonCore``; other > registrations > do not have any default values:: > > # Only lists per-user PythonCore registrations > # Uses fallback values as described in PEP 514 > > import os > import winreg > > def enum_keys(key): > i = 0 > while True: > try: > yield winreg.EnumKey(key, i) > except OSError: > break > i += 1 > > def get_value(key, value_name): > try: > return winreg.QueryValue(key, value_name) > except FileNotFoundError: > return None > > with winreg.OpenKey(winreg.HKEY_CURRENT_USER, > r"Software\Python\PythonCore") as company_key: > print('Company:', get_value(company_key, 'DisplayName') or 'Python > Software Foundation') > print('Support:', get_value(company_key, 'SupportUrl') or > 'http://www.python.org/') > print() > > for tag in enum_keys(company_key): > with winreg.OpenKey(company_key, tag) as tag_key: > print('PythonCore\\' + tag) > print('Name:', get_value(tag_key, 'DisplayName') or ('Python > ' + tag)) > print('Support:', get_value(tag_key, 'SupportUrl') or > 'http://www.python.org/') > print('Version:', get_value(tag_key, 'Version') or tag[:3]) > print('SysVersion:', get_value(tag_key, 'SysVersion') or > tag[:3]) > # Architecture is unknown because we are in HKCU > # Tools may use alternate approaches to determine > architecture when > # the registration does not specify it. > print('SysArchitecture:', get_value(tag_key, > 'SysArchitecture') or '(unknown)') > > try: > ip_key = winreg.OpenKey(company_key, tag + '\\InstallPath') > except FileNotFoundError: > pass > else: > with ip_key: > ip = get_value(ip_key, None) > exe = get_value(ip_key, 'ExecutablePath') or > os.path.join(ip, 'python.exe') > exew = get_value(ip_key, 'WindowedExecutablePath') or > os.path.join(ip, 'python.exe') > print('InstallPath:', ip) > print('ExecutablePath:', exe) > print('WindowedExecutablePath:', exew) > print() > > This example shows a subset of the registration that will be created by a > just-for-me install of 64-bit Python 3.6.0. Other keys may also be created:: > > HKEY_CURRENT_USER\Software\Python\PythonCore > (Default) = (value not set) > DisplayName = "Python Software Foundation" > SupportUrl = "http://www.python.org/" > > HKEY_CURRENT_USER\Software\Python\PythonCore\3.6 > (Default) = (value not set) > DisplayName = "Python 3.6 (64-bit)" > SupportUrl = "http://www.python.org/" > Version = "3.6.0" > SysVersion = "3.6" > SysArchitecture = "64bit" > > HKEY_CURRENT_USER\Software\Python\PythonCore\3.6\Help\Main Python > Documentation > (Default) = > "C:\Users\Me\AppData\Local\Programs\Python\Python36\Doc\python360.chm" > DisplayName = "Python 3.6.0 Documentation" > > HKEY_CURRENT_USER\Software\Python\PythonCore\3.6\InstallPath > (Default) = "C:\Users\Me\AppData\Local\Programs\Python\Python36\" > ExecutablePath = > "C:\Users\Me\AppData\Local\Programs\Python\Python36\python.exe" > WindowedExecutablePath = > "C:\Users\Me\AppData\Local\Programs\Python\Python36\pythonw.exe" > > References > ========== > > .. [1] Registry Redirector (Windows) > (https://msdn.microsoft.com/en-us/library/windows/desktop/aa384232.aspx) > > Copyright > ========= > > This document has been placed in the public domain. > > _______________________________________________ > 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/guido%40python.org -- --Guido van Rossum (python.org/~guido) _______________________________________________ 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