17db96d56Sopenharmony_ci:mod:`venv` --- Creation of virtual environments
27db96d56Sopenharmony_ci================================================
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci.. module:: venv
57db96d56Sopenharmony_ci   :synopsis: Creation of virtual environments.
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci.. moduleauthor:: Vinay Sajip <vinay_sajip@yahoo.co.uk>
87db96d56Sopenharmony_ci.. sectionauthor:: Vinay Sajip <vinay_sajip@yahoo.co.uk>
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci.. versionadded:: 3.3
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci**Source code:** :source:`Lib/venv/`
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci.. index:: pair: Environments; virtual
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci--------------
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci.. _venv-def:
197db96d56Sopenharmony_ci.. _venv-intro:
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ciThe :mod:`!venv` module supports creating lightweight "virtual environments",
227db96d56Sopenharmony_cieach with their own independent set of Python packages installed in
237db96d56Sopenharmony_citheir :mod:`site` directories.
247db96d56Sopenharmony_ciA virtual environment is created on top of an existing
257db96d56Sopenharmony_ciPython installation, known as the virtual environment's "base" Python, and may
267db96d56Sopenharmony_cioptionally be isolated from the packages in the base environment,
277db96d56Sopenharmony_ciso only those explicitly installed in the virtual environment are available.
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ciWhen used from within a virtual environment, common installation tools such as
307db96d56Sopenharmony_ci`pip`_ will install Python packages into a virtual environment
317db96d56Sopenharmony_ciwithout needing to be told to do so explicitly.
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ciSee :pep:`405` for more background on Python virtual environments.
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_ci.. seealso::
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci   `Python Packaging User Guide: Creating and using virtual environments
387db96d56Sopenharmony_ci   <https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment>`__
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci.. include:: ../includes/wasm-notavail.rst
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ciCreating virtual environments
437db96d56Sopenharmony_ci-----------------------------
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci.. include:: /using/venv-create.inc
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci.. _venv-explanation:
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ciHow venvs work
507db96d56Sopenharmony_ci--------------
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ciWhen a Python interpreter is running from a virtual environment,
537db96d56Sopenharmony_ci:data:`sys.prefix` and :data:`sys.exec_prefix`
547db96d56Sopenharmony_cipoint to the directories of the virtual environment,
557db96d56Sopenharmony_ciwhereas :data:`sys.base_prefix` and :data:`sys.base_exec_prefix`
567db96d56Sopenharmony_cipoint to those of the base Python used to create the environment.
577db96d56Sopenharmony_ciIt is sufficient to check
587db96d56Sopenharmony_ci``sys.prefix != sys.base_prefix`` to determine if the current interpreter is
597db96d56Sopenharmony_cirunning from a virtual environment.
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ciA virtual environment may be "activated" using a script in its binary directory
627db96d56Sopenharmony_ci(``bin`` on POSIX; ``Scripts`` on Windows).
637db96d56Sopenharmony_ciThis will prepend that directory to your :envvar:`!PATH`, so that running
647db96d56Sopenharmony_ci:program:`python` will invoke the environment's Python interpreter
657db96d56Sopenharmony_ciand you can run installed scripts without having to use their full path.
667db96d56Sopenharmony_ciThe invocation of the activation script is platform-specific
677db96d56Sopenharmony_ci(:samp:`{<venv>}` must be replaced by the path to the directory
687db96d56Sopenharmony_cicontaining the virtual environment):
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci+-------------+------------+--------------------------------------------------+
717db96d56Sopenharmony_ci| Platform    | Shell      | Command to activate virtual environment          |
727db96d56Sopenharmony_ci+=============+============+==================================================+
737db96d56Sopenharmony_ci| POSIX       | bash/zsh   | :samp:`$ source {<venv>}/bin/activate`           |
747db96d56Sopenharmony_ci|             +------------+--------------------------------------------------+
757db96d56Sopenharmony_ci|             | fish       | :samp:`$ source {<venv>}/bin/activate.fish`      |
767db96d56Sopenharmony_ci|             +------------+--------------------------------------------------+
777db96d56Sopenharmony_ci|             | csh/tcsh   | :samp:`$ source {<venv>}/bin/activate.csh`       |
787db96d56Sopenharmony_ci|             +------------+--------------------------------------------------+
797db96d56Sopenharmony_ci|             | PowerShell | :samp:`$ {<venv>}/bin/Activate.ps1`              |
807db96d56Sopenharmony_ci+-------------+------------+--------------------------------------------------+
817db96d56Sopenharmony_ci| Windows     | cmd.exe    | :samp:`C:\\> {<venv>}\\Scripts\\activate.bat`    |
827db96d56Sopenharmony_ci|             +------------+--------------------------------------------------+
837db96d56Sopenharmony_ci|             | PowerShell | :samp:`PS C:\\> {<venv>}\\Scripts\\Activate.ps1` |
847db96d56Sopenharmony_ci+-------------+------------+--------------------------------------------------+
857db96d56Sopenharmony_ci
867db96d56Sopenharmony_ci.. versionadded:: 3.4
877db96d56Sopenharmony_ci   :program:`fish` and :program:`csh` activation scripts.
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci.. versionadded:: 3.8
907db96d56Sopenharmony_ci   PowerShell activation scripts installed under POSIX for PowerShell Core
917db96d56Sopenharmony_ci   support.
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ciYou don't specifically *need* to activate a virtual environment,
947db96d56Sopenharmony_cias you can just specify the full path to that environment's
957db96d56Sopenharmony_ciPython interpreter when invoking Python.
967db96d56Sopenharmony_ciFurthermore, all scripts installed in the environment
977db96d56Sopenharmony_cishould be runnable without activating it.
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_ciIn order to achieve this, scripts installed into virtual environments have
1007db96d56Sopenharmony_cia "shebang" line which points to the environment's Python interpreter,
1017db96d56Sopenharmony_cii.e. :samp:`#!/{<path-to-venv>}/bin/python`.
1027db96d56Sopenharmony_ciThis means that the script will run with that interpreter regardless of the
1037db96d56Sopenharmony_civalue of :envvar:`!PATH`. On Windows, "shebang" line processing is supported if
1047db96d56Sopenharmony_ciyou have the :ref:`launcher` installed. Thus, double-clicking an installed
1057db96d56Sopenharmony_ciscript in a Windows Explorer window should run it with the correct interpreter
1067db96d56Sopenharmony_ciwithout the environment needing to be activated or on the :envvar:`!PATH`.
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ciWhen a virtual environment has been activated, the :envvar:`!VIRTUAL_ENV`
1097db96d56Sopenharmony_cienvironment variable is set to the path of the environment.
1107db96d56Sopenharmony_ciSince explicitly activating a virtual environment is not required to use it,
1117db96d56Sopenharmony_ci:envvar:`!VIRTUAL_ENV` cannot be relied upon to determine
1127db96d56Sopenharmony_ciwhether a virtual environment is being used.
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci.. warning:: Because scripts installed in environments should not expect the
1157db96d56Sopenharmony_ci   environment to be activated, their shebang lines contain the absolute paths
1167db96d56Sopenharmony_ci   to their environment's interpreters. Because of this, environments are
1177db96d56Sopenharmony_ci   inherently non-portable, in the general case. You should always have a
1187db96d56Sopenharmony_ci   simple means of recreating an environment (for example, if you have a
1197db96d56Sopenharmony_ci   requirements file ``requirements.txt``, you can invoke ``pip install -r
1207db96d56Sopenharmony_ci   requirements.txt`` using the environment's ``pip`` to install all of the
1217db96d56Sopenharmony_ci   packages needed by the environment). If for any reason you need to move the
1227db96d56Sopenharmony_ci   environment to a new location, you should recreate it at the desired
1237db96d56Sopenharmony_ci   location and delete the one at the old location. If you move an environment
1247db96d56Sopenharmony_ci   because you moved a parent directory of it, you should recreate the
1257db96d56Sopenharmony_ci   environment in its new location. Otherwise, software installed into the
1267db96d56Sopenharmony_ci   environment may not work as expected.
1277db96d56Sopenharmony_ci
1287db96d56Sopenharmony_ciYou can deactivate a virtual environment by typing ``deactivate`` in your shell.
1297db96d56Sopenharmony_ciThe exact mechanism is platform-specific and is an internal implementation
1307db96d56Sopenharmony_cidetail (typically, a script or shell function will be used).
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ci.. _venv-api:
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ciAPI
1367db96d56Sopenharmony_ci---
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci.. highlight:: python
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ciThe high-level method described above makes use of a simple API which provides
1417db96d56Sopenharmony_cimechanisms for third-party virtual environment creators to customize environment
1427db96d56Sopenharmony_cicreation according to their needs, the :class:`EnvBuilder` class.
1437db96d56Sopenharmony_ci
1447db96d56Sopenharmony_ci.. class:: EnvBuilder(system_site_packages=False, clear=False, \
1457db96d56Sopenharmony_ci                      symlinks=False, upgrade=False, with_pip=False, \
1467db96d56Sopenharmony_ci                      prompt=None, upgrade_deps=False)
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci    The :class:`EnvBuilder` class accepts the following keyword arguments on
1497db96d56Sopenharmony_ci    instantiation:
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci    * ``system_site_packages`` -- a Boolean value indicating that the system Python
1527db96d56Sopenharmony_ci      site-packages should be available to the environment (defaults to ``False``).
1537db96d56Sopenharmony_ci
1547db96d56Sopenharmony_ci    * ``clear`` -- a Boolean value which, if true, will delete the contents of
1557db96d56Sopenharmony_ci      any existing target directory, before creating the environment.
1567db96d56Sopenharmony_ci
1577db96d56Sopenharmony_ci    * ``symlinks`` -- a Boolean value indicating whether to attempt to symlink the
1587db96d56Sopenharmony_ci      Python binary rather than copying.
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci    * ``upgrade`` -- a Boolean value which, if true, will upgrade an existing
1617db96d56Sopenharmony_ci      environment with the running Python - for use when that Python has been
1627db96d56Sopenharmony_ci      upgraded in-place (defaults to ``False``).
1637db96d56Sopenharmony_ci
1647db96d56Sopenharmony_ci    * ``with_pip`` -- a Boolean value which, if true, ensures pip is
1657db96d56Sopenharmony_ci      installed in the virtual environment. This uses :mod:`ensurepip` with
1667db96d56Sopenharmony_ci      the ``--default-pip`` option.
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci    * ``prompt`` -- a String to be used after virtual environment is activated
1697db96d56Sopenharmony_ci      (defaults to ``None`` which means directory name of the environment would
1707db96d56Sopenharmony_ci      be used). If the special string ``"."`` is provided, the basename of the
1717db96d56Sopenharmony_ci      current directory is used as the prompt.
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci    * ``upgrade_deps`` -- Update the base venv modules to the latest on PyPI
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci    .. versionchanged:: 3.4
1767db96d56Sopenharmony_ci       Added the ``with_pip`` parameter
1777db96d56Sopenharmony_ci
1787db96d56Sopenharmony_ci    .. versionadded:: 3.6
1797db96d56Sopenharmony_ci       Added the ``prompt`` parameter
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci    .. versionadded:: 3.9
1827db96d56Sopenharmony_ci       Added the ``upgrade_deps`` parameter
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci    Creators of third-party virtual environment tools will be free to use the
1857db96d56Sopenharmony_ci    provided :class:`EnvBuilder` class as a base class.
1867db96d56Sopenharmony_ci
1877db96d56Sopenharmony_ci    The returned env-builder is an object which has a method, ``create``:
1887db96d56Sopenharmony_ci
1897db96d56Sopenharmony_ci    .. method:: create(env_dir)
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci        Create a virtual environment by specifying the target directory
1927db96d56Sopenharmony_ci        (absolute or relative to the current directory) which is to contain the
1937db96d56Sopenharmony_ci        virtual environment.  The ``create`` method will either create the
1947db96d56Sopenharmony_ci        environment in the specified directory, or raise an appropriate
1957db96d56Sopenharmony_ci        exception.
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ci        The ``create`` method of the :class:`EnvBuilder` class illustrates the
1987db96d56Sopenharmony_ci        hooks available for subclass customization::
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci            def create(self, env_dir):
2017db96d56Sopenharmony_ci                """
2027db96d56Sopenharmony_ci                Create a virtualized Python environment in a directory.
2037db96d56Sopenharmony_ci                env_dir is the target directory to create an environment in.
2047db96d56Sopenharmony_ci                """
2057db96d56Sopenharmony_ci                env_dir = os.path.abspath(env_dir)
2067db96d56Sopenharmony_ci                context = self.ensure_directories(env_dir)
2077db96d56Sopenharmony_ci                self.create_configuration(context)
2087db96d56Sopenharmony_ci                self.setup_python(context)
2097db96d56Sopenharmony_ci                self.setup_scripts(context)
2107db96d56Sopenharmony_ci                self.post_setup(context)
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci        Each of the methods :meth:`ensure_directories`,
2137db96d56Sopenharmony_ci        :meth:`create_configuration`, :meth:`setup_python`,
2147db96d56Sopenharmony_ci        :meth:`setup_scripts` and :meth:`post_setup` can be overridden.
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci    .. method:: ensure_directories(env_dir)
2177db96d56Sopenharmony_ci
2187db96d56Sopenharmony_ci        Creates the environment directory and all necessary subdirectories that
2197db96d56Sopenharmony_ci        don't already exist, and returns a context object.  This context object
2207db96d56Sopenharmony_ci        is just a holder for attributes (such as paths) for use by the other
2217db96d56Sopenharmony_ci        methods.  If the :class:`EnvBuilder` is created with the arg
2227db96d56Sopenharmony_ci        ``clear=True``, contents of the environment directory will be cleared
2237db96d56Sopenharmony_ci        and then all necessary subdirectories will be recreated.
2247db96d56Sopenharmony_ci
2257db96d56Sopenharmony_ci        The returned context object is a :class:`types.SimpleNamespace` with the
2267db96d56Sopenharmony_ci        following attributes:
2277db96d56Sopenharmony_ci
2287db96d56Sopenharmony_ci        * ``env_dir`` - The location of the virtual environment. Used for
2297db96d56Sopenharmony_ci          ``__VENV_DIR__`` in activation scripts (see :meth:`install_scripts`).
2307db96d56Sopenharmony_ci
2317db96d56Sopenharmony_ci        * ``env_name`` - The name of the virtual environment. Used for
2327db96d56Sopenharmony_ci          ``__VENV_NAME__`` in activation scripts (see :meth:`install_scripts`).
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_ci        * ``prompt`` - The prompt to be used by the activation scripts. Used for
2357db96d56Sopenharmony_ci          ``__VENV_PROMPT__`` in activation scripts (see :meth:`install_scripts`).
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci        * ``executable`` - The underlying Python executable used by the virtual
2387db96d56Sopenharmony_ci          environment. This takes into account the case where a virtual environment
2397db96d56Sopenharmony_ci          is created from another virtual environment.
2407db96d56Sopenharmony_ci
2417db96d56Sopenharmony_ci        * ``inc_path`` - The include path for the virtual environment.
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ci        * ``lib_path`` - The purelib path for the virtual environment.
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci        * ``bin_path`` - The script path for the virtual environment.
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci        * ``bin_name`` - The name of the script path relative to the virtual
2487db96d56Sopenharmony_ci          environment location. Used for ``__VENV_BIN_NAME__`` in activation
2497db96d56Sopenharmony_ci          scripts (see :meth:`install_scripts`).
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_ci        * ``env_exe`` - The name of the Python interpreter in the virtual
2527db96d56Sopenharmony_ci          environment. Used for ``__VENV_PYTHON__`` in activation scripts
2537db96d56Sopenharmony_ci          (see :meth:`install_scripts`).
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci        * ``env_exec_cmd`` - The name of the Python interpreter, taking into
2567db96d56Sopenharmony_ci          account filesystem redirections. This can be used to run Python in
2577db96d56Sopenharmony_ci          the virtual environment.
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ci        .. versionchanged:: 3.12
2617db96d56Sopenharmony_ci           The attribute ``lib_path`` was added to the context, and the context
2627db96d56Sopenharmony_ci           object was documented.
2637db96d56Sopenharmony_ci
2647db96d56Sopenharmony_ci        .. versionchanged:: 3.11
2657db96d56Sopenharmony_ci           The *venv*
2667db96d56Sopenharmony_ci           :ref:`sysconfig installation scheme <installation_paths>`
2677db96d56Sopenharmony_ci           is used to construct the paths of the created directories.
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci    .. method:: create_configuration(context)
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ci        Creates the ``pyvenv.cfg`` configuration file in the environment.
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci    .. method:: setup_python(context)
2747db96d56Sopenharmony_ci
2757db96d56Sopenharmony_ci        Creates a copy or symlink to the Python executable in the environment.
2767db96d56Sopenharmony_ci        On POSIX systems, if a specific executable ``python3.x`` was used,
2777db96d56Sopenharmony_ci        symlinks to ``python`` and ``python3`` will be created pointing to that
2787db96d56Sopenharmony_ci        executable, unless files with those names already exist.
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci    .. method:: setup_scripts(context)
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_ci        Installs activation scripts appropriate to the platform into the virtual
2837db96d56Sopenharmony_ci        environment.
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci    .. method:: upgrade_dependencies(context)
2867db96d56Sopenharmony_ci
2877db96d56Sopenharmony_ci       Upgrades the core venv dependency packages (currently ``pip`` and
2887db96d56Sopenharmony_ci       ``setuptools``) in the environment. This is done by shelling out to the
2897db96d56Sopenharmony_ci       ``pip`` executable in the environment.
2907db96d56Sopenharmony_ci
2917db96d56Sopenharmony_ci       .. versionadded:: 3.9
2927db96d56Sopenharmony_ci
2937db96d56Sopenharmony_ci    .. method:: post_setup(context)
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ci        A placeholder method which can be overridden in third party
2967db96d56Sopenharmony_ci        implementations to pre-install packages in the virtual environment or
2977db96d56Sopenharmony_ci        perform other post-creation steps.
2987db96d56Sopenharmony_ci
2997db96d56Sopenharmony_ci    .. versionchanged:: 3.7.2
3007db96d56Sopenharmony_ci       Windows now uses redirector scripts for ``python[w].exe`` instead of
3017db96d56Sopenharmony_ci       copying the actual binaries. In 3.7.2 only :meth:`setup_python` does
3027db96d56Sopenharmony_ci       nothing unless running from a build in the source tree.
3037db96d56Sopenharmony_ci
3047db96d56Sopenharmony_ci    .. versionchanged:: 3.7.3
3057db96d56Sopenharmony_ci       Windows copies the redirector scripts as part of :meth:`setup_python`
3067db96d56Sopenharmony_ci       instead of :meth:`setup_scripts`. This was not the case in 3.7.2.
3077db96d56Sopenharmony_ci       When using symlinks, the original executables will be linked.
3087db96d56Sopenharmony_ci
3097db96d56Sopenharmony_ci    In addition, :class:`EnvBuilder` provides this utility method that can be
3107db96d56Sopenharmony_ci    called from :meth:`setup_scripts` or :meth:`post_setup` in subclasses to
3117db96d56Sopenharmony_ci    assist in installing custom scripts into the virtual environment.
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_ci    .. method:: install_scripts(context, path)
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ci        *path* is the path to a directory that should contain subdirectories
3167db96d56Sopenharmony_ci        "common", "posix", "nt", each containing scripts destined for the bin
3177db96d56Sopenharmony_ci        directory in the environment.  The contents of "common" and the
3187db96d56Sopenharmony_ci        directory corresponding to :data:`os.name` are copied after some text
3197db96d56Sopenharmony_ci        replacement of placeholders:
3207db96d56Sopenharmony_ci
3217db96d56Sopenharmony_ci        * ``__VENV_DIR__`` is replaced with the absolute path of the environment
3227db96d56Sopenharmony_ci          directory.
3237db96d56Sopenharmony_ci
3247db96d56Sopenharmony_ci        * ``__VENV_NAME__`` is replaced with the environment name (final path
3257db96d56Sopenharmony_ci          segment of environment directory).
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ci        * ``__VENV_PROMPT__`` is replaced with the prompt (the environment
3287db96d56Sopenharmony_ci          name surrounded by parentheses and with a following space)
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci        * ``__VENV_BIN_NAME__`` is replaced with the name of the bin directory
3317db96d56Sopenharmony_ci          (either ``bin`` or ``Scripts``).
3327db96d56Sopenharmony_ci
3337db96d56Sopenharmony_ci        * ``__VENV_PYTHON__`` is replaced with the absolute path of the
3347db96d56Sopenharmony_ci          environment's executable.
3357db96d56Sopenharmony_ci
3367db96d56Sopenharmony_ci        The directories are allowed to exist (for when an existing environment
3377db96d56Sopenharmony_ci        is being upgraded).
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ciThere is also a module-level convenience function:
3407db96d56Sopenharmony_ci
3417db96d56Sopenharmony_ci.. function:: create(env_dir, system_site_packages=False, clear=False, \
3427db96d56Sopenharmony_ci                     symlinks=False, with_pip=False, prompt=None, \
3437db96d56Sopenharmony_ci                     upgrade_deps=False)
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ci    Create an :class:`EnvBuilder` with the given keyword arguments, and call its
3467db96d56Sopenharmony_ci    :meth:`~EnvBuilder.create` method with the *env_dir* argument.
3477db96d56Sopenharmony_ci
3487db96d56Sopenharmony_ci    .. versionadded:: 3.3
3497db96d56Sopenharmony_ci
3507db96d56Sopenharmony_ci    .. versionchanged:: 3.4
3517db96d56Sopenharmony_ci       Added the ``with_pip`` parameter
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci    .. versionchanged:: 3.6
3547db96d56Sopenharmony_ci       Added the ``prompt`` parameter
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci    .. versionchanged:: 3.9
3577db96d56Sopenharmony_ci       Added the ``upgrade_deps`` parameter
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ciAn example of extending ``EnvBuilder``
3607db96d56Sopenharmony_ci--------------------------------------
3617db96d56Sopenharmony_ci
3627db96d56Sopenharmony_ciThe following script shows how to extend :class:`EnvBuilder` by implementing a
3637db96d56Sopenharmony_cisubclass which installs setuptools and pip into a created virtual environment::
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci    import os
3667db96d56Sopenharmony_ci    import os.path
3677db96d56Sopenharmony_ci    from subprocess import Popen, PIPE
3687db96d56Sopenharmony_ci    import sys
3697db96d56Sopenharmony_ci    from threading import Thread
3707db96d56Sopenharmony_ci    from urllib.parse import urlparse
3717db96d56Sopenharmony_ci    from urllib.request import urlretrieve
3727db96d56Sopenharmony_ci    import venv
3737db96d56Sopenharmony_ci
3747db96d56Sopenharmony_ci    class ExtendedEnvBuilder(venv.EnvBuilder):
3757db96d56Sopenharmony_ci        """
3767db96d56Sopenharmony_ci        This builder installs setuptools and pip so that you can pip or
3777db96d56Sopenharmony_ci        easy_install other packages into the created virtual environment.
3787db96d56Sopenharmony_ci
3797db96d56Sopenharmony_ci        :param nodist: If true, setuptools and pip are not installed into the
3807db96d56Sopenharmony_ci                       created virtual environment.
3817db96d56Sopenharmony_ci        :param nopip: If true, pip is not installed into the created
3827db96d56Sopenharmony_ci                      virtual environment.
3837db96d56Sopenharmony_ci        :param progress: If setuptools or pip are installed, the progress of the
3847db96d56Sopenharmony_ci                         installation can be monitored by passing a progress
3857db96d56Sopenharmony_ci                         callable. If specified, it is called with two
3867db96d56Sopenharmony_ci                         arguments: a string indicating some progress, and a
3877db96d56Sopenharmony_ci                         context indicating where the string is coming from.
3887db96d56Sopenharmony_ci                         The context argument can have one of three values:
3897db96d56Sopenharmony_ci                         'main', indicating that it is called from virtualize()
3907db96d56Sopenharmony_ci                         itself, and 'stdout' and 'stderr', which are obtained
3917db96d56Sopenharmony_ci                         by reading lines from the output streams of a subprocess
3927db96d56Sopenharmony_ci                         which is used to install the app.
3937db96d56Sopenharmony_ci
3947db96d56Sopenharmony_ci                         If a callable is not specified, default progress
3957db96d56Sopenharmony_ci                         information is output to sys.stderr.
3967db96d56Sopenharmony_ci        """
3977db96d56Sopenharmony_ci
3987db96d56Sopenharmony_ci        def __init__(self, *args, **kwargs):
3997db96d56Sopenharmony_ci            self.nodist = kwargs.pop('nodist', False)
4007db96d56Sopenharmony_ci            self.nopip = kwargs.pop('nopip', False)
4017db96d56Sopenharmony_ci            self.progress = kwargs.pop('progress', None)
4027db96d56Sopenharmony_ci            self.verbose = kwargs.pop('verbose', False)
4037db96d56Sopenharmony_ci            super().__init__(*args, **kwargs)
4047db96d56Sopenharmony_ci
4057db96d56Sopenharmony_ci        def post_setup(self, context):
4067db96d56Sopenharmony_ci            """
4077db96d56Sopenharmony_ci            Set up any packages which need to be pre-installed into the
4087db96d56Sopenharmony_ci            virtual environment being created.
4097db96d56Sopenharmony_ci
4107db96d56Sopenharmony_ci            :param context: The information for the virtual environment
4117db96d56Sopenharmony_ci                            creation request being processed.
4127db96d56Sopenharmony_ci            """
4137db96d56Sopenharmony_ci            os.environ['VIRTUAL_ENV'] = context.env_dir
4147db96d56Sopenharmony_ci            if not self.nodist:
4157db96d56Sopenharmony_ci                self.install_setuptools(context)
4167db96d56Sopenharmony_ci            # Can't install pip without setuptools
4177db96d56Sopenharmony_ci            if not self.nopip and not self.nodist:
4187db96d56Sopenharmony_ci                self.install_pip(context)
4197db96d56Sopenharmony_ci
4207db96d56Sopenharmony_ci        def reader(self, stream, context):
4217db96d56Sopenharmony_ci            """
4227db96d56Sopenharmony_ci            Read lines from a subprocess' output stream and either pass to a progress
4237db96d56Sopenharmony_ci            callable (if specified) or write progress information to sys.stderr.
4247db96d56Sopenharmony_ci            """
4257db96d56Sopenharmony_ci            progress = self.progress
4267db96d56Sopenharmony_ci            while True:
4277db96d56Sopenharmony_ci                s = stream.readline()
4287db96d56Sopenharmony_ci                if not s:
4297db96d56Sopenharmony_ci                    break
4307db96d56Sopenharmony_ci                if progress is not None:
4317db96d56Sopenharmony_ci                    progress(s, context)
4327db96d56Sopenharmony_ci                else:
4337db96d56Sopenharmony_ci                    if not self.verbose:
4347db96d56Sopenharmony_ci                        sys.stderr.write('.')
4357db96d56Sopenharmony_ci                    else:
4367db96d56Sopenharmony_ci                        sys.stderr.write(s.decode('utf-8'))
4377db96d56Sopenharmony_ci                    sys.stderr.flush()
4387db96d56Sopenharmony_ci            stream.close()
4397db96d56Sopenharmony_ci
4407db96d56Sopenharmony_ci        def install_script(self, context, name, url):
4417db96d56Sopenharmony_ci            _, _, path, _, _, _ = urlparse(url)
4427db96d56Sopenharmony_ci            fn = os.path.split(path)[-1]
4437db96d56Sopenharmony_ci            binpath = context.bin_path
4447db96d56Sopenharmony_ci            distpath = os.path.join(binpath, fn)
4457db96d56Sopenharmony_ci            # Download script into the virtual environment's binaries folder
4467db96d56Sopenharmony_ci            urlretrieve(url, distpath)
4477db96d56Sopenharmony_ci            progress = self.progress
4487db96d56Sopenharmony_ci            if self.verbose:
4497db96d56Sopenharmony_ci                term = '\n'
4507db96d56Sopenharmony_ci            else:
4517db96d56Sopenharmony_ci                term = ''
4527db96d56Sopenharmony_ci            if progress is not None:
4537db96d56Sopenharmony_ci                progress('Installing %s ...%s' % (name, term), 'main')
4547db96d56Sopenharmony_ci            else:
4557db96d56Sopenharmony_ci                sys.stderr.write('Installing %s ...%s' % (name, term))
4567db96d56Sopenharmony_ci                sys.stderr.flush()
4577db96d56Sopenharmony_ci            # Install in the virtual environment
4587db96d56Sopenharmony_ci            args = [context.env_exe, fn]
4597db96d56Sopenharmony_ci            p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)
4607db96d56Sopenharmony_ci            t1 = Thread(target=self.reader, args=(p.stdout, 'stdout'))
4617db96d56Sopenharmony_ci            t1.start()
4627db96d56Sopenharmony_ci            t2 = Thread(target=self.reader, args=(p.stderr, 'stderr'))
4637db96d56Sopenharmony_ci            t2.start()
4647db96d56Sopenharmony_ci            p.wait()
4657db96d56Sopenharmony_ci            t1.join()
4667db96d56Sopenharmony_ci            t2.join()
4677db96d56Sopenharmony_ci            if progress is not None:
4687db96d56Sopenharmony_ci                progress('done.', 'main')
4697db96d56Sopenharmony_ci            else:
4707db96d56Sopenharmony_ci                sys.stderr.write('done.\n')
4717db96d56Sopenharmony_ci            # Clean up - no longer needed
4727db96d56Sopenharmony_ci            os.unlink(distpath)
4737db96d56Sopenharmony_ci
4747db96d56Sopenharmony_ci        def install_setuptools(self, context):
4757db96d56Sopenharmony_ci            """
4767db96d56Sopenharmony_ci            Install setuptools in the virtual environment.
4777db96d56Sopenharmony_ci
4787db96d56Sopenharmony_ci            :param context: The information for the virtual environment
4797db96d56Sopenharmony_ci                            creation request being processed.
4807db96d56Sopenharmony_ci            """
4817db96d56Sopenharmony_ci            url = 'https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py'
4827db96d56Sopenharmony_ci            self.install_script(context, 'setuptools', url)
4837db96d56Sopenharmony_ci            # clear up the setuptools archive which gets downloaded
4847db96d56Sopenharmony_ci            pred = lambda o: o.startswith('setuptools-') and o.endswith('.tar.gz')
4857db96d56Sopenharmony_ci            files = filter(pred, os.listdir(context.bin_path))
4867db96d56Sopenharmony_ci            for f in files:
4877db96d56Sopenharmony_ci                f = os.path.join(context.bin_path, f)
4887db96d56Sopenharmony_ci                os.unlink(f)
4897db96d56Sopenharmony_ci
4907db96d56Sopenharmony_ci        def install_pip(self, context):
4917db96d56Sopenharmony_ci            """
4927db96d56Sopenharmony_ci            Install pip in the virtual environment.
4937db96d56Sopenharmony_ci
4947db96d56Sopenharmony_ci            :param context: The information for the virtual environment
4957db96d56Sopenharmony_ci                            creation request being processed.
4967db96d56Sopenharmony_ci            """
4977db96d56Sopenharmony_ci            url = 'https://bootstrap.pypa.io/get-pip.py'
4987db96d56Sopenharmony_ci            self.install_script(context, 'pip', url)
4997db96d56Sopenharmony_ci
5007db96d56Sopenharmony_ci    def main(args=None):
5017db96d56Sopenharmony_ci        compatible = True
5027db96d56Sopenharmony_ci        if sys.version_info < (3, 3):
5037db96d56Sopenharmony_ci            compatible = False
5047db96d56Sopenharmony_ci        elif not hasattr(sys, 'base_prefix'):
5057db96d56Sopenharmony_ci            compatible = False
5067db96d56Sopenharmony_ci        if not compatible:
5077db96d56Sopenharmony_ci            raise ValueError('This script is only for use with '
5087db96d56Sopenharmony_ci                             'Python 3.3 or later')
5097db96d56Sopenharmony_ci        else:
5107db96d56Sopenharmony_ci            import argparse
5117db96d56Sopenharmony_ci
5127db96d56Sopenharmony_ci            parser = argparse.ArgumentParser(prog=__name__,
5137db96d56Sopenharmony_ci                                             description='Creates virtual Python '
5147db96d56Sopenharmony_ci                                                         'environments in one or '
5157db96d56Sopenharmony_ci                                                         'more target '
5167db96d56Sopenharmony_ci                                                         'directories.')
5177db96d56Sopenharmony_ci            parser.add_argument('dirs', metavar='ENV_DIR', nargs='+',
5187db96d56Sopenharmony_ci                                help='A directory in which to create the '
5197db96d56Sopenharmony_ci                                     'virtual environment.')
5207db96d56Sopenharmony_ci            parser.add_argument('--no-setuptools', default=False,
5217db96d56Sopenharmony_ci                                action='store_true', dest='nodist',
5227db96d56Sopenharmony_ci                                help="Don't install setuptools or pip in the "
5237db96d56Sopenharmony_ci                                     "virtual environment.")
5247db96d56Sopenharmony_ci            parser.add_argument('--no-pip', default=False,
5257db96d56Sopenharmony_ci                                action='store_true', dest='nopip',
5267db96d56Sopenharmony_ci                                help="Don't install pip in the virtual "
5277db96d56Sopenharmony_ci                                     "environment.")
5287db96d56Sopenharmony_ci            parser.add_argument('--system-site-packages', default=False,
5297db96d56Sopenharmony_ci                                action='store_true', dest='system_site',
5307db96d56Sopenharmony_ci                                help='Give the virtual environment access to the '
5317db96d56Sopenharmony_ci                                     'system site-packages dir.')
5327db96d56Sopenharmony_ci            if os.name == 'nt':
5337db96d56Sopenharmony_ci                use_symlinks = False
5347db96d56Sopenharmony_ci            else:
5357db96d56Sopenharmony_ci                use_symlinks = True
5367db96d56Sopenharmony_ci            parser.add_argument('--symlinks', default=use_symlinks,
5377db96d56Sopenharmony_ci                                action='store_true', dest='symlinks',
5387db96d56Sopenharmony_ci                                help='Try to use symlinks rather than copies, '
5397db96d56Sopenharmony_ci                                     'when symlinks are not the default for '
5407db96d56Sopenharmony_ci                                     'the platform.')
5417db96d56Sopenharmony_ci            parser.add_argument('--clear', default=False, action='store_true',
5427db96d56Sopenharmony_ci                                dest='clear', help='Delete the contents of the '
5437db96d56Sopenharmony_ci                                                   'virtual environment '
5447db96d56Sopenharmony_ci                                                   'directory if it already '
5457db96d56Sopenharmony_ci                                                   'exists, before virtual '
5467db96d56Sopenharmony_ci                                                   'environment creation.')
5477db96d56Sopenharmony_ci            parser.add_argument('--upgrade', default=False, action='store_true',
5487db96d56Sopenharmony_ci                                dest='upgrade', help='Upgrade the virtual '
5497db96d56Sopenharmony_ci                                                     'environment directory to '
5507db96d56Sopenharmony_ci                                                     'use this version of '
5517db96d56Sopenharmony_ci                                                     'Python, assuming Python '
5527db96d56Sopenharmony_ci                                                     'has been upgraded '
5537db96d56Sopenharmony_ci                                                     'in-place.')
5547db96d56Sopenharmony_ci            parser.add_argument('--verbose', default=False, action='store_true',
5557db96d56Sopenharmony_ci                                dest='verbose', help='Display the output '
5567db96d56Sopenharmony_ci                                                   'from the scripts which '
5577db96d56Sopenharmony_ci                                                   'install setuptools and pip.')
5587db96d56Sopenharmony_ci            options = parser.parse_args(args)
5597db96d56Sopenharmony_ci            if options.upgrade and options.clear:
5607db96d56Sopenharmony_ci                raise ValueError('you cannot supply --upgrade and --clear together.')
5617db96d56Sopenharmony_ci            builder = ExtendedEnvBuilder(system_site_packages=options.system_site,
5627db96d56Sopenharmony_ci                                           clear=options.clear,
5637db96d56Sopenharmony_ci                                           symlinks=options.symlinks,
5647db96d56Sopenharmony_ci                                           upgrade=options.upgrade,
5657db96d56Sopenharmony_ci                                           nodist=options.nodist,
5667db96d56Sopenharmony_ci                                           nopip=options.nopip,
5677db96d56Sopenharmony_ci                                           verbose=options.verbose)
5687db96d56Sopenharmony_ci            for d in options.dirs:
5697db96d56Sopenharmony_ci                builder.create(d)
5707db96d56Sopenharmony_ci
5717db96d56Sopenharmony_ci    if __name__ == '__main__':
5727db96d56Sopenharmony_ci        rc = 1
5737db96d56Sopenharmony_ci        try:
5747db96d56Sopenharmony_ci            main()
5757db96d56Sopenharmony_ci            rc = 0
5767db96d56Sopenharmony_ci        except Exception as e:
5777db96d56Sopenharmony_ci            print('Error: %s' % e, file=sys.stderr)
5787db96d56Sopenharmony_ci        sys.exit(rc)
5797db96d56Sopenharmony_ci
5807db96d56Sopenharmony_ci
5817db96d56Sopenharmony_ciThis script is also available for download `online
5827db96d56Sopenharmony_ci<https://gist.github.com/vsajip/4673395>`_.
5837db96d56Sopenharmony_ci
5847db96d56Sopenharmony_ci
5857db96d56Sopenharmony_ci.. _setuptools: https://pypi.org/project/setuptools/
5867db96d56Sopenharmony_ci.. _pip: https://pypi.org/project/pip/
587