Resolve relative file:// URLs in [requires] correctly - #163
Merged
Conversation
pyproject.toml's `[tool.robotpy] requires` list accepts PEP 508 direct-URL requirements like `bread @ git+https://...`. Relative `file://` URLs are also valid PEP 508 syntax, but pip rejects them: urlparse interprets the first path segment as the netloc, and pip's url_to_path() raises "non-local file URIs are not supported" for any non-empty, non-localhost netloc. This blocked using path dependencies (e.g. `bread @ file://../../lib/bread`) in monorepos, forcing workarounds like symlinks or pre-built wheels dropped into the pip cache. Fix by resolving relative file:// URLs to absolute file:// URLs against the project directory when loading pyproject.toml. Absolute URLs, non-file schemes, and URLs without a base path (e.g. `loads()` without an explicit base_path) are left untouched.
file:// URLs in requires correctly
file:// URLs in requires correctlyfile:// URLs in [requires] correctly
There was a problem hiding this comment.
Pull request overview
Adds support for relative file:// URL requirements in [tool.robotpy].requires. pyproject._load() (and load/loads) now optionally accept a base_path and rewrite any relative file:// URL in a Requirement to an absolute file:// URI rooted at the project directory, working around pip's rejection of non-empty netlocs caused by urlparse treating the first path segment as netloc.
Changes:
- Added
_resolve_relative_file_urlhelper that detects relativefile://URLs (including thefile://./...form) and rewrites them to absolute URIs rooted atbase_path. - Threaded an optional
base_pathparameter throughload(),loads(), and_load(), applied to every parsed requirement. - Added 5 tests in
tests/test_pyproject.pycovering relative, dot-segment, absolute, non-file, and missing-base-path cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| robotpy_installer/pyproject.py | Adds base_path-aware rewriting of relative file:// requirement URLs. |
| tests/test_pyproject.py | Adds tests covering the new relative-URL resolution behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Member
|
This is a bit esoteric, but if it works for you then it LGTM. Thanks. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What doesn't work
file://URLs in[tool.robotpy]with relative paths.Why this is an issue
PEP 508 permits direct URL requirements like
bread @ file://../../lib/bread.git+https://...already works today becausecli_sync.pyroutes direct URL requirements through pip_wheel. Relativefile://URLs, however, are rejected by pip before that logic is reached: urlparse treats the first path segment as the netloc, andurl_to_path()raises:
This breaks using monorepo-style path dependencies in pyproject.toml when otherwise that section works like normal for a
pyproject.tomlHow
pyproject._load()now takes an optional base_path (defaulted frompyproject.load()to the project directory) andrewrites any relative
file://URL in a Requirement to an absolutefile://URL. Absolute URLs, non-file: schemes,and
loads()without a base path are unchanged.Tests
5 new tests in
tests/test_pyproject.pycovering relativefile://,file://./...dot segments, absolute URLs,non-file URLs, and
loads()with no base path.