diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst index bed799aedfdfb1..fc98f7ee553712 100644 --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -61,6 +61,8 @@ See :pep:`405` for more background on Python virtual environments. .. include:: ../includes/wasm-mobile-notavail.rst +.. _venv-cli: + Creating virtual environments ----------------------------- @@ -298,7 +300,8 @@ creation according to their needs, the :class:`EnvBuilder` class. any existing target directory, before creating the environment. * *symlinks* -- a boolean value indicating whether to attempt to symlink the - Python binary rather than copying. + Python binary rather than copying (defaults to ``False`` on Windows, and + to ``True`` on all other platforms). * *upgrade* -- a boolean value which, if true, will upgrade an existing environment with the running Python - for use when that Python has been @@ -333,6 +336,11 @@ creation according to their needs, the :class:`EnvBuilder` class. .. versionchanged:: 3.13 Added the ``scm_ignore_files`` parameter + .. versionchanged:: 3.14 + The ``symlinks`` parameter's default value was changed from always + ``False`` to being platform dependent — ``False`` on Windows, ``True`` on + all other platforms — matching the :ref:`CLI `. + :class:`EnvBuilder` may be used as a base class. .. method:: create(env_dir) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index adc86a49b0668d..5f9be66faeef25 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -7,6 +7,7 @@ import contextlib import ensurepip +import inspect import os import os.path import pathlib @@ -152,8 +153,7 @@ def _check_output_of_default_create(self): self.assertIn('home = %s' % path, data) self.assertIn('executable = %s' % os.path.realpath(sys.executable), data) - copies = '' if os.name=='nt' else ' --copies' - cmd = (f'command = {sys.executable} -m venv{copies} --without-pip ' + cmd = (f'command = {sys.executable} -m venv --without-pip ' f'--without-scm-ignore-files {self.env_dir}') self.assertIn(cmd, data) fn = self.get_env_file(self.bindir, self.exe) @@ -895,6 +895,13 @@ def test_venvwlauncher(self): except subprocess.CalledProcessError: self.fail("venvwlauncher.exe did not run %s" % exename) + def test_create_matches_envbuilder_defaults(self): + create_signature = inspect.signature(venv.create) + builder_signature = inspect.signature(venv.EnvBuilder.__init__) + for name, parameter in create_signature.parameters.items(): + if parameter.default != parameter.empty: + self.assertEqual(parameter, builder_signature.parameters[name]) + @requireVenvCreate class EnsurePipTest(BaseTest): diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index dc4c9ef3531991..ba579739c7cab7 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -17,6 +17,8 @@ CORE_VENV_DEPS = ('pip',) logger = logging.getLogger(__name__) +_USE_SYMLINKS = os.name != 'nt' + class EnvBuilder: """ @@ -47,7 +49,7 @@ class EnvBuilder: """ def __init__(self, system_site_packages=False, clear=False, - symlinks=False, upgrade=False, with_pip=False, prompt=None, + symlinks=_USE_SYMLINKS, upgrade=False, with_pip=False, prompt=None, upgrade_deps=False, *, scm_ignore_files=frozenset()): self.system_site_packages = system_site_packages self.clear = clear @@ -603,7 +605,7 @@ def upgrade_dependencies(self, context): def create(env_dir, system_site_packages=False, clear=False, - symlinks=False, with_pip=False, prompt=None, upgrade_deps=False, + symlinks=_USE_SYMLINKS, with_pip=False, prompt=None, upgrade_deps=False, *, scm_ignore_files=frozenset()): """Create a virtual environment in a directory.""" builder = EnvBuilder(system_site_packages=system_site_packages, @@ -631,17 +633,13 @@ def main(args=None): action='store_true', dest='system_site', help='Give the virtual environment access to the ' 'system site-packages dir.') - if os.name == 'nt': - use_symlinks = False - else: - use_symlinks = True group = parser.add_mutually_exclusive_group() - group.add_argument('--symlinks', default=use_symlinks, + group.add_argument('--symlinks', default=_USE_SYMLINKS, action='store_true', dest='symlinks', help='Try to use symlinks rather than copies, ' 'when symlinks are not the default for ' 'the platform.') - group.add_argument('--copies', default=not use_symlinks, + group.add_argument('--copies', default=not _USE_SYMLINKS, action='store_false', dest='symlinks', help='Try to use copies rather than symlinks, ' 'even when symlinks are the default for ' diff --git a/Misc/NEWS.d/next/Library/2025-01-31-02-27-53.gh-issue-129382.GI93CM.rst b/Misc/NEWS.d/next/Library/2025-01-31-02-27-53.gh-issue-129382.GI93CM.rst new file mode 100644 index 00000000000000..8599b7e11bed75 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-31-02-27-53.gh-issue-129382.GI93CM.rst @@ -0,0 +1,2 @@ +Updated :class:`venv.EnvBuilder`/:func:`venv.create`'s ``symlinks`` parameter's +default to match the :ref:`CLI `.