diff -Nru python-uritools-1.0.2/CHANGES.rst python-uritools-2.1.0/CHANGES.rst --- python-uritools-1.0.2/CHANGES.rst 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/CHANGES.rst 2017-10-07 14:47:23.000000000 +0000 @@ -1,3 +1,37 @@ +v2.1.0 (2017-10-07) +------------------- + +- Add ``SplitResult.getauthority()``. + +- Add optional ``errors`` parameter to ``SplitResult.gethost()``. + + +v2.0.1 (2017-09-13) +------------------- + +- Officially support Python 3.6. + +- Move documentation to RTD. + +- Fix ``flake8`` checks. + + +v2.0.0 (2016-10-09) +------------------- + +- Drop Python 3.2 support (breaking change). + +- No longer treat semicolons as query separators by default (breaking + change). + +- Add optional ``sep`` parameter to ``SplitResult.getquerydict()`` and + ``SplitResult.getquerylist()`` (breaks ``encoding`` when passed as + positional argument). + +- Add optional ``querysep`` parameter to ``uricompose()`` (breaks + ``encoding`` when passed as positional argument). + + v1.0.2 (2016-04-08) ------------------- diff -Nru python-uritools-1.0.2/debian/changelog python-uritools-2.1.0/debian/changelog --- python-uritools-1.0.2/debian/changelog 2016-08-09 20:52:40.000000000 +0000 +++ python-uritools-2.1.0/debian/changelog 2018-05-01 21:15:38.000000000 +0000 @@ -1,3 +1,24 @@ +python-uritools (2.1.0-1) unstable; urgency=medium + + [ Ondřej Nový ] + * d/control: Set Vcs-* to salsa.debian.org + * d/copyright: Use https protocol in Format field + * d/watch: Use https protocol + + [ Stein Magnus Jodal ] + * New upstream release + * debian/clean + - Remove custom clean rules + * debian/control + - Require Python 3 >= 3.3 + - Require debhelper 10 + - Bump Standards-Version to 4.1.4, no changes required + - Use python3-sphinx unconditionally + * debian/copyright + - Update copyright years + + -- Stein Magnus Jodal Tue, 01 May 2018 23:15:38 +0200 + python-uritools (1.0.2-1) unstable; urgency=medium [ Ondřej Nový ] diff -Nru python-uritools-1.0.2/debian/clean python-uritools-2.1.0/debian/clean --- python-uritools-1.0.2/debian/clean 2016-08-09 20:50:44.000000000 +0000 +++ python-uritools-2.1.0/debian/clean 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -uritools.egg-info/* diff -Nru python-uritools-1.0.2/debian/compat python-uritools-2.1.0/debian/compat --- python-uritools-1.0.2/debian/compat 2016-08-09 20:50:44.000000000 +0000 +++ python-uritools-2.1.0/debian/compat 2018-05-01 21:13:10.000000000 +0000 @@ -1 +1 @@ -9 +10 diff -Nru python-uritools-1.0.2/debian/control python-uritools-2.1.0/debian/control --- python-uritools-1.0.2/debian/control 2016-08-09 20:52:06.000000000 +0000 +++ python-uritools-2.1.0/debian/control 2018-05-01 21:15:38.000000000 +0000 @@ -3,22 +3,22 @@ Priority: optional Maintainer: Debian Python Modules Team Uploaders: Stein Magnus Jodal , -Build-Depends: debhelper (>= 9), +Build-Depends: debhelper (>= 10), dh-python, - python-all (>= 2.7), + python-all, python-ipaddress, python-nose, python-setuptools, - python-sphinx | python3-sphinx, - python3-all (>= 3.2), + python3-all, python3-nose, python3-setuptools, -Standards-Version: 3.9.8 + python3-sphinx, +Standards-Version: 4.1.4 Homepage: https://github.com/tkem/uritools -Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/python-uritools.git -Vcs-Browser: https://anonscm.debian.org/cgit/python-modules/packages/python-uritools.git +Vcs-Git: https://salsa.debian.org/python-team/modules/python-uritools.git +Vcs-Browser: https://salsa.debian.org/python-team/modules/python-uritools X-Python-Version: >= 2.7 -X-Python3-Version: >= 3.2 +X-Python3-Version: >= 3.3 Package: python-uritools Architecture: all diff -Nru python-uritools-1.0.2/debian/copyright python-uritools-2.1.0/debian/copyright --- python-uritools-1.0.2/debian/copyright 2016-08-09 20:50:44.000000000 +0000 +++ python-uritools-2.1.0/debian/copyright 2018-05-01 21:15:38.000000000 +0000 @@ -1,14 +1,14 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: uritools Upstream-Contact: Thomas Kemmer Source: https://github.com/tkem/uritools Files: * -Copyright: 2014-2015 Thomas Kemmer +Copyright: 2014-2017 Thomas Kemmer License: Expat Files: debian/* -Copyright: 2015 Stein Magnus Jodal +Copyright: 2015-2018 Stein Magnus Jodal License: Expat License: Expat diff -Nru python-uritools-1.0.2/debian/.git-dpm python-uritools-2.1.0/debian/.git-dpm --- python-uritools-1.0.2/debian/.git-dpm 2016-08-09 20:50:44.000000000 +0000 +++ python-uritools-2.1.0/debian/.git-dpm 2018-05-01 21:09:42.000000000 +0000 @@ -1,11 +1,11 @@ # see git-dpm(1) from git-dpm package -1f4a349a5b1719fa1b6d6a6907f42e8eed030f8e -1f4a349a5b1719fa1b6d6a6907f42e8eed030f8e -1f4a349a5b1719fa1b6d6a6907f42e8eed030f8e -1f4a349a5b1719fa1b6d6a6907f42e8eed030f8e -python-uritools_1.0.2.orig.tar.gz -1cfb384eae97d5667967eef525fe0a8a0440bcbc -19914 +16358ddb8130b728652fa0278bafb05d247ff66d +16358ddb8130b728652fa0278bafb05d247ff66d +16358ddb8130b728652fa0278bafb05d247ff66d +16358ddb8130b728652fa0278bafb05d247ff66d +python-uritools_2.1.0.orig.tar.gz +668ecd7ad14b9c04a67674ccd0d5a4efebaa4a11 +22284 debianTag="debian/%e%v" patchedTag="patched/%e%v" upstreamTag="upstream/%e%u" diff -Nru python-uritools-1.0.2/debian/watch python-uritools-2.1.0/debian/watch --- python-uritools-1.0.2/debian/watch 2016-08-09 20:50:44.000000000 +0000 +++ python-uritools-2.1.0/debian/watch 2018-05-01 21:09:42.000000000 +0000 @@ -1,3 +1,3 @@ version=3 opts=uversionmangle=s/(rc|a|b|c)/~$1/ \ -http://pypi.debian.net/uritools/uritools-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) +https://pypi.debian.net/uritools/uritools-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) diff -Nru python-uritools-1.0.2/docs/conf.py python-uritools-2.1.0/docs/conf.py --- python-uritools-1.0.2/docs/conf.py 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/docs/conf.py 2017-09-13 20:41:57.000000000 +0000 @@ -4,8 +4,9 @@ metadata = dict(findall(r"__([a-z]+)__ = '([^']+)'", f.read())) return metadata['version'] + project = 'uritools' -copyright = '2014-2016 Thomas Kemmer' +copyright = '2014-2017 Thomas Kemmer' version = get_version(b'../uritools/__init__.py') release = version diff -Nru python-uritools-1.0.2/docs/index.rst python-uritools-2.1.0/docs/index.rst --- python-uritools-1.0.2/docs/index.rst 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/docs/index.rst 2017-09-13 20:40:36.000000000 +0000 @@ -9,26 +9,22 @@ .. code-block:: pycon - >>> from uritools import urisplit, uriunsplit, urijoin, uridefrag - >>> parts = urisplit('foo://user@example.com:8042/over/there?name=ferret#nose') - >>> parts - SplitResult(scheme='foo', authority='user@example.com:8042', path='/over/there', query='name=ferret', fragment='nose') + >>> from uritools import uricompose, urijoin, urisplit, uriunsplit + >>> uricompose(scheme='foo', host='example.com', port=8042, + ... path='/over/there', query={'name': 'ferret'}, + ... fragment='nose') + 'foo://example.com:8042/over/there?name=ferret#nose' + >>> parts = urisplit(_) >>> parts.scheme 'foo' >>> parts.authority - 'user@example.com:8042' - >>> parts.userinfo - 'user' - >>> parts.host - 'example.com' - >>> parts.port - '8042' - >>> uriunsplit(parts[:3] + ('name=swallow&type=African', 'beak')) - 'foo://user@example.com:8042/over/there?name=swallow&type=African#beak' - >>> urijoin('http://www.cwi.nl/~guido/Python.html', 'FAQ.html') - 'http://www.cwi.nl/~guido/FAQ.html' - >>> uridefrag('http://pythonhosted.org/uritools/index.html#constants') - DefragResult(uri='http://pythonhosted.org/uritools/index.html', fragment='constants') + 'example.com:8042' + >>> parts.getport(default=80) + 8042 + >>> parts.getquerydict().get('name') + ['ferret'] + >>> urijoin(uriunsplit(parts), '/right/here?name=swallow#beak') + 'foo://example.com:8042/right/here?name=swallow#beak' For various reasons, the Python 2 :mod:`urlparse` module is not compliant with current Internet standards, does not include Unicode @@ -37,7 +33,7 @@ other issues still remain. As stated in `Lib/urllib/parse.py `_:: - FC 3986 is considered the current standard and any future changes + RFC 3986 is considered the current standard and any future changes to urlparse module should conform with it. The urlparse module is currently not entirely compliant with this RFC due to defacto scenarios for parsing, and for backward compatibility purposes, @@ -54,7 +50,7 @@ The current Internet standard (STD66) defining URI syntax, to which any changes to :mod:`uritools` should conform. If deviations are observed, the module's implementation should be - changed, even if this means breaking backward compatiblity. + changed, even if this means breaking backward compatibility. URI Decomposition @@ -116,17 +112,20 @@ .. autofunction:: uricompose - `authority` may be a Unicode string, :class:`bytes` object, or a - three-item iterable specifying userinfo, host and port - subcomponents. If both `authority` and any of the `userinfo`, - `host` or `port` keyword arguments are given, the keyword argument - will override the corresponding `authority` subcomponent. - - If `query` is a mapping object or a sequence of two-element tuples, - it will be converted to a string of `name=value` pairs seperated by - `&`. + All components may be specified as either Unicode strings, which + will be encoded according to `encoding`, or :class:`bytes` objects. - The returned value is of type :class:`str`. + `authority` may also be passed a three-item iterable specifying + userinfo, host and port subcomponents. If both `authority` and any + of the `userinfo`, `host` or `port` keyword arguments are given, + the keyword argument will override the corresponding `authority` + subcomponent. + + `query` may also be passed a mapping object or a sequence of + two-element tuples, which will be converted to a string of + `name=value` pairs separated by `querysep`. + + The returned URI is of type :class:`str`. .. autofunction:: urijoin diff -Nru python-uritools-1.0.2/LICENSE python-uritools-2.1.0/LICENSE --- python-uritools-1.0.2/LICENSE 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/LICENSE 2017-10-07 14:47:23.000000000 +0000 @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2016 Thomas Kemmer +Copyright (c) 2014-2017 Thomas Kemmer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff -Nru python-uritools-1.0.2/PKG-INFO python-uritools-2.1.0/PKG-INFO --- python-uritools-1.0.2/PKG-INFO 2016-04-08 13:39:31.000000000 +0000 +++ python-uritools-2.1.0/PKG-INFO 2017-10-07 14:48:13.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: uritools -Version: 1.0.2 +Version: 2.1.0 Summary: RFC 3986 compliant, Unicode-aware, scheme-agnostic replacement for urlparse Home-page: https://github.com/tkem/uritools/ Author: Thomas Kemmer Author-email: tkemmer@computer.org License: MIT +Description-Content-Type: UNKNOWN Description: uritools ======================================================================== @@ -15,26 +16,22 @@ .. code-block:: pycon - >>> from uritools import urisplit, uriunsplit, urijoin, uridefrag - >>> parts = urisplit('foo://user@example.com:8042/over/there?name=ferret#nose') - >>> parts - SplitResult(scheme='foo', authority='user@example.com:8042', path='/over/there', query='name=ferret', fragment='nose') + >>> from uritools import uricompose, urijoin, urisplit, uriunsplit + >>> uricompose(scheme='foo', host='example.com', port=8042, + ... path='/over/there', query={'name': 'ferret'}, + ... fragment='nose') + 'foo://example.com:8042/over/there?name=ferret#nose' + >>> parts = urisplit(_) >>> parts.scheme 'foo' >>> parts.authority - 'user@example.com:8042' - >>> parts.userinfo - 'user' - >>> parts.host - 'example.com' - >>> parts.port - '8042' - >>> uriunsplit(parts[:3] + ('name=swallow&type=African', 'beak')) - 'foo://user@example.com:8042/over/there?name=swallow&type=African#beak' - >>> urijoin('http://www.cwi.nl/~guido/Python.html', 'FAQ.html') - 'http://www.cwi.nl/~guido/FAQ.html' - >>> uridefrag('http://pythonhosted.org/uritools/index.html#constants') - DefragResult(uri='http://pythonhosted.org/uritools/index.html', fragment='constants') + 'example.com:8042' + >>> parts.getport(default=80) + 8042 + >>> parts.getquerydict().get('name') + ['ferret'] + >>> urijoin(uriunsplit(parts), '/right/here?name=swallow#beak') + 'foo://example.com:8042/right/here?name=swallow#beak' For various reasons, the Python 2 ``urlparse`` module is not compliant with current Internet standards, does not include Unicode support, and @@ -70,10 +67,6 @@ :target: https://pypi.python.org/pypi/uritools/ :alt: Latest PyPI version - .. image:: http://img.shields.io/pypi/dm/uritools.svg?style=flat - :target: https://pypi.python.org/pypi/uritools/ - :alt: Number of PyPI downloads - .. image:: http://img.shields.io/travis/tkem/uritools/master.svg?style=flat :target: https://travis-ci.org/tkem/uritools/ :alt: Travis CI build status @@ -82,7 +75,10 @@ :target: https://coveralls.io/r/tkem/uritools :alt: Test coverage - - `Documentation`_ + .. image:: https://readthedocs.org/projects/uritools/badge/?version=latest&style=flat + :target: http://uritools.readthedocs.io/en/latest/ + :alt: Documentation Status + - `Issue Tracker`_ - `Source Code`_ - `Change Log`_ @@ -91,12 +87,11 @@ License ------------------------------------------------------------------------ - Copyright (c) 2014-2016 Thomas Kemmer. + Copyright (c) 2014-2017 Thomas Kemmer. Licensed under the `MIT License`_. - .. _Documentation: http://pythonhosted.org/uritools/ .. _Issue Tracker: https://github.com/tkem/uritools/issues/ .. _Source Code: https://github.com/tkem/uritools/ .. _Change Log: https://github.com/tkem/uritools/blob/master/CHANGES.rst @@ -104,7 +99,7 @@ Keywords: uri url urlparse urlsplit urljoin urldefrag Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta +Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Other Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License @@ -113,9 +108,9 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Internet Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -Nru python-uritools-1.0.2/README.rst python-uritools-2.1.0/README.rst --- python-uritools-1.0.2/README.rst 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/README.rst 2017-09-13 21:09:59.000000000 +0000 @@ -7,26 +7,22 @@ .. code-block:: pycon - >>> from uritools import urisplit, uriunsplit, urijoin, uridefrag - >>> parts = urisplit('foo://user@example.com:8042/over/there?name=ferret#nose') - >>> parts - SplitResult(scheme='foo', authority='user@example.com:8042', path='/over/there', query='name=ferret', fragment='nose') + >>> from uritools import uricompose, urijoin, urisplit, uriunsplit + >>> uricompose(scheme='foo', host='example.com', port=8042, + ... path='/over/there', query={'name': 'ferret'}, + ... fragment='nose') + 'foo://example.com:8042/over/there?name=ferret#nose' + >>> parts = urisplit(_) >>> parts.scheme 'foo' >>> parts.authority - 'user@example.com:8042' - >>> parts.userinfo - 'user' - >>> parts.host - 'example.com' - >>> parts.port - '8042' - >>> uriunsplit(parts[:3] + ('name=swallow&type=African', 'beak')) - 'foo://user@example.com:8042/over/there?name=swallow&type=African#beak' - >>> urijoin('http://www.cwi.nl/~guido/Python.html', 'FAQ.html') - 'http://www.cwi.nl/~guido/FAQ.html' - >>> uridefrag('http://pythonhosted.org/uritools/index.html#constants') - DefragResult(uri='http://pythonhosted.org/uritools/index.html', fragment='constants') + 'example.com:8042' + >>> parts.getport(default=80) + 8042 + >>> parts.getquerydict().get('name') + ['ferret'] + >>> urijoin(uriunsplit(parts), '/right/here?name=swallow#beak') + 'foo://example.com:8042/right/here?name=swallow#beak' For various reasons, the Python 2 ``urlparse`` module is not compliant with current Internet standards, does not include Unicode support, and @@ -62,10 +58,6 @@ :target: https://pypi.python.org/pypi/uritools/ :alt: Latest PyPI version -.. image:: http://img.shields.io/pypi/dm/uritools.svg?style=flat - :target: https://pypi.python.org/pypi/uritools/ - :alt: Number of PyPI downloads - .. image:: http://img.shields.io/travis/tkem/uritools/master.svg?style=flat :target: https://travis-ci.org/tkem/uritools/ :alt: Travis CI build status @@ -74,7 +66,10 @@ :target: https://coveralls.io/r/tkem/uritools :alt: Test coverage -- `Documentation`_ +.. image:: https://readthedocs.org/projects/uritools/badge/?version=latest&style=flat + :target: http://uritools.readthedocs.io/en/latest/ + :alt: Documentation Status + - `Issue Tracker`_ - `Source Code`_ - `Change Log`_ @@ -83,12 +78,11 @@ License ------------------------------------------------------------------------ -Copyright (c) 2014-2016 Thomas Kemmer. +Copyright (c) 2014-2017 Thomas Kemmer. Licensed under the `MIT License`_. -.. _Documentation: http://pythonhosted.org/uritools/ .. _Issue Tracker: https://github.com/tkem/uritools/issues/ .. _Source Code: https://github.com/tkem/uritools/ .. _Change Log: https://github.com/tkem/uritools/blob/master/CHANGES.rst diff -Nru python-uritools-1.0.2/setup.cfg python-uritools-2.1.0/setup.cfg --- python-uritools-1.0.2/setup.cfg 2016-04-08 13:39:31.000000000 +0000 +++ python-uritools-2.1.0/setup.cfg 2017-10-07 14:48:13.000000000 +0000 @@ -12,8 +12,9 @@ [upload_sphinx] upload-dir = docs/_build/html +[tool:pytest] + [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -Nru python-uritools-1.0.2/setup.py python-uritools-2.1.0/setup.py --- python-uritools-1.0.2/setup.py 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/setup.py 2017-09-13 21:09:59.000000000 +0000 @@ -5,10 +5,8 @@ # environment markers require a recent setuptools and/or pip version if sys.version_info >= (3, 3) or 'bdist_wheel' in sys.argv: install_requires = [] -elif sys.version_info >= (3, 0): - install_requires = ['ipaddress>=1.0.7'] else: - install_requires = ['ipaddress>=1.0.6'] + install_requires = ['ipaddress'] def get_version(filename): @@ -17,6 +15,7 @@ metadata = dict(findall("__([a-z]+)__ = '([^']+)'", f.read())) return metadata['version'] + setup( name='uritools', version=get_version('uritools/__init__.py'), @@ -33,11 +32,10 @@ packages=find_packages(exclude=['tests', 'tests.*']), install_requires=install_requires, extras_require={ - ':python_version == "2.7"': ['ipaddress>=1.0.6'], - ':python_version == "3.2"': ['ipaddress>=1.0.7'] + ':python_version == "2.7"': ['ipaddress'] }, classifiers=[ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Environment :: Other Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', @@ -46,10 +44,10 @@ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Internet', 'Topic :: Software Development :: Libraries :: Python Modules' ] diff -Nru python-uritools-1.0.2/tests/test_compose.py python-uritools-2.1.0/tests/test_compose.py --- python-uritools-1.0.2/tests/test_compose.py 2016-04-04 07:07:07.000000000 +0000 +++ python-uritools-2.1.0/tests/test_compose.py 2016-10-09 16:52:32.000000000 +0000 @@ -205,9 +205,9 @@ ('?name=a:b:c', dict(name='a:b:c')), ('?name=a?b?c', dict(name='a?b?c')), ('?name=a@b@c', dict(name='a@b@c')), + ('?name=a;b;c', dict(name='a;b;c')), ('?name=a%23b%23c', dict(name='a#b#c')), ('?name=a%26b%26c', dict(name='a&b&c')), - ('?name=a%3Bb%3Bc', dict(name='a;b;c')), ] for uri, query in cases: self.check(uri, query=query) @@ -215,3 +215,13 @@ for query in (0, [1]): with self.assertRaises(TypeError, msg='query=%r' % query): uricompose(query=query) + + def test_query_sep(self): + cases = [ + ('&', '?x=foo&y=bar', [('x', 'foo'), ('y', 'bar')]), + (';', '?x=foo;y=bar', [('x', 'foo'), ('y', 'bar')]), + ('&', '?x=foo;y=bar', [('x', 'foo;y=bar')]), + (';', '?x=foo&y=bar', [('x', 'foo&y=bar')]) + ] + for sep, uri, query in cases: + self.check(uri, query=query, querysep=sep) diff -Nru python-uritools-1.0.2/tests/test_split.py python-uritools-2.1.0/tests/test_split.py --- python-uritools-1.0.2/tests/test_split.py 2016-04-04 07:07:07.000000000 +0000 +++ python-uritools-2.1.0/tests/test_split.py 2017-10-07 14:47:23.000000000 +0000 @@ -82,6 +82,7 @@ self.assertEqual(result.port, '8042') self.assertEqual(result.geturi(), uri) self.assertEqual(result.getscheme(), 'foo') + self.assertEqual(result.getauthority(), ('user', 'example.com', 8042)) self.assertEqual(result.getuserinfo(), 'user') self.assertEqual(result.gethost(), 'example.com') self.assertEqual(result.getport(), 8042) @@ -103,6 +104,7 @@ self.assertEqual(result.port, None) self.assertEqual(result.geturi(), uri) self.assertEqual(result.getscheme(), 'urn') + self.assertEqual(result.getauthority(), (None, None, None)) self.assertEqual(result.getuserinfo(), None) self.assertEqual(result.gethost(), None) self.assertEqual(result.getport(), None) @@ -124,6 +126,7 @@ self.assertEqual(result.port, None) self.assertEqual(result.geturi(), uri) self.assertEqual(result.getscheme(), 'file') + self.assertEqual(result.getauthority(), (None, '', None)) self.assertEqual(result.getuserinfo(), None) self.assertEqual(result.gethost(), '') self.assertEqual(result.getport(), None) @@ -145,6 +148,7 @@ self.assertEqual(result.port, b'8042') self.assertEqual(result.geturi(), uri) self.assertEqual(result.getscheme(), 'foo') + self.assertEqual(result.getauthority(), ('user', 'example.com', 8042)) self.assertEqual(result.getuserinfo(), 'user') self.assertEqual(result.gethost(), 'example.com') self.assertEqual(result.getport(), 8042) @@ -166,6 +170,7 @@ self.assertEqual(result.port, None) self.assertEqual(result.geturi(), uri) self.assertEqual(result.getscheme(), 'urn') + self.assertEqual(result.getauthority(), (None, None, None)) self.assertEqual(result.getuserinfo(), None) self.assertEqual(result.gethost(), None) self.assertEqual(result.getport(), None) @@ -187,6 +192,7 @@ self.assertEqual(result.port, None) self.assertEqual(result.geturi(), uri) self.assertEqual(result.getscheme(), 'file') + self.assertEqual(result.getauthority(), (None, '', None)) self.assertEqual(result.getuserinfo(), None) self.assertEqual(result.gethost(), '') self.assertEqual(result.getport(), None) @@ -202,6 +208,51 @@ self.assertEqual(urisplit(b'foo').getscheme(default='bar'), 'bar') self.assertEqual(urisplit(b'FOO_BAR:/').getscheme(), 'foo_bar') + def test_getauthority(self): + from ipaddress import IPv4Address, IPv6Address + cases = [ + ('urn:example:animal:ferret:nose', + None, + (None, None, None)), + ('file:///', + None, + (None, '', None)), + ('http://userinfo@Test.python.org:5432/foo/', + None, + ('userinfo', 'test.python.org', 5432)), + ('http://userinfo@12.34.56.78:5432/foo/', + None, + ('userinfo', IPv4Address('12.34.56.78'), 5432)), + ('http://userinfo@[::1]:5432/foo/', + None, + ('userinfo', IPv6Address('::1'), 5432)), + ('urn:example:animal:ferret:nose', + ('nobody', 'localhost', 42), + ('nobody', 'localhost', 42)), + ('file:///', + ('nobody', 'localhost', 42), + ('nobody', 'localhost', 42)), + ('http://Test.python.org/foo/', + ('nobody', 'localhost', 42), + ('nobody', 'test.python.org', 42)), + ('http://userinfo@Test.python.org/foo/', + ('nobody', 'localhost', 42), + ('userinfo', 'test.python.org', 42)), + ('http://Test.python.org:5432/foo/', + ('nobody', 'localhost', 42), + ('nobody', 'test.python.org', 5432)), + ('http://userinfo@Test.python.org:5432/foo/', + ('nobody', 'localhost', 42), + ('userinfo', 'test.python.org', 5432)), + ] + for uri, default, authority in cases: + self.assertEqual(urisplit(uri).getauthority(default), authority) + for uri in ['http://[::1/', 'http://::1]/']: + with self.assertRaises(ValueError, msg='%r' % uri): + urisplit(uri).getauthority() + with self.assertRaises(ValueError, msg='%r' % uri): + urisplit(uri.encode()).getauthority() + def test_gethost(self): from ipaddress import IPv4Address, IPv6Address cases = [ @@ -269,38 +320,58 @@ def test_getquery(self): cases = [ - ("?", [], {}), - ("?&", [], {}), - ("?&&", [], {}), - ("?=", + ('', [], {}), + ('?', [], {}), + ('?&', [], {}), + ('?&&', [], {}), + ('?=', [('', '')], {'': ['']}), - ("?=a", + ('?=a', [('', 'a')], {'': ['a']}), - ("?a", + ('?a', [('a', None)], {'a': [None]}), - ("?a=", + ('?a=', [('a', '')], {'a': ['']}), - ("?&a=b", + ('?&a=b', [('a', 'b')], {'a': ['b']}), - ("?a=a+b&b=b+c", + ('?a=a+b&b=b+c', [('a', 'a+b'), ('b', 'b+c')], {'a': ['a+b'], 'b': ['b+c']}), - ("?a=a%20b&b=b%20c", + ('?a=a%20b&b=b%20c', [('a', 'a b'), ('b', 'b c')], {'a': ['a b'], 'b': ['b c']}), - ("?a=1&a=2", + ('?a=1&a=2', [('a', '1'), ('a', '2')], {'a': ['1', '2']}), ] for query, querylist, querydict in cases: - self.assertEqual(urisplit(query).getquerylist(), querylist, + parts = urisplit(query) + self.assertEqual(parts.getquerylist(), querylist, 'Error parsing query dict for %r' % query) - self.assertEqual(urisplit(query).getquerydict(), querydict, + self.assertEqual(parts.getquerydict(), querydict, + 'Error parsing query list for %r' % query) + + def test_getquerysep(self): + cases = [ + ('&', '?a=b', [('a', 'b')]), + (';', '?a=b', [('a', 'b')]), + ('&', '?a=a+b&b=b+c', [('a', 'a+b'), ('b', 'b+c')]), + (';', '?a=a+b;b=b+c', [('a', 'a+b'), ('b', 'b+c')]), + ('&', '?a=a+b;b=b+c', [('a', 'a+b;b=b+c')]), + (';', '?a=a+b&b=b+c', [('a', 'a+b&b=b+c')]), + ('&', '?a&b', [('a', None), ('b', None)]), + (';', '?a;b', [('a', None), ('b', None)]), + (b'&', u'?a&b', [('a', None), ('b', None)]), + (u'&', b'?a&b', [('a', None), ('b', None)]), + ] + for sep, query, querylist in cases: + parts = urisplit(query) + self.assertEqual(parts.getquerylist(sep), querylist, 'Error parsing query list for %r' % query) def test_ip_literal(self): diff -Nru python-uritools-1.0.2/tox.ini python-uritools-2.1.0/tox.ini --- python-uritools-1.0.2/tox.ini 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/tox.ini 2017-09-13 21:09:59.000000000 +0000 @@ -2,9 +2,8 @@ envlist = check-manifest,docs,flake8,py [testenv] -# coverage 4.0 drops Python 3.2 compatibility deps = - coverage<4 + coverage pytest pytest-cov commands = diff -Nru python-uritools-1.0.2/uritools/compose.py python-uritools-2.1.0/uritools/compose.py --- python-uritools-1.0.2/uritools/compose.py 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/uritools/compose.py 2016-10-09 16:52:32.000000000 +0000 @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import ipaddress import numbers import re @@ -10,12 +8,15 @@ from .encoding import uriencode from .split import uriunsplit +_unicode = type(u'') +_strtypes = (bytes, _unicode) + # RFC 3986 3.1: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) -_SCHEME_RE = re.compile(br"\A[A-Za-z][A-Za-z0-9+.-]*\Z") +_SCHEME_RE = re.compile(b'^[A-Za-z][A-Za-z0-9+.-]*$') # RFC 3986 3.2: authority = [ userinfo "@" ] host [ ":" port ] -_AUTHORITY_RE_BYTES = re.compile(br"\A(?:(.*)@)?(.*?)(?::([0-9]*))?\Z") -_AUTHORITY_RE_STRING = re.compile(r"\A(?:(.*)@)?(.*?)(?::([0-9]*))?\Z") +_AUTHORITY_RE_BYTES = re.compile(b'^(?:(.*)@)?(.*?)(?::([0-9]*))?$') +_AUTHORITY_RE_UNICODE = re.compile(u'^(?:(.*)@)?(.*?)(?::([0-9]*))?$') # safe component characters _SAFE_USERINFO = SUB_DELIMS + ':' @@ -91,35 +92,39 @@ return b'' -def _querylist(items, encoding, safe=re.sub('[;&]', '', _SAFE_QUERY)): +def _querylist(items, sep, encoding): terms = [] append = terms.append + safe = _SAFE_QUERY.replace(sep, '') for key, value in items: name = uriencode(key, safe, encoding) if value is None: append(name) - elif isinstance(value, (bytes, type(''))): + elif isinstance(value, _strtypes): append(name + b'=' + uriencode(value, safe, encoding)) else: append(name + b'=' + uriencode(str(value), safe, encoding)) - return b'&'.join(terms) + if isinstance(sep, bytes): + return sep.join(terms) + else: + return sep.encode('ascii').join(terms) -def _querydict(mapping, encoding): +def _querydict(mapping, sep, encoding): items = [] for key, value in mapping.items(): - if isinstance(value, (bytes, type(''))): + if isinstance(value, _strtypes): items.append((key, value)) elif isinstance(value, Iterable): items.extend([(key, v) for v in value]) else: items.append((key, value)) - return _querylist(items, encoding) + return _querylist(items, sep, encoding) def uricompose(scheme=None, authority=None, path='', query=None, fragment=None, userinfo=None, host=None, port=None, - encoding='utf-8'): + querysep='&', encoding='utf-8'): """Compose a URI string from its individual components.""" # RFC 3986 3.1: Scheme names consist of a sequence of characters @@ -141,8 +146,8 @@ authority = (None, None, None) elif isinstance(authority, bytes): authority = _AUTHORITY_RE_BYTES.match(authority).groups() - elif isinstance(authority, type('')): - authority = _AUTHORITY_RE_STRING.match(authority).groups() + elif isinstance(authority, _unicode): + authority = _AUTHORITY_RE_UNICODE.match(authority).groups() elif not isinstance(authority, Iterable): raise TypeError('Invalid authority type') elif len(authority) != 3: @@ -184,12 +189,12 @@ # pairs and one frequently used value is a reference to another # URI, it is sometimes better for usability to avoid percent- # encoding those characters. - if isinstance(query, (bytes, type(''))): + if isinstance(query, _strtypes): query = uriencode(query, _SAFE_QUERY, encoding) elif isinstance(query, Mapping): - query = _querydict(query, encoding) + query = _querydict(query, querysep, encoding) elif isinstance(query, Iterable): - query = _querylist(query, encoding) + query = _querylist(query, querysep, encoding) elif query is not None: raise TypeError('Invalid query type') diff -Nru python-uritools-1.0.2/uritools/defrag.py python-uritools-2.1.0/uritools/defrag.py --- python-uritools-1.0.2/uritools/defrag.py 2016-04-04 07:07:07.000000000 +0000 +++ python-uritools-2.1.0/uritools/defrag.py 2016-10-09 16:52:32.000000000 +0000 @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import collections from .encoding import uridecode @@ -18,7 +16,7 @@ elif isinstance(fragment, bytes): return self.uri + b'#' + fragment else: - return self.uri + '#' + fragment + return self.uri + u'#' + fragment def getfragment(self, default=None, encoding='utf-8', errors='strict'): """Return the decoded fragment identifier, or `default` if the @@ -37,5 +35,5 @@ if isinstance(uristring, bytes): parts = uristring.partition(b'#') else: - parts = uristring.partition('#') + parts = uristring.partition(u'#') return DefragResult(parts[0], parts[2] if parts[1] else None) diff -Nru python-uritools-1.0.2/uritools/encoding.py python-uritools-2.1.0/uritools/encoding.py --- python-uritools-1.0.2/uritools/encoding.py 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/uritools/encoding.py 2017-09-13 20:42:27.000000000 +0000 @@ -2,15 +2,22 @@ from .chars import UNRESERVED +if isinstance(chr(0), bytes): + _fromint = chr +else: + def _fromint(i): return bytes([i]) + try: _fromhex = bytes.fromhex except AttributeError: def _fromhex(x): return chr(int(x, 16)) -if isinstance(chr(0), bytes): - _fromint = chr +try: + 0 in b'' +except TypeError: + def _tointseq(b): return memoryview(b).tolist() else: - def _fromint(i): return bytes([i]) + def _tointseq(b): return b # RFC 3986 2.1: For consistency, URI producers and normalizers should @@ -18,7 +25,8 @@ def _pctenc(byte): return ('%%%02X' % byte).encode() -_unreserved = frozenset(memoryview(UNRESERVED.encode('ascii')).tolist()) + +_unreserved = frozenset(_tointseq(UNRESERVED.encode())) _encoded = { b'': [_fromint(i) if i in _unreserved else _pctenc(i) for i in range(256)] @@ -31,29 +39,25 @@ def uriencode(uristring, safe='', encoding='utf-8', errors='strict'): """Encode a URI string or string component.""" - if isinstance(uristring, bytes): - values = memoryview(uristring).tolist() - else: - values = memoryview(uristring.encode(encoding, errors)).tolist() + if not isinstance(uristring, bytes): + uristring = uristring.encode(encoding, errors) if not isinstance(safe, bytes): safe = safe.encode('ascii') try: - encode = _encoded[safe].__getitem__ + encoded = _encoded[safe] except KeyError: - enclist = _encoded[b''][:] - for i in memoryview(safe).tolist(): - enclist[i] = _fromint(i) - _encoded[safe] = enclist - encode = enclist.__getitem__ - return b''.join(map(encode, values)) + encoded = _encoded[b''][:] + for i in _tointseq(safe): + encoded[i] = _fromint(i) + _encoded[safe] = encoded + return b''.join(map(encoded.__getitem__, _tointseq(uristring))) def uridecode(uristring, encoding='utf-8', errors='strict'): """Decode a URI string or string component.""" - if isinstance(uristring, bytes): - parts = uristring.split(b'%') - else: - parts = uristring.encode(encoding or 'ascii', errors).split(b'%') + if not isinstance(uristring, bytes): + uristring = uristring.encode(encoding or 'ascii', errors) + parts = uristring.split(b'%') result = [parts[0]] append = result.append decode = _decoded.get diff -Nru python-uritools-1.0.2/uritools/__init__.py python-uritools-2.1.0/uritools/__init__.py --- python-uritools-1.0.2/uritools/__init__.py 2016-04-08 13:38:44.000000000 +0000 +++ python-uritools-2.1.0/uritools/__init__.py 2017-10-07 14:47:23.000000000 +0000 @@ -30,4 +30,4 @@ 'uriunsplit' ) -__version__ = '1.0.2' +__version__ = '2.1.0' diff -Nru python-uritools-1.0.2/uritools/join.py python-uritools-2.1.0/uritools/join.py --- python-uritools-1.0.2/uritools/join.py 2016-04-04 07:07:07.000000000 +0000 +++ python-uritools-2.1.0/uritools/join.py 2016-10-09 16:52:32.000000000 +0000 @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from .split import urisplit diff -Nru python-uritools-1.0.2/uritools/split.py python-uritools-2.1.0/uritools/split.py --- python-uritools-1.0.2/uritools/split.py 2016-04-04 07:07:07.000000000 +0000 +++ python-uritools-2.1.0/uritools/split.py 2017-10-07 14:47:23.000000000 +0000 @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import collections import ipaddress import re @@ -26,7 +24,7 @@ # appropriate error for "address mechanism not supported". if isinstance(address, bytes): address = address.decode('ascii') - if address.startswith('v'): + if address.startswith(u'v'): raise ValueError('address mechanism not supported') return ipaddress.IPv6Address(address) @@ -110,6 +108,25 @@ else: return scheme.lower() + def getauthority(self, default=None, encoding='utf-8', errors='strict'): + """Return the decoded userinfo, host and port subcomponents of the URI + authority as a three-item tuple. + + """ + # TBD: (userinfo, host, port) kwargs, default string? + if default is None: + default = (None, None, None) + elif not isinstance(default, collections.Iterable): + raise TypeError('Invalid default type') + elif len(default) != 3: + raise ValueError('Invalid default length') + # TODO: this could be much more efficient by using a dedicated regex + return ( + self.getuserinfo(default[0], encoding, errors), + self.gethost(default[1], errors), + self.getport(default[2]) + ) + def getuserinfo(self, default=None, encoding='utf-8', errors='strict'): """Return the decoded userinfo subcomponent of the URI authority, or `default` if the original URI did not contain a userinfo @@ -122,7 +139,7 @@ else: return uridecode(userinfo, encoding, errors) - def gethost(self, default=None): + def gethost(self, default=None, errors='strict'): """Return the decoded host subcomponent of the URI authority as a string or an :mod:`ipaddress` address object, or `default` if the original URI did not contain a host. @@ -134,9 +151,9 @@ elif host.startswith(self.LBRACKET) and host.endswith(self.RBRACKET): return _ip_literal(host[1:-1]) elif host.startswith(self.LBRACKET) or host.endswith(self.RBRACKET): - raise ValueError('Invalid host %r' % host) # FIXME: remove? - else: - return _ipv4_address(host) or uridecode(host, 'utf-8').lower() + raise ValueError('Invalid host %r' % host) + # TODO: faster check for IPv4 address? + return _ipv4_address(host) or uridecode(host, 'utf-8', errors).lower() def getport(self, default=None): """Return the port subcomponent of the URI authority as an @@ -166,32 +183,34 @@ else: return uridecode(query, encoding, errors) - def getquerydict(self, encoding='utf-8', errors='strict'): - """Split the query component into individual `name=value` pairs and - return a dictionary of query variables. The dictionary keys - are the unique query variable names and the values are lists - of values for each name. + def getquerydict(self, sep='&', encoding='utf-8', errors='strict'): + """Split the query component into individual `name=value` pairs + separated by `sep` and return a dictionary of query variables. + The dictionary keys are the unique query variable names and + the values are lists of values for each name. """ dict = collections.defaultdict(list) - for name, value in self.getquerylist(encoding, errors): + for name, value in self.getquerylist(sep, encoding, errors): dict[name].append(value) return dict - def getquerylist(self, encoding='utf-8', errors='strict'): - """Split the query component into individual `name=value` pairs and - return a list of `(name, value)` tuples. + def getquerylist(self, sep='&', encoding='utf-8', errors='strict'): + """Split the query component into individual `name=value` pairs + separated by `sep`, and return a list of `(name, value)` + tuples. """ - if self.query: - qsl = [self.query] - else: + if not self.query: return [] - for sep in self.QUERYSEP: - qsl = [s for qs in qsl for s in qs.split(sep) if s] + elif isinstance(sep, type(self.query)): + qsl = self.query.split(sep) + elif isinstance(sep, bytes): + qsl = self.query.split(sep.decode('ascii')) + else: + qsl = self.query.split(sep.encode('ascii')) items = [] - for qs in qsl: - parts = qs.partition(self.EQ) + for parts in [qs.partition(self.EQ) for qs in qsl if qs]: name = uridecode(parts[0], encoding, errors) if parts[1]: value = uridecode(parts[2], encoding, errors) @@ -295,10 +314,8 @@ DIGITS = b'0123456789' - QUERYSEP = (b';', b'&') - -class SplitResultString(SplitResult): +class SplitResultUnicode(SplitResult): __slots__ = () # prevent creation of instance dictionary @@ -312,16 +329,16 @@ """, flags=re.VERBOSE) # RFC 3986 2.2 gen-delims - COLON, SLASH, QUEST, HASH, LBRACKET, RBRACKET, AT = ':/?#[]@' + COLON, SLASH, QUEST, HASH, LBRACKET, RBRACKET, AT = ( + u':', u'/', u'?', u'#', u'[', u']', u'@' + ) # RFC 3986 3.3 dot-segments - DOT, DOTDOT = '.', '..' - - EMPTY, EQ = '', '=' + DOT, DOTDOT = u'.', u'..' - DIGITS = '0123456789' + EMPTY, EQ = u'', u'=' - QUERYSEP = ';&' + DIGITS = u'0123456789' def urisplit(uristring): @@ -334,7 +351,7 @@ if isinstance(uristring, bytes): result = SplitResultBytes else: - result = SplitResultString + result = SplitResultUnicode return result(*result.RE.match(uristring).groups()) @@ -344,5 +361,5 @@ if isinstance(path, bytes): result = SplitResultBytes else: - result = SplitResultString + result = SplitResultUnicode return result(scheme, authority, path, query, fragment).geturi() diff -Nru python-uritools-1.0.2/uritools.egg-info/PKG-INFO python-uritools-2.1.0/uritools.egg-info/PKG-INFO --- python-uritools-1.0.2/uritools.egg-info/PKG-INFO 2016-04-08 13:39:31.000000000 +0000 +++ python-uritools-2.1.0/uritools.egg-info/PKG-INFO 2017-10-07 14:48:13.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: uritools -Version: 1.0.2 +Version: 2.1.0 Summary: RFC 3986 compliant, Unicode-aware, scheme-agnostic replacement for urlparse Home-page: https://github.com/tkem/uritools/ Author: Thomas Kemmer Author-email: tkemmer@computer.org License: MIT +Description-Content-Type: UNKNOWN Description: uritools ======================================================================== @@ -15,26 +16,22 @@ .. code-block:: pycon - >>> from uritools import urisplit, uriunsplit, urijoin, uridefrag - >>> parts = urisplit('foo://user@example.com:8042/over/there?name=ferret#nose') - >>> parts - SplitResult(scheme='foo', authority='user@example.com:8042', path='/over/there', query='name=ferret', fragment='nose') + >>> from uritools import uricompose, urijoin, urisplit, uriunsplit + >>> uricompose(scheme='foo', host='example.com', port=8042, + ... path='/over/there', query={'name': 'ferret'}, + ... fragment='nose') + 'foo://example.com:8042/over/there?name=ferret#nose' + >>> parts = urisplit(_) >>> parts.scheme 'foo' >>> parts.authority - 'user@example.com:8042' - >>> parts.userinfo - 'user' - >>> parts.host - 'example.com' - >>> parts.port - '8042' - >>> uriunsplit(parts[:3] + ('name=swallow&type=African', 'beak')) - 'foo://user@example.com:8042/over/there?name=swallow&type=African#beak' - >>> urijoin('http://www.cwi.nl/~guido/Python.html', 'FAQ.html') - 'http://www.cwi.nl/~guido/FAQ.html' - >>> uridefrag('http://pythonhosted.org/uritools/index.html#constants') - DefragResult(uri='http://pythonhosted.org/uritools/index.html', fragment='constants') + 'example.com:8042' + >>> parts.getport(default=80) + 8042 + >>> parts.getquerydict().get('name') + ['ferret'] + >>> urijoin(uriunsplit(parts), '/right/here?name=swallow#beak') + 'foo://example.com:8042/right/here?name=swallow#beak' For various reasons, the Python 2 ``urlparse`` module is not compliant with current Internet standards, does not include Unicode support, and @@ -70,10 +67,6 @@ :target: https://pypi.python.org/pypi/uritools/ :alt: Latest PyPI version - .. image:: http://img.shields.io/pypi/dm/uritools.svg?style=flat - :target: https://pypi.python.org/pypi/uritools/ - :alt: Number of PyPI downloads - .. image:: http://img.shields.io/travis/tkem/uritools/master.svg?style=flat :target: https://travis-ci.org/tkem/uritools/ :alt: Travis CI build status @@ -82,7 +75,10 @@ :target: https://coveralls.io/r/tkem/uritools :alt: Test coverage - - `Documentation`_ + .. image:: https://readthedocs.org/projects/uritools/badge/?version=latest&style=flat + :target: http://uritools.readthedocs.io/en/latest/ + :alt: Documentation Status + - `Issue Tracker`_ - `Source Code`_ - `Change Log`_ @@ -91,12 +87,11 @@ License ------------------------------------------------------------------------ - Copyright (c) 2014-2016 Thomas Kemmer. + Copyright (c) 2014-2017 Thomas Kemmer. Licensed under the `MIT License`_. - .. _Documentation: http://pythonhosted.org/uritools/ .. _Issue Tracker: https://github.com/tkem/uritools/issues/ .. _Source Code: https://github.com/tkem/uritools/ .. _Change Log: https://github.com/tkem/uritools/blob/master/CHANGES.rst @@ -104,7 +99,7 @@ Keywords: uri url urlparse urlsplit urljoin urldefrag Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta +Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Other Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License @@ -113,9 +108,9 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Internet Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -Nru python-uritools-1.0.2/uritools.egg-info/requires.txt python-uritools-2.1.0/uritools.egg-info/requires.txt --- python-uritools-1.0.2/uritools.egg-info/requires.txt 2016-04-08 13:39:31.000000000 +0000 +++ python-uritools-2.1.0/uritools.egg-info/requires.txt 2017-10-07 14:48:13.000000000 +0000 @@ -1,7 +1,3 @@ - [:python_version == "2.7"] -ipaddress>=1.0.6 - -[:python_version == "3.2"] -ipaddress>=1.0.7 \ No newline at end of file +ipaddress