Commit 14b7f1ee by David Hotham Committed by GitHub

Cleo 2.0 (#7070)

parent ba97fea0
......@@ -51,8 +51,8 @@ poetry-core = "^1.3.2"
poetry-plugin-export = "^1.2.0"
"backports.cached-property" = { version = "^1.0.2", python = "<3.8" }
cachecontrol = { version = "^0.12.9", extras = ["filecache"] }
cleo = "^1.0.0a5"
crashtest = "^0.3.0"
cleo = "^2.0.0"
crashtest = "^0.4.1"
dulwich = "^0.20.46"
filelock = "^3.8.0"
html5lib = "^1.0"
......@@ -168,9 +168,6 @@ warn_unused_ignores = false
[[tool.mypy.overrides]]
module = [
'cachecontrol.*',
'cachy.*',
'cleo.*',
'crashtest.*',
'lockfile.*',
'pexpect.*',
'pkginfo.*',
......
......@@ -6,13 +6,13 @@ import re
from contextlib import suppress
from importlib import import_module
from typing import TYPE_CHECKING
from typing import Any
from typing import cast
from cleo.application import Application as BaseApplication
from cleo.events.console_command_event import ConsoleCommandEvent
from cleo.events.console_events import COMMAND
from cleo.events.event_dispatcher import EventDispatcher
from cleo.exceptions import CleoException
from cleo.exceptions import CleoError
from cleo.formatters.style import Style
from cleo.io.null_io import NullIO
......@@ -24,7 +24,7 @@ from poetry.console.commands.command import Command
if TYPE_CHECKING:
from collections.abc import Callable
from cleo.events.console_command_event import ConsoleCommandEvent
from cleo.events.event import Event
from cleo.io.inputs.argv_input import ArgvInput
from cleo.io.inputs.definition import Definition
from cleo.io.inputs.input import Input
......@@ -93,7 +93,7 @@ COMMANDS = [
]
class Application(BaseApplication): # type: ignore[misc]
class Application(BaseApplication):
def __init__(self) -> None:
super().__init__("poetry", __version__)
......@@ -137,8 +137,8 @@ class Application(BaseApplication): # type: ignore[misc]
@property
def command_loader(self) -> CommandLoader:
command_loader: CommandLoader | None = self._command_loader
assert command_loader is not None
command_loader = self._command_loader
assert isinstance(command_loader, CommandLoader)
return command_loader
def reset_poetry(self) -> None:
......@@ -194,7 +194,7 @@ class Application(BaseApplication): # type: ignore[misc]
# We need to check if the command being run
# is the "run" command.
definition = self.definition
with suppress(CleoException):
with suppress(CleoError):
io.input.bind(definition)
name = io.input.first_argument
......@@ -215,7 +215,7 @@ class Application(BaseApplication): # type: ignore[misc]
for shortcut in shortcuts:
run_input.add_parameter_option("-" + shortcut.lstrip("-"))
with suppress(CleoException):
with suppress(CleoError):
run_input.bind(definition)
for option_name, value in input.options.items():
......@@ -227,12 +227,13 @@ class Application(BaseApplication): # type: ignore[misc]
super()._configure_io(io)
def register_command_loggers(
self, event: ConsoleCommandEvent, event_name: str, _: Any
self, event: Event, event_name: str, _: EventDispatcher
) -> None:
from poetry.console.logging.filters import POETRY_FILTER
from poetry.console.logging.io_formatter import IOFormatter
from poetry.console.logging.io_handler import IOHandler
assert isinstance(event, ConsoleCommandEvent)
command = event.command
if not isinstance(command, Command):
return
......@@ -277,12 +278,11 @@ class Application(BaseApplication): # type: ignore[misc]
logger.setLevel(_level)
def configure_env(
self, event: ConsoleCommandEvent, event_name: str, _: Any
) -> None:
def configure_env(self, event: Event, event_name: str, _: EventDispatcher) -> None:
from poetry.console.commands.env_command import EnvCommand
from poetry.console.commands.self.self_command import SelfCommand
assert isinstance(event, ConsoleCommandEvent)
command = event.command
if not isinstance(command, EnvCommand) or isinstance(command, SelfCommand):
return
......@@ -305,10 +305,11 @@ class Application(BaseApplication): # type: ignore[misc]
@classmethod
def configure_installer_for_event(
cls, event: ConsoleCommandEvent, event_name: str, _: Any
cls, event: Event, event_name: str, _: EventDispatcher
) -> None:
from poetry.console.commands.installer_command import InstallerCommand
assert isinstance(event, ConsoleCommandEvent)
command = event.command
if not isinstance(command, InstallerCommand):
return
......
......@@ -2,7 +2,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from cleo.exceptions import LogicException
from cleo.exceptions import CleoLogicError
from cleo.loaders.factory_command_loader import FactoryCommandLoader
......@@ -12,11 +12,11 @@ if TYPE_CHECKING:
from cleo.commands.command import Command
class CommandLoader(FactoryCommandLoader): # type: ignore[misc]
class CommandLoader(FactoryCommandLoader):
def register_factory(
self, command_name: str, factory: Callable[[], Command]
) -> None:
if command_name in self._factories:
raise LogicException(f'The command "{command_name}" already exists.')
raise CleoLogicError(f'The command "{command_name}" already exists.')
self._factories[command_name] = factory
......@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
from typing import Any
from cleo.commands.command import Command as BaseCommand
from cleo.exceptions import ValueException
from cleo.exceptions import CleoValueError
if TYPE_CHECKING:
......@@ -12,7 +12,7 @@ if TYPE_CHECKING:
from poetry.poetry import Poetry
class Command(BaseCommand): # type: ignore[misc]
class Command(BaseCommand):
loggers: list[str] = []
_poetry: Poetry | None = None
......@@ -28,7 +28,10 @@ class Command(BaseCommand): # type: ignore[misc]
self._poetry = poetry
def get_application(self) -> Application:
application: Application = self.application
from poetry.console.application import Application
application = self.application
assert isinstance(application, Application)
return application
def reset_poetry(self) -> None:
......@@ -37,5 +40,5 @@ class Command(BaseCommand): # type: ignore[misc]
def option(self, name: str, default: Any = None) -> Any:
try:
return super().option(name)
except ValueException:
except CleoValueError:
return default
......@@ -22,7 +22,7 @@ class DebugInfoCommand(Command):
]
)
)
command = self.application.get("env info")
command = self.get_application().get("env info")
exit_code: int = command.run(self.io)
return exit_code
from __future__ import annotations
from typing import TYPE_CHECKING
from cleo.helpers import argument
from cleo.helpers import option
from cleo.io.outputs.output import Verbosity
......@@ -8,6 +10,10 @@ from poetry.console.commands.init import InitCommand
from poetry.console.commands.show import ShowCommand
if TYPE_CHECKING:
from cleo.ui.table import Rows
class DebugResolveCommand(InitCommand):
name = "debug resolve"
description = "Debugs dependency resolution."
......@@ -86,7 +92,7 @@ class DebugResolveCommand(InitCommand):
self.line("")
if self.option("tree"):
show_command = self.application.find("show")
show_command = self.get_application().find("show")
assert isinstance(show_command, ShowCommand)
show_command.init_styles(self.io)
......@@ -103,7 +109,7 @@ class DebugResolveCommand(InitCommand):
table = self.table(style="compact")
table.style.set_vertical_border_chars("", " ")
rows = []
rows: Rows = []
if self.option("install"):
env = EnvManager(self.poetry).get()
......
......@@ -176,7 +176,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
self._determine_requirements(self.option("dependency"))
)
question = "Would you like to define your main dependencies interactively?"
question_text = "Would you like to define your main dependencies interactively?"
help_message = """\
You can specify a package in the following forms:
- A single name (<b>requests</b>): this will search for matches on PyPI
......@@ -190,7 +190,7 @@ You can specify a package in the following forms:
"""
help_displayed = False
if self.confirm(question, True):
if self.confirm(question_text, True):
if self.io.is_interactive():
self.line(help_message)
help_displayed = True
......@@ -206,10 +206,10 @@ You can specify a package in the following forms:
self._determine_requirements(self.option("dev-dependency"))
)
question = (
question_text = (
"Would you like to define your development dependencies interactively?"
)
if self.confirm(question, True):
if self.confirm(question_text, True):
if self.io.is_interactive() and not help_displayed:
self.line(help_message)
......@@ -338,8 +338,8 @@ You can specify a package in the following forms:
"Enter the version constraint to require "
"(or leave blank to use the latest version):"
)
question.attempts = 3
question.validator = lambda x: (x or "").strip() or False
question.set_max_attempts(3)
question.set_validator(lambda x: (x or "").strip() or None)
package_constraint = self.ask(question)
......
......@@ -12,6 +12,7 @@ from poetry.console.commands.group_command import GroupCommand
if TYPE_CHECKING:
from cleo.io.io import IO
from cleo.ui.table import Rows
from packaging.utils import NormalizedName
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.package import Package
......@@ -160,7 +161,7 @@ lists all packages available."""
return 0
rows = [
rows: Rows = [
["<info>name</>", f" : <c1>{pkg.pretty_name}</>"],
["<info>version</>", f" : <b>{pkg.pretty_version}</b>"],
["<info>description</>", f" : {pkg.description}"],
......
from __future__ import annotations
from typing import TYPE_CHECKING
from cleo.helpers import argument
from poetry.console.commands.command import Command
if TYPE_CHECKING:
from cleo.ui.table import Rows
class SourceShowCommand(Command):
name = "source show"
description = "Show information about sources configured for the project."
......@@ -40,7 +46,7 @@ class SourceShowCommand(Command):
continue
table = self.table(style="compact")
rows = [
rows: Rows = [
["<info>name</>", f" : <c1>{source.name}</>"],
["<info>url</>", f" : {source.url}"],
[
......
from __future__ import annotations
from cleo.exceptions import CleoSimpleException
from cleo.exceptions import CleoError
class PoetrySimpleConsoleException(CleoSimpleException): # type: ignore[misc]
class PoetryConsoleError(CleoError):
pass
......@@ -9,7 +9,7 @@ if TYPE_CHECKING:
from cleo.io.inputs.definition import Definition
class RunArgvInput(ArgvInput): # type: ignore[misc]
class RunArgvInput(ArgvInput):
def __init__(
self,
argv: list[str] | None = None,
......
......@@ -6,17 +6,15 @@ from typing import TYPE_CHECKING
from crashtest.contracts.has_solutions_for_exception import HasSolutionsForException
from poetry.puzzle.exceptions import SolverProblemError
if TYPE_CHECKING:
from crashtest.contracts.solution import Solution
from poetry.puzzle.exceptions import SolverProblemError
class PythonRequirementSolutionProvider(HasSolutionsForException): # type: ignore[misc]
class PythonRequirementSolutionProvider(HasSolutionsForException):
def can_solve(self, exception: Exception) -> bool:
from poetry.puzzle.exceptions import SolverProblemError
if not isinstance(exception, SolverProblemError):
return False
......@@ -28,9 +26,10 @@ class PythonRequirementSolutionProvider(HasSolutionsForException): # type: igno
return bool(m)
def get_solutions(self, exception: SolverProblemError) -> list[Solution]:
def get_solutions(self, exception: Exception) -> list[Solution]:
from poetry.mixology.solutions.solutions.python_requirement_solution import (
PythonRequirementSolution,
)
assert isinstance(exception, SolverProblemError)
return [PythonRequirementSolution(exception)]
......@@ -10,7 +10,7 @@ if TYPE_CHECKING:
from poetry.puzzle.exceptions import SolverProblemError
class PythonRequirementSolution(Solution): # type: ignore[misc]
class PythonRequirementSolution(Solution):
def __init__(self, exception: SolverProblemError) -> None:
from poetry.core.constraints.version import parse_constraint
......
......@@ -59,7 +59,7 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
class Indicator(ProgressIndicator): # type: ignore[misc]
class Indicator(ProgressIndicator):
CONTEXT: str | None = None
@staticmethod
......
......@@ -17,7 +17,7 @@ from dulwich.errors import NotGitRepository
from dulwich.refs import ANNOTATED_TAG_SUFFIX
from dulwich.repo import Repo
from poetry.console.exceptions import PoetrySimpleConsoleException
from poetry.console.exceptions import PoetryConsoleError
from poetry.utils.authenticator import get_default_authenticator
from poetry.utils.helpers import remove_directory
......@@ -223,7 +223,7 @@ class Git:
try:
SystemGit.clone(url, target)
except CalledProcessError:
raise PoetrySimpleConsoleException(
raise PoetryConsoleError(
f"Failed to clone {url}, check your git configuration and permissions"
" for this repository."
)
......@@ -235,9 +235,7 @@ class Git:
try:
SystemGit.checkout(revision, target)
except CalledProcessError:
raise PoetrySimpleConsoleException(
f"Failed to checkout {url} at '{revision}'"
)
raise PoetryConsoleError(f"Failed to checkout {url} at '{revision}'")
repo = Repo(str(target))
return repo
......@@ -264,7 +262,7 @@ class Git:
try:
refspec.resolve(remote_refs=remote_refs)
except KeyError: # branch / ref does not exist
raise PoetrySimpleConsoleException(
raise PoetryConsoleError(
f"Failed to clone {url} at '{refspec.key}', verify ref exists on"
" remote."
)
......@@ -313,7 +311,7 @@ class Git:
e,
)
raise PoetrySimpleConsoleException(
raise PoetryConsoleError(
f"Failed to clone {url} at '{refspec.key}', verify ref exists on"
" remote."
)
......
......@@ -16,7 +16,7 @@ from dulwich.config import ConfigFile
from dulwich.repo import Repo
from poetry.core.pyproject.toml import PyProjectTOML
from poetry.console.exceptions import PoetrySimpleConsoleException
from poetry.console.exceptions import PoetryConsoleError
from poetry.utils.authenticator import Authenticator
from poetry.vcs.git import Git
from poetry.vcs.git.backend import GitRefSpec
......@@ -146,7 +146,7 @@ def test_git_clone_default_branch_head(
def test_git_clone_fails_for_non_existent_branch(source_url: str):
branch = uuid.uuid4().hex
with pytest.raises(PoetrySimpleConsoleException) as e:
with pytest.raises(PoetryConsoleError) as e:
Git.clone(url=source_url, branch=branch)
assert f"Failed to clone {source_url} at '{branch}'" in str(e.value)
......@@ -155,7 +155,7 @@ def test_git_clone_fails_for_non_existent_branch(source_url: str):
def test_git_clone_fails_for_non_existent_revision(source_url: str):
revision = sha1(uuid.uuid4().bytes).hexdigest()
with pytest.raises(PoetrySimpleConsoleException) as e:
with pytest.raises(PoetryConsoleError) as e:
Git.clone(url=source_url, revision=revision)
assert f"Failed to clone {source_url} at '{revision}'" in str(e.value)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment