Treat invalid percent encoding consistently

The present form of ``requote_uri`` unnecessarily divides invalid cases.

When alpha-numeric, '%' is quoted to '%25'.
E.g. ``%pp`` to ``%25pp``.

When not alpha-numeric, '%' is kept as is.
E.g. ``%--`` to ``%--``.
(Note these two examples are in the tests,
and the latter is for ``unquote_unreserved``,
but the result is the same.)
Or ``%<<`` to ``%%3C%3C``.

but I think '%' should be quoted in all invalid cases.
(Or to put it differently, isolated '%' must be quoted.)

I can not find the rational in the code history.

(0) The original implementation
(1) Added 'isalnum'
(2) Added try clause and error message.
(3) Added more try clause and one of the present test.
(4) Added another of the present test.

(0)
**URI cleanup of non-path components**
https://github.com/psf/requests/commits?author=mgiuca
https://github.com/psf/requests/compare/12f9aa36..690426ac

(1)
**fix for #630 - unquote_unreserved raising ValueError on invalid URI-escape sequences**
https://github.com/psf/requests/pull/641
https://github.com/psf/requests/commit/cb15310d6aacd1c1e3b3345b6096d24ea2b79d49

(2)
**Better percent-escape exception**
https://github.com/psf/requests/pull/1514

(3)
**Attempt to quote anyway if unquoting fails**
https://github.com/psf/requests/pull/2393

(4)
**Added unit tests for utils module**
https://github.com/psf/requests/pull/3024

@mgiuca himself recently changed his mind.
https://github.com/whatwg/url/issues/369#issuecomment-359336557

(the point of that particular comment is to make '%s -> %s' a special case,
and it may be better to take this into consideration here (later),
but he agrees on the baseline ('%' -> '%25'))

Hello,

I haven't dug deeply into the issue (but please note that my previous interaction with this project was in 2012, so it's entirely possible I made a mistake or changed my mind since then!) Also note that the entire URL standard has been rewritten since then, the [URL standard](https://url.spec.whatwg.org/) that I'm commenting on in the above quote didn't exist in 2012.

Based on your above description, I agree that it doesn't make sense to treat `%xx` differently depending on whether `x` is alphanumeric. The best thing to do is probably say "if xx are both _hex digits_, keep it as-is, otherwise, expand "%" to "%25". But as you noted, then you will transform "%s" into "%25s", which breaks URLs that are designed to have things substituted into them later.

> But as you noted, then you will transform "%s" into "%25s", which breaks URLs that are designed to have things substituted into them later.

Except that once passed to an HTTP client, nothing will be substituting anything into them later. And if this is being returned as part of a redirect in the Location header then that means that the user will want to handle redirects themselves, otherwise the re-quoting is most likely valid.

> if this is being returned as part of a redirect in the Location header

Is it possible at all, in case of registerProtocolHandler's '%s' url?

What are you talking about `registerProtocolHandler`? Are you looking at the right project?

It is the only case url parser has to specially handle ``'%' + <single character>``.

That's why in the above comment link, mgiuca was considering:

> "%s" -> "%s" (with validation error)
> "%6%3D" -> "%6%3D" (with validation error)

In any other cases, my proposal in the first comment should be OK.

And it is the concern for *general* url parsers.
I'm not sure, but A HTTP client may not need wholly embrace this.

> And it is the concern for _general_ url parsers.

Quick note that the strings accepted by `registerProtocolHandler` are _not_ technically URLs (after all, they unambiguously are invalid, since you can't follow a `%` with an `s` in URL syntax). They are template strings that, when substituted, form a URL.

A generic URL parser does not need to be able to handle `%s` properly. It's a question for the authors of a given URL parser whether it's useful to be able to handle `%s` without double-quoting it.

@mgiuca thank you!