Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TypeError in issue #158/#159 #160

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

wcooley
Copy link
Contributor

@wcooley wcooley commented May 31, 2018

This makes only one more test pass (now only 3 failing) but at least prevents the TypeError when attempting to add a list and a tuple.

pytest output attached
pytest-out-2.txt

This makes only one more test pass (now only 3 failing) but at least
prevents the `TypeError` when attempting to add a `list` and a `tuple`.
@mahmoud
Copy link
Owner

mahmoud commented Feb 11, 2019

It's taken a while to arrive at the correct course of action, but this pickle of an issue has finally been fixed in 19.0.0, just released. Thanks for your work, and your patience :)

@mahmoud
Copy link
Owner

mahmoud commented Feb 11, 2019

Thought I was closing a different issue, reopening!

@mahmoud mahmoud reopened this Feb 11, 2019
@pytest.mark.parametrize(
('expected', 'base', 'a', 'b'), [
('https://host/b', 'https://host', 'a', '/b'),
('https://host/a/b', 'https://host', 'a', 'b'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using

boltons.urlutils.URL(boltons.urlutils.URL('https://host').navigate('a')).navigate('b')

the expected result should be https://host/b

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked at this in a long time, so pardon me if I'm completely backwards and no longer clear on what I thought behavior should be.

When you say, "the expected result should be", where are you basing that "should be" on? The scant documentation says, "Useful for navigating those relative links with ease." I consider this analogous to using cd on a Unix system; all references are relative unless the destination starts with /.

Actually, the vexing nature of the way things work now is more apparent if you have multiple path segments:

>>> boltons.urlutils.URL('https://host/a/b/c').navigate('d')
URL('https://host/a/b/d')
>>> boltons.urlutils.URL('https://host/a/b/c').navigate('../d')
URL('https://host/a/d')
>>> boltons.urlutils.URL('https://host/a/b/c/').navigate('../d')
URL('https://host/a/b/d')
>>> boltons.urlutils.URL('https://host/a/b/c').navigate('#d')
URL('https://host/a/b/c#d')

What I find most surprising is that, without a trailing slash on the base, navigate with a non-fragment argument assumes the last part of the path is (erm, not sure about the right terminology) a "leaf" instead of a "stem" (or "file" instead of a "directory"?).

To make a relative link from an URL without a trialing slash with the behavior you're describing, you have to: 1. to_text() 2. conditionally append a '/' (normalize() will not make // -> /) 3. recreate URL. Because the URL object is immutable, it's much easier to change the string argument to enable "upwards" navigation by pre-pending '../'. This is what I would find less surprising:

>>> boltons.urlutils.URL('https://host/a/b/c').navigate('d')
URL('https://host/a/b/c/d')
>>> boltons.urlutils.URL('https://host/a/b/c').navigate('../d')
URL('https://host/a/b/d')
>>> boltons.urlutils.URL('https://host/a/b/c/').navigate('../d')
URL('https://host/a/b/d')

Unfortunately, I think this ship has sailed; changing this behavior would be massively backwards-incompatible.

('https://host/b', 'https://host', 'a', '/b'),
('https://host/a/b', 'https://host', 'a', 'b'),
('https://host/a/b', 'https://host', 'a/', 'b'),
('https://host/a/b', 'https://host', '/a', 'b'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using

boltons.urlutils.URL(boltons.urlutils.URL('https://host').navigate('/a')).navigate('b')

the expected result should be https://host/b

('https://host/a/b', 'https://host', 'a/', 'b'),
('https://host/a/b', 'https://host', '/a', 'b'),
('https://host/a/b', 'https://host/a/', None, 'b'),
('https://host/a/b', 'https://host/a', None, 'b'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using

boltons.urlutils.URL(boltons.urlutils.URL('https://host').navigate('/a')).navigate('b')

the expected result should be https://host/b

@allanlei
Copy link
Contributor

allanlei commented Jan 9, 2022

@mahmoud @wcooley I've extended this PR in #298.

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.

3 participants