A Python implementation of RFC 3986 including validation and authority parsing.
Use pip to install rfc3986 like so:
pip install rfc3986
The following are the two most common use cases envisioned for rfc3986.
To parse a URI and receive something very similar to the standard library's urllib.parse.urlparse
fromrfc3986importurlparsessh=urlparse('ssh://[email protected]:29418/openstack/glance.git') print(ssh.scheme) # => sshprint(ssh.userinfo) # => userprint(ssh.params) # => Noneprint(ssh.port) # => 29418To create a copy of it with new pieces you can use copy_with:
new_ssh=ssh.copy_with( scheme='https'userinfo='', port=443, path='/openstack/glance' ) print(new_ssh.scheme) # => httpsprint(new_ssh.userinfo) # => None# etc.To parse a URI into a convenient named tuple, you can simply:
fromrfc3986importuri_referenceexample=uri_reference('http://example.com') email=uri_reference('mailto:[email protected]') ssh=uri_reference('ssh://[email protected]:29418/openstack/keystone.git')With a parsed URI you can access data about the components:
print(example.scheme) # => httpprint(email.path) # => [email protected]print(ssh.userinfo) # => userprint(ssh.host) # => git.openstack.orgprint(ssh.port) # => 29418It can also parse URIs with unicode present:
uni=uri_reference(b'http://httpbin.org/get?utf8=\xe2\x98\x83') # ☃print(uni.query) # utf8=%E2%98%83With a parsed URI you can also validate it:
ifssh.is_valid(): subprocess.call(['git', 'clone', ssh.unsplit()])You can also take a parsed URI and normalize it:
mangled=uri_reference('hTTp://exAMPLe.COM') print(mangled.scheme) # => hTTpprint(mangled.authority) # => exAMPLe.COMnormal=mangled.normalize() print(normal.scheme) # => httpprint(mangled.authority) # => example.comBut these two URIs are (functionally) equivalent:
ifnormal==mangled: webbrowser.open(normal.unsplit())Your paths, queries, and fragments are safe with us though:
mangled=uri_reference('hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth') normal=mangled.normalize() assertnormal=='hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth'assertnormal=='http://example.com/Some/reallY/biZZare/pAth'assertnormal!='http://example.com/some/really/bizzare/path'If you do not actually need a real reference object and just want to normalize your URI:
fromrfc3986importnormalize_uriassert (normalize_uri('hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth') =='http://example.com/Some/reallY/biZZare/pAth')You can also very simply validate a URI:
fromrfc3986importis_valid_uriassertis_valid_uri('hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth')You can validate that a particular string is a valid URI and require independent components:
fromrfc3986importis_valid_uriassertis_valid_uri('http://localhost:8774/v2/resource', require_scheme=True, require_authority=True, require_path=True) # Assert that a mailto URI is invalid if you require an authority# componentassertis_valid_uri('mailto:[email protected]', require_authority=True) isFalseIf you have an instance of a URIReference, you can pass the same arguments to URIReference#is_valid, e.g.,
fromrfc3986importuri_referencehttp=uri_reference('http://localhost:8774/v2/resource') asserturi.is_valid(require_scheme=True, require_authority=True, require_path=True) # Assert that a mailto URI is invalid if you require an authority# componentmailto=uri_reference('mailto:[email protected]') asserturi.is_valid(require_authority=True) isFalseThis is a direct competitor to this library, with extra features, licensed under the GPL.
This can parse URIs in the manner of RFC 3986 but provides no validation and only recently added Python 3 support.
Standard library's urlparse/urllib.parse
The functions in these libraries can only split a URI (valid or not) and provide no validation.
This project follows and enforces the Python Software Foundation's Code of Conduct.
If you would like to contribute but do not have a bug or feature in mind, feel free to email Ian and find out how you can help.
The git repository for this project is maintained at https://github.com/python-hyper/rfc3986