Skip to content

Fix path assignment losing absoluteness - #202

Closed
afonsojanu wants to merge 1 commit into
gruns:masterfrom
afonsojanu:fix/path-assignment-loses-absoluteness
Closed

afonsojanu wants to merge 1 commit into
gruns:masterfrom
afonsojanu:fix/path-assignment-loses-absoluteness

Conversation

@afonsojanu

Copy link
Copy Markdown

Fixes #144.

Reassigning a Path back onto furl.path, like f.path = f.path / 'c', silently turns an absolute path relative:

>>> f = furl('file:///a/b')
>>> f.path
Path('/a/b')
>>> f.path = f.path / 'c'
>>> f.path
Path('a/b/c')       # lost the leading slash

The bug is in Path.load(). When it's handed a Path instance (rather than a string), it tries to infer isabsolute by checking whether segments[0] == '', which is how a parsed path string signals absoluteness. A Path object's own .segments never carries that leading empty entry though, it gets popped off during parsing and only gets reinserted temporarily inside __str__ for rendering. So loading from a Path instance always computed isabsolute as False, regardless of what the source path actually was.

The fix reads .isabsolute directly off the source Path when that's what's being loaded, instead of trying to reconstruct it from segments that don't encode it for this input type. String and list inputs are untouched, same behavior as before.

Added a test covering the exact assignment pattern from the issue (both the absolute file:///a/b case and a relative one), and confirmed it fails on master and passes with the fix.

Ran the full suite locally: 76 passed, plus this new one, and 2 pre-existing IPv6-related failures unrelated to this change (already tracked in #182, happens on master too regardless of this patch).

Reassigning a Path back onto furl.path, like `f.path = f.path / 'c'`,
was silently turning an absolute path relative. The culprit is in
Path.load(): when it's handed a Path instance rather than a string,
it reuses that Path's .segments to figure out whether the result
should be absolute, checking for a leading empty segment. That check
only works for strings, though, since a Path's .segments never keeps
that leading '' around (it gets popped off once the path is parsed
and only gets reinserted temporarily inside __str__ for rendering).
So a Path built from an already-absolute path would come back through
load() as if it had been relative all along.

The fix reads .isabsolute straight off the source Path instead of
trying to reconstruct it from segments that don't carry that
information for this input type. Added a test covering both the
absolute and relative round trip through this exact assignment
pattern, plus the file:// reproducer from the original report.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Loosing absolute path on assignation

1 participant