未验证 提交 d4ca501f 编写于 作者: F Frost Ming

reuse cached wheels

上级 ec8d0023
Reuse the cached built wheels to accelerate the installation.
......@@ -18,7 +18,7 @@ from pdm.cli.utils import (
)
from pdm.exceptions import NoPythonVersion, PdmUsageError, ProjectError
from pdm.formats import FORMATS
from pdm.formats.base import array_of_inline_tables
from pdm.formats.base import array_of_inline_tables, make_inline_table
from pdm.installers.installers import format_dist
from pdm.iostream import LOCK, stream
from pdm.models.builders import EnvBuilder
......@@ -362,24 +362,22 @@ def do_init(
python_requires: str = "",
) -> None:
"""Bootstrap the project and create a pyproject.toml"""
import tomlkit
data = {
"project": {
"name": name,
"version": version,
"description": "",
"authors": array_of_inline_tables([{"name": author, "email": email}]),
"license": tomlkit.inline_table({"text": license}),
"license": make_inline_table({"text": license}),
"urls": {"homepage": ""},
"dependencies": [],
"dev-dependencies": [],
"requires-python": python_requires,
},
"build-system": {"requires": ["pdm-pep517"], "build-backend": "pdm.pep517.api"},
}
if python_requires and python_requires != "*":
get_specifier(python_requires)
data["requires-python"] = python_requires
if not project.pyproject:
project._pyproject = data
else:
......
......@@ -5,7 +5,7 @@ from pip._vendor.pkg_resources import safe_name
from pdm.cli.commands.base import BaseCommand
from pdm.iostream import stream
from pdm.models.candidates import Candidate
from pdm.models.metadata import Metadata
from pdm.models.project_info import ProjectInfo
from pdm.models.requirements import parse_requirement
from pdm.project import Project
......@@ -43,9 +43,9 @@ class Command(BaseCommand):
metadata = latest.get_metadata()
if metadata._legacy:
result = Metadata(dict(metadata._legacy.items()), True)
result = ProjectInfo(dict(metadata._legacy.items()), True)
else:
result = Metadata(dict(metadata._data), False)
result = ProjectInfo(dict(metadata._data), False)
if latest_stable:
result.latest_stable_version = str(latest_stable.version)
if installed:
......
......@@ -13,6 +13,7 @@ from resolvelib.structs import DirectedGraph
from pdm.exceptions import ProjectError
from pdm.formats import FORMATS
from pdm.formats.base import make_inline_table
from pdm.iostream import stream
from pdm.models.environment import WorkingSet
from pdm.models.requirements import Requirement, strip_extras
......@@ -332,9 +333,7 @@ def format_lockfile(mapping, fetched_dependencies, summary_collection):
for r in fetched_dependencies[k].values():
name, req = r.as_req_dict()
if getattr(req, "items", None) is not None:
inline = tomlkit.inline_table()
inline.update(req)
deps.add(name, inline)
deps.add(name, make_inline_table(req))
else:
deps.add(name, req)
if len(deps) > 0:
......@@ -345,8 +344,7 @@ def format_lockfile(mapping, fetched_dependencies, summary_collection):
array = tomlkit.array()
array.multiline(True)
for filename, hash_value in v.hashes.items():
inline = tomlkit.inline_table()
inline.update({"file": filename, "hash": hash_value})
inline = make_inline_table({"file": filename, "hash": hash_value})
array.append(inline)
if array:
file_hashes.add(key, array)
......
......@@ -79,13 +79,18 @@ class MetaConverter(collections.abc.Mapping, metaclass=_MetaConverterMeta):
NAME_EMAIL_RE = re.compile(r"(?P<name>[^,]+?)\s*<(?P<email>.+)>\s*$")
def make_inline_table(data):
"""Create an inline table from the given data."""
table = tomlkit.inline_table()
table.update(data)
return table
def array_of_inline_tables(value, multiline=True):
container = tomlkit.array()
container.multiline(multiline)
for item in value:
table = tomlkit.inline_table()
table.update(item)
container.append(table)
container.append(make_inline_table(item))
return container
......
......@@ -4,7 +4,7 @@ from pathlib import Path
import tomlkit
import tomlkit.exceptions
from pdm.formats.base import MetaConverter, convert_from
from pdm.formats.base import MetaConverter, convert_from, make_inline_table
def check_fingerprint(project, filename):
......@@ -46,7 +46,7 @@ class FlitMetaConverter(MetaConverter):
if "maintainer" in metadata:
self._data["maintainers"] = _get_author(metadata, "maintainer")
if "license" in metadata:
self._data["license"] = {"text", metadata.pop("license")}
self._data["license"] = make_inline_table({"text", metadata.pop("license")})
if "urls" in metadata:
self._data["urls"] = metadata.pop("urls")
if "home-page" in metadata:
......
......@@ -3,7 +3,13 @@ import functools
import tomlkit
import tomlkit.exceptions
from pdm.formats.base import MetaConverter, Unset, convert_from, parse_name_email
from pdm.formats.base import (
MetaConverter,
Unset,
convert_from,
make_inline_table,
parse_name_email,
)
from pdm.models.requirements import Requirement
......@@ -38,9 +44,7 @@ class LegacyMetaConverter(MetaConverter):
@convert_from("license")
def license(self, value):
table = tomlkit.inline_table()
table["text"] = value
return table
return make_inline_table({"text": value})
@convert_from("source")
def source(self, value):
......
......@@ -5,7 +5,13 @@ import re
import tomlkit
import tomlkit.exceptions
from pdm.formats.base import MetaConverter, Unset, convert_from, parse_name_email
from pdm.formats.base import (
MetaConverter,
Unset,
convert_from,
make_inline_table,
parse_name_email,
)
from pdm.models.markers import Marker
from pdm.models.requirements import Requirement
from pdm.models.specifiers import PySpecSet
......@@ -82,7 +88,7 @@ class PoetryMetaConverter(MetaConverter):
@convert_from("license")
def license(self, value):
return {"text": value}
return make_inline_table({"text": value})
@convert_from(name="requires-python")
def requires_python(self, source):
......
......@@ -313,10 +313,26 @@ class Environment:
shutil.copy(downloaded.path, download_dir)
except shutil.SameFileError:
pass
# Now all source is prepared, build it.
if ireq.link.is_wheel:
# If the file is a wheel, should be already present under download dir.
return (self.project.cache("wheels") / ireq.link.filename).as_posix()
else:
# Check the built wheel cache again after hashes are resolved.
cache_entry = wheel_cache.get_cache_entry(
ireq.link,
ireq.req.project_name,
pip_shims.get_supported(
version="".join(
map(str, get_python_version(self.python_executable)[:2])
)
),
)
if cache_entry is not None:
stream.logger.debug("Using cached wheel link: %s", cache_entry.link)
return cache_entry.link.file_path
# Otherwise, now all source is prepared, build it.
with EnvBuilder(ireq.unpacked_source_directory, self) as builder:
if ireq.editable:
ret = builder.build_egg_info(kwargs["build_dir"])
......
......@@ -3,7 +3,7 @@ from typing import Dict, Iterator, List, Tuple, Union
from pdm.iostream import stream
class Metadata:
class ProjectInfo:
def __init__(self, data: Dict[str, Union[str, List[str]]], legacy: bool) -> None:
self._data = data
self.legacy = legacy
......
......@@ -3,7 +3,7 @@ import re
import urllib.parse as urlparse
import warnings
from pathlib import Path
from typing import Any, Dict, List, Optional, Sequence, Union
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
from pip._vendor.packaging.markers import InvalidMarker
from pip._vendor.pkg_resources import Requirement as PackageRequirement
......@@ -173,6 +173,31 @@ class Requirement:
def as_line(self) -> str:
raise NotImplementedError
def as_req_dict(self) -> Tuple[str, RequirementDict]:
r = {}
if self.editable:
r["editable"] = True
if self.extras:
r["extras"] = sorted(self.extras)
if self.is_vcs:
r[self.vcs] = self.repo
elif self.path and self.is_local_dir:
r["path"] = self.str_path
elif self.url:
r["url"] = self.url
if self.marker:
r["marker"] = str(self.marker).replace('"', "'")
if self.specifier:
r["version"] = str(self.specifier)
elif self.is_named:
r["version"] = "*"
if len(r) == 1 and next(iter(r), None) == "version":
r = r["version"]
for attr in ["index", "allow_prereleases", "ref"]:
if getattr(self, attr) is not None:
r[attr] = getattr(self, attr)
return self.project_name, r
def matches(self, line: str) -> bool:
"""Return whether the passed in PEP 508 string
is the same requirement as this one.
......
......@@ -177,7 +177,7 @@ class Project:
def iter_sections(self) -> Iterable[str]:
if self.meta.dependencies:
yield "default"
if self.meta.dev_dependencies:
if self.meta.get("dev-dependencies"):
yield "dev"
if self.meta.optional_dependencies:
yield from self.meta.optional_dependencies.keys()
......
......@@ -11,7 +11,9 @@ class MutableMetadata(Metadata, MutableMapping):
def __init__(self, filepath, data=None) -> None:
self.filepath = filepath
self._metadata = data or self._read_pyproject(filepath)
if data is None:
data = self._read_pyproject(filepath)
self._metadata = data
def __getitem__(self, k):
return self._metadata[k]
......
......@@ -281,7 +281,7 @@ def test_remove_package_exist_in_multi_section(project, repository, working_set)
actions.do_add(project, packages=["requests"])
actions.do_add(project, dev=True, packages=["urllib3"])
actions.do_remove(project, dev=True, packages=["urllib3"])
assert not any("urllib3" in line for line in project.meta.dev_dependencies)
assert not any("urllib3" in line for line in project.meta["dev-dependencies"])
assert "urllib3" in working_set
assert "requests" in working_set
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册