From 019b7181cc984a4549bcda539021e6422474923b Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 21 Jan 2025 23:47:51 +0000 Subject: [PATCH 01/10] Initial commit of PEP 772 --- peps/pep-0772.rst | 1614 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1614 insertions(+) create mode 100644 peps/pep-0772.rst diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst new file mode 100644 index 00000000000..d0a4bee8584 --- /dev/null +++ b/peps/pep-0772.rst @@ -0,0 +1,1614 @@ +PEP: 772 +Title: A Python Installation Manager for Windows +Author: Steve Dower +PEP-Delegate: TBD +Discussions-To: https://discuss.python.org/t/pre-pep-a-python-installation-manager-for-windows/74556 +Status: Draft +Type: Standards Track +Topic: Release +Created: 12-12-2024 +Python-Version: N/A +Post-History: 18-12-2024 +Resolution: TBD + + +Abstract +======== + +Installation of the python.org Python distribution on Windows is complex. +There are three main approaches with roughly equivalent levels of user +experience, and yet all of these suffer from different limitations, including +failing to satisfy modern usage scenarios. This PEP proposes a design for +a single Windows install workflow tool that satisfies all the needs of the +existing installers for the platform, while avoiding most of their limitations, +and provides the core team with the ability to manage releases for many years +to come. + +Reader's Note +------------- + +This document is a detailed *proposal*, intended to assist in an "approve" or +"reject" decision on the replacement of the existing install formats for Python +on Windows with a new format. It is not intended to be a binding specification, +nor is it user documentation or an interoperability specification. The actual +implementation may vary over time as needs change, and that is not to be +considered a "violation" of this PEP. Any interfaces and protocols meant for +public use will be independently documented and maintained in accordance with +standard deprecation timelines. + +Documentation on installing Python on Windows can be found at +`docs.python.org/using/windows.html `__. + +Background +========== + +There are a large range of needs users may have that lead to them wanting +to install a Python runtime. Many, likely most, are interested in running +(perhaps writing) short scripts, such as those that perform a simple task, +or help teach someone a concept. Some users are looking for a specific version +to integrate with existing code or another application. Some are after a full +set of different interpreter versions to perform testing. + +In this section, we discuss the expectations that users have of "installing +Python", provide an overview of the existing installers for Windows, and +identify some of the gaps and challenges inherent in these offerings. + +Expectations +------------ + +Based on significant anecdotal experience and analysis of quantitative data +available (though not necessarily public), we make the following assertions +about the majority of Python users on Windows: + +* most users just want the latest stable version +* most users want a "one-click" (or fewer) install +* most users do not want to use administrator privileges +* most users will benefit from installing maintenance updates +* most users expect the ``python`` command to work after installation + +The primary support for these assertions is that the most popular installers +actively chosen by users are the latest stable release on python.org, and +the latest stable release on the Windows Store, both of which meet these +requirements. + +We make the following assumptions about other significant sets of users. +These may have some overlap between groups, and at least some users expect +all of them. + +* some users want to install Python programmatically +* some users want to install a particular version +* some users want to install many versions +* some users want to install for all users of their machine +* some users do not want Start Menu shortcuts +* some users want to install as part of their project's build process +* some users want to install as part of their project's install process +* some users intend to never update their install +* some users expect the ``py`` command to work after installation + +These assumptions have all been demonstrated over time to exist, though the +relative importance has not been quantified. The Nuget packages and the +embeddable distro can meet most of these needs. + +Traditional Installer +--------------------- + +The traditional installer is an executable downloadable directly from +python.org that installs the entire development kit for Python. This includes +the CPython interpreter, the standard library, Python headers and import +libraries, builds of Tcl and Tk, the documentation as HTML files, the runtime +and standard library test suite, Start Menu shortcuts for Python and IDLE, +debugging symbols and debug builds of the binaries, the ``py.exe`` launcher +and its file associations, and functionality to modify the user's ``PATH`` +environment variable, enable long-path support on their system, pre-generate +``.pyc`` files for the standard library, and install pip. +As of 3.13, it also includes a set of experimental free-threaded binaries. +Many of these components are optional. + +After downloading the executable, users are presented with a "quick install" +option, which installs into their user directory with most options enabled. +We believe that most users select this option. + +A second option alongside the quick install takes the user to two pages worth +of options, listing the components that they need not install, as well as other +options such as the install directory and whether to install for all users. + +All of these options may be specified on the command line, and there is also an +option to proceed with the install without displaying any UI. +Based on feedback and bug reports, all of these options are used by at least +some users. However, as we do not track install telemetry, we have no way to +know which options are more important than others. + +Behind the scenes, the traditional installer is a Burn bundle, generated using +the Wix Toolset installer framework, containing one or more MSI files for each +feature. This framework is used extensively by Microsoft themselves, and +provides the most direct method of using Windows Installer. The bundle is a +custom C++ application, based on their template, which allows us to customise +the overall behaviour of the installer to determine precisely which MSI files +should actually be installed. The process of copying files, updating the +registry, and generating shortcuts is handled entirely by Windows Installer. + +As well as the intended uses, it is understood that many users will (attempt to) +use the traditional installer for other scenarios, such as unregistered installs +and automated CI system installs. While better alternatives are available, they +are not as obvious, and the hope is that a future design would make these +scenarios easier. + +Windows Store +------------- + +The Windows Store packages for CPython are produced as part of our normal +release process using almost all identical binaries to the other packages. +Due to being in an app store package, the primary ``python.exe`` is enhanced +to be able to determine its location properly, and alternative ``pip.exe`` and +other shortcuts are included to make up for the lack of ``PATH`` environment +variable settings. These are implemented in ``PC\\python_uwp.cpp`` in our repo. + +These packages are installed by searching for Python in the Microsoft Store +app, which will find results for each major version since 3.8. Users then have +to select a version and install it. These packages include the CPython +interpreter, standard library, Tcl/Tk, IDLE and pip, and create file +associations, Start Menu shortcuts, and global commands for ``python.exe``, +``python3.exe``, ``python3.X.exe``, ``pip[3[.X]].exe`` and ``idle[3[.X]].exe``. +No ``PATH`` modification is possible or required, though users may need to +manage their global shortcuts through the "Manage App Execution Alias" settings +page. + +In addition, Microsoft has added to a clean Windows install a default +``python.exe`` command. This captures attempts by users to launch Python on +a machine that has not yet installed it. When launched directly, the command +will open the Microsoft Store app to the page containing the recommended +Python app, typically the latest version. This app is entirely controlled by +Microsoft. Based on telemetry associated with the Python app (which *is* +controlled by the upstream Python project), approximately 300,000 installs +per month come through this redirector, making up about 90% of the total +installs of that version. + +Behind the scenes, the Store package is based on Microsoft's new installer +technology for apps known as APPX or MSIX. These are essentially plain ZIP +files with a small amount of metadata, except that installation is handled +by the operating system. They are always extracted to a fixed location, +accessible to all users but not modifiable by any, and automatically updated +to the latest release. The user's own data is stored in an OS-managed location +in their user profile, and is able to be reset, backed-up and restored using +regular OS functionality. + +Nuget Package +------------- + +The Nuget packages for CPython are produced and published as part of our +normal release process. The contents are identical to the traditional +installer. A Nuget package is published to nuget.org, which is a package +manager typically associated with .NET languages, but highly integrated with +any project supported by Visual Studio. This makes it a nice format for users +who want a lightweight install of Python as part of their regular build process, +and can simplify embedding scenarios. + +The packages are installed using any tool capable of using the Nuget API, or +may be downloaded directly once the URL of the package is known. The package is +a plain ZIP file with some metadata. It contains the CPython interpreter, the +standard library, development headers and import libraries, and pip. It does +not execute any code at install time, and users must locate the package +themselves in order to launch the ``python.exe`` contained within. + +Embeddable Package +------------------ + +The embeddable package for CPython is produced and published as part of our +normal release process. It is published to python.org alongside the +traditional installer. The contents are identical, however, the layout is +changed to store all binaries at the top level, with the standard library +packed into a ZIP file. A ``._pth`` file is included to override ``sys.path`` +so that only the files that are part of the distro are used, and environment +variables or registry entries are ignored. + +This package does not include pip, as the intention is for it to be embedded +into a broader application. Other libraries should be installed at build time, +since after distribution the runtime is meant to be an internal implementation +detail of the app it is a part of. + +As well as its intended use, some users attempt to use this package as a +development kit rather than a runtime package. This is believed to be due to +those users preferring to avoid "heavyweight" installers, and believing that +this package is intended to be a "portable" install (extract and run), likely +because it is the only ZIP file option listed on the python.org download pages +(speaking to the importance of clarity and limiting options on those pages). +It is hoped that a future installer design will avoid or limit this confusion. + +Alternate Distributions +----------------------- + +While outside of our purview as the core team, alternate distributions of Python +for Windows often use a project, workflow or environment-centric model for +installation of the runtime. By this, we mean that the tool is installed first, +and is used to create a working space that includes a runtime, as well as other +dependencies. Examples of these tools include conda and uv. + +Two observations are worth making about these tools. Firstly, they are often +praised for being low impact, in that they usually don't install additional +entry points or files for the runtime, making the install fast and also isolated +to a single project. Secondly, their users often appreciate the ease of +selecting a particular version of a runtime, or alternatively, not having to +select at all because existing specifications (or constraints) can choose for +them. + +These tools tend to meet many of the second set of expectations described above, +usually combining multiple tasks in a single command to reduce the cognitive +overhead of learning how to use and combine multiple commands. + +It's also worth pointing out that the core team does not view these alternate +distributions as competitors to any upstream distribution. They are a +fundamental part of how the open source ecosystem is intended to work. Our own +distributions are a convenience for those who choose to use them, as not all +scenarios are well served by a workflow tool or even a pre-built package. + + +Challenges +---------- + +There are numerous challenges we face with the current set of installers, +which largely break down into two categories: mismatched or unachievable +user expectations, and general unreliability. + +The traditional installer has the highest level of unreliability. The Windows +Installer technology is very old, and effectively no longer under development. +While its basic functionality is okay, interference may come from many sources, +such as virus scanners, other installers, system configuration, admin policies, +and even other files in the same directory as the installer. On top of this, +most of its advanced and beneficial functionality such as update patches, +incremental updates, and automatic rollback are unimportant for Python users. + +Most user expectations are *defined* by the traditional installer, and so by +definition, it meets them. One primary gap is that it is not able to create an +"unmanaged" install - that is, the equivalent of only copying files onto the +user's system without registration. If you have installed it once, and you +try to install it again, you will only even be able to manage (or upgrade) the +existing install. This can lead to installs moving on update, which will +break users. + +Additionally, the ``PATH`` environment variable cannot be intelligently +modified - at best, we can prepend or append the install path. This usually +results in the most recent install of Python being the highest priority. For +example, if the user has Python 3.14 installed and then installs (or updates) +3.13, the ``python`` command will switch from the later version to the earlier +version. + +The ``py.exe`` launcher, defined in PEP 397 and implicitly updated by PEP 514, +is an attempt to avoid this particular issue. It uses its own logic for finding +installed versions without relying on ``PATH``. However, the PEP 514 logic does +not allow for prerelease or experimental builds to be treated specially, and so +``py.exe`` often prefers these builds by default over the non-experimental +version expected by the user. + +The Windows Store package is very reliable, with the exception of the global +shortcuts. Rather than modifying ``PATH`` to add its own directory, these +shortcuts are created in a single OS managed directory that has all the +shortcuts defined by any app. Users are able to modify their ``PATH`` to exclude +or de-prioritise this directory, leading to unreliable or inconsistent +behaviour, and historically we have also seen this caused by installers. +For example, installing Python from the Store followed by Python from the +traditional installer with its ``PATH`` modification enabled will almost always +shadow the Store package's Python with the later install. + +User expectations that are un-met by the Store package tend to be performance +and technical. Due to the overhead of launching an app, Python starts up slower. +Because apps are designed to be isolated from each other, it is more difficult +to use hidden directories (such as ``AppData`` or ``TEMP``) to communicate +between different versions of Python, as each version has its own space. Apps +are subject to stricter security requirements that legacy applications start +disabled, such as DLL hijacking protection, which causes some libraries to fail. +The ``python3`` and ``python`` shortcuts are managed through system settings, +and the user interface is not very good (and not going to be improved, according +to Microsoft). Without managing these, it is relatively easy for an undesired +version to be launched, though in general the targets can only be changed +manually by the user, and not by merely installing another app. + +Both the Nuget package and the embeddable distro are as simple and reliable to +install as extracting an archive file, though it's worth noting that for many +Python users this is not a common task. They provide no install management at +all, and cannot be reliably updated other than by deleting and re-extracting. +User expectations that are un-met are almost always due to users selecting the +wrong installer. Both these packages are for specialised cases, and while they +are documented as such, the attraction of a plain ZIP file leads some users into +failure. + +Overview of PyManager +===================== + +("PyManager" name open for bikeshedding) + +PyManager is the internal name of our proposed replacement installer tool. It +will be distributed both in the Windows Store and on python.org as an MSIX +package. Downloading from either source will get an identical package, and +both will support automatic updates (through the Store) for new releases. + +The user visible name will be "Python Install Manager", published by the +Python Software Foundation. After publishing, we will request that Microsoft +adjust their ``python.exe`` stub to open to this new app. + +This app does not directly provide a version of Python, but it does provide the +global commands that users expect to work, as well as file associations and +Start menu shortcuts. The OS will prompt users to launch the app after install, +which will trigger an automatic install of the current release of CPython and +then launch it. From the user's perspective, they have the same initial +experience as today, with one added progress bar on first launch. + +The global commands provided by the app must be static and bundled into the app +itself. They can only change their behaviour at runtime, and cannot be +redirected to different executables except by the user (and then only to another +installed app). So the commands to be provided by PyManager are ``python.exe``, +``python3.exe``, ``py.exe``, ``pymanager.exe``. Each of these must have the +ability to inspect the user's system and choose the correct runtime to launch. +Additionally, ``py`` and ``pymanager`` will have management subcommands to allow +adding and removing runtimes. + +In line with PEP 394 and the default behaviour of Windows, the recommended +command for launching Python is ``python.exe``. As provided by PyManager, this +will locate an existing install, either among those that PyManager manages or +using PEP 514, or it will install the latest available version of CPython and +select that. The ``python3.exe`` command behaves similarly, but is only allowed +to find 3.x installs from python.org. + +The ``py.exe`` command provided by PyManager will be recommended for most +management use, due to its brevity. ``py install ...``, ``py list ...`` and so +on. The proposed commands are detailed later. The existing behaviour of the +PEP 397 launcher is preserved, however, launching through ``py`` will not +automatically install runtimes (by default). If one is requested but is not +installed, users will just get an error. The ``py run ...`` subcommand, however, +will install automatically, and supports the same options as bare ``py``. + +These commands are added at very low priority in the user's ``PATH`` by the OS. +Every existing configuration we may have created on a user's machine will take +precedence over these commands, and so these are a last resort in place of an +error message. As a result, we can generally assume that a user is launching +these commands because they haven't configured a stronger preference (for +example, a user who has activated an environment will never launch our +``python.exe``, because activation will put a different one ahead of it, and a +user who wants precisely the behaviour of the existing ``py.exe`` can just +install it and will never launch our new one). + +The ``pymanager.exe`` command is to allow for handling ambiguous situations. +Existing installs of Python and the launcher may shadow ``python.exe`` and +``py.exe``, but in an automated environment, this can make administrative +scripts unreliable, and so the ``pymanager`` command is unlikely to refer to +something other than PyManager. It has all the subcommands, and launching it +with no command specified will print help for the user. + + +Replacing other installers +-------------------------- + +Our intent is to immediately stop publishing individual versions to the Windows +Store, and to deprecate and phase out the traditional installer and Nuget +packages by 3.16. The embeddable distro would remain, but its listing on +python.org download pages would be phased out and it will be available only +through PyManager. + +PyManager will be made available as an app package downloadable manually from +python.org, and the double-click install experience is generally smooth. This +provides an equivalent to the current approach of downloading from our site. +It will bundle a recent (unspecified) version of CPython so that the download +can be moved to a non-internet connected machine and still provide a Python +runtime after install. + +Some automated deployment scenarios do not work with the newer MSIX format, and +so a simple MSI will also be provided on python.org. This will have no options +or user interface, and require administrative privileges, which are typically +available for these kinds of scenarios. This MSI would be discouraged for most +users, and the MSIX should be the default. + +It's worth noting that there is no way to make the MSI install fully compatible +with the MSIX, and users with both will likely encounter confusion or problems. +It is anticipated that only users without Store app support will use the MSI. + +Our release processes will start publishing plain ZIP packages to python.org. +These will be available from the FTP pages, but will not be listed directly on +regular download pages. + +Third-party tools that currently distribute their own builds of CPython will be +welcome to use ours, though will be expected to be the initial point of contact +for their users requiring support. + + +Project ownership and development +--------------------------------- + +PyManager will be developed and maintained in its own repository adjacent to +the CPython repository, and under the same terms. The CPython CLA will apply, +and all (and only) core developers will have commit rights. + +PyManager releases are independent from CPython releases. There is no need for +versions to match, or releases to be simultaneous. Unless otherwise arranged, +the PyManager release manager is whoever is the build manager for Windows. + + +Specification +============= + +.. note:: + In this document, all command line options will be shown with one or two + hyphens. In implementation, all options will support one or two hyphens or a + forward slash, to be permissive of both Windows and UNIX conventions. + +Exec subcommand +--------------- + +.. code:: text + + pymanager exec -V:tag [interpreter opts] [script.py|-m module|-c code] [script args] + pymanager exec -3.* ... + pymanager exec [--only-managed] [--[no-]install] [-V:|-3.*] ... + py [-V:|-3.*] ... + python ... + python3 ... + +This subcommand is used to select and launch a runtime. It is the default action +for the ``py`` command, and the only action supported by the ``python`` and +``python3`` commands. The default options are subtly different in each case for +consistency with existing use of these commands. + +This subcommand is available on both ``py`` and ``pymanager``. However, since +``py`` offers it by default, we would not expect users to use it there. The +intent is that the ``py``, ``python`` and ``python3`` commands are the default +ways to launch a runtime, and ``pymanager exec`` is for advanced scenarios. + +The ``-V:tag`` command is used to request a specific runtime from the command +line. The tag is a ``Company\\Tag`` pair, or just ``Tag`` if no slash is +included, and is used as defined by PEP 514. The ``-3.*`` option is interpreted +as ``-V:PythonCore\\3.*``. This option is only available for ``py`` and +``py exec`` variants. + +If no tag is specified on the command line, and a script file is specified, +the script will be inspected for a shebang. If one is found that matches a +recognised pattern, it will either provide the tag to be used for search, or it +will override all other processing and its specified executable will be launched +without further effort being made. This is to handle the (unfortunate) legacy +support of arbitrary Windows-specific paths being allowed in what was meant to +be a portability feature. In general, shebangs including simple patterns like +``/usr/bin/python3.13`` are intended, while those that use ``/usr/bin/env +python`` are unlikely to be of benefit since the environment tends to be less +reliable than our search. + +If no tag is yet requested, the ``VIRTUAL_ENV`` environment variable will be +consulted to see if an environment has been activated. If so, that will become +the request. + +If a tag has been requested at this stage, the ``python3`` command will verify +that it matches ``PythonCore\\3.*`` and exit with an error if not. This allows +allows the ``python3`` command to be used in an active environment consistent +with other platforms, but not if the environment would not have included the +command. This applies to most existing versions of Python on Windows. (The +alternative to this behaviour is to make ``python3`` always error when an +environment is active, as anything else would behave inconsistently for the +user.) + +If no tag is requested, the default will be consulted. For ``python3``, this is +``PythonCore\\3``, but for all other commands it is read from configuration +(which might involve an environment variable). If it's still empty, any tag will +be allowed. + +The best installed runtime matching the tag is then selected and launched with +the remaining command line. + +If no matching runtime is found, and the ``--install`` option is set, it will be +installed and then launched. This is the default for ``py exec``, and also for +``python`` but only when no runtime was requested (which implies that no +runtimes were installed). In all other cases, if no install is found, an error +is printed and the process exits. + + +Install subcommand +------------------ + +.. code:: text + + py install [-s|--source ] [-f|--force] [-u|--upgrade] [tag ...] + py install [-s|--source ] [-t|--target ] [tag ...] + py install [-s|--source ] [-d|--download ] [tag ...] + py install --refresh + +.. note:: + This and all later subcommands are also available under ``pymanager``. + However, as we intend for ``py`` to be the usual command, we only show that + one. + +This subcommand will install one or more runtimes onto the current machine. +The tags are ``Company\\Tag`` pairs (or just ``Tag`` if no slash is included), +and are used to search the index file. Company names match as case-insensitive +prefixes, preferring a full match over a prefix, and tags use case-insensitive, +number-aware matches, with dotted numbers treated as versions. Tags must match +one of the listed "install for" tags, and entries list multiple such tags to +handle abbreviated requests. + +For example, the ``3.10.5`` entry would list all of ``3``, ``3.10`` and +``3.10.5`` as tags to be installed for. A request for ``3.10`` would match one +of these and so the entry is selected. Due to the number-aware matches, a +request for ``03.0010`` would also match, and ``3.10.50`` would not. + +Tags may also be specified as a constraint, using ``>``, ``>=``, ``<``, ``<=`` +or ``!=`` followed by the ``Company\\Tag`` or ``Tag`` value. When matching a +constraint only the primary tag metadata is used for comparisons. Since the +comparisons are version-aware, constraints such as ``>3.10`` will select +3.11 as a minimum, while ``>3.10.0`` may select 3.10.1. + +The behaviour of constraints against arbitrary tags is likely to be unintuitive +in some circumstances. It is anticipated that constraints will mainly be used +with upstream releases, which typically use version-shaped tags, and primarily +for cases where other metadata such as ``Requires-Python`` are being handled. +Users are expected to use shorter tags for convenience, rather than ranges. + +The default index file is hosted on python.org, and contains install information +including package URLs and hashes for all installable versions. An alternate +index may be specified by the user or their administrator (see Configuration +below). Entries in the index file list the full tags they should be installed +for, and if an exact match is found the package will be selected. In the case +of no exact match, a prefix match will be used. In both cases, numbers in the +tag are treated logically - that is, ``3.1`` is a prefix of ``3.1.2`` but not of +``3.10``. + +If a tag is already satisfied by an existing install, nothing will be installed. +The user must pass an ``--upgrade`` or ``--force`` option to replace the +existing install; the former will only replace it with a newer version, while +the latter will remove and replace even with the same version. + +Calling the command without providing any tags will install the latest default +version (in effect, the first non-prerelease entry in the index). +Passing ``--upgrade`` with no tags is an error. + +Passing ``--refresh`` will regenerate all metadata and shortcuts for all +installs. This is intentionally applied to all installs at once, as shortcut +prioritisation relies on all installs being consistent (for example, the latest +3.x version should get the ``python3.exe`` shortcut, which gets complicated if +users can choose to only refresh an older install). + +If a ``--target `` option is passed with only a single tag, that runtime +will be extracted to the specified directory without being registered as an +install (or generating aliases or shortcuts). This is intended to cover +embedding cases, or downloading the files for incompatible platforms. Passing +multiple tags with ``--target`` is an error. + +If the ``--download `` option is passed, runtimes will be downloaded to the +specified directory as their source packages, and an ``index.json`` will be +created referencing these files. This index can be referenced later to perform +offline installs with ``python install --source [tag ...]``. + + +Uninstall subcommand +-------------------- + +.. code:: text + + py uninstall [-y|--yes] [--purge] [tag ...] + +This subcommand will uninstall one or more runtimes on the current machine. Tags +are exactly as for the install command, including prefix matching, but only +inspect existing installs. Unless the ``--yes`` option is passed, the user will +be prompted before uninstalling each runtime. + +If the ``--purge`` option is passed with no tags, then (after confirmation) all +runtimes will be removed, along with shortcuts and any cached files. + + +List subcommand +--------------- + +.. code:: text + + py list [-f|--format ] [-1|--one] [--only-managed] [tag ...] + py list [-f|--format ] [-1|--one] [--online] [--source ] [tag ...] + py [--list|-0] + py [--list-paths|-0p] + +This subcommand will list any or all installs matching the specified tags or +ranges. If no tags are provided, lists all installs. Runtimes not managed by +PyManager (including an active virtual environment) may be listed separately. + +The default format is user-friendly. Other formats will include machine-readable +and single string formats (e.g. ``--format=prefix`` simply prints ``sys.prefix`` +on a line by itself). The exact list of formats is left to implementation. + +If ``--one`` is provided, only the best result is listed. This is to assist +shell scripts that want to locate the default (or a suitable) runtime without +launching it. (Note that "best" is loosely defined, but will always be the +user's preferred default environment if it is included in the results.) + +The ``--only-managed`` option omits runtimes that were discovered but are not +managed by PyManager, for example, those found using a regular PEP 514 lookup. + +Passing ``--source`` (or ``--online`` to implicitly pass the default source) +will search an online index rather than currently installed runtimes. The option +is here rather than on the ``install`` subcommand because the filtering and +formatting options are already available on ``list``. + +The legacy ``--list``, ``--list-paths``, ``-0`` and ``-0p`` arguments from the +``py.exe`` launcher will also be provided. However, they will not support the +new options listed here, and are limited to reproducing the output from the +existing launcher. Unmanaged installs are not distinguishable in this listing. + + +Help subcommand +--------------- + +.. code:: text + + py help + +This subcommand will display the help text for each specified command, or if +none specified, will show the list of commands. Specifying one command is the +equivalent of ``py --help``. Showing the list of subcommands is the +default action for the ``pymanager`` command. + +The command is added primarily to offer a simple way to tell users how to find +more information: they can be told to run ``py help``. This avoids having to +override or extend the ``python -?`` output, which otherwise forwards to the +selected runtime and already prints at least one screen's worth of text. + +After an automatic install (e.g. running ``python`` with nothing installed), a +message will be displayed telling users that they can run ``py help`` for more +information on how to manage their installs. + + +Environment Variables +--------------------- + +No environment variables can be updated automatically when installing a Store +app, and so no updates will be done automatically. The core commands should +already be available on a correctly functioning machine. + +One directory within the user's PyManager data directory is set aside for +generated aliases. If desired, the user can add this directory to their ``PATH`` +themselves. The contents of this directory will be managed by PyManager, and +will contain executables to directly launch installed runtimes (for example, +``python3.exe`` and ``python3.13.exe`` for an install of Python 3.13). Whenever +aliases are added to this directory, ``PATH`` will be checked and if it is +missing, the user will be presented a message containing the path to add. + +Scripts installed by packages installed into a runtime will be in yet another +directory. Due to the current design, we do not believe it is safe to have them +all install into a single directory, or a directory shared by multiple runtimes. +However, a future development may include a command for PyManager to generate +its own entry points based on metadata in installed packages. + + +Start Menu Shortcuts +-------------------- + +A Start Menu shortcut will be added to launch PyManager documentation in the +user's default web browser. No applications are added to the Start Menu. + +When installing Python runtimes, the install definition may specify Start Menu +shortcuts to create for the install. + + +File Associations +----------------- + +Standard file associations will be created when installing PyManager, and will +launch scripts and packaged apps with PyManager's global ``python.exe`` alias. +This provides sensible behaviour for users who are double-clicking on scripts or +``.pyz`` files. + + +Windowed Executables +-------------------- + +For each of the global aliases described earlier, a ``*w.exe`` also exists. +These launch without creating or attaching a console window, which typically +means they will only display UI created by the script. For example, IDLE always +launches using ``pythonw.exe``, as this avoids an unnecessary native console. + +These commands otherwise behave identically to their console counterparts. + + +Configuration +------------- + +PyManager is configured using a hierarchy of JSON-based configuration files. +Command-line options always override configuration file options. Configuration +files in user editable locations may be disabled by a configuration or +command-line option. + +In ascending order of priority, these will be located: + +* within the app package +* specified by admin-only configuration (see below) +* in the ``base_config`` setting (default: none) +* in the ``user_config`` setting (default: ``%AppData%\\Python\\PyManager.json``) +* in the ``additional_config`` setting (default: ``%PYTHON_MANAGER_CONFIG%``) +* specified with the ``-c`` command line option + +The specific behaviour of each configuration option is left to implementation. +However, a number of intended options are discussed in other sections. + +App package configuration is provided to allow PyManager to be embedded in other +applications or packages. For example, an alternative distribution may want to +include PyManager but have it locate installs from their own index. The app +package configuration allows reusing our build and overriding the default +settings. + +The ``user_config`` and ``additional_config`` settings are pre-configured in +earlier configuration files, allowing them to be overridden by admin-only +configuration or an alternate root configuration. If a configuration file +overwrites the setting that caused the file to be loaded, it is ignored. +The ``base_config`` setting is similar, but starts empty and is intended for +easy overriding through admin configuration. + +Admin-only configuration is provided to allow administrators to manage systems +under their control using existing tools, such as group policy or registry +updates. By design, these controls cannot be overridden, such that it is +possible for administrators to deploy policy that prevents or limits the use of +PyManager. These controls are essential to allow PyManager to be deployed safely +into certain environments, and without them, it would simply be disallowed and +those users would have no access to Python. + +The intent is for the main admin-only configuration to be a path to a new +``base_config`` configuration file that an administrator can deploy to any +controlled location. This allows a network administrator to control the source +of their users' default Python runtimes, without forcibly restricting them, or +to override the other sources for configuration files (apart from the command +line option). + + +Index Schema +------------ + +The index file is made available either online or locally, and provides +PyManager with all the information needed to find, select, install, and manage +any Python runtime. + +The index is stored as JSON. The main top level key is ``versions``, which +contains a list of objects. Each version object has its own schema version, and +there is no overall file schema version. Future changes may add additional +top-level keys to provide functionality that cannot be safely integrated into +an existing one. + +Version objects may be split between the index file and a ``__install__.json`` +stored in the root of each package archive. The entries in the bundled file will +fill in any gaps from the index file. This is intended to allow the typically +large ``shortcuts`` key to be removed from the index file, but may also extend +to ``alias``, ``executable`` and ``executable_args``. Omitting other keys from +the index may result in problems installing the package. + +A second top-level key ``next`` contains an optional URL to another index. This +may be used if PyManager cannot find a suitable package in the included +versions. The intent is to allow for older indexes to be archived and only +accessed when required, reducing the size of the initial download without +cutting off users from older versions. + +The initial schema is shown below:: + + SCHEMA = { + "versions": [ + { + # Should be 1. + "schema": int, + + # Unique ID used for install detection/side-by-side. + # Must be valid as a filename. + "id": str, + + # Name to display in the UI + "displayName": str, + + # Version used to sort packages. Also determines prerelease status. + # Should follow Python's format, but is only compared among releases + # with the same Company. + "sort-version": Version, + + # Specifies platforms to consider this package for. + # Initially, 'win32' is the only supported value. Others may be + # defined in the future. This condition is evaluated silently, and + # is not intended to replace platform requests in "install-for". + "platform": [str], + + # Company field, used for filtering and displayed as the publisher. + "company": str, + + # Default tag, mainly for UI purposes. + # It should also be specified in 'install-for' and 'run-for'. + "tag": str, + + # List of tags to install this package for. This does not have to be + # unique across all installs; the first match will be selected. + "install-for": [str], + + # List of tags to run this package for. Does not have to be unique + # across all installs; the first match will be selected. The target + # is the executable path relative to the root of the archive. + # Explicit args (optional) are inserted before user args. + "run-for": [{"tag": str, "target": str, "args": [str], "windowed": int}, ...], + + # List of global CLI aliases to create for this package. Does not + # have to be unique across all installs; the first match will be + # created. + "alias": [{"name": str, "target": str, "windowed": int}, ...], + + # List of shortcuts to create for this package. Additional keys on + # each instance are allowed based on the value of 'kind'. + # Initially, 'kind' supports the following values: + # * 'pep514' - other keys define registry values to set + # * 'start' - generate shortcuts in the user's Start Menu + # * 'uninstall' - generate an Add/Remove Programs entry + "shortcuts": [{"kind": str, ...}, ...] + + # Default executable path, relative to the root of the archive. + # Usually the values from 'run-for' will be used instead, and this + # is mainly for display purposes. + "executable": str, + # Default executable args + "executable_args": [str], + + # URL to download the package archive from + "url": str, + + # Optional set of hashes to validate the download. Hashes are stored + # as hex digests. Any hash supported by hashlib without OpenSSL is + # permitted. + "hash": { + "": str, + } + } + ], + + # Full or partial URL to the next index file + "next": str, + } + + +Shebang Processing +------------------ + +For limited compatibility with scripts designed for sh-like shells, PyManager +will check scripts for a shebang line. A shebang line specifying a Python +command will be used (when not overridden on the command line) to select a +suitable runtime for the script. + +Unlike the support currently in the ``py.exe`` launcher, we propose to reduce +this functionality to only support Python commands where the command matches +a global alias listed for an install. (The existing launcher is able to run any +executable, and attempts to extract version information from the command, rather +than simple matching.) + +The specific patterns to be detected are left to the implementation. + + +Rationale +========= + +"Changing" the python.exe command +--------------------------------- + +It may be argued that the global ``python.exe`` alias provided by PyManager is +"not real Python" and so should use a different name. While this is strictly +true, there are three reasons we argue that it should be used. + +Firstly, thousands of users *daily* install through the Store page after being +led there by having typed ``python`` at the terminal of a clean machine. Due to +how this redirection is implemented, if the app they install does not provide a +``python`` command, then the redirection will remain in place. In order to +ensure that users do not get stuck always going back to the Store, we need to +provide this command. (The same applies to ``python3``.) + +Second, the alternative to the "not real" alias is not "the real" one. It's +nothing. We don't have the ability to replace the global static alias with one +that follows the user's preference or installs, and so the alternative would be +to provide nothing and have ``python`` be an error in all cases. This is worse, +and in our opinion, actively harmful to Python's reputation. + +Third, although the underlying implementation of the ``python`` alias is more +complex than the default ``Programs/python.c``, the experience of using it is +identical. The alias is only launched in the absence of another expressed +preference (that is, there's nothing else on ``PATH``), it respects any +indirect preferences (such as through configuration or shebangs), and it +launches the most appropriate version of Python available on the user's machine. +This is much closer to the desired behaviour of the global ``python`` command +than any alternative. + + +Replacing py.exe +---------------- + +The ``py.exe`` launcher exists to provide some of the functionality that will be +replicated by PyManager - specifically, the ability to launch an already +installed runtime. Despite its long history, the launcher does not seem to have +become the preferred method for most users, with many preferring the global +modifications to the ``PATH`` environment variable. However, the command itself +has come to be relied upon, and should be preserved as long as possible. This is +achieved in two ways. + +Firstly, we install our own ``py.exe`` alias with PyManager that provides the +same functionality, along with PyManager specific functionality. This is +intended to become the default/preferred install of ``py.exe`` over time. + +Second, we generate PEP 514 metadata (when requested) for each install, which +allows a legacy ``py.exe`` to continue to work normally with installs managed by +PyManager. + +Due to how the existing ``py.exe`` launcher configures itself, and how the MSIX +package for PyManager is constrained, it is not possible for PyManager's ``py`` +alias to override the launcher. As a result, users who install the launcher will +always find ``py`` resolving to the launcher. Ultimately, the only way to +resolve this in favour of PyManager is to uninstall the launcher, which can be +done through the standard Installed Apps control panel. + + +Interaction with venv +--------------------- + +An activated virtual environment, as implemented by the standard library +``venv`` module, will modify the user's ``PATH`` environment variable to ensure +that the venv launcher will take precedence over other executables. As a result, +when a venv has been activated, PyManager can only be launched by its aliases +other than ``python``. + +This means that working virtual environments will behave as they do today with +no additional support from PyManager. + + + +Backwards Compatibility +======================= + +In general, there are no compatibility guarantees to the install process between +major versions (``3.x`` to ``3.y``), and so "having to use a different +installer" is not considered compatibility breakage. The versions of Python +installed are only impacted by this change to the extent that the install method +modified their behaviour. In general, most installs will be closer to the +behaviour of having been built from source by the user themselves. + +That said, there are a number of changes that will impact certain users when +they do move to a new install process. This section outlines as many of these +changes as we are aware of, in no particular order, and will likely form the +basis of a migration guide. + + +Scripted downloads +------------------ + +Users who wrote scripts to generate the download filename of our old installer +will find those scripts are broken. These URLs were never guaranteed stable or +predictable, and so we have no recourse to do anything other than apologise and +suggest users use our own tooling for downloads. + +The deprecation period for the traditional installer allows time for these users +to learn about the upcoming change. + + +Scripted installs +----------------- + +Users who wrote scripts to execute our installer with particular options will +have to change their script. Most options have been removed, to begin with, and +those that remain have new spelling. Since it is not possible to reach a state +where options for the old installer are being passed to the new without manual +intervention (that is, someone has to change the command already), this is +considered an acceptable change. + +The deprecation period for the traditional installer allows time for these users +to learn about the upcoming change. + + +Old runtime installed +--------------------- + +Users with existing runtimes installed will find them selected by PyManager and +its aliases, provided the registration is not corrupt. + +The priority order among installed runtimes has changed to only include +prerelease versions when specifically requested (for example, ``-V:3`` will +match 3.14.0 rather than 3.15.0a1, but ``-V:3.15`` will match 3.15.0a1), and to +correctly sort text suffixes on tags (for example, 3.14t is now *lower* +priority than 3.14). + +While it is possible to provide warnings in cases where this may be impacting a +user, such warnings would be considered very noisy (e.g. a message every time +you launch ``python`` because you have a prerelease installed that wasn't +selected) and require complicating the selection logic unnecessarily. This +change will be documented only. + + +Old py.exe launcher installed +----------------------------- + +Users who do not manually uninstall an old ``py.exe`` launcher will find that +both their existing and new installs of Python are found, though where versions +match the existing install will take priority over the new install (whereas the +new ``py`` would select the new install). + +They will also find that commands such as ``py list`` do not work. The solution +here is to use Windows Settings to uninstall the launcher. + +There is no way to detect that a user has accidentally left an old ``py`` +installed, or to remove it for them. This change will be documented only. + + +Misconfigured venv activated +---------------------------- + +Users who activate a corrupt or misconfigured virtual environment that is either +missing its ``python.exe`` or has it not on ``PATH`` may receive a different +error from before. + +PyManager's global ``python`` alias will be found and executed instead, +suppressing any system "not found" error. As it fails to find the environment's +actual runtime, it will then fail, though the code and message may be different. + +As this scenario requires an already corrupt system, this change will be +documented only. + + +Old version availability +------------------------ + +Python versions prior to the first release of PyManager can be backfilled into +the python.org index, either based on newly repackaged archives or using the +almost equivalent packages from Nuget (the latter does not include Tcl/Tk, +making them significantly incompatible for some users, but this is likely okay +for especially old versions). + + +Administrator installs +---------------------- + +Installing a copy of Python for all users is no longer possible, as PyManager +will only install into the user's own directory. No scenario has been presented +to show that per-machine installs are in line with our intent for the upstream +distribution, and so we will simply not provide an option for them. Third +parties who desire this functionality are encouraged to provide their own +distributions. + +PyManager can only be installed for all users, and can be extensively configured +by an administrator, including to constrain the actual runtimes which users may +install. Additionally, PyManager supports local extraction for bundling, and so +embedding apps can easily generate their own layout, which can be installed for +all users if they so desire. + +As this scenario requires administrator intervention with or without any +changes, this will be documented only. + + +Build-time installs +------------------- + +Users currently using Nuget packages will also have to change to a new workflow. +Further investigation is required to determine how best to support this, as it +is possible that the PyManager MSIX package may not be installable on all +continuous integration systems. No differences are anticipated between a package +installed by PyManager compared to one installed by Nuget. + +Users using the embeddable distro may have to change to a new method for +discovering the URL to the packages, though the recommendation would be to use +PyManager to discover and install. No differences are anticipated due to the +change of installer, and the embeddable distro package would be identical to +today. + + +Security Implications +===================== + +In this section we compare the security implications of the installer itself to +the existing installers. The implications of Python being installed on a machine +are out of scope, and the ability of a malicious user to execute the installer +is also out of scope. + +The typical risk introduced by an installer is that an elevated install may make +changes to a system that allow a low-privileged user to later affect a +high-privilege user, for example, by inappropriately setting access control on +shared folders. PyManager only operates as the same privilege level as the user, +and therefore cannot introduce any escalation path. + +An install using the MSI described earlier may introduce additional risks, due +to using older installer technology. Typical users are directed towards the MSIX +or Windows Store install paths, which are safe, and it is assumed that users +of the MSI are capable of ensuring the security of their install process (for +example, by correctly quoting their commands to launch the installer and +ensuring the initial system configuration is suitable). + +Once PyManager is installed on a machine, it is likely that malicious users will +use it to install Python. The admin-only configuration described earlier in +"Configuration" is intended to control these scenarios. Ultimately though, an +attacker who can run PyManager is able to do whatever the user can do, and only +a complete application whitelisting approach can prevent the use of Python. + +Runtime installs by PyManager are fully accessible by, and modifiable by, the +current user. This is equivalent to typical installs using the traditional +installer or a Nuget package, but is more vulnerable to tampering than a Store +install or a per-machine install with the traditional installer. It is not +possible to fully protect an install from the user who installed it. + +The aliases generated by PyManager when installing a runtime are designed to +use a signed, unmodified executable that uses an adjacent data file to launch +the correct target. This can be easily abused to direct the launcher to launch +an alternative, however, the only way to resolve this would sacrifice the trust +in the executable itself, making it trivial to replace it instead of the data. +Such risk already exists, and is equivalent to replacing the script that a user +may launch, or any part of the standard library. Importantly, since aliases are +not shared between users, there is no escalation of privilege along this route. + +PyManager has no mechanism to perform a per-machine install. This may be useful +functionality to some users, as it would allow an install to be completely +unmodifiable by the regular user (excluding virtual environments and the user +site folders). Such functionality may be manually imitated by an administrator +using PyManager and other OS commands, but it is not considered a critical +workflow. The recommended alternative is for an administrator to provide +PyManager and override its configuration. + + +Impact on Existing PEPs +======================= + +This proposal would effectively replace PEP 397 ("Python launcher for Windows") +and PEP 486 ("Make the Python Launcher aware of virtual environments") by +defining the same functionality as part of a new tool with the same name. Both +are already considered final, and the launcher is defined by its documentation +and normal compatibility processes. New functionality is based on the current +implementation, and not the original PEP text. + +This proposal has no impact on PEP 394 ("The “python” Command on Unix-Like +Systems"), and is believed to be consistent with it in devising an approach for +Windows that allows similar guidance to be given to users on all platforms. + +This proposal has no impact on PEP 514 ("Python registration in the Windows +registry"), and in fact improves our ability to follow it with a more flexible +system for registering our own runtimes. Tools that follow PEP 514 will find any +runtimes that choose to use the registration, regardless of how they were +installed. + + +How to Teach This +================= + +Basic Use +--------- + +A central goal of this proposal is that "type 'python' in your terminal" will be +sufficient instruction for the most basic cases. Thanks to the redirector added +by Microsoft, following this instruction will at least result in something +useful happening, and with PyManager we can ensure that "something useful" means +that the user is running the latest version. + +To explain what is actually happening, we propose the following as introductory +text: + +.. code:: text + + Python installs on Windows are managed using an installer tool. After it has + been installed, you can run ``python`` to launch the interpreter, and it will + choose the best version already installed, available online, or referenced by + the script you are launching (if any). If you have a preference for a + particular version, you can specify it with ``py -V:`` followed + by the rest of your command. + + To install a version of Python without running any command, use ``py install + ``. You can see all of your installs with ``py list`` and remove them + with ``py uninstall ``. Run ``py help`` to see all the options that + are available. + + Because each version of Python will be shared by all your projects, we + recommend using virtual environments. This will usually be created for a + particular Python version by running ``py -V: -m venv .venv``, and + activated with ``.venv\Scripts\Activate``. Now, rather than the install + manager, ``python`` or ``py`` will always launch your virtual environment, and + any packages you install are only available while this environment is active. + To get access to the manager again, you can ``deactivate`` the environment, or + use ``py ``. + +Many Python projects include information about how to launch their projects as +part of their own README files. Historically, such information has been +complicated due to the range of options available to users. We propose that, +after the install manager is published, such guidance could be written along +these lines: + +.. code:: text + + To install and use our application, first install Python following the + guidance for your operating system at https://docs.python.org/using/. Then, + create a virtual environment and use 'pip' to install. + + ``python3 -m venv .venv`` + ``source .venv/bin/activate`` or ``.venv\Scripts\Activate`` (on Windows) + ``python -m pip install OurAwesomePackage`` + ... + +If instructions will not include information about virtual environments, then +the ``python`` or ``python3`` command can be shown, and on Windows both will +operate as intended for users with the install manager. + +Instructions currently referring to ``py`` for Windows can continue to do so, as +the install manager provides a practically equivalent command. Projects that +wish to provide Windows-specific instructions, such as by using the ``-V:`` +or ``--install`` options to install the correct version, should also link to the +https://docs.python.org/using/windows.html documentation as guidance for +ensuring that the install manager is installed. + + +Uninstallation +-------------- + +Complete uninstallation is an important topic to cover before a user is likely +to consider removing the install manager. Since not all parts of installs can be +automatically cleaned up when removing the manager, we choose not to remove most +of them. So while the default ``python`` and ``py`` commands will go away, all +the runtimes that were installed are still present and usable. + +We suggest an explanation like this: + +.. code:: text + + Before you uninstall the Python install manager, you'll want to uninstall any + runtimes that you added. This can be done easily with the "purge" option: + + ``py uninstall --purge`` + + This will remove all installs and any shortcuts that would otherwise be left + behind. If you already removed the manager, you can reinstall it and run the + above uninstall command again to clean up. Individual runtimes can be + uninstalled by replacing the ``--purge`` option with the tag, found by looking + at ``python list``. + + +Configuration +------------- + +Configuration files are a common feature that will be documented, but do not +need to be taught to regular users. Similarly, advanced deployment options, such +as those that might be used by system administrators or organisations wanting +their users to use a preferred index, are best covered in reference material. + + +Custom Index +------------ + +We suggest that indexes only need to be introduced when instructing users to +install a specialised runtime or distribution. Administrators seeking to provide +an index are anticipated to actively seek out the relevant information in the +documentation. + +To explain how and when to use an alternate index, we propose text along these +lines: + +.. code:: text + + Our distribution can be installed on Windows using the Python Install Manager + (include link) by referencing our index: + + ``py install --source latest`` + + This index contains all our versions. Use ``py list --source `` to + see everything that is available. + + +Reference Implementation +======================== + +The reference implementation is available at https://github.com/zooba/pymanager/ +with a precompiled MSIX package under the Releases at +https://github.com/zooba/pymanager/releases. This sample includes a bundled +index, rather than a hosted one, and references a range of existing Nuget +packages to allow install testing. + + +Rejected Ideas +============== + +Make PyManager available on all platforms +----------------------------------------- + +While we are not inherently opposed to this idea, it relies on many more +components being aligned before it can become possible. + +Firstly, as it stands, the reference implementation has a lot of +Windows-specific knowledge. Equivalent knowledge for other platforms would need +to be collated and implemented, as well as any additional behaviours specific to +non-Windows platforms. + +Second, we need a source of pre-built, relocatable binaries that can be +extracted onto the system. While such sources do exist, due to our position in +the supply chain, we cannot justifiably use them (they should be using us). For +Windows, our own binaries already meet these criteria, so we can repackage them +without modification. + +Third, the current implementation relies on a bundled Python runtime, which must +be isolated from any user interference for obvious reasons. This would also +require the relocatable binaries mentioned above, which we currently only have +for Windows. + +Due to the additional steps needed to make this functional on other platforms, +and the fact that there isn't a need to replace existing installers for those +platforms, we consider this idea out of scope for this PEP. It may be pursued in +the future. + + +Include a runtime pre-installed with the manager +------------------------------------------------ + +The proposal is to have a full Python runtime included with PyManager, so that +its ``python.exe`` alias can refer directly to it rather than resolving to the +best available version dynamically. + +It is very important for stability and updates that runtime releases are +fully independent of the manager. Updating the manager should be possible +without affecting any existing runtime installs, and likewise there should be +no requirement to update the manager to get a newer runtime. + +Hypothetically, if we were to include Python 3.14.0 with the manager such that +it did not need to be installed, it would be a breaking change to later replace +that with 3.15.0. As we only have a single install for the manager, this would +result in the newest installs getting the oldest runtime. + +This would also ignore the status of PyManager's ``python`` alias as being of an +unspecified version - when the user is launching this alias, it's because they +didn't care what version they get enough to specify one. In that situation, we +ought to select the best available, and allow them the options to stabilise it +as is appropriate (whether through a shebang or an active environment). + + +Include a runtime INSTEAD OF the manager +---------------------------------------- + +This is the current situation, which we are trying to change. If you made this +argument, and somehow still read this far, please go back and start again. + + +Use a built-in module rather than subcommands +--------------------------------------------- + +Two alternatives to using commands like ``py list`` or ``py install`` that have +been proposed are to use either dedicated modules, invoked like ``py -m list`` +and ``py -m install``, or a single dedicated module invoked like ``py -m manage +list``. This idea is rejected on the basis that it attempts to reuse existing +semantics for a scenario that cannot be reliably implemented by those semantics, +and so will require a special case that is harder to explain, understand, and +maintain. + +The main reason this idea is rejected is due to the interaction of two otherwise +desirable semantics: first, that the default ``py`` command should launch the +latest available runtime as if it were launched directly; and second, that the +behaviour of ``-m`` should not be treated as a special case in some +circumstances. If the first part were dropped, we would freely modify the +command to behave as users expect - nobody would be raising compatibility +concerns at all if we were agreed to completely break compatibility. However, if +the second constraint were dropped, users would bear the burden of the ensuring +confusion. (We aren't proposing dropping either - this is a rejected idea, after +all - but it helps to illustrate what the options are.) + +First, since one of the subcommands is intended to install your first runtime, +we cannot treat ``python -m [manage] install`` as if it is running through the +default runtime - there isn't one! It inherently requires special case handling +in order to read the command and execute it through a different program. + +Additionally, Python allows other options to precede or mingle with the ``-m``, +which would have to be supported by this special case. + +Finally, the semantics of the ``-m`` option include searching the initial +``sys.path`` for matching module names. This is a considerably more broad search +than a bare name. ``py -m install`` would gladly execute ``install.py``, +``install.pyc``, ``install.pyd``, ``install\\__init__.py``, and more after +searching a number of directories found by inspecting the file system, the +environment, the registry, as well as any transitively included paths found in +those. Compared to ``py install``, which would *only* look for a file called +precisely ``install`` in the current working directory, the ``-m`` behaviour is +far more likely to be already relied upon by real scenarios. (For example, +Django projects typically have a ``manage.py`` script, meaning that ``py -m +manage`` would always behave incorrectly.) + +Changing ``py -m install`` to *not* behave like ``-m``, but instead to execute +an internal command, is vastly more likely to break users than changing +``py install``. As such, this idea is rejected. + + +Use a new command-line option rather than subcommands +----------------------------------------------------- + +A reasonable alternative to subcommands is to specify their names with leading +punctuation, like an option rather than a subcommand. For example, this may look +like ``py /install ...`` rather than ``py install``, or ``py --list``. Because +some of these are currently errors for a normal CPython interpreter, they +could be added without any backwards compatibility concern. + +Notably, however, the typical Windows format of a leading slash is not an error +in CPython. Windows users therefore cannot directly transfer existing knowledge +and must learn a new way to specify options. As we are proposing a Windows +specific tool, this is a terrible start. Additionally, those users familiar with +Unix-style command lines will recognise the misuse of options as commands. + +We desire to create a clean interface, and starting with a design that includes +obvious warts or learning challenges is counter to that goal. Modern tools +universally use subcommands for these purposes, and so the idea to use something +different is rejected. + + +Improving the current traditional installer instead +--------------------------------------------------- + +Rather than creating a new install mechanism, we could invest in maintaining the +current installer. At this stage, however, our current installer is based +entirely on retired technology. Windows is no longer developing the Windows +Installer service, and Wix are no longer improving the version of their toolset +that we use. Migrating to a newer Wix Toolset is a significant amount of work, +and ultimately still leaves us tied to old technologies. + +As mentioned earlier, the most beneficial functionality provided by Windows +Installer is not used for CPython, and generally has caused more issues than it +has ever solved (for example, accidental downgrades due to automatically +collected file version information). + +The implementation of the Burn bundle, which is our primary source of installer +logic, is in C++ and integrated into a framework that few core developers are +familiar with. This makes maintenance challenging, and is not a good long term +position to take. Migrating desired features such as registration-free installs +into the Burn bundle is not possible (without writing the end-to-end +reimplementation and integrating it as an afterthought). + +Our view is that maintaining the current traditional installer is at least as +much effort as implementing a new installer, and would not provide meaningful +benefits for the core team or for our users. As such, this idea is rejected. + + +Delete the Store package completely +----------------------------------- + +Removing the Store packages would reduce the number of options users face when +choosing a Python runtime. By all measures apart from reliability and security, +the traditional installer is entirely sufficient as a substitute. The effort to +migrate parts of the ecosystem to more secure settings (such as not relying on +DLL hijacking) has largely occurred, but some packages remain that still only +work with less secure configurations, and moving all users back to these +configurations would ensure that users of these packages would not face the +issues they face today. + +However, the majority of users of the Store packages appear to have no +complaints. Anecdotally, they are often fully satisfied by the Store install, +and particularly appreciate the ease and reliability of installation. (And on a +personal note, this author has been using Store packages exclusively since +Python 3.8 with no blocking issues.) + +The greatest number of issues have been caused by misconfigured ``PATH`` +variables and the default ``python.exe`` redirector installed by Microsoft. In +other words, entirely unrelated to our own package (though sometimes related to +unresolvable issues in our other installer). For the sake of the high number of +successful installs through this path, we consider the burden of diagnosing and +assisting impacted users to be worthwhile, and consider the idea to simply drop +the Store package rejected. + +That said, when PyManager is published to the Store, we would plan to delist all +existing runtimes on the Store to ensure users find the manager. This only +impacts new installs, and anyone who has previously installed a particular +version (even on another machine, if they were logged in) will be able to +continue to use and install those versions. + + +Rely on WinGet or equivalents +----------------------------- + +WinGet, Chocolatey, and other similar tools are not installers in the sense that +we require. They use their own repository of metadata to download, validate, and +run installers. Without our own installer, they have nothing to run, and so +cannot be used. + +It is possible that their metadata will not support installing PyManager and +then running it to install a particular runtime. If this is the case, they may +need to investigate using our binary packages directly. + +Currently, none of these install tools are officially supported by CPython, and +so we have no obligation to make them work. + + +Make every version a Windows Store package +------------------------------------------ + +It is possible to release each version to the Windows Store as we currently do, +but make them unlisted and rely on an installer (potentially PyManager, WinGet, +or another tool that can install Store packages). This would avoid the risk of +overwhelming the user, while greatly simplifying our own reponsibilities for +package management. + +This approach would leave a significant burden on whichever contributor has +access to the Store publishing interface, as updating packages is a manual +operation. Additionally, it would leave every Python runtime with the technical +limitations outlined earlier. As such, this idea is rejected. + +Making every version a MSIX package rather than a ZIP, even though this avoids +the Store publishing interface, would still impose technical limitations on +users. It is also rejected. + + +Just publish the plain ZIP file +------------------------------- + +Publishing the plain ZIP file is part of the plan, however, it will not be +visibly listed (for example, on the python.org downloads pages, though they will +be visible in the FTP view). An alternative would be to publish and list these +packages, and expect users to download and manually extract and configure them. + +Given the workflows we see, we believe that most users do not want to configure +a Python install at all. Not only do they not want to choose the install +location, they do not want to choose a version, or even have to search for a +download provider or instructions. However, they do want to be able to find an +install later, launch, update or remove it, or list all known installs. + +It is also worth recognising that there will be more ZIP files than are +currently listed on the Download pages, and so the list of files will become +longer. Choosing the correct download is already challenging for users (those +who bypass the primary "Download" button and view the list of all available +versions and then files), and we have no desire to make it more challenging. + +The index protocol and download list will be available for tools that wish to +use it, or for users who are willing to navigate JSON in order to find the URL. +The ``--target`` option on the install command also provides a trivial download +and extract operation, allowing users to have the same experience as a ZIP file. + + +Only publish PyManager to one place +----------------------------------- + +Whether the Windows Store or python.org, it would be viable to publish to only +one location. + +However, users strongly expect to be able to download *something* from +python.org. If we were to remove any option at all, we would inevitably hurt our +users. Without an MSIX available on python.org, users have no way to transfer +the package to another machine, or to fully script the initial install of the +manager. + +Many users rely on the Windows Store app to install packages, and the built-in +redirector in Windows can only open to a Store page. As such, removing the Store +app is equivalent to denying hundreds of thousands of installs each month. + +Additionally, automatic updates are only supported through the Store. We would +have to implement automatic updates manually if we did not publish there. It is +possible to have the MSIX from python.org find its own updates on the Store, and +we can assume that machines without access are responsible for their own +updates. + +The two builds are practically identical. The only difference between the MSIX +we provide to the Store and the one that goes to python.org is package signing: +we sign the python.org package ourselves, while the Store package is signed as +part of the publish process. Otherwise, there is no additional cost to producing +and publishing both packages. + + +Inline Script Metadata +---------------------- + +PEP 723 introduced inline script metadata, a structured comment intended for +third-party tools to interpret and then launch a Python script in the correct +environment. An example taken from that PEP: + + # /// script + # requires-python = ">=3.11" + # dependencies = [ + # "requests<3", + # "rich", + # ] + # /// + +PyManager has no integrated support for installing dependencies, and does not +propose adding any. As a result, we could not fully implement handling of this +metadata, and as we consider partial handling to be worse than nothing, we +choose not to implement any. + +It is possible for a user to specify the constraint directly as an option, for +example, ``py -V:>=3.11 my-script.py`` to get the selection behaviour. + +We could also detect the metadata and warn if the selected runtime does not +match its requirement, but this is not part of the initial proposal. + + + +Open Issues +=========== + +TODO: Raise open issues + + +Footnotes +========= + +TODO: Collate references + + +Copyright +========= + +This document is placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive. From 7e027b3ff05eb1a06944d2dc7533df7e264c125a Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 21 Jan 2025 23:50:15 +0000 Subject: [PATCH 02/10] Cleanup lint issues --- peps/pep-0772.rst | 50 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst index d0a4bee8584..1768bb8ff9d 100644 --- a/peps/pep-0772.rst +++ b/peps/pep-0772.rst @@ -6,10 +6,8 @@ Discussions-To: https://discuss.python.org/t/pre-pep-a-python-installation-manag Status: Draft Type: Standards Track Topic: Release -Created: 12-12-2024 -Python-Version: N/A -Post-History: 18-12-2024 -Resolution: TBD +Created: 21-Jan-2025 +Post-History: 18-Dec-2024 Abstract @@ -246,7 +244,7 @@ Challenges ---------- There are numerous challenges we face with the current set of installers, -which largely break down into two categories: mismatched or unachievable +which largely break down into two categories: mismatched or unachievable user expectations, and general unreliability. The traditional installer has the highest level of unreliability. The Windows @@ -781,47 +779,47 @@ The initial schema is shown below:: { # Should be 1. "schema": int, - + # Unique ID used for install detection/side-by-side. # Must be valid as a filename. "id": str, - + # Name to display in the UI "displayName": str, - + # Version used to sort packages. Also determines prerelease status. # Should follow Python's format, but is only compared among releases # with the same Company. "sort-version": Version, - + # Specifies platforms to consider this package for. # Initially, 'win32' is the only supported value. Others may be # defined in the future. This condition is evaluated silently, and # is not intended to replace platform requests in "install-for". "platform": [str], - + # Company field, used for filtering and displayed as the publisher. "company": str, - + # Default tag, mainly for UI purposes. # It should also be specified in 'install-for' and 'run-for'. "tag": str, - + # List of tags to install this package for. This does not have to be # unique across all installs; the first match will be selected. "install-for": [str], - + # List of tags to run this package for. Does not have to be unique # across all installs; the first match will be selected. The target # is the executable path relative to the root of the archive. # Explicit args (optional) are inserted before user args. "run-for": [{"tag": str, "target": str, "args": [str], "windowed": int}, ...], - + # List of global CLI aliases to create for this package. Does not # have to be unique across all installs; the first match will be # created. "alias": [{"name": str, "target": str, "windowed": int}, ...], - + # List of shortcuts to create for this package. Additional keys on # each instance are allowed based on the value of 'kind'. # Initially, 'kind' supports the following values: @@ -829,17 +827,17 @@ The initial schema is shown below:: # * 'start' - generate shortcuts in the user's Start Menu # * 'uninstall' - generate an Add/Remove Programs entry "shortcuts": [{"kind": str, ...}, ...] - + # Default executable path, relative to the root of the archive. # Usually the values from 'run-for' will be used instead, and this # is mainly for display purposes. "executable": str, # Default executable args "executable_args": [str], - + # URL to download the package archive from "url": str, - + # Optional set of hashes to validate the download. Hashes are stored # as hex digests. Any hash supported by hashlib without OpenSSL is # permitted. @@ -848,7 +846,7 @@ The initial schema is shown below:: } } ], - + # Full or partial URL to the next index file "next": str, } @@ -1177,12 +1175,12 @@ text: the script you are launching (if any). If you have a preference for a particular version, you can specify it with ``py -V:`` followed by the rest of your command. - + To install a version of Python without running any command, use ``py install ``. You can see all of your installs with ``py list`` and remove them with ``py uninstall ``. Run ``py help`` to see all the options that are available. - + Because each version of Python will be shared by all your projects, we recommend using virtual environments. This will usually be created for a particular Python version by running ``py -V: -m venv .venv``, and @@ -1203,7 +1201,7 @@ these lines: To install and use our application, first install Python following the guidance for your operating system at https://docs.python.org/using/. Then, create a virtual environment and use 'pip' to install. - + ``python3 -m venv .venv`` ``source .venv/bin/activate`` or ``.venv\Scripts\Activate`` (on Windows) ``python -m pip install OurAwesomePackage`` @@ -1236,9 +1234,9 @@ We suggest an explanation like this: Before you uninstall the Python install manager, you'll want to uninstall any runtimes that you added. This can be done easily with the "purge" option: - + ``py uninstall --purge`` - + This will remove all installs and any shortcuts that would otherwise be left behind. If you already removed the manager, you can reinstall it and run the above uninstall command again to clean up. Individual runtimes can be @@ -1270,9 +1268,9 @@ lines: Our distribution can be installed on Windows using the Python Install Manager (include link) by referencing our index: - + ``py install --source latest`` - + This index contains all our versions. Use ``py list --source `` to see everything that is available. From 2023f636a69b7a98bca59fbc87feae1d23743971 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 21 Jan 2025 23:59:28 +0000 Subject: [PATCH 03/10] Update URL --- peps/pep-0772.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst index 1768bb8ff9d..9de234ee0a7 100644 --- a/peps/pep-0772.rst +++ b/peps/pep-0772.rst @@ -2,7 +2,7 @@ PEP: 772 Title: A Python Installation Manager for Windows Author: Steve Dower PEP-Delegate: TBD -Discussions-To: https://discuss.python.org/t/pre-pep-a-python-installation-manager-for-windows/74556 +Discussions-To: https://discuss.python.org/t/pep-772-a-python-installation-manager-for-windows/77900 Status: Draft Type: Standards Track Topic: Release From b7de057df7aaa135993f2f6e3effe6fd97ec5dd5 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 22 Jan 2025 00:06:41 +0000 Subject: [PATCH 04/10] Update peps/pep-0772.rst Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- peps/pep-0772.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst index 9de234ee0a7..43f855befd5 100644 --- a/peps/pep-0772.rst +++ b/peps/pep-0772.rst @@ -1,13 +1,14 @@ PEP: 772 Title: A Python Installation Manager for Windows Author: Steve Dower -PEP-Delegate: TBD -Discussions-To: https://discuss.python.org/t/pep-772-a-python-installation-manager-for-windows/77900 +Discussions-To: https://discuss.python.org/t/77900/ Status: Draft Type: Standards Track Topic: Release Created: 21-Jan-2025 -Post-History: 18-Dec-2024 +Post-History: + `18-Dec-2024 `__, + `21-Jan-2025 `__, Abstract From 2d4cf4cc00c623236fe7e4c7aa69d66c8854a169 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 22 Jan 2025 00:07:20 +0000 Subject: [PATCH 05/10] Add me to codeowners --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6ac66492831..6b195c7e3cc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -648,6 +648,7 @@ peps/pep-0767.rst @carljm peps/pep-0768.rst @pablogsal peps/pep-0769.rst @facundobatista peps/pep-0770.rst @sethmlarson @brettcannon +peps/pep-0772.rst @zooba # ... peps/pep-0777.rst @warsaw # ... From 1a2d225ebcacb5d874bad859fcfd96acf738b4d3 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 22 Jan 2025 00:41:05 +0000 Subject: [PATCH 06/10] Apply suggestions from code review Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- peps/pep-0772.rst | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst index 43f855befd5..5852008694f 100644 --- a/peps/pep-0772.rst +++ b/peps/pep-0772.rst @@ -140,12 +140,12 @@ release process using almost all identical binaries to the other packages. Due to being in an app store package, the primary ``python.exe`` is enhanced to be able to determine its location properly, and alternative ``pip.exe`` and other shortcuts are included to make up for the lack of ``PATH`` environment -variable settings. These are implemented in ``PC\\python_uwp.cpp`` in our repo. +variable settings. These are implemented in :file:`PC\\python_uwp.cpp` in our repo. These packages are installed by searching for Python in the Microsoft Store app, which will find results for each major version since 3.8. Users then have to select a version and install it. These packages include the CPython -interpreter, standard library, Tcl/Tk, IDLE and pip, and create file +interpreter, standard library, Tcl/Tk, IDLE, and pip, and create file associations, Start Menu shortcuts, and global commands for ``python.exe``, ``python3.exe``, ``python3.X.exe``, ``pip[3[.X]].exe`` and ``idle[3[.X]].exe``. No ``PATH`` modification is possible or required, though users may need to @@ -271,7 +271,7 @@ example, if the user has Python 3.14 installed and then installs (or updates) 3.13, the ``python`` command will switch from the later version to the earlier version. -The ``py.exe`` launcher, defined in PEP 397 and implicitly updated by PEP 514, +The ``py.exe`` launcher, defined in :pep:`397` and implicitly updated by :pep:`514`, is an attempt to avoid this particular issue. It uses its own logic for finding installed versions without relying on ``PATH``. However, the PEP 514 logic does not allow for prerelease or experimental builds to be treated specially, and so @@ -340,17 +340,17 @@ ability to inspect the user's system and choose the correct runtime to launch. Additionally, ``py`` and ``pymanager`` will have management subcommands to allow adding and removing runtimes. -In line with PEP 394 and the default behaviour of Windows, the recommended +In line with :pep:`394` and the default behaviour of Windows, the recommended command for launching Python is ``python.exe``. As provided by PyManager, this will locate an existing install, either among those that PyManager manages or -using PEP 514, or it will install the latest available version of CPython and +using :pep:`514`, or it will install the latest available version of CPython and select that. The ``python3.exe`` command behaves similarly, but is only allowed to find 3.x installs from python.org. The ``py.exe`` command provided by PyManager will be recommended for most management use, due to its brevity. ``py install ...``, ``py list ...`` and so on. The proposed commands are detailed later. The existing behaviour of the -PEP 397 launcher is preserved, however, launching through ``py`` will not +:pep:`397` launcher is preserved, however, launching through ``py`` will not automatically install runtimes (by default). If one is requested but is not installed, users will just get an error. The ``py run ...`` subcommand, however, will install automatically, and supports the same options as bare ``py``. @@ -378,7 +378,7 @@ Replacing other installers Our intent is to immediately stop publishing individual versions to the Windows Store, and to deprecate and phase out the traditional installer and Nuget -packages by 3.16. The embeddable distro would remain, but its listing on +packages by Python 3.16. The embeddable distro would remain, but its listing on python.org download pages would be phased out and it will be available only through PyManager. @@ -773,7 +773,9 @@ versions. The intent is to allow for older indexes to be archived and only accessed when required, reducing the size of the initial download without cutting off users from older versions. -The initial schema is shown below:: +The initial schema is shown below: + +.. code:: python SCHEMA = { "versions": [ From 21ffec0f39d6e277bdab44c0a0a849d6a54205e7 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 22 Jan 2025 00:41:59 +0000 Subject: [PATCH 07/10] Apply suggestions from code review --- peps/pep-0772.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst index 5852008694f..a9c26afd253 100644 --- a/peps/pep-0772.rst +++ b/peps/pep-0772.rst @@ -85,8 +85,9 @@ all of them. * some users expect the ``py`` command to work after installation These assumptions have all been demonstrated over time to exist, though the -relative importance has not been quantified. The Nuget packages and the -embeddable distro can meet most of these needs. +relative importance has not been quantified. The :ref:`NuGet packages +` and the :ref:`embeddable distro +` can meet most of these needs. Traditional Installer --------------------- @@ -293,8 +294,8 @@ and technical. Due to the overhead of launching an app, Python starts up slower. Because apps are designed to be isolated from each other, it is more difficult to use hidden directories (such as ``AppData`` or ``TEMP``) to communicate between different versions of Python, as each version has its own space. Apps -are subject to stricter security requirements that legacy applications start -disabled, such as DLL hijacking protection, which causes some libraries to fail. +are subject to stricter security requirements that legacy applications usually +have disabled, such as DLL hijacking protection, which causes some libraries to fail. The ``python3`` and ``python`` shortcuts are managed through system settings, and the user interface is not very good (and not going to be improved, according to Microsoft). Without managing these, it is relatively easy for an undesired From d9736cf5757be39b03b24219bc8bc654ba2bfa07 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 22 Jan 2025 00:49:07 +0000 Subject: [PATCH 08/10] Apply suggestions from code review Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- peps/pep-0772.rst | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst index a9c26afd253..2b98f426c1b 100644 --- a/peps/pep-0772.rst +++ b/peps/pep-0772.rst @@ -9,6 +9,7 @@ Created: 21-Jan-2025 Post-History: `18-Dec-2024 `__, `21-Jan-2025 `__, +Replaces: 397, 486 Abstract @@ -937,7 +938,7 @@ Interaction with venv --------------------- An activated virtual environment, as implemented by the standard library -``venv`` module, will modify the user's ``PATH`` environment variable to ensure +:mod:`venv` module, will modify the user's ``PATH`` environment variable to ensure that the venv launcher will take precedence over other executables. As a result, when a venv has been activated, PyManager can only be launched by its aliases other than ``python``. @@ -951,7 +952,7 @@ Backwards Compatibility ======================= In general, there are no compatibility guarantees to the install process between -major versions (``3.x`` to ``3.y``), and so "having to use a different +minor versions (``3.x`` to ``3.y``), and so "having to use a different installer" is not considered compatibility breakage. The versions of Python installed are only impacted by this change to the extent that the install method modified their behaviour. In general, most installs will be closer to the @@ -1008,8 +1009,8 @@ selected) and require complicating the selection logic unnecessarily. This change will be documented only. -Old py.exe launcher installed ------------------------------ +Old ``py.exe`` launcher installed +--------------------------------- Users who do not manually uninstall an old ``py.exe`` launcher will find that both their existing and new installs of Python are found, though where versions @@ -1138,18 +1139,18 @@ PyManager and override its configuration. Impact on Existing PEPs ======================= -This proposal would effectively replace PEP 397 ("Python launcher for Windows") -and PEP 486 ("Make the Python Launcher aware of virtual environments") by +This proposal would effectively replace :pep:`397` ("Python launcher for Windows") +and :pep:`486` ("Make the Python Launcher aware of virtual environments") by defining the same functionality as part of a new tool with the same name. Both are already considered final, and the launcher is defined by its documentation and normal compatibility processes. New functionality is based on the current implementation, and not the original PEP text. -This proposal has no impact on PEP 394 ("The “python” Command on Unix-Like +This proposal has no impact on :pep`394` ("The “python” Command on Unix-Like Systems"), and is believed to be consistent with it in devising an approach for Windows that allows similar guidance to be given to users on all platforms. -This proposal has no impact on PEP 514 ("Python registration in the Windows +This proposal has no impact on :pep`514` ("Python registration in the Windows registry"), and in fact improves our ability to follow it with a more flexible system for registering our own runtimes. Tools that follow PEP 514 will find any runtimes that choose to use the registration, regardless of how they were @@ -1219,7 +1220,7 @@ Instructions currently referring to ``py`` for Windows can continue to do so, as the install manager provides a practically equivalent command. Projects that wish to provide Windows-specific instructions, such as by using the ``-V:`` or ``--install`` options to install the correct version, should also link to the -https://docs.python.org/using/windows.html documentation as guidance for +:ref:`documentation ` as guidance for ensuring that the install manager is installed. @@ -1576,6 +1577,8 @@ PEP 723 introduced inline script metadata, a structured comment intended for third-party tools to interpret and then launch a Python script in the correct environment. An example taken from that PEP: +.. code:: python + # /// script # requires-python = ">=3.11" # dependencies = [ @@ -1596,7 +1599,6 @@ We could also detect the metadata and warn if the selected runtime does not match its requirement, but this is not part of the initial proposal. - Open Issues =========== From 55d5380bae2c58937d904916f97272b211f29396 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 22 Jan 2025 09:36:39 +0000 Subject: [PATCH 09/10] Add some self-notes --- peps/pep-0772.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/peps/pep-0772.rst b/peps/pep-0772.rst index 2b98f426c1b..c26ce1f695c 100644 --- a/peps/pep-0772.rst +++ b/peps/pep-0772.rst @@ -1,4 +1,4 @@ -PEP: 772 +PEP: 773 Title: A Python Installation Manager for Windows Author: Steve Dower Discussions-To: https://discuss.python.org/t/77900/ @@ -906,6 +906,8 @@ launches the most appropriate version of Python available on the user's machine. This is much closer to the desired behaviour of the global ``python`` command than any alternative. +TODO: Note that this follows Gentoo's design as well + Replacing py.exe ---------------- @@ -1112,6 +1114,8 @@ use it to install Python. The admin-only configuration described earlier in attacker who can run PyManager is able to do whatever the user can do, and only a complete application whitelisting approach can prevent the use of Python. +TODO: Notes about security of package acquisition (tl;dr: TLS) + Runtime installs by PyManager are fully accessible by, and modifiable by, the current user. This is equivalent to typical installs using the traditional installer or a Nuget package, but is more vulnerable to tampering than a Store @@ -1146,11 +1150,11 @@ are already considered final, and the launcher is defined by its documentation and normal compatibility processes. New functionality is based on the current implementation, and not the original PEP text. -This proposal has no impact on :pep`394` ("The “python” Command on Unix-Like +This proposal has no impact on :pep:`394` ("The “python” Command on Unix-Like Systems"), and is believed to be consistent with it in devising an approach for Windows that allows similar guidance to be given to users on all platforms. -This proposal has no impact on :pep`514` ("Python registration in the Windows +This proposal has no impact on :pep:`514` ("Python registration in the Windows registry"), and in fact improves our ability to follow it with a more flexible system for registering our own runtimes. Tools that follow PEP 514 will find any runtimes that choose to use the registration, regardless of how they were From bc5a1bafda64fd83bac251d93173cb4401e94231 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 22 Jan 2025 09:37:30 +0000 Subject: [PATCH 10/10] Change to 773 --- .github/CODEOWNERS | 2 +- peps/{pep-0772.rst => pep-0773.rst} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename peps/{pep-0772.rst => pep-0773.rst} (100%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6b195c7e3cc..fbacbd2388a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -648,7 +648,7 @@ peps/pep-0767.rst @carljm peps/pep-0768.rst @pablogsal peps/pep-0769.rst @facundobatista peps/pep-0770.rst @sethmlarson @brettcannon -peps/pep-0772.rst @zooba +peps/pep-0773.rst @zooba # ... peps/pep-0777.rst @warsaw # ... diff --git a/peps/pep-0772.rst b/peps/pep-0773.rst similarity index 100% rename from peps/pep-0772.rst rename to peps/pep-0773.rst