You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Alternate RFC 3986 compliant URI parsing module #43453
A new way for parsing URI. I have not reviewed it even after saying I would like to, but having the dependency issue resolved, I think it is good to look at it again, especially if it leads some helpful approaches to parsing IRI.
"accepted" is a little too strong for the current status of this :)
I've removed the easy tag as well (making the case for this or something like it in the standard library it going to involve a fair bit of effort - the coding was actually the comparatively easy part).
I still like the higher level API concept, although I might not do it exactly as presented here any more.
Independently of introducing a new parsing API, it would be worthwhile extracting the parsing tests from the attached module to make sure the *existing* parser can handle them all correctly.
Regarding the module, I’m a bit reluctant. I see value in providing low-level building blocks (think OS calls) and high-level utilities for regular use, but here it seems that urllib.parse and urischemes are at the same level. I’m not opposed to the functionality itself—I would like to use a class simply named “URI” (and generally get better names, that is RFC names instead of specific inventions), have components normalization and such goodies—but I think the existing module can get fixes and improvements. I fear the confusion that could be caused by having two modules for the same task, unless you want to propose that the new module deprecate urllib.parse.
Just to be clear, even *I* don't think adding urischemes as it stands is a particularly great idea, and I wrote it. The only reason I haven't closed the issue is because I'd like to see it mined for additional tests in test_urlparse and perhaps even implementation or API enhancements in url.parse first.
(The latter becomes a lot more likely if the urischemes implementation passes tests that url.parse fails)
I also think, since I wrote this, the various urllib parsing methods were updated to return named tuple instances with properties, so a lot of the awkwardness of extracting partial values went away. (i.e. returning structured objects already raised the level of the urllib APIs from the "tuple-of-strings" level they used to be sitting at)
I do still assert that urischemes is slightly "higher level" than the current incarnation of similar functionality in urllib.parse. Universal Resource Identifiers are more encompassing than Universal Resource Locators and Universal Resource Names, and the new APIs explicitly deal with both kinds of URI. There are subtle differences in the assumptions you're allowed to make when you may have a URN rather than a URL, so I believe the current module sometimes does the wrong thing when given one of the former.
That said, it's been a long time since I've needed to remember the details, so I don't recall exactly where the current module gets URI handling wrong (or at least, did back in 2006). The intro to RFC 3986 is a good place to start in learning the differences though - Sir Tim writes good docs :)
Here's a slightly modified version of urischeme.py that can be run under Python 3 and compares its results with urllib.parse, printing out the mismatches.
The major differences seem to be 1) urischeme fills in the default port if it's not explicitly provided, e.g. http urls have the port set to 80, 2) the path is returned as '/', not the empty string, for the URL http://host, 3) urllib.parse.urljoin() doesn't get rid of ./ and ../ in URLs.
seems like something worth fixing in urllib.parse. The others probably present some backward-compatibility issues.
The test-mining this was kept open for looks done — I pulled the attachments (uriparse.py, testurlparse.py, akuchling's urischemes port) and ran their 129 urljoin cases against current main. Results:
RFC 3986 section 5.4 coverage: all 90 corpus rows on the section 5.4 base are already in test_urlparse.py (test_RFC1808/test_RFC2396/test_RFC3986/test_urljoins), including the strict-vs-relaxed http:g case.
The 2010 criterion above — does urischemes pass tests the existing parser fails? No. All 27 divergences are deliberate, none an unfiled bug: the same-scheme relaxation, the uses_relative scheme gate (bpo-22118, 2014), and the empty-segment collapse (bpo-22278, 2014).
akuchling's 2013 mismatches: urljoin not removing .//../ — since fixed by the RFC 3986 switch. The other two are deliberate: urllib.parse doesn't fill scheme-default ports, and returns an empty path (not /) for an authority-only URL.
With the module itself set aside in 2010, this looks closable as not planned.
Activity
orsenthil commentedon Jul 11, 2010
A new way for parsing URI. I have not reviewed it even after saying I would like to, but having the dependency issue resolved, I think it is good to look at it again, especially if it leads some helpful approaches to parsing IRI.
ncoghlan commentedon Jul 11, 2010
"accepted" is a little too strong for the current status of this :)
I've removed the easy tag as well (making the case for this or something like it in the standard library it going to involve a fair bit of effort - the coding was actually the comparatively easy part).
merwok commentedon Nov 2, 2010
Is this still relevant? Can’t the improvements make it into urllib.parse?
ncoghlan commentedon Nov 2, 2010
I still like the higher level API concept, although I might not do it exactly as presented here any more.
Independently of introducing a new parsing API, it would be worthwhile extracting the parsing tests from the attached module to make sure the *existing* parser can handle them all correctly.
merwok commentedon Nov 3, 2010
Sure, adding tests is a no-brainer.
Regarding the module, I’m a bit reluctant. I see value in providing low-level building blocks (think OS calls) and high-level utilities for regular use, but here it seems that urllib.parse and urischemes are at the same level. I’m not opposed to the functionality itself—I would like to use a class simply named “URI” (and generally get better names, that is RFC names instead of specific inventions), have components normalization and such goodies—but I think the existing module can get fixes and improvements. I fear the confusion that could be caused by having two modules for the same task, unless you want to propose that the new module deprecate urllib.parse.
Senthil, what is your opinion?
ncoghlan commentedon Nov 3, 2010
Just to be clear, even *I* don't think adding urischemes as it stands is a particularly great idea, and I wrote it. The only reason I haven't closed the issue is because I'd like to see it mined for additional tests in test_urlparse and perhaps even implementation or API enhancements in url.parse first.
(The latter becomes a lot more likely if the urischemes implementation passes tests that url.parse fails)
I also think, since I wrote this, the various urllib parsing methods were updated to return named tuple instances with properties, so a lot of the awkwardness of extracting partial values went away. (i.e. returning structured objects already raised the level of the urllib APIs from the "tuple-of-strings" level they used to be sitting at)
I do still assert that urischemes is slightly "higher level" than the current incarnation of similar functionality in urllib.parse. Universal Resource Identifiers are more encompassing than Universal Resource Locators and Universal Resource Names, and the new APIs explicitly deal with both kinds of URI. There are subtle differences in the assumptions you're allowed to make when you may have a URN rather than a URL, so I believe the current module sometimes does the wrong thing when given one of the former.
That said, it's been a long time since I've needed to remember the details, so I don't recall exactly where the current module gets URI handling wrong (or at least, did back in 2006). The intro to RFC 3986 is a good place to start in learning the differences though - Sir Tim writes good docs :)
akuchling commentedon Nov 13, 2013
Here's a slightly modified version of urischeme.py that can be run under Python 3 and compares its results with urllib.parse, printing out the mismatches.
The major differences seem to be 1) urischeme fills in the default port if it's not explicitly provided, e.g. http urls have the port set to 80, 2) the path is returned as '/', not the empty string, for the URL http://host, 3) urllib.parse.urljoin() doesn't get rid of ./ and ../ in URLs.
soreavis commentedon Jul 19, 2026
The test-mining this was kept open for looks done — I pulled the attachments (uriparse.py, testurlparse.py, akuchling's urischemes port) and ran their 129 urljoin cases against current main. Results:
http:gcase.uses_relativescheme gate (bpo-22118, 2014), and the empty-segment collapse (bpo-22278, 2014)..//../— since fixed by the RFC 3986 switch. The other two are deliberate:urllib.parsedoesn't fill scheme-default ports, and returns an empty path (not/) for an authority-only URL.With the module itself set aside in 2010, this looks closable as not planned.