Commit a7e93ac
committed
fix: fail on unreachable planned conda packages
After ``apply_categories`` walks forward from each requested input
spec, every planned package should have at least one category. A
package without any category is an orphan: the lockfile dependency
graph cannot explain why this package is in the plan.
Orphans are not tolerated. They would silently vanish from the v1
lockfile output (which emits one entry per category, so a package
with no category produces zero entries) and the resulting
environment would install fewer packages than the solver actually
planned. This is the silent-vanishing variant of the
conda#896 chain that cache-side and lockfile-side heal
do not catch -- it surfaces only after categorization.
Add ``conda_lock.solver.graph_integrity.assert_no_orphaned_conda_packages``
which owns the entire orphan policy:
- Definition of an orphaned planned package.
- No reverse-propagation of categories. ``apply_categories``'
forward walk is the only categorization path. Reverse-prop
hides the broken-graph signal in single-category projects
(every orphan with any categorized dependency would silently
inherit ``main``, and the hard-fail would never fire on real
conda#896-style breakage), and ``"P depends on X (main)"`` does not
prove ``"main needs P"``; a permissive variant would launder
dev-only solver artifacts into main installs.
- Why ``pip`` is not normally an orphan even though nothing the
user explicitly requests transitively depends on it: both
conda's ``add_pip_as_python_dependency`` and libmamba's
repo-load injection mutate ``python``'s declared dependencies
to include ``pip`` at metadata-load time. So a healthy
forward walk from ``python`` reaches ``pip`` in normal
operation, and an orphaned ``pip`` indicates broken solver
metadata rather than the expected shape.
- ``CONDA_LOCK_ALLOW_ORPHANED_LOCKFILE=1`` escape hatch:
intentionally ugly, demotes the hard-fail to a loud WARNING and
assigns orphans to ``main`` so they survive v1 serialization.
This is for implementation-bug emergencies (a buggy custom
solver, missing ``add_pip_as_python_dependency`` injection on
an exotic channel) not a configuration knob. The WARNING
spells out the over-install consequence: every ``conda-lock
install`` invocation -- even ones without
``--dev-dependencies`` or ``-e <category>`` -- will install
the orphans, potentially over-installing dev-only solver
artifacts into production environments.
Add ``OrphanLockedDependencyError`` in ``conda_lock.errors``;
``solve_conda`` calls
``assert_no_orphaned_conda_packages(planned, platform)`` after
``apply_categories``. The module docstring on
``conda_lock.conda_solver`` introduces the ``solver/*`` split as
a whole so a new reader sees the layering on first opening the
file.
Six component tests in ``tests/component/test_graph_integrity.py``
pin the policy contract:
- ``test_solve_conda_accepts_pip_via_python_add_pip_dependency``:
the *normal* shape. ``python.depends == ["pip"]`` makes ``pip``
forward-reachable; ``pip`` inherits ``python``'s requested
category without rescue.
- ``test_solve_conda_hard_fails_when_python_metadata_omits_pip``:
the abnormal-metadata shape. ``python.depends == []`` makes
``pip`` unreachable; the orphan check hard-fails. The test
docstring names this as broken solver metadata, not normal
solver auto-install behavior.
- ``test_solve_conda_envvar_demotes_orphan_to_warning``: pins
``CONDA_LOCK_ALLOW_ORPHANED_LOCKFILE=1`` semantics. WARNING
fires (explicitly mentioning ``main``,
``--dev-dependencies`` / ``-e <category>``, and the envvar
name so the message can't silently weaken), orphans are
assigned to ``main``, ``solve_conda`` returns instead of
raising.
- ``test_solve_conda_hard_fails_on_unrecoverable_orphan``: the
classic conda#896-corrupt-cache shape -- ``zlib`` planned with
empty depends, no categorized package transitively requires
it -- hard-fails with regenerate-from-sources guidance and
the envvar escape named in the error message.
- ``test_solve_conda_orphan_via_dep_breakage_still_hard_fails``:
multi-category corrupt-cache variant.
- ``test_solve_conda_passes_when_dependency_graph_is_intact``:
positive sanity check.1 parent e01c171 commit a7e93ac
4 files changed
Lines changed: 694 additions & 9 deletions
File tree
- conda_lock
- solver
- tests/component
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
1 | 27 | | |
2 | 28 | | |
3 | 29 | | |
| |||
27 | 53 | | |
28 | 54 | | |
29 | 55 | | |
| 56 | + | |
30 | 57 | | |
31 | 58 | | |
32 | 59 | | |
| |||
150 | 177 | | |
151 | 178 | | |
152 | 179 | | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
153 | 186 | | |
154 | 187 | | |
155 | 188 | | |
| |||
331 | 364 | | |
332 | 365 | | |
333 | 366 | | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
342 | 375 | | |
343 | 376 | | |
344 | 377 | | |
| |||
547 | 580 | | |
548 | 581 | | |
549 | 582 | | |
550 | | - | |
551 | 583 | | |
552 | 584 | | |
553 | 585 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
0 commit comments