python-hyper/hyperlink

Add AbstractURL type

mahmoud opened this issue · 2 comments

Per @wsanchez and @twm in #126, consensus seems to be that hyperlink would benefit from an interface/ABC which could be for both DecodedURL and URL/EncodedURL.

AbstractURL is the current name frontrunner, as URL is already taken for legacy reasons.

To quote @twm:

These methods seem to be equivalent between URL and DecodedURL in the sense that they do semantically identical things:

to_text()
to_uri()
to_iri()
normalize()
absolute
scheme
port
rooted

__bytes__ should probably be on this list (per #55). DecodedURL appears to lack it.

I'd also suggest that URL's get_decoded_url() method and DecodedURL's encoded_url property should be part of any common interface. This would be useful in treq to avoid a chain of isinstance() checks.

click() is also similar between the two, though only the DecodedURL version accepts a DecodedURL.

Further discussion to follow, no doubt.

glyph commented

I think this is tempting but probably wrong. Pretty much nothing should be treating a decoded URL as encoded or vice-versa. What kind of code wants a shared type?

twm commented

In twisted/treq#279 I was looking to accept both. Almost all treq needs is the ability to ultimately convert to bytes (which you can do with the methods I listed as "equivalent" above).

There is a code path there that conditionally wants DecodedURL, though — merging the params argument (see twisted/treq#283, reviews appreciated!). So for this purpose it would be useful to do something like:

if params:
    decoded_url = parsed_url.get_decoded_url()
    parsed_url = decoded_url.replace(
        query=decoded_url.query + tuple(_coerced_query_params(params))
    ).encoded_url

So that is part of the motivation for my previous comment, particularly that get_decoded_url() and encoded_url should be present on both. Is that compelling? Eh, I'm not so sure. It's not much code in treq either way.

The other part of my motivation is that I wanted to make sure that URL.get() and DecodedURL.get() aren't part of any "shared" part. They are parallel, but distinct, so appearing in a base type would confuse matters. It is confusing enough that they have the same name.