|
25 | 25 | from virtualenv.__main__ import run, run_with_catch
|
26 | 26 | from virtualenv.create.creator import DEBUG_SCRIPT, Creator, get_env_debug_info
|
27 | 27 | from virtualenv.create.pyenv_cfg import PyEnvCfg
|
| 28 | +from virtualenv.create.via_global_ref import api |
28 | 29 | from virtualenv.create.via_global_ref.builtin.cpython.common import is_macos_brew
|
29 | 30 | from virtualenv.create.via_global_ref.builtin.cpython.cpython3 import CPython3Posix
|
30 | 31 | from virtualenv.discovery.py_info import PythonInfo
|
@@ -690,3 +691,63 @@ def func(self):
|
690 | 691 |
|
691 | 692 | cmd = [str(tmp_path), "--seeder", "app-data", "--without-pip", "--creator", "venv"]
|
692 | 693 | cli_run(cmd)
|
| 694 | + |
| 695 | + |
| 696 | +def test_fallback_to_copies_if_symlink_unsupported(tmp_path, python, mocker): |
| 697 | + """Test that creating a virtual environment falls back to copies when filesystem has no symlink support.""" |
| 698 | + if is_macos_brew(PythonInfo.from_exe(python)): |
| 699 | + pytest.skip("brew python on darwin may not support copies, which is tested separately") |
| 700 | + |
| 701 | + # Given a filesystem that does not support symlinks |
| 702 | + mocker.patch("virtualenv.create.via_global_ref.api.fs_supports_symlink", return_value=False) |
| 703 | + |
| 704 | + # When creating a virtual environment (no method specified) |
| 705 | + cmd = [ |
| 706 | + "-v", |
| 707 | + "-p", |
| 708 | + str(python), |
| 709 | + str(tmp_path), |
| 710 | + "--without-pip", |
| 711 | + "--activators", |
| 712 | + "", |
| 713 | + ] |
| 714 | + result = cli_run(cmd) |
| 715 | + |
| 716 | + # Then the creation should succeed and the creator should report it used copies |
| 717 | + assert result.creator is not None |
| 718 | + assert result.creator.symlinks is False |
| 719 | + |
| 720 | + |
| 721 | +def test_fail_gracefully_if_no_method_supported(tmp_path, python, mocker): |
| 722 | + """Test that virtualenv fails gracefully when no creation method is supported.""" |
| 723 | + # Given a filesystem that does not support symlinks |
| 724 | + mocker.patch("virtualenv.create.via_global_ref.api.fs_supports_symlink", return_value=False) |
| 725 | + |
| 726 | + # And a creator that does not support copying |
| 727 | + if not is_macos_brew(PythonInfo.from_exe(python)): |
| 728 | + original_init = api.ViaGlobalRefMeta.__init__ |
| 729 | + |
| 730 | + def new_init(self, *args, **kwargs): |
| 731 | + original_init(self, *args, **kwargs) |
| 732 | + self.copy_error = "copying is not supported" |
| 733 | + |
| 734 | + mocker.patch("virtualenv.create.via_global_ref.api.ViaGlobalRefMeta.__init__", new=new_init) |
| 735 | + |
| 736 | + # When creating a virtual environment |
| 737 | + with pytest.raises(RuntimeError) as excinfo: |
| 738 | + cli_run( |
| 739 | + [ |
| 740 | + "-p", |
| 741 | + str(python), |
| 742 | + str(tmp_path), |
| 743 | + "--without-pip", |
| 744 | + ], |
| 745 | + ) |
| 746 | + |
| 747 | + # Then a RuntimeError should be raised with a detailed message |
| 748 | + assert "neither symlink or copy method supported" in str(excinfo.value) |
| 749 | + assert "symlink: the filesystem does not supports symlink" in str(excinfo.value) |
| 750 | + if is_macos_brew(PythonInfo.from_exe(python)): |
| 751 | + assert "copy: Brew disables copy creation" in str(excinfo.value) |
| 752 | + else: |
| 753 | + assert "copy: copying is not supported" in str(excinfo.value) |
0 commit comments