Bug fixes
- On Windows, freeze output now writes an editable location as
-e file:///C:/projinstead of-e C:\proj, which pip read asC:projand rejected. This covers an editable install with no version control, one with no remote or an invalid remote, and one whose lookup timed out. On other platforms, a location that holds a backslash also becomes afile://URL (#862) by @gaborbernat. - Read
direct_url.json,RECORD,.egg-linkfiles,.hg/hgrcand.svn/entriesonly when they are regular files of at most 16 MiB, asMETADATAalready was. A FIFO in place ofdirect_url.jsonorRECORDmade--freezeor--computed sizewait for a writer, and a link to/dev/zeroor a multi-gigabyte file made them allocate until the allocator or the OOM killer stopped the run. Freeze now prints the version pin for such a package, its size counts as zero, and an unreadable.egg-link,hgrcorentriesfile counts as absent (#855) by @gaborbernat. - Stop waiting for a command at its timeout even when a process it started still holds its output open. A
poetrywrapper script that ran the real command withoutexecused to keep the environment probe waiting until that command exited, past the 5 second timeout; the same applied to the VCS commands that freeze runs and todot. Such a command now counts as timed out at the deadline, also when it exited first and left the other process running. pipdeptree does not stop that process (#849) by @gaborbernat. -o cyclonedx-jsonwrites each--computedvalue as plain text, with one property per name forunique-deps-names. Before, a string kept its JSON quotes ("\"2.1 KB\"") and a list became one JSON array string.--depthhelp names the formats it applies to, andpipdeptree.render()no longer callssvgandpsbinary formats when it rejects them by Bernát Gábor.-o jsonlists themetadatafields of each package in the order given to--metadata, as the other formats and pipdeptree 3.x do. Since 4.0.0 it sorted them by name by Bernát Gábor.from-index --requirementserrors on Windows now name the requirements file as a plainC:\...path instead of the\\?\C:\...form. This coversfile:line: invalid requirement,recursive requirements includeand the nesting depth error by Bernát Gábor.from-index --requirementsnow prints a warning for each-i,--index-urlor--extra-index-urlline in a requirements file, naming the file, the line and the command-line flag to use instead. The resolve still ignores these lines, and--warn failmakes the run exit with code 1. Before, it skipped them without a word, so a pip-compile file for a private index resolved against PyPI with no hint why (#853) by @gaborbernat.from-indexnow rejects an-e/--editableline in a constraints file withsource requirements cannot be constraints, the error a plain path or URL constraint already gets. Before, the editable project joined the resolve as an extra top-level requirement, so its dependencies could change the versions picked for the real requirements. pip refuses the same file (#850) by @gaborbernat.from-indexnow resolves a local project given as a barefile:URL, such asfile:///abs/pathor-e file:///abs/path, on the command line or in a requirements file. Before, it read the URL as a relative path and failed withNo such file or directory (os error 2). A relativefile:URL, bare or asname @ file:./pkg, now resolves against the working directory as pip does, where the named form used to readfile:pkgas/pkg. A local source that cannot be read now fails with an error that names its path (#851) by @gaborbernat.from-indexnow treats an emptyPIP_EXTRA_INDEX_URLas unset and reads the extra indexes fromUV_EXTRA_INDEX_URL, as it already did forPIP_INDEX_URLandUV_INDEX_URL. Before, the empty value left the resolve with no extra index, so a package that only theUV_EXTRA_INDEX_URLindex served failed to resolve by Bernát Gábor.meson setupworks on systems that shippython3without apythoncommand. The stable ABI check now runs under the interpreter that runs Meson, the same one the build targets, instead of the firstpythononPATH(#856) by @gaborbernat.
Security
- Percent-encode whitespace and control characters in the URLs, VCS remotes and subdirectories of freeze output, and write an editable location that holds one as a
file://URL. Before, an installed distribution could add a line such as--index-urlto the requirements file through itsdirect_url.json,.egg-linkor a shipped checkout, and an escape sequence reached the terminal. An editable location with a space now installs withpip install -rinstead of pip reading only the text before the space (#844) by @gaborbernat. - Print the warnings the
from-indexresolver logs, such as a skipped release whose metadata does not parse, as a pipdeptree warning that--warn silencehides, with control characters replaced by U+FFFD. The same replacement now applies to Python errors the resolver raises. Before, Python wrote these warnings to stderr with the index's escape sequences intact, even under--warn silence(#847) by @gaborbernat. - Reject a
Requires-Distmarker, or a lock packagemarker, longer than 1024 bytes or with more than 16extracomparisons before parsing it. Parsing builds a decision diagram that can double in size with each clause ofextraalternatives, and a marker of about 900 bytes took 12 seconds and 15 GB of memory to parse. Installed metadata reports such a marker with theInvalid requirement foundwarning;from-lockstops with an error naming the package. pipdeptree also collects the extras a marker names by visiting each node of the parsed marker once, instead of converting it to disjunctive normal form, andfrom-lockstops with an error when thenameof adependenciesentry is not a project name (#860) by @gaborbernat. - Skip the interpreter that
poetry env info --executablereports when it lies inside the project in the working directory, such as a.venvnext to thepyproject.toml. With no virtual or conda environment active, a plainpipdeptreeand--python autoused to run that interpreter, so a cloned repository that committed both ran its own program as the user. A plain run now inspects the interpreter running pipdeptree, and--python autofails to detect an environment. To inspect that environment, activate it or pass its interpreter to--pythonby Bernát Gábor. - Stop
from-indexwith an error when the resolver pins a package name or version longer than 255 bytes, asfrom-lockalready does. The text, JSON and freeze outputs copy a version once per edge, so an index could make them print megabytes from one long version (#843) by @gaborbernat.