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

lock: allow for no-update refresh of lock files #3034

Merged
merged 1 commit into from
Oct 2, 2020
Merged
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
10 changes: 9 additions & 1 deletion poetry/console/commands/lock.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from cleo import option

from .installer_command import InstallerCommand


Expand All @@ -6,6 +8,12 @@ class LockCommand(InstallerCommand):
name = "lock"
description = "Locks the project dependencies."

options = [
option(
"no-update", None, "Do not update locked versions, only refresh lock file."
),
]

help = """
The <info>lock</info> command reads the <comment>pyproject.toml</> file from the
current directory, processes it, and locks the dependencies in the <comment>poetry.lock</>
Expand All @@ -21,6 +29,6 @@ def handle(self):
self.poetry.config.get("experimental.new-installer", False)
)

self._installer.lock()
self._installer.lock(update=not self.option("no-update"))

return self._installer.run()
26 changes: 22 additions & 4 deletions poetry/installation/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ def set_locker(self, locker): # type: (Locker) -> Installer
return self

def run(self):
# Check if refresh
if not self._update and self._lock and self._locker.is_locked():
return self._do_refresh()

# Force update if there is no lock file present
if not self._update and not self._locker.is_locked():
self._update = True
Expand Down Expand Up @@ -137,11 +141,11 @@ def update(self, update=True): # type: (bool) -> Installer

return self

def lock(self): # type: () -> Installer
def lock(self, update=True): # type: (bool) -> Installer
"""
Prepare the installer for locking only.
"""
self.update()
self.update(update=update)
self.execute_operations(False)
self._lock = True

Expand Down Expand Up @@ -173,6 +177,20 @@ def use_executor(self, use_executor=True): # type: (bool) -> Installer

return self

def _do_refresh(self):
# Checking extras
for extra in self._extras:
if extra not in self._package.extras:
raise ValueError("Extra [{}] is not specified.".format(extra))

ops = self._get_operations_from_lock(self._locker.locked_repository(True))
local_repo = Repository()
self._populate_local_repo(local_repo, ops)

self._write_lock_file(local_repo, force=True)

return 0

def _do_install(self, local_repo):
from poetry.puzzle import Solver

Expand Down Expand Up @@ -285,8 +303,8 @@ def _do_install(self, local_repo):
# Execute operations
return self._execute(ops)

def _write_lock_file(self, repo): # type: (Repository) -> None
if self._update and self._write_lock:
def _write_lock_file(self, repo, force=True): # type: (Repository, bool) -> None
if force or (self._update and self._write_lock):
updated_lock = self._locker.set_lock_data(self._package, repo.packages)

if updated_lock:
Expand Down
119 changes: 119 additions & 0 deletions tests/installation/fixtures/old-lock-refresh.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
[[package]]
name = "attrs"
version = "17.4.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = "*"

[package.extras]
dev = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface", "sphinx", "zope.interface"]
docs = ["sphinx", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface"]

[[package]]
name = "colorama"
version = "0.3.9"
description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = "*"

[[package]]
name = "funcsigs"
version = "1.0.2"
description = "Python function signatures from PEP362 for Python 2.6, 2.7 and 3.2+"
category = "dev"
optional = false
python-versions = "*"

[[package]]
name = "more-itertools"
version = "4.1.0"
description = "More routines for operating on iterables, beyond itertools"
category = "dev"
optional = false
python-versions = "*"

[package.dependencies]
six = ">=1.0.0,<2.0.0"

[[package]]
name = "pluggy"
version = "0.6.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[[package]]
name = "py"
version = "1.5.3"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[[package]]
name = "pytest"
version = "3.5.0"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[package.dependencies]
attrs = ">=17.4.0"
colorama = "*"
funcsigs = {version = "*", markers = "python_version < \"3.0\""}
more-itertools = ">=4.0.0"
pluggy = ">=0.5,<0.7"
py = ">=1.5.0"
six = ">=1.10.0"

[[package]]
name = "six"
version = "1.11.0"
description = "Python 2 and 3 compatibility utilities"
category = "dev"
optional = false
python-versions = "*"

[metadata]
lock-version = "1.1"
python-versions = "*"
content-hash = "123456789"

[metadata.files]
attrs = [
{file = "attrs-17.4.0-py2.py3-none-any.whl", hash = "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"},
{file = "attrs-17.4.0.tar.gz", hash = "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"},
]
colorama = [
{file = "colorama-0.3.9-py2.py3-none-any.whl", hash = "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda"},
{file = "colorama-0.3.9.tar.gz", hash = "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"},
]
funcsigs = [
{file = "funcsigs-1.0.2-py2.py3-none-any.whl", hash = "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca"},
{file = "funcsigs-1.0.2.tar.gz", hash = "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"},
]
more-itertools = [
{file = "more-itertools-4.1.0.tar.gz", hash = "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44"},
{file = "more_itertools-4.1.0-py2-none-any.whl", hash = "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e"},
{file = "more_itertools-4.1.0-py3-none-any.whl", hash = "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea"},
]
pluggy = [
{file = "pluggy-0.6.0.tar.gz", hash = "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"},
]
py = [
{file = "py-1.5.3-py2.py3-none-any.whl", hash = "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"},
{file = "py-1.5.3.tar.gz", hash = "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881"},
]
pytest = [
{file = "pytest-3.5.0-py2.py3-none-any.whl", hash = "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c"},
{file = "pytest-3.5.0.tar.gz", hash = "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1"},
]
six = [
{file = "six-1.11.0-py2.py3-none-any.whl", hash = "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"},
{file = "six-1.11.0.tar.gz", hash = "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"},
]
38 changes: 38 additions & 0 deletions tests/installation/test_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,44 @@ def test_installer_uses_prereleases_if_they_are_compatible(
assert 2 == installer.executor.installations_count


def test_installer_can_refresh_old_lock_files(locker, package, repo, installed, config):
pool = Pool()
pool.add_repository(repo)

locker.locked(True)
locker.mock_lock_data(fixture("old-lock"))

for pkg in locker.locked_repository(with_dev_reqs=True).packages:
dependency = Factory.create_dependency(
name=pkg.name,
constraint=pkg.to_dependency().constraint,
category=pkg.category,
)
package.add_dependency(dependency)
repo.add_package(pkg)

installer = Installer(
NullIO(),
MockEnv(),
package,
locker,
pool,
config,
installed=None,
executor=Executor(MockEnv(), pool, config, NullIO()),
)
installer.use_executor()

installer.lock(update=False)
installer.run()

assert 0 == installer.executor.installations_count
assert 0 == installer.executor.updates_count
assert 0 == installer.executor.removals_count

assert locker.written_data == fixture("old-lock-refresh")


def test_installer_can_handle_old_lock_files(
installer, locker, package, repo, installed, config
):
Expand Down