virtualenv 21.2.3__tar.gz → 21.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {virtualenv-21.2.3 → virtualenv-21.3.0}/PKG-INFO +1 -1
- {virtualenv-21.2.3 → virtualenv-21.3.0}/pyproject.toml +1 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/__init__.py +2 -0
- virtualenv-21.3.0/src/virtualenv/activation/xonsh/__init__.py +34 -0
- virtualenv-21.3.0/src/virtualenv/activation/xonsh/activate.xsh +101 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/config/cli/parser.py +3 -2
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/plugin/base.py +8 -2
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/via_app_data/pip_install/base.py +29 -1
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/acquire.py +63 -0
- virtualenv-21.3.0/src/virtualenv/seed/wheels/embed/__init__.py +120 -0
- virtualenv-21.3.0/src/virtualenv/seed/wheels/embed/pip-26.1-py3-none-any.whl +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/periodic_update.py +12 -2
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/zipapp.py +14 -16
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/version.py +2 -2
- virtualenv-21.3.0/tasks/upgrade_wheels.py +265 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/conftest.py +22 -9
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_activation_support.py +3 -2
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_powershell.py +2 -1
- virtualenv-21.3.0/tests/unit/activation/test_xonsh.py +91 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py +57 -1
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/wheels/test_acquire.py +33 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/wheels/test_bundle.py +64 -1
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/wheels/test_periodic_update.py +17 -4
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/test_util.py +28 -0
- virtualenv-21.2.3/src/virtualenv/seed/wheels/embed/__init__.py +0 -60
- virtualenv-21.2.3/tasks/upgrade_wheels.py +0 -157
- {virtualenv-21.2.3 → virtualenv-21.3.0}/.gitignore +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/LICENSE +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/README.md +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/__main__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/activator.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/bash/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/bash/activate.sh +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/batch/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/batch/activate.bat +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/batch/deactivate.bat +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/batch/pydoc.bat +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/cshell/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/cshell/activate.csh +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/fish/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/fish/activate.fish +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/nushell/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/nushell/activate.nu +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/powershell/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/powershell/activate.ps1 +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/python/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/python/activate_this.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/activation/via_template.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/app_data/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/app_data/base.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/app_data/na.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/app_data/read_only.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/app_data/via_disk_folder.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/app_data/via_tempdir.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/config/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/config/cli/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/config/convert.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/config/env_var.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/config/ini.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/creator.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/debug.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/describe.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/pyenv_cfg.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/_virtualenv.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/api.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/builtin_way.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/cpython/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/cpython/common.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/graalpy/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/pypy/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/pypy/common.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/ref.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/rustpython/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/store.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/create/via_global_ref/venv.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/discovery/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/discovery/builtin.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/discovery/cached_py_info.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/discovery/discover.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/discovery/py_info.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/discovery/py_spec.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/info.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/py.typed +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/report.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/plugin/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/plugin/activators.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/plugin/creators.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/plugin/discovery.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/plugin/seeders.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/run/session.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/base_embed.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/pip_invoke.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/via_app_data/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/via_app_data/pip_install/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/via_app_data/pip_install/copy.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/via_app_data/pip_install/symlink.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/via_app_data/via_app_data.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/seeder.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/bundle.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/embed/pip-25.0.1-py3-none-any.whl +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/embed/pip-26.0.1-py3-none-any.whl +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/embed/setuptools-75.3.4-py3-none-any.whl +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/embed/setuptools-82.0.1-py3-none-any.whl +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/embed/wheel-0.45.1-py3-none-any.whl +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/wheels/util.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/error.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/lock.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/path/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/path/_permission.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/path/_sync.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/path/_win.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/util/subprocess/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tasks/__main__zipapp.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tasks/make_zipapp.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tasks/release.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tasks/update_embedded.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/conftest.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/integration/test_cachedir_tag.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/integration/test_race_condition_simulation.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/integration/test_run_int.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/integration/test_zipapp.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/types.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_activator.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_bash.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_batch.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_csh.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_fish.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_nushell.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/activation/test_python_activator.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/config/cli/test_help_formatter.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/config/cli/test_parser.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/config/test___main__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/config/test_env_var.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/config/test_ini.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/conftest.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/console_app/demo/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/console_app/demo/__main__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/console_app/setup.cfg +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/console_app/setup.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/test_creator.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/test_interpreters.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/_test_race_condition_helper.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/conftest.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/cpython/conftest.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/cpython/cpython3_win_embed.json +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/cpython/cpython3_win_free_threaded.json +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/cpython/test_cpython3_posix.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/cpython/test_cpython3_win.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/pypy/deb_pypy37.json +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/pypy/deb_pypy38.json +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/pypy/portable_pypy38.json +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/pypy/test_pypy3.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/rustpython/rustpython_posix.json +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/rustpython/rustpython_windows.json +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/rustpython/test_rustpython.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/testing/__init__.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/testing/helpers.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/testing/path.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/builtin/testing/py_info.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/greet/greet2.c +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/greet/greet3.c +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/greet/setup.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/test_api.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/test_build_c_ext.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/create/via_global_ref/test_race_condition.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/discovery/test_discovery.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/embed/test_base_embed.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/embed/test_pip_invoke.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/wheels/test_acquire_find_wheel.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/seed/wheels/test_wheels_util.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/test_file_limit.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tests/unit/test_run.py +0 -0
- {virtualenv-21.2.3 → virtualenv-21.3.0}/tox.toml +0 -0
|
@@ -65,6 +65,7 @@ entry-points."virtualenv.activate".fish = "virtualenv.activation.fish:FishActiva
|
|
|
65
65
|
entry-points."virtualenv.activate".nushell = "virtualenv.activation.nushell:NushellActivator"
|
|
66
66
|
entry-points."virtualenv.activate".powershell = "virtualenv.activation.powershell:PowerShellActivator"
|
|
67
67
|
entry-points."virtualenv.activate".python = "virtualenv.activation.python:PythonActivator"
|
|
68
|
+
entry-points."virtualenv.activate".xonsh = "virtualenv.activation.xonsh:XonshActivator"
|
|
68
69
|
entry-points."virtualenv.create".cpython3-mac-brew = "virtualenv.create.via_global_ref.builtin.cpython.mac_os:CPython3macOsBrew"
|
|
69
70
|
entry-points."virtualenv.create".cpython3-mac-framework = "virtualenv.create.via_global_ref.builtin.cpython.mac_os:CPython3macOsFramework"
|
|
70
71
|
entry-points."virtualenv.create".cpython3-posix = "virtualenv.create.via_global_ref.builtin.cpython.cpython3:CPython3Posix"
|
|
@@ -7,6 +7,7 @@ from .fish import FishActivator
|
|
|
7
7
|
from .nushell import NushellActivator
|
|
8
8
|
from .powershell import PowerShellActivator
|
|
9
9
|
from .python import PythonActivator
|
|
10
|
+
from .xonsh import XonshActivator
|
|
10
11
|
|
|
11
12
|
__all__ = [
|
|
12
13
|
"BashActivator",
|
|
@@ -16,4 +17,5 @@ __all__ = [
|
|
|
16
17
|
"NushellActivator",
|
|
17
18
|
"PowerShellActivator",
|
|
18
19
|
"PythonActivator",
|
|
20
|
+
"XonshActivator",
|
|
19
21
|
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from virtualenv.activation.via_template import ViaTemplateActivator
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from collections.abc import Iterator
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from virtualenv.create.creator import Creator
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class XonshActivator(ViaTemplateActivator):
|
|
15
|
+
def templates(self) -> Iterator[str]:
|
|
16
|
+
yield "activate.xsh"
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def quote(string: str) -> str:
|
|
20
|
+
"""Quote as a Python literal — xonsh parses the activation script as Python."""
|
|
21
|
+
return repr(string)
|
|
22
|
+
|
|
23
|
+
def replacements(self, creator: Creator, dest_folder: Path) -> dict[str, str]:
|
|
24
|
+
data = super().replacements(creator, dest_folder)
|
|
25
|
+
data.update({
|
|
26
|
+
"__TCL_LIBRARY__": getattr(creator.interpreter, "tcl_lib", None) or "",
|
|
27
|
+
"__TK_LIBRARY__": getattr(creator.interpreter, "tk_lib", None) or "",
|
|
28
|
+
})
|
|
29
|
+
return data
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"XonshActivator",
|
|
34
|
+
]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# This file must be used with "source bin/activate.xsh" *from xonsh*.
|
|
2
|
+
# You cannot run it directly.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class _VirtualEnvActivator:
|
|
6
|
+
"""xonsh activation for virtualenv.
|
|
7
|
+
|
|
8
|
+
Rendered into ``<venv>/bin/activate.xsh`` by the template in
|
|
9
|
+
``src/virtualenv/activation/xonsh/`` at generate-time.
|
|
10
|
+
|
|
11
|
+
- Project: https://github.com/pypa/virtualenv
|
|
12
|
+
- Template source: https://github.com/pypa/virtualenv/tree/main/src/virtualenv/activation/xonsh
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# Stashed in _OLD_VIRTUAL_{name} when the variable was not set before
|
|
16
|
+
# activation. deactivate treats this as "unset" rather than "restore to
|
|
17
|
+
# this string". Chosen to be vanishingly unlikely as a real value.
|
|
18
|
+
_UNSET_SENTINEL = "__virtualenv_was_not_set__"
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
self.env = __xonsh__.env
|
|
22
|
+
try:
|
|
23
|
+
# Values substituted by virtualenv's XonshActivator at generate-time.
|
|
24
|
+
# If this file was sourced before template rendering, the bare
|
|
25
|
+
# identifiers below resolve to NameError.
|
|
26
|
+
self.embedded_virtual_env = __VIRTUAL_ENV__
|
|
27
|
+
self.embedded_virtual_prompt = __VIRTUAL_PROMPT__
|
|
28
|
+
self.embedded_bin_name = __BIN_NAME__
|
|
29
|
+
self.embedded_tcl_library = __TCL_LIBRARY__
|
|
30
|
+
self.embedded_tk_library = __TK_LIBRARY__
|
|
31
|
+
except NameError:
|
|
32
|
+
print("virtualenv activate.xsh: template was not rendered")
|
|
33
|
+
raise
|
|
34
|
+
# Variables this activator may save+override; deactivate walks this list.
|
|
35
|
+
self.managed_vars = ("PATH", "PYTHONHOME", "TCL_LIBRARY", "TK_LIBRARY")
|
|
36
|
+
|
|
37
|
+
def _backup_name(self, name):
|
|
38
|
+
return f"_OLD_VIRTUAL_{name}"
|
|
39
|
+
|
|
40
|
+
def _save(self, name):
|
|
41
|
+
"""Stash the current value (or sentinel if unset) so deactivate can undo."""
|
|
42
|
+
backup = self._backup_name(name)
|
|
43
|
+
self.env[backup] = self.env[name] if name in self.env else self._UNSET_SENTINEL
|
|
44
|
+
|
|
45
|
+
def _override(self, name, value):
|
|
46
|
+
self._save(name)
|
|
47
|
+
self.env[name] = value
|
|
48
|
+
|
|
49
|
+
def _drop(self, name):
|
|
50
|
+
self._save(name)
|
|
51
|
+
self.env.pop(name, None)
|
|
52
|
+
|
|
53
|
+
def register_pydoc(self):
|
|
54
|
+
aliases["pydoc"] = ["python", "-m", "pydoc"]
|
|
55
|
+
|
|
56
|
+
def unregister_pydoc(self):
|
|
57
|
+
aliases.pop("pydoc", None)
|
|
58
|
+
|
|
59
|
+
def activate(self):
|
|
60
|
+
from os.path import join, basename
|
|
61
|
+
|
|
62
|
+
aliases["deactivate"] = self.deactivate
|
|
63
|
+
self.deactivate(["nondestructive"]) # wipe any stale state from a prior activation
|
|
64
|
+
|
|
65
|
+
$VIRTUAL_ENV = self.embedded_virtual_env
|
|
66
|
+
$VIRTUAL_ENV_PROMPT = self.embedded_virtual_prompt or basename($VIRTUAL_ENV)
|
|
67
|
+
|
|
68
|
+
self._override("PATH", [join($VIRTUAL_ENV, self.embedded_bin_name), *$PATH])
|
|
69
|
+
self._drop("PYTHONHOME")
|
|
70
|
+
for name, value in (("TCL_LIBRARY", self.embedded_tcl_library), ("TK_LIBRARY", self.embedded_tk_library)):
|
|
71
|
+
if value:
|
|
72
|
+
self._override(name, value)
|
|
73
|
+
|
|
74
|
+
self.register_pydoc()
|
|
75
|
+
|
|
76
|
+
def deactivate(self, args=None):
|
|
77
|
+
for name in self.managed_vars:
|
|
78
|
+
backup = self._backup_name(name)
|
|
79
|
+
if backup not in self.env:
|
|
80
|
+
continue
|
|
81
|
+
previous = self.env[backup]
|
|
82
|
+
del self.env[backup]
|
|
83
|
+
if previous == self._UNSET_SENTINEL:
|
|
84
|
+
self.env.pop(name, None)
|
|
85
|
+
else:
|
|
86
|
+
self.env[name] = previous
|
|
87
|
+
for name in ("VIRTUAL_ENV", "VIRTUAL_ENV_PROMPT"):
|
|
88
|
+
self.env.pop(name, None)
|
|
89
|
+
self.unregister_pydoc()
|
|
90
|
+
if args is None or "nondestructive" not in args:
|
|
91
|
+
del aliases["deactivate"]
|
|
92
|
+
try:
|
|
93
|
+
del __xonsh__.xontrib.virtualenv
|
|
94
|
+
except AttributeError:
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if not hasattr(__xonsh__, "xontrib"):
|
|
99
|
+
__xonsh__.xontrib = __xonsh__.imp.types.SimpleNamespace()
|
|
100
|
+
__xonsh__.xontrib.virtualenv = _VirtualEnvActivator()
|
|
101
|
+
__xonsh__.xontrib.virtualenv.activate()
|
|
@@ -113,7 +113,8 @@ class VirtualEnvConfigParser(ArgumentParser):
|
|
|
113
113
|
if outcome is not None:
|
|
114
114
|
break
|
|
115
115
|
if outcome is not None:
|
|
116
|
-
action.default,
|
|
116
|
+
action.default, default_source = outcome
|
|
117
|
+
vars(action)["default_source"] = default_source
|
|
117
118
|
else:
|
|
118
119
|
outcome = action.default, "default"
|
|
119
120
|
self.options.set_src(action.dest, *outcome)
|
|
@@ -122,7 +123,7 @@ class VirtualEnvConfigParser(ArgumentParser):
|
|
|
122
123
|
self._fix_defaults()
|
|
123
124
|
self.add_argument("-h", "--help", action="help", default=SUPPRESS, help="show this help message and exit")
|
|
124
125
|
|
|
125
|
-
def parse_known_args(
|
|
126
|
+
def parse_known_args( # ty: ignore[invalid-method-override]
|
|
126
127
|
self, args: Sequence[str] | None = None, namespace: VirtualEnvOptions | None = None
|
|
127
128
|
) -> tuple[VirtualEnvOptions, list[str]]:
|
|
128
129
|
if namespace is None:
|
|
@@ -22,8 +22,14 @@ class PluginLoader:
|
|
|
22
22
|
@classmethod
|
|
23
23
|
def entry_points_for(cls, key: str) -> OrderedDict[str, type]:
|
|
24
24
|
if sys.version_info >= (3, 10) or importlib_metadata_version >= (3, 6):
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
selected = list(cls.entry_points().select(group=key)) # ty: ignore[unresolved-attribute]
|
|
26
|
+
else:
|
|
27
|
+
selected = list(cls.entry_points().get(key, [])) # ty: ignore[unresolved-attribute]
|
|
28
|
+
# Third-party packages may register entry points with the same name as virtualenv's
|
|
29
|
+
# built-ins (e.g. xonsh's own `virtualenv.activate.xonsh`). Sort so built-ins are
|
|
30
|
+
# inserted last into the OrderedDict, making them win on name collision.
|
|
31
|
+
selected.sort(key=lambda e: e.value.startswith("virtualenv."))
|
|
32
|
+
return OrderedDict((e.name, e.load()) for e in selected)
|
|
27
33
|
|
|
28
34
|
@staticmethod
|
|
29
35
|
def entry_points() -> object:
|
{virtualenv-21.2.3 → virtualenv-21.3.0}/src/virtualenv/seed/embed/via_app_data/pip_install/base.py
RENAMED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import ntpath
|
|
4
5
|
import os
|
|
6
|
+
import posixpath
|
|
5
7
|
import re
|
|
6
8
|
import zipfile
|
|
7
9
|
from abc import ABC, abstractmethod
|
|
@@ -21,6 +23,24 @@ if TYPE_CHECKING:
|
|
|
21
23
|
LOGGER = logging.getLogger(__name__)
|
|
22
24
|
|
|
23
25
|
|
|
26
|
+
def _safe_extract_zip(zip_ref: zipfile.ZipFile, target_dir: Path) -> None:
|
|
27
|
+
# Guard against zip slip: a wheel is a zip and a tampered entry name (absolute path or one containing ``..``)
|
|
28
|
+
# could escape ``target_dir``.
|
|
29
|
+
base = target_dir.resolve()
|
|
30
|
+
for info in zip_ref.infolist():
|
|
31
|
+
name = info.filename
|
|
32
|
+
if name.startswith(("/", "\\")) or ntpath.isabs(name) or posixpath.isabs(name):
|
|
33
|
+
msg = f"refusing to extract absolute path entry from wheel: {name!r}"
|
|
34
|
+
raise RuntimeError(msg)
|
|
35
|
+
candidate = (base / name).resolve()
|
|
36
|
+
try:
|
|
37
|
+
candidate.relative_to(base)
|
|
38
|
+
except ValueError as exc:
|
|
39
|
+
msg = f"refusing to extract entry escaping target directory: {name!r}"
|
|
40
|
+
raise RuntimeError(msg) from exc
|
|
41
|
+
zip_ref.extractall(str(target_dir))
|
|
42
|
+
|
|
43
|
+
|
|
24
44
|
class PipInstall(ABC):
|
|
25
45
|
def __init__(self, wheel: Path, creator: Creator, image_folder: Path) -> None:
|
|
26
46
|
self._wheel = wheel
|
|
@@ -49,11 +69,19 @@ class PipInstall(ABC):
|
|
|
49
69
|
LOGGER.debug("generated console scripts %s", " ".join(i.name for i in consoles))
|
|
50
70
|
|
|
51
71
|
def build_image(self) -> None:
|
|
72
|
+
"""Extract the seed wheel into the image directory and fix up its RECORD file.
|
|
73
|
+
|
|
74
|
+
Each archive entry is validated before extraction so a tampered wheel cannot escape the image directory via an
|
|
75
|
+
absolute path or ``..`` traversal.
|
|
76
|
+
|
|
77
|
+
:raises RuntimeError: if the wheel contains an entry that would land outside the image directory.
|
|
78
|
+
|
|
79
|
+
"""
|
|
52
80
|
# 1. first extract the wheel
|
|
53
81
|
LOGGER.debug("build install image for %s to %s", self._wheel.name, self._image_dir)
|
|
54
82
|
with zipfile.ZipFile(str(self._wheel)) as zip_ref:
|
|
55
83
|
self._shorten_path_if_needed(zip_ref)
|
|
56
|
-
zip_ref
|
|
84
|
+
_safe_extract_zip(zip_ref, self._image_dir)
|
|
57
85
|
self._extracted = True
|
|
58
86
|
# 2. now add additional files not present in the distribution
|
|
59
87
|
new_files = self._generate_new_files()
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
+
import re
|
|
6
7
|
import sys
|
|
7
8
|
from operator import eq, lt
|
|
8
9
|
from pathlib import Path
|
|
@@ -18,6 +19,34 @@ if TYPE_CHECKING:
|
|
|
18
19
|
|
|
19
20
|
LOGGER = logging.getLogger(__name__)
|
|
20
21
|
|
|
22
|
+
# PEP 503 normalized distribution name. Anything outside this character set on the way to ``pip download`` means
|
|
23
|
+
# somebody is smuggling pip options or extras, so reject it before we build the command line.
|
|
24
|
+
_DISTRIBUTION_RE = re.compile(
|
|
25
|
+
r"""
|
|
26
|
+
^
|
|
27
|
+
(?P<name>
|
|
28
|
+
[A-Za-z0-9] # must start with an alnum
|
|
29
|
+
(?:[A-Za-z0-9._-]* # inner chars: alnum plus . _ -
|
|
30
|
+
[A-Za-z0-9])? # must also end with an alnum (unless length is 1)
|
|
31
|
+
)
|
|
32
|
+
$
|
|
33
|
+
""",
|
|
34
|
+
re.VERBOSE,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Version specifier that matches what ``Version.as_version_spec`` emits: either empty, ``==<ver>`` or ``<<ver>`` where
|
|
38
|
+
# ``<ver>`` is a subset of PEP 440 public versions. Kept deliberately strict so a crafted version cannot inject pip
|
|
39
|
+
# flags.
|
|
40
|
+
_VERSION_SPEC_RE = re.compile(
|
|
41
|
+
r"""
|
|
42
|
+
^
|
|
43
|
+
(?P<operator>==|<) # only the operators Version.as_version_spec can emit
|
|
44
|
+
(?P<version>[A-Za-z0-9._+!-]+) # PEP 440 public-version character set, no whitespace
|
|
45
|
+
$
|
|
46
|
+
""",
|
|
47
|
+
re.VERBOSE,
|
|
48
|
+
)
|
|
49
|
+
|
|
21
50
|
|
|
22
51
|
def get_wheel( # noqa: PLR0913
|
|
23
52
|
distribution: str,
|
|
@@ -63,6 +92,26 @@ def download_wheel( # noqa: PLR0913
|
|
|
63
92
|
to_folder: Path,
|
|
64
93
|
env: dict[str, str],
|
|
65
94
|
) -> Wheel:
|
|
95
|
+
"""Invoke ``pip download`` in a subprocess to fetch a seed wheel.
|
|
96
|
+
|
|
97
|
+
:param distribution: PEP 503 normalized project name; rejected if it contains anything other than
|
|
98
|
+
``[A-Za-z0-9._-]``.
|
|
99
|
+
:param version_spec: optional version specifier of the form ``==<ver>`` or ``<<ver>`` as emitted by
|
|
100
|
+
:func:`Version.as_version_spec`, or ``None``/empty for the latest compatible release.
|
|
101
|
+
:param for_py_version: major.minor Python version to pass through to ``pip --python-version``.
|
|
102
|
+
:param search_dirs: additional directories to treat as a local wheel index when bootstrapping pip.
|
|
103
|
+
:param app_data: application data store used to locate the embedded pip wheel.
|
|
104
|
+
:param to_folder: directory the downloaded wheel is written into.
|
|
105
|
+
:param env: environment mapping passed through to the subprocess.
|
|
106
|
+
|
|
107
|
+
:returns: the downloaded :class:`Wheel`.
|
|
108
|
+
|
|
109
|
+
:raises ValueError: if ``distribution`` or ``version_spec`` fail the strict allow-list check.
|
|
110
|
+
:raises CalledProcessError: if ``pip download`` exits with a non-zero status.
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
_check_distribution(distribution)
|
|
114
|
+
_check_version_spec(version_spec)
|
|
66
115
|
to_download = f"{distribution}{version_spec or ''}"
|
|
67
116
|
LOGGER.debug("download wheel %s %s to %s", to_download, for_py_version, to_folder)
|
|
68
117
|
cmd = [
|
|
@@ -143,6 +192,20 @@ def pip_wheel_env_run(search_dirs: list[Path], app_data: AppData, env: dict[str,
|
|
|
143
192
|
return env
|
|
144
193
|
|
|
145
194
|
|
|
195
|
+
def _check_distribution(distribution: str) -> None:
|
|
196
|
+
if not _DISTRIBUTION_RE.fullmatch(distribution):
|
|
197
|
+
msg = f"refusing to download wheel for suspicious distribution name: {distribution!r}"
|
|
198
|
+
raise ValueError(msg)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _check_version_spec(version_spec: str | None) -> None:
|
|
202
|
+
if not version_spec:
|
|
203
|
+
return
|
|
204
|
+
if not _VERSION_SPEC_RE.fullmatch(version_spec):
|
|
205
|
+
msg = f"refusing to download wheel with suspicious version spec: {version_spec!r}"
|
|
206
|
+
raise ValueError(msg)
|
|
207
|
+
|
|
208
|
+
|
|
146
209
|
__all__ = [
|
|
147
210
|
"download_wheel",
|
|
148
211
|
"get_wheel",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import zipfile
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from virtualenv.info import IS_ZIPAPP, ROOT
|
|
8
|
+
from virtualenv.seed.wheels.util import Wheel
|
|
9
|
+
|
|
10
|
+
BUNDLE_FOLDER = Path(__file__).absolute().parent
|
|
11
|
+
BUNDLE_SUPPORT = {
|
|
12
|
+
"3.8": {
|
|
13
|
+
"pip": "pip-25.0.1-py3-none-any.whl",
|
|
14
|
+
"setuptools": "setuptools-75.3.4-py3-none-any.whl",
|
|
15
|
+
"wheel": "wheel-0.45.1-py3-none-any.whl",
|
|
16
|
+
},
|
|
17
|
+
"3.9": {
|
|
18
|
+
"pip": "pip-26.0.1-py3-none-any.whl",
|
|
19
|
+
"setuptools": "setuptools-82.0.1-py3-none-any.whl",
|
|
20
|
+
},
|
|
21
|
+
"3.10": {
|
|
22
|
+
"pip": "pip-26.1-py3-none-any.whl",
|
|
23
|
+
"setuptools": "setuptools-82.0.1-py3-none-any.whl",
|
|
24
|
+
},
|
|
25
|
+
"3.11": {
|
|
26
|
+
"pip": "pip-26.1-py3-none-any.whl",
|
|
27
|
+
"setuptools": "setuptools-82.0.1-py3-none-any.whl",
|
|
28
|
+
},
|
|
29
|
+
"3.12": {
|
|
30
|
+
"pip": "pip-26.1-py3-none-any.whl",
|
|
31
|
+
"setuptools": "setuptools-82.0.1-py3-none-any.whl",
|
|
32
|
+
},
|
|
33
|
+
"3.13": {
|
|
34
|
+
"pip": "pip-26.1-py3-none-any.whl",
|
|
35
|
+
"setuptools": "setuptools-82.0.1-py3-none-any.whl",
|
|
36
|
+
},
|
|
37
|
+
"3.14": {
|
|
38
|
+
"pip": "pip-26.1-py3-none-any.whl",
|
|
39
|
+
"setuptools": "setuptools-82.0.1-py3-none-any.whl",
|
|
40
|
+
},
|
|
41
|
+
"3.15": {
|
|
42
|
+
"pip": "pip-26.1-py3-none-any.whl",
|
|
43
|
+
"setuptools": "setuptools-82.0.1-py3-none-any.whl",
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
MAX = "3.8"
|
|
47
|
+
|
|
48
|
+
# SHA-256 of every bundled wheel. Verified on load so a corrupted or tampered wheel on disk fails loud instead of
|
|
49
|
+
# being handed to pip. Generated together with ``BUNDLE_SUPPORT`` by ``tasks/upgrade_wheels.py``.
|
|
50
|
+
BUNDLE_SHA256 = {
|
|
51
|
+
"pip-25.0.1-py3-none-any.whl": "c46efd13b6aa8279f33f2864459c8ce587ea6a1a59ee20de055868d8f7688f7f",
|
|
52
|
+
"pip-26.0.1-py3-none-any.whl": "bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b",
|
|
53
|
+
"pip-26.1-py3-none-any.whl": "4e8486d821d814b77319acb7b9e8bf5a4ee7590a643e7cb21029f209be8573c1",
|
|
54
|
+
"setuptools-75.3.4-py3-none-any.whl": "2dd50a7f42dddfa1d02a36f275dbe716f38ed250224f609d35fb60a09593d93e",
|
|
55
|
+
"setuptools-82.0.1-py3-none-any.whl": "a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb",
|
|
56
|
+
"wheel-0.45.1-py3-none-any.whl": "708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_VERIFIED_WHEELS: set[str] = set()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_embed_wheel(distribution: str, for_py_version: str) -> Wheel | None:
|
|
63
|
+
"""Return the bundled wheel that ships with virtualenv for a given distribution and Python version.
|
|
64
|
+
|
|
65
|
+
:param distribution: project name of the seed package, for example ``pip`` or ``setuptools``.
|
|
66
|
+
:param for_py_version: major.minor Python version string the environment will be created for.
|
|
67
|
+
|
|
68
|
+
:returns: a :class:`Wheel` pointing at the verified bundled file, or ``None`` when no wheel is bundled for the
|
|
69
|
+
requested combination.
|
|
70
|
+
|
|
71
|
+
:raises RuntimeError: if the bundled wheel on disk fails SHA-256 verification.
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
mapping = BUNDLE_SUPPORT.get(for_py_version, {}) or BUNDLE_SUPPORT[MAX]
|
|
75
|
+
wheel_file = mapping.get(distribution)
|
|
76
|
+
if wheel_file is None:
|
|
77
|
+
return None
|
|
78
|
+
path = BUNDLE_FOLDER / wheel_file
|
|
79
|
+
_verify_bundled_wheel(path)
|
|
80
|
+
return Wheel.from_path(path)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _verify_bundled_wheel(path: Path) -> None:
|
|
84
|
+
name = path.name
|
|
85
|
+
if name in _VERIFIED_WHEELS:
|
|
86
|
+
return
|
|
87
|
+
expected = BUNDLE_SHA256.get(name)
|
|
88
|
+
if expected is None:
|
|
89
|
+
msg = f"bundled wheel {name} has no recorded sha256 in BUNDLE_SHA256"
|
|
90
|
+
raise RuntimeError(msg)
|
|
91
|
+
actual = _hash_bundled_wheel(path)
|
|
92
|
+
if actual != expected:
|
|
93
|
+
msg = f"bundled wheel {name} sha256 mismatch: expected {expected}, got {actual}"
|
|
94
|
+
raise RuntimeError(msg)
|
|
95
|
+
_VERIFIED_WHEELS.add(name)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _hash_bundled_wheel(path: Path) -> str:
|
|
99
|
+
# ``path`` is under the package directory; when virtualenv runs from a zipapp the wheel lives inside the
|
|
100
|
+
# archive and cannot be opened as a regular file, so read the bytes straight from the zipapp entry.
|
|
101
|
+
digest = hashlib.sha256()
|
|
102
|
+
if IS_ZIPAPP:
|
|
103
|
+
entry = path.resolve().relative_to(Path(ROOT).resolve()).as_posix()
|
|
104
|
+
with zipfile.ZipFile(ROOT, "r") as archive, archive.open(entry) as stream:
|
|
105
|
+
for chunk in iter(lambda: stream.read(1 << 20), b""):
|
|
106
|
+
digest.update(chunk)
|
|
107
|
+
else:
|
|
108
|
+
with path.open("rb") as stream:
|
|
109
|
+
for chunk in iter(lambda: stream.read(1 << 20), b""):
|
|
110
|
+
digest.update(chunk)
|
|
111
|
+
return digest.hexdigest()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
__all__ = [
|
|
115
|
+
"BUNDLE_FOLDER",
|
|
116
|
+
"BUNDLE_SHA256",
|
|
117
|
+
"BUNDLE_SUPPORT",
|
|
118
|
+
"MAX",
|
|
119
|
+
"get_embed_wheel",
|
|
120
|
+
]
|
|
@@ -360,10 +360,20 @@ def release_date_for_wheel_path(dest: Path) -> datetime | None:
|
|
|
360
360
|
return None
|
|
361
361
|
|
|
362
362
|
|
|
363
|
+
#: Opt-in escape hatch to restore the pre-2026 behavior of falling back to an unverified HTTPS context when the
|
|
364
|
+
#: verified request fails. Off by default: a failed TLS handshake on the PyPI metadata lookup now aborts the update
|
|
365
|
+
#: instead of silently downgrading, because the response drives which wheel version virtualenv thinks is up to date.
|
|
366
|
+
_INSECURE_FALLBACK_ENV = "VIRTUALENV_PERIODIC_UPDATE_INSECURE"
|
|
367
|
+
|
|
368
|
+
|
|
363
369
|
def _request_context() -> Generator[ssl.SSLContext | None, None, None]:
|
|
364
370
|
yield None
|
|
365
|
-
|
|
366
|
-
|
|
371
|
+
if os.environ.get(_INSECURE_FALLBACK_ENV):
|
|
372
|
+
LOGGER.warning(
|
|
373
|
+
"falling back to unverified HTTPS for PyPI metadata because %s is set",
|
|
374
|
+
_INSECURE_FALLBACK_ENV,
|
|
375
|
+
)
|
|
376
|
+
yield ssl._create_unverified_context() # noqa: S323, SLF001
|
|
367
377
|
|
|
368
378
|
|
|
369
379
|
_PYPI_CACHE = {}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import os
|
|
5
4
|
import zipfile
|
|
6
|
-
from
|
|
5
|
+
from pathlib import Path
|
|
7
6
|
|
|
8
|
-
from virtualenv.info import
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from pathlib import Path
|
|
7
|
+
from virtualenv.info import ROOT
|
|
12
8
|
|
|
13
9
|
LOGGER = logging.getLogger(__name__)
|
|
14
10
|
|
|
@@ -29,16 +25,18 @@ def extract(full_path: str | Path, dest: Path) -> None:
|
|
|
29
25
|
|
|
30
26
|
|
|
31
27
|
def _get_path_within_zip(full_path: str | Path) -> str:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
# Use Path.relative_to so symlinks and ``..`` segments cannot slip through a string ``startswith`` check. The zipapp
|
|
29
|
+
# root is a real file we own so ``resolve`` is safe; anything that does not resolve under ROOT is a bug or an
|
|
30
|
+
# attempt to escape the archive and we refuse it.
|
|
31
|
+
resolved = Path(full_path).resolve()
|
|
32
|
+
root = Path(ROOT).resolve()
|
|
33
|
+
try:
|
|
34
|
+
relative = resolved.relative_to(root)
|
|
35
|
+
except ValueError as exc:
|
|
36
|
+
msg = f"full_path={resolved} should be within ROOT={root}"
|
|
37
|
+
raise RuntimeError(msg) from exc
|
|
38
|
+
# Zip entries always use forward slashes regardless of platform.
|
|
39
|
+
return relative.as_posix()
|
|
42
40
|
|
|
43
41
|
|
|
44
42
|
__all__ = [
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '21.
|
|
22
|
-
__version_tuple__ = version_tuple = (21,
|
|
21
|
+
__version__ = version = '21.3.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (21, 3, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|