Skip to content

Commit b8fcbde

Browse files
committed
locker/installer: drop support for reading very old lock files (prior lock file version 1.0 and Poetry 1.1) (python-poetry#9345)
1 parent 66e1240 commit b8fcbde

File tree

7 files changed

+34
-247
lines changed

7 files changed

+34
-247
lines changed

src/poetry/installation/installer.py

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from poetry.repositories import RepositoryPool
1414
from poetry.repositories.installed_repository import InstalledRepository
1515
from poetry.repositories.lockfile_repository import LockfileRepository
16-
from poetry.utils.extras import get_extra_package_names
1716

1817

1918
if TYPE_CHECKING:
@@ -301,11 +300,6 @@ def _do_install(self) -> int:
301300
extras=set(self._extras),
302301
)
303302

304-
# We need to filter operations so that packages
305-
# not compatible with the current system,
306-
# or optional and not requested, are dropped
307-
self._filter_operations(ops, lockfile_repo)
308-
309303
# Validate the dependencies
310304
for op in ops:
311305
dep = op.package.to_dependency()
@@ -344,34 +338,5 @@ def _populate_lockfile_repo(
344338
if not repo.has_package(package):
345339
repo.add_package(package)
346340

347-
def _filter_operations(self, ops: Iterable[Operation], repo: Repository) -> None:
348-
extra_packages = self._get_extra_packages(repo)
349-
for op in ops:
350-
package = op.target_package if isinstance(op, Update) else op.package
351-
352-
if op.job_type == "uninstall":
353-
continue
354-
355-
if not self._env.is_valid_for_marker(package.marker):
356-
op.skip("Not needed for the current environment")
357-
continue
358-
359-
# If a package is optional and not requested
360-
# in any extra we skip it
361-
if package.optional and package.name not in extra_packages:
362-
op.skip("Not required")
363-
364-
def _get_extra_packages(self, repo: Repository) -> set[NormalizedName]:
365-
"""
366-
Returns all package names required by extras.
367-
368-
Maybe we just let the solver handle it?
369-
"""
370-
return get_extra_package_names(
371-
repo.packages,
372-
{k: [d.name for d in v] for k, v in self._package.extras.items()},
373-
self._extras,
374-
)
375-
376341
def _get_installed(self) -> InstalledRepository:
377342
return InstalledRepository.load(self._env)

src/poetry/packages/locker.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from poetry.core.constraints.version import parse_constraint
1919
from poetry.core.packages.dependency import Dependency
2020
from poetry.core.packages.package import Package
21-
from poetry.core.version.markers import parse_marker
2221
from poetry.core.version.requirements import InvalidRequirement
2322
from tomlkit import array
2423
from tomlkit import comment
@@ -205,22 +204,6 @@ def locked_repository(self) -> LockfileRepository:
205204

206205
package.extras = package_extras
207206

208-
if "marker" in info:
209-
package.marker = parse_marker(info["marker"])
210-
else:
211-
# Compatibility for old locks
212-
if "requirements" in info:
213-
dep = Dependency("foo", "0.0.0")
214-
for name, value in info["requirements"].items():
215-
if name == "python":
216-
dep.python_versions = value
217-
elif name == "platform":
218-
dep.platform = value
219-
220-
split_dep = dep.to_pep_508(False).split(";")
221-
if len(split_dep) > 1:
222-
package.marker = parse_marker(split_dep[1].strip())
223-
224207
for dep_name, constraint in info.get("dependencies", {}).items():
225208
root_dir = self.lock.parent
226209
if package.source_type == "directory":
@@ -348,7 +331,12 @@ def _get_lock_data(self) -> dict[str, Any]:
348331
)
349332

350333
metadata = lock_data["metadata"]
351-
lock_version = Version.parse(metadata.get("lock-version", "1.0"))
334+
if "lock-version" not in metadata:
335+
raise RuntimeError(
336+
"The lock file is not compatible with the current version of Poetry.\n"
337+
"Regenerate the lock file with the `poetry lock` command."
338+
)
339+
lock_version = Version.parse(metadata["lock-version"])
352340
current_version = Version.parse(self._VERSION)
353341
accepted_versions = parse_constraint(self._READ_VERSION_RANGE)
354342
lock_version_allowed = accepted_versions.allows(lock_version)

src/poetry/puzzle/transaction.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ def calculate_operations(
5555
uninstalls: set[NormalizedName] = set()
5656
for result_package, priority in self._result_packages:
5757
installed = False
58+
is_unsolicited_extra = extras is not None and (
59+
result_package.optional and result_package.name not in extra_packages
60+
)
5861

5962
for installed_package in self._installed_packages:
6063
if result_package.name == installed_package.name:
6164
installed = True
6265

6366
# Extras that were not requested are always uninstalled.
64-
if extras is not None and (
65-
result_package.optional
66-
and result_package.name not in extra_packages
67-
):
67+
if is_unsolicited_extra:
6868
uninstalls.add(installed_package.name)
6969
operations.append(Uninstall(installed_package))
7070

@@ -100,7 +100,10 @@ def calculate_operations(
100100
installed
101101
or (skip_directory and result_package.source_type == "directory")
102102
):
103-
operations.append(Install(result_package, priority=priority))
103+
op = Install(result_package, priority=priority)
104+
if is_unsolicited_extra:
105+
op.skip("Not required")
106+
operations.append(op)
104107

105108
if with_uninstalls:
106109
for current_package in self._current_packages:

tests/console/commands/self/test_remove_plugins.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,13 @@ def install_plugin(installed: Repository) -> None:
4848
"optional": False,
4949
"platform": "*",
5050
"python-versions": "*",
51-
"checksum": [],
51+
"files": [],
5252
},
5353
],
5454
"metadata": {
55+
"lock-version": "2.0",
5556
"python-versions": "^3.6",
56-
"platform": "*",
5757
"content-hash": "123456789",
58-
"files": {"poetry-plugin": []},
5958
},
6059
}
6160
system_pyproject_file.parent.joinpath("poetry.lock").write_text(

tests/installation/fixtures/old-lock.test

Lines changed: 0 additions & 112 deletions
This file was deleted.

tests/installation/test_installer.py

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,80 +2234,6 @@ def test_installer_uses_prereleases_if_they_are_compatible(
22342234
assert installer.executor.installations_count == 2
22352235

22362236

2237-
def test_installer_can_handle_old_lock_files(
2238-
locker: Locker,
2239-
package: ProjectPackage,
2240-
repo: Repository,
2241-
installed: CustomInstalledRepository,
2242-
config: Config,
2243-
pypi_repository: PyPiRepository,
2244-
) -> None:
2245-
pool = RepositoryPool()
2246-
pool.add_repository(pypi_repository)
2247-
2248-
package.add_dependency(Factory.create_dependency("pytest", "^3.5", groups=["dev"]))
2249-
2250-
locker.locked()
2251-
locker.mock_lock_data(fixture("old-lock"))
2252-
2253-
installer = Installer(
2254-
NullIO(),
2255-
MockEnv(),
2256-
package,
2257-
locker,
2258-
pool,
2259-
config,
2260-
installed=installed,
2261-
executor=Executor(MockEnv(), pool, config, NullIO()),
2262-
)
2263-
result = installer.run()
2264-
assert result == 0
2265-
2266-
assert installer.executor.installations_count == 6
2267-
2268-
installer = Installer(
2269-
NullIO(),
2270-
MockEnv(version_info=(2, 7, 18)),
2271-
package,
2272-
locker,
2273-
pool,
2274-
config,
2275-
installed=installed,
2276-
executor=Executor(
2277-
MockEnv(version_info=(2, 7, 18)),
2278-
pool,
2279-
config,
2280-
NullIO(),
2281-
),
2282-
)
2283-
result = installer.run()
2284-
assert result == 0
2285-
2286-
# funcsigs will be added
2287-
assert installer.executor.installations_count == 7
2288-
2289-
installer = Installer(
2290-
NullIO(),
2291-
MockEnv(version_info=(2, 7, 18), platform="win32"),
2292-
package,
2293-
locker,
2294-
pool,
2295-
config,
2296-
installed=installed,
2297-
executor=Executor(
2298-
MockEnv(version_info=(2, 7, 18), platform="win32"),
2299-
pool,
2300-
config,
2301-
NullIO(),
2302-
),
2303-
)
2304-
result = installer.run()
2305-
assert result == 0
2306-
2307-
# colorama will be added
2308-
assert installer.executor.installations_count == 8
2309-
2310-
23112237
def test_installer_does_not_write_lock_file_when_installation_fails(
23122238
installer: Installer,
23132239
locker: Locker,

tests/packages/test_locker.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,24 @@ def test_locker_should_raise_an_error_if_lock_version_is_newer_and_not_allowed(
745745
_ = locker.lock_data
746746

747747

748+
def test_locker_should_raise_an_error_if_no_lock_version(
749+
locker: Locker, caplog: LogCaptureFixture
750+
) -> None:
751+
"""Lock file prior Poetry 1.1 have no lock file version."""
752+
content = """\
753+
[metadata]
754+
python-versions = "~2.7 || ^3.4"
755+
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
756+
"""
757+
caplog.set_level(logging.WARNING, logger="poetry.packages.locker")
758+
759+
with open(locker.lock, "w", encoding="utf-8") as f:
760+
f.write(content)
761+
762+
with pytest.raises(RuntimeError, match="^The lock file is not compatible"):
763+
_ = locker.lock_data
764+
765+
748766
def test_root_extras_dependencies_are_ordered(
749767
locker: Locker, root: ProjectPackage, fixture_base: Path
750768
) -> None:

0 commit comments

Comments
 (0)