Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update poetry-core via poetry self update #5306

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 105 additions & 51 deletions src/poetry/console/commands/self/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

if TYPE_CHECKING:
from poetry.core.packages.package import Package
from poetry.core.semver.version import Version

from poetry.repositories.pool import Pool

Expand All @@ -35,6 +34,7 @@ class SelfUpdateCommand(Command):
"Output the operations but do not execute anything "
"(implicitly enables --verbose).",
),
option("core", None, "The poetry-core version to update to.", flag=False),
]

_data_dir = None
Expand Down Expand Up @@ -88,22 +88,114 @@ def pool(self) -> Pool:
return pool

def handle(self) -> int:
from poetry.core.packages.dependency import Dependency
from poetry.utils._compat import metadata

poetry_release = self._find_poetry_release()
core_release = self._find_compatible_core_release(poetry_release)

update_releases = [
release
for release in {poetry_release, core_release}
if release.version.text != metadata.version(release.name)
]

if not update_releases:
self.line("You are using the latest version")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.line("You are using the latest version")
self.line("You are already using the latest version.")

return 0

msg = [
f"<c1>{release.pretty_name}</c1> to <c2>{release.version}</c2>"
for release in update_releases
]
self.line(f"Updating {' and '.join(msg)}.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.line(f"Updating {' and '.join(msg)}.")
self.line(f"Updating {', '.join(msg)}.")

self.line("")

self.update(update_releases)

if poetry_release in update_releases:
self._make_bin()

self.line("")
self.line(f"Successfully updated {' and '.join(msg)}. Great!")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.line(f"Successfully updated {' and '.join(msg)}. Great!")
self.line(f"Successfully updated {', '.join(msg)}!")


return 0

def update(self, releases: list[Package]) -> None:
from poetry.utils.env import EnvManager

env = EnvManager.get_system_env(naive=True)

# We can't use is_relative_to() since it's only available in Python 3.9+
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment could be a little more descriptive -- we're throwing away the result of the env.path call because it throws an exception when the paths are not adjacent, right?

try:
env.path.relative_to(self.data_dir)
except ValueError:
# Poetry was not installed using the recommended installer
from poetry.console.exceptions import PoetrySimpleConsoleException

raise PoetrySimpleConsoleException(
"Poetry was not installed with the recommended installer, "
"so it cannot be updated automatically."
)

self._update(releases)

def _find_poetry_release(self) -> Package:
from poetry.core.semver.version import Version

from poetry.__version__ import __version__
from poetry.utils._compat import metadata

is_prerelease = False
version = self.argument("version")
if not version:
version = ">=" + __version__
is_prerelease = Version.parse(metadata.version("poetry")).is_prerelease()
version = ">=" + metadata.version("poetry")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use str.format() here -- it's a bit more readable.


release = self._find_release(
"poetry", version, is_prerelease or self.option("preview")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use these as kwargs for readability.

)
return release

def _find_compatible_core_release(self, poetry_release: Package) -> Package:
from poetry.core.semver.version import Version

from poetry.console.exceptions import PoetrySimpleConsoleException

core = self.option("core")

for dependency in poetry_release.all_requires:
if dependency.name == "poetry-core":
if core and not dependency.constraint.allows(Version.parse(core)):
raise PoetrySimpleConsoleException(
f"poetry-core {core} is not supported by poetry"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
f"poetry-core {core} is not supported by poetry"
f"poetry-core {core} is not supported by Poetry"

f" {poetry_release.version}."
)

core = core or str(dependency.constraint)
break
else:
raise PoetrySimpleConsoleException(
"No compatible version of poetry-core for poetry"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"No compatible version of poetry-core for poetry"
"No compatible version of poetry-core for Poetry"

f" {poetry_release.version}."
)

core_release = self._find_release("poetry-core", core, True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use kwargs here, please.


return core_release

def _find_release(self, name: str, version: str, preview: bool) -> Package:
from poetry.core.packages.dependency import Dependency

from poetry.console.exceptions import PoetrySimpleConsoleException

repo = self.pool.repositories[0]

packages = repo.find_packages(
Dependency("poetry", version, allows_prereleases=self.option("preview"))
Dependency(name, version, allows_prereleases=preview)
)
if not packages:
self.line("No release found for the specified version")
return 1
raise PoetrySimpleConsoleException(
"No release found for the specified version."
)

def cmp(x: Package, y: Package) -> int:
if x.version == y.version:
Expand All @@ -115,7 +207,7 @@ def cmp(x: Package, y: Package) -> int:
release = None
for package in packages:
if package.is_prerelease():
if self.option("preview"):
if preview:
release = package

break
Expand All @@ -126,49 +218,9 @@ def cmp(x: Package, y: Package) -> int:

break

if release is None:
self.line("No new release found")
return 1

if release.version == Version.parse(__version__):
self.line("You are using the latest version")
return 0

self.line(f"Updating <c1>Poetry</c1> to <c2>{release.version}</c2>")
self.line("")

self.update(release)

self.line("")
self.line(
f"<c1>Poetry</c1> (<c2>{release.version}</c2>) is installed now. Great!"
)

return 0

def update(self, release: Package) -> None:
from poetry.utils.env import EnvManager

version = release.version

env = EnvManager.get_system_env(naive=True)

# We can't use is_relative_to() since it's only available in Python 3.9+
try:
env.path.relative_to(self.data_dir)
except ValueError:
# Poetry was not installed using the recommended installer
from poetry.console.exceptions import PoetrySimpleConsoleException

raise PoetrySimpleConsoleException(
"Poetry was not installed with the recommended installer, "
"so it cannot be updated automatically."
)
return release

self._update(version)
self._make_bin()

def _update(self, version: Version) -> None:
def _update(self, releases: list[Package]) -> None:
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.project_package import ProjectPackage

Expand All @@ -183,7 +235,9 @@ def _update(self, version: Version) -> None:

root = ProjectPackage("poetry-updater", "0.0.0")
root.python_versions = ".".join(str(c) for c in env.version_info[:3])
root.add_dependency(Dependency("poetry", version.text))

for release in releases:
root.add_dependency(Dependency(release.name, release.version.text))

installer = Installer(
self.io,
Expand Down
Loading