未验证 提交 124340af 编写于 作者: F Frost Ming 提交者: GitHub

Merge pull request #114 from frostming/feature/show

New command: show
Add `show` command to show package metadata.
......@@ -59,7 +59,7 @@ class Command(BaseCommand):
"""Search for PyPI packages"""
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument("query")
parser.add_argument("query", help="Query string to search")
def handle(self, project: Project, options: argparse.Namespace) -> None:
result = project.get_repository().search(options.query)
......
import argparse
from 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.requirements import parse_requirement
from pdm.project import Project
def normalize_package(name):
return safe_name(name).lower()
def filter_stable(candidate: Candidate) -> bool:
return not candidate.version.is_prerelease
class Command(BaseCommand):
"""Show the package information"""
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument(
"package", type=normalize_package, help="Specify the package name",
)
def handle(self, project: Project, options: argparse.Namespace) -> None:
package = options.package
req = parse_requirement(package)
repository = project.get_repository()
# reverse the result so that latest is at first.
matches = repository.find_matches(
req, project.environment.python_requires, True
)[::-1]
latest = next(iter(matches))
latest_stable = next(filter(filter_stable, matches), None)
installed = project.environment.get_working_set().get(package)
metadata = latest.get_metadata()
if metadata._legacy:
result = Metadata(dict(metadata._legacy.items()), True)
else:
result = Metadata(dict(metadata._data), False)
if latest_stable:
result.latest_stable_version = str(latest_stable.version)
if installed:
result.installed_version = str(installed.version)
stream.display_columns(list(result.generate_rows()))
from typing import Dict, Iterator, List, Tuple, Union
from pdm.iostream import stream
class Metadata:
def __init__(self, data: Dict[str, Union[str, List[str]]], legacy: bool) -> None:
self._data = data
self.legacy = legacy
self.latest_stable_version = ""
self.installed_version = ""
def generate_rows(self) -> Iterator[Tuple[str, str]]:
if self.legacy:
yield from self._legacy_generate_rows()
return
yield stream.cyan("Name:"), self._data["name"]
yield stream.cyan("Latest version:"), self._data["version"]
if self.latest_stable_version:
yield (stream.cyan("Latest stable version:"), self.latest_stable_version)
if self.installed_version:
yield (stream.green("Installed version:"), self.installed_version)
yield stream.cyan("Summary:"), self._data.get("summary", "")
contacts = (
self._data.get("extensions", {}).get("python.details", {}).get("contacts")
)
if contacts:
author_contact = next(
iter(c for c in contacts if c["role"] == "author"), {}
)
yield stream.cyan("Author:"), author_contact.get("name", "")
yield stream.cyan("Author email:"), author_contact.get("email", "")
yield stream.cyan("License:"), self._data.get("license", "")
yield stream.cyan("Homepage:"), self._data.get("extensions", {}).get(
"python.details", {}
).get("project_urls", {}).get("Home", "")
yield stream.cyan("Project URLs:"), self._data.get("project_url", "")
yield stream.cyan("Platform:"), self._data.get("platform", "")
yield stream.cyan("Keywords:"), ", ".join(self._data.get("keywords", []))
def _legacy_generate_rows(self) -> Iterator[Tuple[str, str]]:
yield stream.cyan("Name:"), self._data["Name"]
yield stream.cyan("Latest version:"), self._data["Version"]
if self.latest_stable_version:
yield (stream.cyan("Latest stable version:"), self.latest_stable_version)
if self.installed_version:
yield (stream.green("Installed version:"), self.installed_version)
yield stream.cyan("Summary:"), self._data.get("Summary", "")
yield stream.cyan("Author:"), self._data.get("Author", "")
yield stream.cyan("Author email:"), self._data.get("Author-email", "")
yield stream.cyan("License:"), self._data.get("License", "")
yield stream.cyan("Homepage:"), self._data.get("Home-page", "")
if self._data.get("Project-URL"):
lines = [":".join(parts) for parts in self._data.get("Project-URL")]
yield stream.cyan("Project URLs:"), lines[0]
for line in lines[1:]:
yield "", line
yield stream.cyan("Platform:"), ", ".join(self._data.get("Platform", []))
yield stream.cyan("Keywords:"), ", ".join(self._data.get("Keywords", []))
......@@ -264,3 +264,13 @@ def test_search_package(project, invoke):
result = invoke(["search", "requests"], obj=project)
assert result.exit_code == 0
assert len(result.output.splitlines()) > 0
def test_show_package_on_pypi(invoke):
result = invoke(["show", "ipython"])
assert result.exit_code == 0
assert "ipython" in result.output.splitlines()[0]
result = invoke(["show", "requests"])
assert result.exit_code == 0
assert "requests" in result.output.splitlines()[0]
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册