コード例 #1
0
ファイル: test_specifiers.py プロジェクト: stacklens/pdm
def test_impossible_pyspec():
    spec = PySpecSet(">=3.6,<3.4")
    a = PySpecSet(">=2.7")
    assert spec.is_impossible
    assert (spec & a).is_impossible
    assert spec | a == a
    spec_copy = spec.copy()
    assert spec_copy.is_impossible
    assert str(spec_copy) == "impossible"
コード例 #2
0
ファイル: repositories.py プロジェクト: stacklens/pdm
 def get_dependencies(
         self,
         candidate: Candidate) -> Tuple[List[Requirement], PySpecSet, str]:
     """Get (dependencies, python_specifier, summary) of the candidate."""
     requirements, requires_python, summary = [], "", ""
     last_ext_info = None
     for getter in self.dependency_generators():
         try:
             requirements, requires_python, summary = getter(candidate)
         except CandidateInfoNotFound:
             last_ext_info = sys.exc_info()
             continue
         break
     else:
         if last_ext_info is not None:
             raise last_ext_info[1].with_traceback(last_ext_info[2])
     requirements = [parse_requirement(line) for line in requirements]
     if candidate.req.extras:
         # HACK: If this candidate has extras, add the original candidate
         # (same pinned version, no extras) as its dependency. This ensures
         # the same package with different extras (treated as distinct by
         # the resolver) have the same version.
         self_req = candidate.req.copy()
         self_req.extras = None
         requirements.append(self_req)
     return requirements, PySpecSet(requires_python), summary
コード例 #3
0
ファイル: test_resolve.py プロジェクト: danieleades/pdm
    def resolve_func(
        lines,
        requires_python="",
        allow_prereleases=None,
        strategy="all",
        tracked_names=None,
    ):
        repository.environment.python_requires = PySpecSet(requires_python)
        if allow_prereleases is not None:
            project.tool_settings["allow_prereleases"] = allow_prereleases
        requirements = []
        for line in lines:
            if line.startswith("-e "):
                requirements.append(parse_requirement(line[3:], True))
            else:
                requirements.append(parse_requirement(line))
        provider = project.get_provider(strategy, tracked_names)

        ui = project.core.ui
        with ui.open_spinner("Resolving dependencies") as spin, ui.logging(
                "lock"):
            reporter = SpinnerReporter(spin, requirements)
            resolver = Resolver(provider, reporter)
            mapping, *_ = _resolve(resolver, requirements,
                                   repository.environment.python_requires)
            return mapping
コード例 #4
0
def test_non_editable_no_override_editable(project, working_set, is_editable):
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(
        project,
        editables=[
            "git+https://github.com/test-root/demo.git#egg=demo",
            "git+https://github.com/test-root/demo-module.git#egg=demo-module",
        ],
    )
    actions.do_add(
        project,
        packages=["git+https://github.com/test-root/demo.git#egg=demo"],
        no_editable=not is_editable,
    )
    assert working_set["demo-module"].link_file
    assert bool(working_set["demo"].link_file) is is_editable
    dependencies = project.get_pyproject_dependencies("default")
    if is_editable:
        assert dependencies == [
            "-e git+https://github.com/test-root/demo.git#egg=demo",
            "-e git+https://github.com/test-root/demo-module.git#egg=demo-module",
            "demo @ git+https://github.com/test-root/demo.git",
        ]
    else:
        assert dependencies == [
            "demo @ git+https://github.com/test-root/demo.git",
            "-e git+https://github.com/test-root/demo-module.git#egg=demo-module",
        ]
コード例 #5
0
ファイル: test_resolve.py プロジェクト: pcskys/pdm
def resolve_requirements(
    repository,
    lines,
    requires_python="",
    allow_prereleases=None,
    strategy="reuse",
    preferred_pins=None,
    tracked_names=None,
):
    requirements = {}
    if isinstance(lines, list):
        lines = {"default": lines}
    for k, v in lines.items():
        for line in v:
            req = parse_requirement(line)
            requirements.setdefault(k, {})[identify(req)] = req
    requires_python = PySpecSet(requires_python)
    if not preferred_pins:
        provider = BaseProvider(repository, requires_python, allow_prereleases)
    else:
        provider_class = (ReusePinProvider
                          if strategy == "reuse" else EagerUpdateProvider)
        provider = provider_class(
            preferred_pins,
            tracked_names or (),
            repository,
            requires_python,
            allow_prereleases,
        )
    flat_reqs = list(
        itertools.chain(*[deps.values() for _, deps in requirements.items()]))
    reporter = SimpleReporter(flat_reqs)
    resolver = Resolver(provider, reporter)
    mapping, *_ = resolve(resolver, requirements, requires_python)
    return mapping
コード例 #6
0
    def find_matches(
        self,
        requirement: Requirement,
        requires_python: PySpecSet = PySpecSet(),
        allow_prereleases: Optional[bool] = None,
        allow_all: bool = False,
    ) -> List[Candidate]:
        """Find matching candidates of a requirement.

        :param requirement: the given requirement.
        :param requires_python: the Python version constraint.
        :param allow_prereleases: whether allow prerelease versions, or let us determine
            if not given. If no non-prerelease is available, prereleases will be used.
        :param allow_all: whether allow all wheels.
        :returns: a list of candidates.
        """
        if requirement.is_named:
            return self._find_named_matches(
                requirement, requires_python, allow_prereleases, allow_all
            )
        else:
            # Fetch metadata so that resolver can know the candidate's name.
            can = Candidate(requirement, self.environment)
            can.get_metadata()
            return [can]
コード例 #7
0
 def get_dependencies(
     self, candidate: Candidate
 ) -> tuple[list[Requirement], PySpecSet, str]:
     """Get (dependencies, python_specifier, summary) of the candidate."""
     requires_python, summary = "", ""
     requirements: list[str] = []
     last_ext_info = None
     for getter in self.dependency_generators():
         try:
             requirements, requires_python, summary = getter(candidate)
         except CandidateInfoNotFound:
             last_ext_info = sys.exc_info()
             continue
         break
     else:
         if last_ext_info is not None:
             raise last_ext_info[1].with_traceback(last_ext_info[2])  # type: ignore
     reqs = [parse_requirement(line) for line in requirements]
     if candidate.req.extras:
         # XXX: If the requirement has extras, add the original candidate
         # (without extras) as its dependency. This ensures the same package with
         # different extras resolve to the same version.
         self_req = dataclasses.replace(candidate.req, extras=None, marker=None)
         reqs.append(self_req)
     # Store the metadata on the candidate for caching
     candidate.requires_python = requires_python
     candidate.summary = summary
     return reqs, PySpecSet(requires_python), summary
コード例 #8
0
def test_add_editable_package(project, working_set, is_dev):
    # Ensure that correct python version is used.
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(project, is_dev, packages=["demo"])
    actions.do_add(
        project,
        is_dev,
        editables=["git+https://github.com/test-root/demo.git#egg=demo"],
    )
    group = (
        project.tool_settings["dev-dependencies"]["dev"]
        if is_dev
        else project.meta["dependencies"]
    )
    assert "demo" in group[0]
    assert "-e git+https://github.com/test-root/demo.git#egg=demo" in group[1]
    locked_candidates = project.locked_repository.all_candidates
    assert (
        locked_candidates["demo"].prepare(project.environment).revision
        == "1234567890abcdef"
    )
    assert locked_candidates["idna"].version == "2.7"
    assert "idna" in working_set

    actions.do_sync(project, no_editable=True)
    assert not working_set["demo"].link_file
コード例 #9
0
ファイル: test_resolve.py プロジェクト: xareelee/pdm
def resolve_requirements(
    repository,
    lines,
    requires_python="",
    allow_prereleases=None,
    strategy="all",
    preferred_pins=None,
    tracked_names=None,
):
    requirements = []
    for line in lines:
        if line.startswith("-e "):
            requirements.append(parse_requirement(line[3:], True))
        else:
            requirements.append(parse_requirement(line))
    requires_python = PySpecSet(requires_python)
    if not preferred_pins:
        provider = BaseProvider(repository, requires_python, allow_prereleases)
    else:
        provider_class = (ReusePinProvider
                          if strategy == "reuse" else EagerUpdateProvider)
        provider = provider_class(
            preferred_pins,
            tracked_names or (),
            repository,
            requires_python,
            allow_prereleases,
        )
    ui = termui.UI()
    with ui.open_spinner("Resolving dependencies") as spin, ui.logging("lock"):
        reporter = SpinnerReporter(spin, requirements)
        resolver = Resolver(provider, reporter)
        mapping, *_ = resolve(resolver, requirements, requires_python)
        return mapping
コード例 #10
0
ファイル: test_deprecation.py プロジェクト: pawamoy/pdm
def test_deprecated_section_argument(project, invoke, working_set):
    project.environment.python_requires = PySpecSet(">=3.6")
    r = invoke(["add", "--section", "optional", "demo"], obj=project)
    assert r.exit_code == 0
    assert "DEPRECATED" in r.stderr

    assert "demo" in working_set
    assert "demo" in project.get_dependencies("optional")
コード例 #11
0
ファイル: requirements.py プロジェクト: shalevy1/pdm
 def marker(self, value) -> None:
     try:
         m = self._marker = get_marker(value)
         if not m:
             self.marker_no_python, self.requires_python = None, PySpecSet()
         else:
             self.marker_no_python, self.requires_python = m.split_pyspec()
     except InvalidMarker as e:
         raise RequirementError("Invalid marker: %s" % str(e)) from None
コード例 #12
0
ファイル: test_actions.py プロジェクト: ulwlu/pdm
def test_editable_package_override_non_editable(project, working_set):
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(
        project,
        packages=["git+https://github.com/test-root/demo.git#egg=demo"])
    actions.do_add(
        project,
        editables=["git+https://github.com/test-root/demo.git#egg=demo"],
    )
    assert working_set["demo"].editable
コード例 #13
0
    def find_candidates(
        self,
        requirement: Requirement,
        requires_python: PySpecSet = PySpecSet(),
        allow_prereleases: Optional[bool] = None,
        allow_all: bool = False,
    ) -> Iterable[Candidate]:
        """Find candidates of the given NamedRequirement. Let it to be implemented in
        subclasses.
        """
        # `allow_prereleases` is None means leave it to specifier to decide whether to
        # include prereleases
        if allow_prereleases is None:
            allow_prereleases = requirement.allow_prereleases

        requires_python = requires_python & requirement.requires_python
        cans = list(self._find_candidates(requirement))

        sorted_cans = sorted(
            (
                c
                for c in cans
                if requirement.specifier.contains(c.version, allow_prereleases)
                and (allow_all or requires_python.is_subset(c.requires_python))
            ),
            key=lambda c: (c.version, c.link.is_wheel),
            reverse=True,
        )

        if not sorted_cans and allow_prereleases is None:
            # No non-pre-releases is found, force pre-releases now
            sorted_cans = sorted(
                (
                    c
                    for c in cans
                    if requirement.specifier.contains(c.version, True)
                    and (allow_all or requires_python.is_subset(c.requires_python))
                ),
                key=lambda c: c.version,
                reverse=True,
            )
        return sorted_cans
コード例 #14
0
ファイル: conftest.py プロジェクト: shalevy1/pdm
    def find_candidates(
        self,
        requirement: Requirement,
        requires_python: PySpecSet = PySpecSet(),
        allow_prereleases: Optional[bool] = None,
        allow_all: bool = False,
    ) -> List[Candidate]:
        if allow_prereleases is None:
            allow_prereleases = requirement.allow_prereleases

        cans = []
        for version, candidate in self._pypi_data.get(requirement.key,
                                                      {}).items():
            c = Candidate(
                requirement,
                self.environment,
                name=requirement.project_name,
                version=version,
            )
            c.requires_python = candidate.get("requires_python", "")
            cans.append(c)

        sorted_cans = sorted(
            (c for c in cans
             if requirement.specifier.contains(c.version, allow_prereleases)),
            key=lambda c: c.version,
            reverse=True,
        )
        if not allow_all:
            sorted_cans = [
                can for can in sorted_cans
                if requires_python.is_subset(can.requires_python)
            ]
        if not sorted_cans and allow_prereleases is None:
            # No non-pre-releases is found, force pre-releases now
            sorted_cans = sorted(
                (c for c in cans
                 if requirement.specifier.contains(c.version, True)),
                key=lambda c: c.version,
                reverse=True,
            )
        return sorted_cans
コード例 #15
0
    def find_candidates(
        self,
        requirement: Requirement,
        requires_python: PySpecSet = PySpecSet(),
        allow_prereleases: Optional[bool] = None,
        allow_all: bool = False,
    ) -> Iterable[Candidate]:
        sources = self.get_filtered_sources(requirement)
        # `allow_prereleases` is None means leave it to specifier to decide whether to
        # include prereleases
        if allow_prereleases is None:
            allow_prereleases = requirement.allow_prereleases

        with self.environment.get_finder(sources) as finder, allow_all_wheels():
            cans = [
                Candidate.from_installation_candidate(c, requirement, self.environment)
                for c in finder.find_all_candidates(requirement.project_name)
            ]
        sorted_cans = sorted(
            (
                c
                for c in cans
                if requirement.specifier.contains(c.version, allow_prereleases)
                and (allow_all or requires_python.is_subset(c.requires_python))
            ),
            key=lambda c: (c.version, c.link.is_wheel),
            reverse=True,
        )

        if not sorted_cans and allow_prereleases is None:
            # No non-pre-releases is found, force pre-releases now
            sorted_cans = sorted(
                (
                    c
                    for c in cans
                    if requirement.specifier.contains(c.version, True)
                    and (allow_all or requires_python.is_subset(c.requires_python))
                ),
                key=lambda c: c.version,
                reverse=True,
            )
        return sorted_cans
コード例 #16
0
ファイル: repositories.py プロジェクト: stacklens/pdm
 def _find_named_matches(
     self,
     requirement: Requirement,
     requires_python: PySpecSet = PySpecSet(),
     allow_prereleases: Optional[bool] = None,
     allow_all: bool = False,
 ) -> List[Candidate]:
     """Find candidates of the given NamedRequirement. Let it to be implemented in
     subclasses.
     """
     raise NotImplementedError
コード例 #17
0
ファイル: markers.py プロジェクト: pawamoy/pdm
def _build_pyspec_from_marker(markers: List[Any]) -> PySpecSet:
    def split_version(version: str) -> List[str]:
        if "," in version:
            return [v.strip() for v in version.split(",")]
        return version.split()

    groups = [PySpecSet()]
    for marker in markers:
        if isinstance(marker, list):
            # It is a submarker
            groups[-1] = groups[-1] & _build_pyspec_from_marker(marker)
        elif isinstance(marker, tuple):
            key, op, version = [i.value for i in marker]
            if key == "python_version":
                if op == ">":
                    int_versions = [int(ver) for ver in version.split(".")]
                    int_versions[-1] += 1
                    version = ".".join(str(v) for v in int_versions)
                    op = ">="
                elif op in ("==", "!="):
                    if len(version.split(".")) < 3:
                        version += ".*"
                elif op in ("in", "not in"):
                    version = " ".join(v + ".*"
                                       for v in split_version(version))
            if op == "in":
                pyspec = reduce(operator.or_,
                                (PySpecSet(f"=={v}")
                                 for v in split_version(version)))
            elif op == "not in":
                pyspec = reduce(operator.and_,
                                (PySpecSet(f"!={v}")
                                 for v in split_version(version)))
            else:
                pyspec = PySpecSet(f"{op}{version}")
            groups[-1] = groups[-1] & pyspec
        else:
            assert marker in ("and", "or")
            if marker == "or":
                groups.append(PySpecSet())
    return reduce(operator.or_, groups)
コード例 #18
0
ファイル: requirements.py プロジェクト: shalevy1/pdm
 def __init__(self, **kwargs):
     self._marker = None
     self.from_section = "default"
     self.marker_no_python = None  # type: Optional[Marker]
     self.requires_python = PySpecSet()  # type: PySpecSet
     for k, v in kwargs.items():
         if k == "specifier":
             v = get_specifier(v)
         setattr(self, k, v)
     if self.name and not self.project_name:
         self.project_name = safe_name(self.name)
         self.key = self.project_name.lower()
コード例 #19
0
ファイル: core.py プロジェクト: LouisStAmour/pdm
 def environment(self) -> Environment:
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(
             "==" + get_python_version(self.python_executable, True)[0])
         return env
     if self.config["use_venv"] and is_venv_python(self.python_executable):
         # Only recognize venv created by python -m venv and virtualenv>20
         return GlobalEnvironment(self)
     return Environment(self)
コード例 #20
0
 def get_environment(self) -> Environment:
     """Get the environment selected by this project"""
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(f"=={self.python.version}")
         return env
     if self.config["use_venv"] and is_venv_python(self.python.executable):
         # Only recognize venv created by python -m venv and virtualenv>20
         return GlobalEnvironment(self)
     return Environment(self)
コード例 #21
0
ファイル: test_actions.py プロジェクト: ulwlu/pdm
def test_remove_both_normal_and_editable_packages(project, is_dev):
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(project, is_dev, packages=["demo"])
    actions.do_add(
        project,
        is_dev,
        editables=["git+https://github.com/test-root/demo.git#egg=demo"],
    )
    section = "dev-dependencies" if is_dev else "dependencies"
    actions.do_remove(project, is_dev, packages=["demo"])
    assert not project.meta[section]
    assert "demo" not in project.get_locked_candidates(
        "dev" if is_dev else "default")
コード例 #22
0
def test_add_package_unconstrained_rewrite_specifier(project):
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(project, packages=["django"], no_self=True)
    locked_candidates = project.locked_repository.all_candidates
    assert locked_candidates["django"].version == "2.2.9"
    assert project.meta.dependencies[0] == "django~=2.2"

    actions.do_add(
        project, packages=["django-toolbar"], no_self=True, unconstrained=True
    )
    locked_candidates = project.locked_repository.all_candidates
    assert locked_candidates["django"].version == "1.11.8"
    assert project.meta.dependencies[0] == "django~=1.11"
コード例 #23
0
ファイル: test_actions.py プロジェクト: pi-dal/pdm
def test_remove_both_normal_and_editable_packages(project, is_dev):
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(project, is_dev, packages=["demo"])
    actions.do_add(
        project,
        is_dev,
        editables=["git+https://github.com/test-root/demo.git#egg=demo"],
    )
    section = (project.tool_settings["dev-dependencies"]["dev"]
               if is_dev else project.meta["dependencies"])
    actions.do_remove(project, is_dev, packages=["demo"])
    assert not section
    assert "demo" not in project.locked_repository.all_candidates
コード例 #24
0
 def environment(self) -> Environment:
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(
             "==" + get_python_version(env.python_executable, True))
         return env
     if self.config["use_venv"]:
         venv_python = get_venv_python(self.root)
         if venv_python:
             self.project_config["python.path"] = venv_python
             return GlobalEnvironment(self)
     return Environment(self)
コード例 #25
0
ファイル: repositories.py プロジェクト: leibowitz/pdm
 def find_candidates(
     self,
     requirement: Requirement,
     requires_python: PySpecSet = ALLOW_ALL_PYTHON,
     allow_prereleases: Optional[bool] = None,
     allow_all: bool = False,
 ) -> Iterable[Candidate]:
     for key, info in self.candidate_info.items():
         if key[0] != requirement.identify():
             continue
         if not (requires_python & PySpecSet(info[1])).contains(
                 str(self.environment.interpreter.version)):
             continue
         can = self.packages[key]
         can.requires_python = info[1]
         yield can
コード例 #26
0
def test_add_remote_package_url(project, is_dev):
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(
        project,
        is_dev,
        packages=["http://fixtures.test/artifacts/demo-0.0.1-py2.py3-none-any.whl"],
    )
    group = (
        project.tool_settings["dev-dependencies"]["dev"]
        if is_dev
        else project.meta["dependencies"]
    )
    assert (
        group[0]
        == "demo @ http://fixtures.test/artifacts/demo-0.0.1-py2.py3-none-any.whl"
    )
コード例 #27
0
def test_add_cached_vcs_requirement(project, mocker):
    project.environment.python_requires = PySpecSet(">=3.6")
    url = "git+https://github.com/test-root/demo.git@1234567890abcdef#egg=demo"
    built_path = FIXTURES / "artifacts/demo-0.0.1-py2.py3-none-any.whl"
    wheel_cache = project.make_wheel_cache()
    cache_path = Path(wheel_cache.get_path_for_link(Link(url)))
    if not cache_path.exists():
        cache_path.mkdir(parents=True)
    shutil.copy2(built_path, cache_path)
    downloader = mocker.patch("pdm.models.pip_shims.unpack_url")
    builder = mocker.patch("pdm.builders.WheelBuilder.build")
    actions.do_add(project, packages=[url], no_self=True)
    lockfile_entry = next(p for p in project.lockfile["package"] if p["name"] == "demo")
    assert lockfile_entry["revision"] == "1234567890abcdef"
    downloader.assert_not_called()
    builder.assert_not_called()
コード例 #28
0
 def find_candidates(
     self,
     requirement: Requirement,
     allow_prereleases: bool | None = None,
     ignore_requires_python: bool = False,
 ) -> Iterable[Candidate]:
     for key, info in self.candidate_info.items():
         if key[0] != requirement.identify():
             continue
         if not PySpecSet(info[1]).contains(
             str(self.environment.interpreter.version), True
         ):
             continue
         can = self.packages[key]
         can.requires_python = info[1]
         can.prepare(self.environment)
         can.req = requirement
         yield can
コード例 #29
0
ファイル: test_actions.py プロジェクト: ulwlu/pdm
def test_add_editable_package(project, working_set, is_dev):
    # Ensure that correct python version is used.
    project.environment.python_requires = PySpecSet(">=3.6")
    actions.do_add(project, is_dev, packages=["demo"])
    actions.do_add(
        project,
        is_dev,
        editables=["git+https://github.com/test-root/demo.git#egg=demo"],
    )
    section = "dev-dependencies" if is_dev else "dependencies"
    assert "demo" in project.meta[section][0]
    assert ("-e git+https://github.com/test-root/demo.git#egg=demo"
            in project.meta[section][1])
    locked_candidates = project.get_locked_candidates(
        "dev" if is_dev else "default")
    assert locked_candidates["demo"].revision == "1234567890abcdef"
    assert locked_candidates["idna"].version == "2.7"
    assert "idna" in working_set
コード例 #30
0
 def get_environment(self) -> Environment:
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(f"=={self.python.version}")
         return env
     if self.config["python.use_venv"]:
         if self.project_config.get("python.path") and not os.getenv(
                 "PDM_IGNORE_SAVED_PYTHON"):
             return (GlobalEnvironment(self) if is_venv_python(
                 self.python.executable) else Environment(self))
         if os.getenv("VIRTUAL_ENV"):
             venv = os.getenv("VIRTUAL_ENV")
             self.core.ui.echo(
                 f"Detected inside an active virtualenv {termui.green(venv)}, "
                 "reuse it.")
             # Temporary usage, do not save in .pdm.toml
             self._python = PythonInfo.from_path(get_venv_python(
                 Path(venv)))
             return GlobalEnvironment(self)
         existing_venv = next((venv for _, venv in iter_venvs(self)), None)
         if existing_venv:
             self.core.ui.echo(
                 f"Virtualenv {termui.green(str(existing_venv))} is reused.",
                 err=True,
             )
             path = existing_venv
         else:
             # Create a virtualenv using the selected Python interpreter
             self.core.ui.echo(
                 "python.use_venv is on, creating a virtualenv for this project...",
                 fg="yellow",
                 err=True,
             )
             backend: str = self.config["venv.backend"]
             venv_backend = BACKENDS[backend](self, None)
             path = venv_backend.create(None, (), False,
                                        self.config["venv.in_project"])
             self.core.ui.echo(f"Virtualenv {path} is created successfully")
         self.python = PythonInfo.from_path(get_venv_python(path))
         return GlobalEnvironment(self)
     else:
         return Environment(self)