Lock discrepancy¶
- class wreck.lock_discrepancy.PkgsWithIssues¶
- wreck.lock_discrepancy.PkgsWithIssues: dict[str, dict[str, packaging.version.Version | set[packaging.version.Version]]]
Packages by a dict containing highest version and other versions
- wreck.lock_discrepancy.__all__: tuple[str, str, str, str, str, str, str, str, str] = ("PkgsWithIssues", "Resolvable", "ResolvedMsg", "UnResolvable", "get_ss_set", "filter_acceptable", "has_discrepancies_version", "get_the_fixes", "write_to_file_nudge_pin")¶
Module exports
- wreck.lock_discrepancy.is_module_debug: bool = False¶
Flag to turn on module level logging. Should be off in production
- wreck.lock_discrepancy._logger: logging.Logger¶
Module level logger
- class wreck.lock_discrepancy.Resolvable(venv_path: str | Path, pkg_name: str, qualifiers: str, nudge_unlock: str, nudge_lock: str)¶
Resolvable dependency conflict. Can find the lines for the pkg, in
.unlockand.lockfiles, using (loader and) venv_path and pkg_name.Limitation: Qualifiers e.g. python_version and os_name
haphazard usage
All pkg lines need the same qualifier. Often missing. Make uniform. Like a pair of earings.
rigorous usage
There can be one or more qualifiers. In which case, nonobvious which qualifier to use where.
- Variables:
venv_path (str | pathlib.Path) – Relative or absolute path to venv base folder
pkg_name (str) – package name
qualifiers (str) – qualifiers joined together into one str. Whitespace before the 1st semicolon not preserved.
nudge_unlock (str) – For
.unlockfiles. Nudge pin e.g.pkg_name>=some_version. If pkg_name entry in an.unlockfile, replace otherwise add entrynudge_lock (str) – For
.lockfiles. Nudge pin e.g.pkg_name==some_version. If pkg_name entry in a.lockfile, replace otherwise add entry
- class wreck.lock_discrepancy.ResolvedMsg(venv_path: str, abspath_f: Path, nudge_pin_line: str)¶
Fixed dependency version discrepancies (aka issues)
Does not include the original line
- Variables:
venv_path (str) – venv relative or absolute path
abspath_f (pathlib.Path) – Absolute path to requirements file
nudge_pin_line (str) – What the line will become
- class wreck.lock_discrepancy.UnResolvable(venv_path: str, pkg_name: str, qualifiers: str, sss: set[SpecifierSet], v_highest: Version, v_others: set[Version], pins: set[PinDatum])¶
Cannot resolve this dependency conflict.
Go out of our way to clearly and cleanly present sufficient details on the issue.
The most prominent details being the package name and Pins (from relevant
.unlockfiles).Track down issue
With issue explanation. Look at the
.lockto see the affected package’s parent(s). The parents’ package pins may be the cause of the conflict.The parents’ package
pyproject.tomlfile is the first place to look for strange dependency restrictions. Why a restriction was imposed upon a dependency may not be well documented. Look in the repo issues. Search for the dependency package nameUpgrading
lock inspect is not a dependency upgrader. Priority is to sync
.unlockand.lockfiles.Recommend always doing a dry run
pip compile --dry-run some-requirement.inor looking at upgradable packages within the venv.pip list -o- Variables:
venv_path (str | pathlib.Path) – Relative or absolute path to venv base folder
pkg_name (str) – package name
qualifiers (str) – qualifiers joined together into one str. Whitespace before the 1st semicolon not preserved.
sss (set[packaging.specifiers.SpecifierSet]) – Set of SpecifierSet, for this package, are the dependency version restrictions found in
.unlockfilesv_highest (packaging.version.Version) – Hints at the process taken to find a Version which satisfies SpecifierSets. First this highest version was checked
v_others (set[packaging.version.Version]) – After highest version, all other potential versions are checked. The potential versions come from the
.lockfiles. So if a version doesn’t exist in one.lock, it’s never tried.pins (set[wreck.lock_datum.PinDatum]) –
Has the absolute path to each requirements file and the dependency version restriction.
Make this readable
- sss: set[SpecifierSet]¶
- wreck.lock_discrepancy.extract_full_package_name(line, pkg_name_desired)¶
Extract first occurrence of exact package name. Algo uses tokens, not regex.
- Parameters:
- Returns:
is_different_pkg – True indicates can be either similar or different package is_known_oper – None means could not parse line. bool known/unknown operator pkg – package name. Alphanumeric hyphen underscore and period oper - operator e.g.
>=remaining – everything following the operator- Return type:
tuple[bool, bool | None, str | None, str | None, str | None]
See also
- wreck.lock_discrepancy.filter_acceptable(set_pindatum, set_ss, highest, others)¶
SpecifierSetdoes the heavy lifting, filtering out unacceptable possibilitiesget_ss_set()has already filtered invalid operators- Parameters:
set_pindatum¶ (set[wreck.lock_datum.PinDatum]) – PinDatum for the same package, from all
.lockfilesset_ss¶ (set[packaging.specifiers.SpecifierSet]) – set of all SpecifierSet
highest¶ (packaging.version.Version) – Highest Version amongst the choices
others¶ (set[packaging.version.Version]) – Other known Version detected within (same venv)
.lockfiles
- Returns:
set_acceptable, lst_specifiers, is_eq_affinity
- Return type:
tuple[set[packaging.specifiers.SpecifierSet], list[list[str]], packaging.version.Version | None]
- wreck.lock_discrepancy.get_compatible_release(highest: Version, lsts_specifiers: list[list[str]])¶
highest = <Version('25.3')> lst_specifiers = ['~=25.0'] lsts_specifiers = [['<=25.3'], ['~=25.0']] set_acceptable = {<Version('25.0')>, <Version('25.3')>}For nudge pin lock
Since
~=25.0is equivalent to>= 25.0, == 25.*Any other limiter would be on the upper limit Versionhighestacceptable Version is correctFor nudge pin unlock
In the unlock nudge pin, would be nice to take into account all lsts_specifiers. Create a set. Combine all and comma separate
- wreck.lock_discrepancy.get_ss_set(set_pindatum)¶
Create a set of all SpecifierSet
- Parameters:
set_pindatum¶ (set[wreck.lock_datum.PinDatum]) – PinDatum for the same package, from all
.lockfiles- Returns:
set of SpecifierSet
- Return type:
- Raises:
packaging.specifiers.InvalidSpecifier– In SpecifierSet unsupported operator
- wreck.lock_discrepancy.get_the_fixes(set_acceptable, lsts_specifiers, highest, is_eq_affinity_value, is_ss_count_zero)¶
When a
.lockfile is created, it is built from:one
.infilerecursively resolved constraints and requirements files
But not all. Therein lies the rub. Trying to choose based on the limited info at hand.
This algo will fail when there is an unnoticed pin that limits the version.
get_ss_set()has already filtered invalid operators- Parameters:
set_acceptable¶ (set[packaging.specifiers.SpecifierSet]) – Set of acceptable
highest¶ (packaging.version.Version) – Highest Version amongst the choices
is_eq_affinity_value¶ (packaging.version.Version | None) – A Specifier explicitly limits to one version
is_ss_count_zero¶ (bool) – True if set_ss is empty otherwise False
- Returns:
lock nudge pin w/o preceding pkg_name unlock nudge pin w/o preceding pkg_name bool False if unresolvable otherwise True
- Return type:
- Raises:
wreck.exceptions.PinMoreThanTwoSpecifiers– a pin contains >2 specifierswreck.exceptions.ArbitraryEqualityNotImplemented–===operator not implemented
- wreck.lock_discrepancy.has_discrepancies_version(d_by_pkg: wreck.lock_datum.DatumByPkg)¶
Across
.lockfiles, packages with discrepancies.Comparison limited to equality
- Parameters:
d_by_pkg¶ (wreck.lock_datum.DatumByPkg) – Within one venv, all lock packages’
set[PinDatum]- Returns:
pkg name / highest version. Only packages with discrepancies. With the highest version, know which version to nudge to.
- Return type:
- wreck.lock_discrepancy.nudge_pin_lock_v1(found)¶
Assumes found is not None aka unresolvable
Will later need to prepend pkg_name
- Parameters:
str_operator¶ (packaging.version.Version) – Semantic version
- Returns:
lock nudge pin
- Return type:
- wreck.lock_discrepancy.nudge_pin_unlock_v1(str_operator, found)¶
Assumes found is not None aka unresolvable.
Will later need to prepend pkg_name
- Parameters:
str_operator¶ (packaging.version.Version) – Operator
str_operator¶ – Semantic version
- Returns:
unlock nudge pin
- Return type:
- wreck.lock_discrepancy.write_to_file_nudge_pin(path_f, pkg_name, nudge_pin_line)¶
Nudge pin must include a newline (os.linesep) If package line exists in file, overwrite. Otherwise append nudge pin line