Exemple #1
0
def do_info(
    project: Project,
    python: bool = False,
    show_project: bool = False,
    env: bool = False,
) -> None:
    """Show project information."""
    check_project_file(project)
    python_path = project.python_executable
    python_version, is_64bit = get_python_version(python_path, True)
    if not python and not show_project and not env:
        rows = [
            (termui.cyan("PDM version:", bold=True), project.core.version),
            (
                termui.cyan("Python Interpreter:", bold=True),
                python_path +
                f" ({get_python_version_string(python_version, is_64bit)})",
            ),
            (termui.cyan("Project Root:", bold=True), project.root.as_posix()),
        ]
        project.core.ui.display_columns(rows)
        return

    if python:
        project.core.ui.echo(python_path)
    if show_project:
        project.core.ui.echo(project.root.as_posix())
    if env:
        project.core.ui.echo(
            json.dumps(project.environment.marker_environment, indent=2))
Exemple #2
0
    def handle(self, project: Project, options: argparse.Namespace) -> None:
        check_project_file(project)
        interpreter = project.python
        if options.python:
            project.core.ui.echo(str(interpreter.executable))
        elif options.where:
            project.core.ui.echo(str(project.root))
        elif options.packages:
            project.core.ui.echo(str(project.environment.packages_path))
        elif options.env:
            project.core.ui.echo(
                json.dumps(project.environment.marker_environment, indent=2))
        else:

            rows = [
                (termui.cyan("PDM version:", bold=True), project.core.version),
                (
                    termui.cyan("Python Interpreter:", bold=True),
                    f"{interpreter.executable} ({interpreter.identifier})",
                ),
                (termui.cyan("Project Root:",
                             bold=True), project.root.as_posix()),
                (
                    termui.cyan("Project Packages:", bold=True),
                    str(project.environment.packages_path),
                ),
            ]
            project.core.ui.display_columns(rows)
Exemple #3
0
    def handle(self, project: Project, options: argparse.Namespace) -> None:
        if project.pyproject_file.exists():
            project.core.ui.echo("{}".format(
                termui.cyan("pyproject.toml already exists, update it now.")))
        else:
            project.core.ui.echo("{}".format(
                termui.cyan("Creating a pyproject.toml for PDM...")))
        non_interactive = options.non_interactive
        if non_interactive:
            actions.do_use(project, "3", True)
        else:
            actions.do_use(project)
        is_library = (False if non_interactive else click.confirm(
            "Is the project a library that will be upload to PyPI?", ))
        if is_library:
            name = self.ask("Project name", project.root.name, non_interactive)
            version = self.ask("Project version", "0.1.0", non_interactive)
        else:
            name, version = "", ""
        license = self.ask("License(SPDX name)", "MIT", non_interactive)

        git_user, git_email = get_user_email_from_git()
        author = self.ask("Author name", git_user, non_interactive)
        email = self.ask("Author email", git_email, non_interactive)
        python_version = f"{project.python.major}.{project.python.minor}"
        python_requires = self.ask("Python requires('*' to allow any)",
                                   f">={python_version}", non_interactive)

        actions.do_init(project, name, version, license, author, email,
                        python_requires)
        if not non_interactive:
            actions.ask_for_import(project)
Exemple #4
0
    def handle(self, project: Project, options: argparse.Namespace) -> None:
        if project.pyproject_file.exists():
            project.core.ui.echo("{}".format(
                termui.cyan("pyproject.toml already exists, update it now.")))
        else:
            project.core.ui.echo("{}".format(
                termui.cyan("Creating a pyproject.toml for PDM...")))
        actions.do_use(project)
        is_library = click.confirm(
            "Is the project a library that will be upload to PyPI?", )
        if is_library:
            name = click.prompt("Project name", default=project.root.name)
            version = click.prompt("Project version", default="0.1.0")
        else:
            name, version = "", ""
        license = click.prompt("License(SPDX name)", default="MIT")

        git_user, git_email = get_user_email_from_git()
        author = click.prompt("Author name", default=git_user)
        email = click.prompt("Author email", default=git_email)
        python_version, _ = get_python_version(project.python_executable, True,
                                               2)
        python_requires = click.prompt("Python requires('*' to allow any)",
                                       default=f">={python_version}")

        actions.do_init(project, name, version, license, author, email,
                        python_requires)
        actions.ask_for_import(project)
Exemple #5
0
def ask_for_import(project: Project) -> None:
    """Show possible importable files and ask user to decide"""
    importable_files = list(find_importable_files(project))
    if not importable_files:
        return
    project.core.ui.echo(
        termui.cyan("Found following files from other formats that you may import:")
    )
    for i, (key, filepath) in enumerate(importable_files):
        project.core.ui.echo(f"{i}. {termui.green(filepath.as_posix())} ({key})")
    project.core.ui.echo(
        "{}. {}".format(
            len(importable_files),
            termui.yellow("don't do anything, I will import later."),
        )
    )
    choice = click.prompt(
        "Please select:",
        type=click.Choice([str(i) for i in range(len(importable_files) + 1)]),
        show_default=False,
    )
    if int(choice) == len(importable_files):
        return
    key, filepath = importable_files[int(choice)]
    do_import(project, str(filepath), key)
Exemple #6
0
def do_use(project: Project,
           python: Optional[str] = "",
           first: Optional[bool] = False) -> None:
    """Use the specified python version and save in project config.
    The python can be a version string or interpreter path.
    """
    def version_matcher(py_version):
        return project.python_requires.contains(str(py_version.version))

    python = python.strip()

    found_interpreters = list(
        dict.fromkeys(
            filter(version_matcher, project.find_interpreters(python))))
    if not found_interpreters:
        raise NoPythonVersion("Python interpreter is not found on the system.")
    if first or len(found_interpreters) == 1:
        selected_python = found_interpreters[0]
    else:
        project.core.ui.echo("Please enter the Python interpreter to use")
        for i, py_version in enumerate(found_interpreters):
            python_version = str(py_version.version)
            is_64bit = py_version.get_architecture() == "64bit"
            version_string = get_python_version_string(python_version,
                                                       is_64bit)
            project.core.ui.echo(
                f"{i}. {termui.green(py_version.executable)} ({version_string})"
            )
        selection = click.prompt(
            "Please select:",
            type=click.Choice([str(i)
                               for i in range(len(found_interpreters))]),
            default="0",
            show_choices=False,
        )
        selected_python = found_interpreters[int(selection)]

    old_path = project.config.get("python.path")
    new_path = selected_python.executable
    python_version = str(selected_python.version)
    is_64bit = selected_python.get_architecture() == "64bit"
    project.core.ui.echo("Using Python interpreter: {} ({})".format(
        termui.green(str(new_path)),
        get_python_version_string(python_version, is_64bit),
    ))
    project.python_executable = new_path
    if old_path and Path(old_path) != Path(new_path) and not project.is_global:
        project.core.ui.echo(termui.cyan("Updating executable scripts..."))
        project.environment.update_shebangs(new_path)
Exemple #7
0
    def _format_action(self, action: Action) -> str:
        # determine the required width and the entry label
        help_position = min(self._action_max_length + 2,
                            self._max_help_position)
        help_width = max(self._width - help_position, 11)
        action_width = help_position - self._current_indent - 2
        action_header = self._format_action_invocation(action)

        # no help; start on same line and add a final newline
        if not action.help:
            tup = self._current_indent, "", action_header
            action_header = "%*s%s\n" % tup

        # short action name; start on the same line and pad two spaces
        elif len(action_header) <= action_width:
            tup = self._current_indent, "", action_width, action_header  # type: ignore
            action_header = "%*s%-*s  " % tup  # type: ignore
            indent_first = 0

        # long action name; start on the next line
        else:
            tup = self._current_indent, "", action_header  # type: ignore
            action_header = "%*s%s\n" % tup
            indent_first = help_position

        # collect the pieces of the action help
        parts = [termui.cyan(action_header)]

        # if there was help for the action, add lines of help text
        if action.help:
            help_text = self._expand_help(action)
            help_lines = self._split_lines(help_text, help_width)
            parts.append("%*s%s\n" % (indent_first, "", help_lines[0]))
            for line in help_lines[1:]:
                parts.append("%*s%s\n" % (help_position, "", line))

        # or add a newline if the description doesn't end with one
        elif not action_header.endswith("\n"):
            parts.append("\n")

        # if there are any sub-actions, add their help as well
        for subaction in self._iter_indented_subactions(action):
            parts.append(self._format_action(subaction))

        # return a single string
        return self._join_parts(parts)
Exemple #8
0
def do_use(project: Project, python: str = "", first: bool = False) -> None:
    """Use the specified python version and save in project config.
    The python can be a version string or interpreter path.
    """
    def version_matcher(py_version: PythonInfo) -> bool:
        return project.python_requires.contains(str(py_version.version))

    if python:
        python = python.strip()

    found_interpreters = list(
        dict.fromkeys(
            filter(version_matcher, project.find_interpreters(python))))
    if not found_interpreters:
        raise NoPythonVersion("Python interpreter is not found on the system.")
    if first or len(found_interpreters) == 1:
        selected_python = found_interpreters[0]
    else:
        project.core.ui.echo("Please enter the Python interpreter to use")
        for i, py_version in enumerate(found_interpreters):
            project.core.ui.echo(
                f"{i}. {termui.green(py_version.executable)} ({py_version.identifier})"
            )
        selection = click.prompt(
            "Please select:",
            type=click.Choice([str(i)
                               for i in range(len(found_interpreters))]),
            default="0",
            show_choices=False,
        )
        selected_python = found_interpreters[int(selection)]

    old_path = project.python.executable if "python.path" in project.config else None
    new_path = selected_python.executable
    project.core.ui.echo("Using Python interpreter: {} ({})".format(
        termui.green(str(new_path)),
        selected_python.identifier,
    ))
    project.python = selected_python
    if (old_path and Path(old_path) != Path(new_path)
            and not project.environment.is_global):
        project.core.ui.echo(termui.cyan("Updating executable scripts..."))
        project.environment.update_shebangs(old_path, new_path)
Exemple #9
0
def do_use(
    project: Project,
    python: str = "",
    first: bool = False,
    ignore_remembered: bool = False,
) -> None:
    """Use the specified python version and save in project config.
    The python can be a version string or interpreter path.
    """
    if python:
        python = python.strip()

    def version_matcher(py_version: PythonInfo) -> bool:
        return project.python_requires.contains(str(py_version.version), True)

    if not project.cache_dir.exists():
        project.cache_dir.mkdir(parents=True)
    use_cache: JSONFileCache[str, str] = JSONFileCache(
        project.cache_dir / "use_cache.json"
    )
    selected_python: PythonInfo | None = None
    if python and not ignore_remembered:
        if use_cache.has_key(python):
            path = use_cache.get(python)
            cached_python = PythonInfo.from_path(path)
            if not cached_python.valid:
                project.core.ui.echo(
                    f"The last selection is corrupted. {path!r}",
                    fg="red",
                    err=True,
                )
            elif version_matcher(cached_python):
                project.core.ui.echo(
                    "Using the last selection, add '-i' to ignore it.",
                    fg="yellow",
                    err=True,
                )
                selected_python = cached_python

    if selected_python is None:
        found_interpreters = list(dict.fromkeys(project.find_interpreters(python)))
        matching_interperters = list(filter(version_matcher, found_interpreters))
        if not found_interpreters:
            raise NoPythonVersion("Python interpreter is not found on the system.")
        if not matching_interperters:
            project.core.ui.echo("Interpreters found but not matching:", err=True)
            for py in found_interpreters:
                project.core.ui.echo(f"  - {py.executable} ({py.identifier})", err=True)
            raise NoPythonVersion(
                "No python is found meeting the requirement "
                f"{termui.green('python' + str(project.python_requires))}"
            )
        if first or len(matching_interperters) == 1:
            selected_python = matching_interperters[0]
        else:
            project.core.ui.echo("Please enter the Python interpreter to use")
            for i, py_version in enumerate(matching_interperters):
                project.core.ui.echo(
                    f"{i}. {termui.green(str(py_version.executable))} "
                    f"({py_version.identifier})"
                )
            selection = click.prompt(
                "Please select:",
                type=click.Choice([str(i) for i in range(len(matching_interperters))]),
                default="0",
                show_choices=False,
            )
            selected_python = matching_interperters[int(selection)]
        if python:
            use_cache.set(python, selected_python.path.as_posix())

    if not selected_python.valid:
        path = str(selected_python.executable)
        raise InvalidPyVersion(f"Invalid Python interpreter: {path}")

    old_python = project.python if "python.path" in project.config else None
    project.core.ui.echo(
        "Using Python interpreter: {} ({})".format(
            termui.green(str(selected_python.executable)),
            selected_python.identifier,
        )
    )
    project.python = selected_python
    if (
        old_python
        and old_python.path != selected_python.path
        and not project.environment.is_global
    ):
        project.core.ui.echo(termui.cyan("Updating executable scripts..."))
        project.environment.update_shebangs(selected_python.executable.as_posix())
Exemple #10
0
 def generate_rows(self) -> Iterator[tuple[str, str]]:
     yield termui.cyan("Name:"), self._parsed["name"]
     yield termui.cyan("Latest version:"), self._parsed["version"]
     if self.latest_stable_version:
         yield (termui.cyan("Latest stable version:"),
                self.latest_stable_version)
     if self.installed_version:
         yield (termui.green("Installed version:"), self.installed_version)
     yield termui.cyan("Summary:"), self._parsed.get("summary", "")
     yield termui.cyan("Requires Python:"), self._parsed["requires-python"]
     yield termui.cyan("Author:"), self._parsed.get("author", "")
     yield termui.cyan("Author email:"), self._parsed.get("email", "")
     yield termui.cyan("License:"), self._parsed.get("license", "")
     yield termui.cyan("Homepage:"), self._parsed.get("homepage", "")
     yield from itertools.zip_longest(
         (termui.cyan("Project URLs:"), ),
         self._parsed.get("project-urls", []),
         fillvalue="",
     )
     yield termui.cyan("Platform:"), self._parsed.get("platform", "")
     yield termui.cyan("Keywords:"), self._parsed.get("keywords", "")
Exemple #11
0
 def _legacy_generate_rows(self) -> Iterator[Tuple[str, str]]:
     yield termui.cyan("Name:"), self._data["Name"]
     yield termui.cyan("Latest version:"), self._data["Version"]
     if self.latest_stable_version:
         yield (termui.cyan("Latest stable version:"),
                self.latest_stable_version)
     if self.installed_version:
         yield (termui.green("Installed version:"), self.installed_version)
     yield termui.cyan("Summary:"), self._data.get("Summary", "")
     yield termui.cyan("Author:"), self._data.get("Author", "")
     yield termui.cyan("Author email:"), self._data.get("Author-email", "")
     yield termui.cyan("License:"), self._data.get("License", "")
     yield termui.cyan("Requires python:"), self._data.get(
         "Requires-Python", "")
     yield termui.cyan("Platform:"), ", ".join(
         self._data.get("Platform", []))
     yield termui.cyan("Keywords:"), ", ".join(
         self._data.get("Keywords", []))
     yield termui.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 termui.cyan("Project URLs:"), lines[0]
         for line in lines[1:]:
             yield "", line
Exemple #12
0
 def generate_rows(self) -> Iterator[Tuple[str, str]]:
     if self.legacy:
         yield from self._legacy_generate_rows()
         return
     yield termui.cyan("Name:"), self._data["name"]
     yield termui.cyan("Latest version:"), self._data["version"]
     if self.latest_stable_version:
         yield (termui.cyan("Latest stable version:"),
                self.latest_stable_version)
     if self.installed_version:
         yield (termui.green("Installed version:"), self.installed_version)
     yield termui.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 termui.cyan("Author:"), author_contact.get("name", "")
         yield termui.cyan("Author email:"), author_contact.get("email", "")
     yield termui.cyan("License:"), self._data.get("license", "")
     yield termui.cyan("Homepage:"), self._data.get("extensions", {}).get(
         "python.details", {}).get("project_urls", {}).get("Home", "")
     yield termui.cyan("Project URLs:"), self._data.get("project_url", "")
     yield termui.cyan("Platform:"), self._data.get("platform", "")
     yield termui.cyan("Keywords:"), ", ".join(
         self._data.get("keywords", []))