Hello community, here is the log from the commit of package python-rfc3986 for openSUSE:Factory checked in at 2017-08-13 14:57:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-rfc3986 (Old) and /work/SRC/openSUSE:Factory/.python-rfc3986.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-rfc3986" Sun Aug 13 14:57:45 2017 rev:4 rq:515844 version:1.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-rfc3986/python-rfc3986.changes 2017-06-18 13:51:01.481463552 +0200 +++ /work/SRC/openSUSE:Factory/.python-rfc3986.new/python-rfc3986.changes 2017-08-13 14:57:46.484707568 +0200 @@ -1,0 +2,18 @@ +Thu Aug 10 07:22:30 UTC 2017 - [email protected] + +- update to 1.1.0: + * Bump version to 1.1.0 + * Fix theme setting for documentation + * Exclude solitary line from coverage + * Note the version we added Validator in + * Fix documentation builds on RTD + * Add check_validity_of to vaildator docs + * Add some chars (!, =, etc) as allowed to the userinfo part of authority + * Add release notes for v1.1.0 + * Add a separate testcase for special chars in userinfo and revert changes to other tests + * Add validation to eliminate URIReference.is_valid + * Add deprecation notices to old URIReference methods + * Make tests fail: add "%20!=" part to userinfo which is allowed as per RFC3986 +- Convert to singlespec + +------------------------------------------------------------------- Old: ---- rfc3986-1.0.0.tar.gz New: ---- rfc3986-1.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-rfc3986.spec ++++++ --- /var/tmp/diff_new_pack.uzsf3h/_old 2017-08-13 14:57:47.476568376 +0200 +++ /var/tmp/diff_new_pack.uzsf3h/_new 2017-08-13 14:57:47.488566692 +0200 @@ -16,22 +16,22 @@ # +%{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-rfc3986 -Version: 1.0.0 +Version: 1.1.0 Release: 0 Summary: Validating URI References per RFC 3986 License: Apache-2.0 Group: Development/Languages/Python Url: https://rfc3986.rtfd.org Source: https://pypi.io/packages/source/r/rfc3986/rfc3986-%{version}.tar.gz -BuildRequires: python-devel -BuildRequires: python-setuptools +BuildRequires: %{python_module devel} +BuildRequires: %{python_module setuptools} +BuildRequires: python-rpm-macros BuildRoot: %{_tmppath}/%{name}-%{version}-build -%if 0%{?suse_version} && 0%{?suse_version} <= 1110 -%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} -%else BuildArch: noarch -%endif + +%python_subpackages %description A Python implementation of `RFC 3986`_ including validation and authority @@ -41,12 +41,12 @@ %setup -q -n rfc3986-%{version} %build -python setup.py build +%python_build %install -python setup.py install --prefix=%{_prefix} --root=%{buildroot} +%python_install -%files +%files %{python_files} %defattr(-,root,root,-) %doc AUTHORS.rst LICENSE README.rst %{python_sitelib}/* ++++++ rfc3986-1.0.0.tar.gz -> rfc3986-1.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/PKG-INFO new/rfc3986-1.1.0/PKG-INFO --- old/rfc3986-1.0.0/PKG-INFO 2017-05-10 13:59:35.000000000 +0200 +++ new/rfc3986-1.1.0/PKG-INFO 2017-07-18 14:18:10.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: rfc3986 -Version: 1.0.0 +Version: 1.1.0 Summary: Validating URI References per RFC 3986 Home-page: http://rfc3986.readthedocs.io Author: Ian Cordasco diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/docs/source/api-ref/uri.rst new/rfc3986-1.1.0/docs/source/api-ref/uri.rst --- old/rfc3986-1.0.0/docs/source/api-ref/uri.rst 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/docs/source/api-ref/uri.rst 2017-07-18 13:35:25.000000000 +0200 @@ -17,3 +17,19 @@ .. automethod:: rfc3986.uri.URIReference.is_absolute .. automethod:: rfc3986.uri.URIReference.authority_info + + +Deprecated Methods +================== + +.. automethod:: rfc3986.uri.URIReference.is_valid + +.. automethod:: rfc3986.uri.URIReference.authority_is_valid + +.. automethod:: rfc3986.uri.URIReference.scheme_is_valid + +.. automethod:: rfc3986.uri.URIReference.path_is_valid + +.. automethod:: rfc3986.uri.URIReference.query_is_valid + +.. automethod:: rfc3986.uri.URIReference.fragment_is_valid diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/docs/source/api-ref/validators.rst new/rfc3986-1.1.0/docs/source/api-ref/validators.rst --- old/rfc3986-1.0.0/docs/source/api-ref/validators.rst 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/docs/source/api-ref/validators.rst 2017-07-17 23:55:18.000000000 +0200 @@ -12,6 +12,8 @@ .. automethod:: rfc3986.validators.Validator.allow_use_of_password +.. automethod:: rfc3986.validators.Validator.check_validity_of + .. automethod:: rfc3986.validators.Validator.forbid_use_of_password .. automethod:: rfc3986.validators.Validator.require_presence_of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/docs/source/conf.py new/rfc3986-1.1.0/docs/source/conf.py --- old/rfc3986-1.0.0/docs/source/conf.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/docs/source/conf.py 2017-05-10 14:06:41.000000000 +0200 @@ -91,7 +91,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/docs/source/release-notes/1.1.0.rst new/rfc3986-1.1.0/docs/source/release-notes/1.1.0.rst --- old/rfc3986-1.0.0/docs/source/release-notes/1.1.0.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/rfc3986-1.1.0/docs/source/release-notes/1.1.0.rst 2017-07-18 13:58:28.000000000 +0200 @@ -0,0 +1,15 @@ +1.1.0 -- 2017-07-18 +------------------- + +- Correct the regular expression for the User Information sub-component of the + Authority Component. + + See also `GitHub #26`_ + +- :meth:`~rfc3986.validators.Validator.check_validity_of` to the + :class:`~rfc3986.validators.Validator` class. See + :ref:`Validating URIs <validating>` documentation for more information. + +.. links +.. _GitHub #26: + https://github.com/sigmavirus24/rfc3986/pull/26 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/docs/source/release-notes/index.rst new/rfc3986-1.1.0/docs/source/release-notes/index.rst --- old/rfc3986-1.0.0/docs/source/release-notes/index.rst 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/docs/source/release-notes/index.rst 2017-07-18 13:54:44.000000000 +0200 @@ -10,6 +10,7 @@ .. toctree:: + 1.1.0 1.0.0 0.x Release Series diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/docs/source/user/validating.rst new/rfc3986-1.1.0/docs/source/user/validating.rst --- old/rfc3986-1.0.0/docs/source/user/validating.rst 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/docs/source/user/validating.rst 2017-07-18 13:58:33.000000000 +0200 @@ -1,3 +1,5 @@ +.. _validating: + ================= Validating URIs ================= @@ -7,6 +9,7 @@ sometimes overlap and othertimes they don't and it's not very convenient. Luckily, |rfc3986| makes validating URIs far simpler. + Example Usage ============= @@ -14,7 +17,10 @@ :class:`~rfc3986.validators.Validator` which takes no parameters. After that we can call methods on the instance to indicate what we want to validate. -Let's assume that we're building something that takes user input for a URl and +Allowing Only Trusted Domains and Schemes +----------------------------------------- + +Let's assume that we're building something that takes user input for a URL and we want to ensure that URL is only ever using a specific domain with https. In that case, our code would look like this: @@ -52,6 +58,9 @@ fail the third. This is specifically because we only allow URLs using ``https`` as a scheme and ``github.com`` as the domain name. +Preventing Leaks of User Credentials +------------------------------------ + Next, let's imagine that we want to prevent leaking user credentials. In that case, we want to ensure that there is no password in the user information portion of the authority. In that case, our new validator would look like this: @@ -87,6 +96,9 @@ ... rfc3986.exceptions.PasswordForbidden +Requiring the Presence of Components +------------------------------------ + Up until now, we have assumed that we will get a URL that has the appropriate components for validation. For example, we assume that we will have a URL that has a scheme and hostname. However, our current validation doesn't require @@ -134,7 +146,42 @@ ... 'https://github.com/sigmavirus24/rfc3986' ... )) -.. links +Checking the Validity of Components +----------------------------------- + +As of version 1.1.0, |rfc3986| allows users to check the validity of a URI +Reference using a :class:`~rfc3986.validators.Validator`. Along with the above +examples we can also check that a URI is valid per :rfc:`3986`. The validation +of the components is pre-determined so all we need to do is specify which +components we want to validate: + +.. doctest:: + + >>> from rfc3986 import validators, uri_reference + >>> valid_uri = uri_reference('https://github.com/') + >>> validator = validators.Validator().allow_schemes( + ... 'https', + ... ).allow_hosts( + ... 'github.com', + ... ).forbid_use_of_password( + ... ).require_presence_of( + ... 'scheme', 'host', + ... ).check_validity_of( + ... 'scheme', 'host', 'path', + ... ) + >>> validator.validate(valid_uri) + >>> invalid_uri = valid_uri.copy_with(path='/#invalid/path') + >>> validator.validate(invalid_uri) + Traceback (most recent call last): + ... + rfc3986.exceptions.InvalidComponentsError + +Paths are not allowed to contain a ``#`` character unless it's +percent-encoded. This is why our ``invalid_uri`` raises an exception when we +attempt to validate it. + + +.. links .. _validating an email address: http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/src/rfc3986/__init__.py new/rfc3986-1.1.0/src/rfc3986/__init__.py --- old/rfc3986-1.0.0/src/rfc3986/__init__.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/src/rfc3986/__init__.py 2017-07-18 14:16:53.000000000 +0200 @@ -34,7 +34,7 @@ __author_email__ = '[email protected]' __license__ = 'Apache v2.0' __copyright__ = 'Copyright 2014 Rackspace' -__version__ = '1.0.0' +__version__ = '1.1.0' __all__ = ( 'ParseResult', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/src/rfc3986/abnf_regexp.py new/rfc3986-1.1.0/src/rfc3986/abnf_regexp.py --- old/rfc3986-1.0.0/src/rfc3986/abnf_regexp.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/src/rfc3986/abnf_regexp.py 2017-07-17 23:21:23.000000000 +0200 @@ -132,7 +132,9 @@ IPv4_RE, IP_LITERAL_RE, ) -USERINFO_RE = '^[A-Za-z0-9_.~\-%:]+' +USERINFO_RE = '^([' + UNRESERVED_RE + SUB_DELIMITERS_RE + ':]|%s)+' % ( + PCT_ENCODED +) PORT_RE = '[0-9]{1,5}' # #################### diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/src/rfc3986/exceptions.py new/rfc3986-1.1.0/src/rfc3986/exceptions.py --- old/rfc3986-1.0.0/src/rfc3986/exceptions.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/src/rfc3986/exceptions.py 2017-07-17 23:21:23.000000000 +0200 @@ -90,3 +90,22 @@ ) ) self.uri = uri + + +class InvalidComponentsError(ValidationError): + """Exception raised when one or more components are invalid.""" + + def __init__(self, uri, *component_names): + """Initialize the error with the invalid component name(s).""" + verb = 'was' + if len(component_names) > 1: + verb = 'were' + + self.uri = uri + self.components = sorted(component_names) + components = ', '.join(self.components) + super(InvalidComponentsError, self).__init__( + "{} {} found to be invalid".format(components, verb), + uri, + self.components, + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/src/rfc3986/uri.py new/rfc3986-1.1.0/src/rfc3986/uri.py --- old/rfc3986-1.0.0/src/rfc3986/uri.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/src/rfc3986/uri.py 2017-07-18 13:36:32.000000000 +0200 @@ -15,6 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from collections import namedtuple +import warnings from . import compat from . import exceptions as exc @@ -210,6 +211,10 @@ def is_valid(self, **kwargs): """Determine if the URI is valid. + .. deprecated:: 1.1.0 + + Use the :class:`~rfc3986.validators.Validator` object instead. + :param bool require_scheme: Set to ``True`` if you wish to require the presence of the scheme component. :param bool require_authority: Set to ``True`` if you wish to require @@ -223,6 +228,9 @@ :returns: ``True`` if the URI is valid. ``False`` otherwise. :rtype: bool """ + warnings.warn("Please use rfc3986.validators.Validator instead. " + "This method will be eventually removed.", + DeprecationWarning) validators = [ (self.scheme_is_valid, kwargs.get('require_scheme', False)), (self.authority_is_valid, kwargs.get('require_authority', False)), @@ -235,6 +243,10 @@ def authority_is_valid(self, require=False): """Determine if the authority component is valid. + .. deprecated:: 1.1.0 + + Use the :class:`~rfc3986.validators.Validator` object instead. + :param bool require: Set to ``True`` to require the presence of this component. :returns: @@ -242,6 +254,9 @@ :rtype: bool """ + warnings.warn("Please use rfc3986.validators.Validator instead. " + "This method will be eventually removed.", + DeprecationWarning) try: self.authority_info() except exc.InvalidAuthority: @@ -256,41 +271,69 @@ def scheme_is_valid(self, require=False): """Determine if the scheme component is valid. + .. deprecated:: 1.1.0 + + Use the :class:`~rfc3986.validators.Validator` object instead. + :param str require: Set to ``True`` to require the presence of this component. :returns: ``True`` if the scheme is valid. ``False`` otherwise. :rtype: bool """ + warnings.warn("Please use rfc3986.validators.Validator instead. " + "This method will be eventually removed.", + DeprecationWarning) return validators.scheme_is_valid(self.scheme, require) def path_is_valid(self, require=False): """Determine if the path component is valid. + .. deprecated:: 1.1.0 + + Use the :class:`~rfc3986.validators.Validator` object instead. + :param str require: Set to ``True`` to require the presence of this component. :returns: ``True`` if the path is valid. ``False`` otherwise. :rtype: bool """ + warnings.warn("Please use rfc3986.validators.Validator instead. " + "This method will be eventually removed.", + DeprecationWarning) return validators.path_is_valid(self.path, require) def query_is_valid(self, require=False): """Determine if the query component is valid. + .. deprecated:: 1.1.0 + + Use the :class:`~rfc3986.validators.Validator` object instead. + :param str require: Set to ``True`` to require the presence of this component. :returns: ``True`` if the query is valid. ``False`` otherwise. :rtype: bool """ + warnings.warn("Please use rfc3986.validators.Validator instead. " + "This method will be eventually removed.", + DeprecationWarning) return validators.query_is_valid(self.query, require) def fragment_is_valid(self, require=False): """Determine if the fragment component is valid. + .. deprecated:: 1.1.0 + + Use the Validator object instead. + :param str require: Set to ``True`` to require the presence of this component. :returns: ``True`` if the fragment is valid. ``False`` otherwise. :rtype: bool """ + warnings.warn("Please use rfc3986.validators.Validator instead. " + "This method will be eventually removed.", + DeprecationWarning) return validators.fragment_is_valid(self.fragment, require) def normalize(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/src/rfc3986/validators.py new/rfc3986-1.1.0/src/rfc3986/validators.py --- old/rfc3986-1.0.0/src/rfc3986/validators.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/src/rfc3986/validators.py 2017-07-17 23:21:23.000000000 +0200 @@ -21,6 +21,8 @@ class Validator(object): """Object used to configure validation of all objects in rfc3986. + .. versionadded:: 1.0 + Example usage:: >>> from rfc3986 import api, validators @@ -68,10 +70,13 @@ 'query': False, 'fragment': False, } + self.validated_components = self.required_components.copy() def allow_schemes(self, *schemes): """Require the scheme to be one of the provided schemes. + .. versionadded:: 1.0 + :param schemes: Schemes, without ``://`` that are allowed. :returns: @@ -86,6 +91,8 @@ def allow_hosts(self, *hosts): """Require the host to be one of the provided hosts. + .. versionadded:: 1.0 + :param hosts: Hosts that are allowed. :returns: @@ -100,6 +107,8 @@ def allow_ports(self, *ports): """Require the port to be one of the provided ports. + .. versionadded:: 1.0 + :param ports: Ports that are allowed. :returns: @@ -114,18 +123,63 @@ return self def allow_use_of_password(self): - """Allow passwords to be present in the URI.""" + """Allow passwords to be present in the URI. + + .. versionadded:: 1.0 + + :returns: + The validator instance. + :rtype: + Validator + """ self.allow_password = True return self def forbid_use_of_password(self): - """Prevent passwords from being included in the URI.""" + """Prevent passwords from being included in the URI. + + .. versionadded:: 1.0 + + :returns: + The validator instance. + :rtype: + Validator + """ self.allow_password = False return self + def check_validity_of(self, *components): + """Check the validity of the components provided. + + This can be specified repeatedly. + + .. versionadded:: 1.1 + + :param components: + Names of components from :attr:`Validator.COMPONENT_NAMES`. + :returns: + The validator instance. + :rtype: + Validator + """ + components = [c.lower() for c in components] + for component in components: + if component not in self.COMPONENT_NAMES: + raise ValueError( + '"{}" is not a valid component'.format(component) + ) + self.validated_components.update({ + component: True for component in components + }) + return self + def require_presence_of(self, *components): """Require the components provided. + This can be specified repeatedly. + + .. versionadded:: 1.0 + :param components: Names of components from :attr:`Validator.COMPONENT_NAMES`. :returns: @@ -147,6 +201,8 @@ def validate(self, uri): """Check a URI for conditions specified on this validator. + .. versionadded:: 1.0 + :param uri: Parsed URI to validate. :type uri: @@ -158,6 +214,8 @@ :raises PasswordForbidden: When a password is present in the userinfo component but is not permitted by configuration. + :raises InvalidComponentsError: + When a component was found to be invalid. """ if not self.allow_password: check_password(uri) @@ -167,8 +225,15 @@ for component, required in self.required_components.items() if required ] + validated_components = [ + component + for component, required in self.validated_components.items() + if required + ] if required_components: ensure_required_components_exist(uri, required_components) + if validated_components: + ensure_components_are_valid(uri, validated_components) ensure_one_of(self.allowed_schemes, uri, 'scheme') ensure_one_of(self.allowed_hosts, uri, 'host') @@ -309,3 +374,55 @@ # If the host exists, and it might be IPv4, check each byte in the # address. return all([0 <= int(byte, base=10) <= 255 for byte in host.split('.')]) + + +_COMPONENT_VALIDATORS = { + 'scheme': scheme_is_valid, + 'path': path_is_valid, + 'query': query_is_valid, + 'fragment': fragment_is_valid, +} + +_SUBAUTHORITY_VALIDATORS = set(['userinfo', 'host', 'port']) + + +def subauthority_component_is_valid(uri, component): + """Determine if the userinfo, host, and port are valid.""" + try: + subauthority_dict = uri.authority_info() + except exceptions.InvalidAuthority: + return False + + # If we can parse the authority into sub-components and we're not + # validating the port, we can assume it's valid. + if component != 'port': + return True + + try: + port = int(subauthority_dict['port']) + except TypeError: + # If the port wasn't provided it'll be None and int(None) raises a + # TypeError + return True + + return (0 <= port <= 65535) + + +def ensure_components_are_valid(uri, validated_components): + """Assert that all components are valid in the URI.""" + invalid_components = set([]) + for component in validated_components: + if component in _SUBAUTHORITY_VALIDATORS: + if not subauthority_component_is_valid(uri, component): + invalid_components.add(component) + # Python's peephole optimizer means that while this continue *is* + # actually executed, coverage.py cannot detect that. See also, + # https://bitbucket.org/ned/coveragepy/issues/198/continue-marked-as-not-covered + continue # nocov: Python 2.7, 3.3, 3.4 + + validator = _COMPONENT_VALIDATORS[component] + if not validator(getattr(uri, component)): + invalid_components.add(component) + + if invalid_components: + raise exceptions.InvalidComponentsError(uri, *invalid_components) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/src/rfc3986.egg-info/PKG-INFO new/rfc3986-1.1.0/src/rfc3986.egg-info/PKG-INFO --- old/rfc3986-1.0.0/src/rfc3986.egg-info/PKG-INFO 2017-05-10 13:59:35.000000000 +0200 +++ new/rfc3986-1.1.0/src/rfc3986.egg-info/PKG-INFO 2017-07-18 14:18:10.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: rfc3986 -Version: 1.0.0 +Version: 1.1.0 Summary: Validating URI References per RFC 3986 Home-page: http://rfc3986.readthedocs.io Author: Ian Cordasco diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/src/rfc3986.egg-info/SOURCES.txt new/rfc3986-1.1.0/src/rfc3986.egg-info/SOURCES.txt --- old/rfc3986-1.0.0/src/rfc3986.egg-info/SOURCES.txt 2017-05-10 13:59:35.000000000 +0200 +++ new/rfc3986-1.1.0/src/rfc3986.egg-info/SOURCES.txt 2017-07-18 14:18:10.000000000 +0200 @@ -23,6 +23,7 @@ docs/source/release-notes/0.4.1.rst docs/source/release-notes/0.4.2.rst docs/source/release-notes/1.0.0.rst +docs/source/release-notes/1.1.0.rst docs/source/release-notes/index.rst docs/source/user/building.rst docs/source/user/parsing.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/tests/base.py new/rfc3986-1.1.0/tests/base.py --- old/rfc3986-1.0.0/tests/base.py 2017-01-19 15:23:04.000000000 +0100 +++ new/rfc3986-1.1.0/tests/base.py 2017-07-17 23:21:23.000000000 +0200 @@ -58,6 +58,23 @@ assert uri.fragment is None assert uri.userinfo == 'user:pass' + def test_handles_tricky_userinfo( + self, uri_with_port_and_tricky_userinfo): + """ + Test that self.test_class can handle a URI with unusual + (non a-z) chars in userinfo. + """ + uri = self.test_class.from_string(uri_with_port_and_tricky_userinfo) + assert uri.scheme == 'ssh' + # 6 == len('ftp://') + assert uri.authority == uri_with_port_and_tricky_userinfo[6:] + assert uri.host != uri.authority + assert str(uri.port) == '22' + assert uri.path is None + assert uri.query is None + assert uri.fragment is None + assert uri.userinfo == 'user%20!=:pass' + def test_handles_basic_uri_with_path(self, basic_uri_with_path): """Test that self.test_class can handle a URI with a path.""" uri = self.test_class.from_string(basic_uri_with_path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/tests/conftest.py new/rfc3986-1.1.0/tests/conftest.py --- old/rfc3986-1.0.0/tests/conftest.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/tests/conftest.py 2017-07-17 23:21:23.000000000 +0200 @@ -81,6 +81,11 @@ @pytest.fixture(params=valid_hosts) +def uri_with_port_and_tricky_userinfo(request): + return 'ssh://%s@%s:22' % ('user%20!=:pass', request.param) + + [email protected](params=valid_hosts) def basic_uri_with_path(request): return 'http://%s/path/to/resource' % request.param diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rfc3986-1.0.0/tests/test_validators.py new/rfc3986-1.1.0/tests/test_validators.py --- old/rfc3986-1.0.0/tests/test_validators.py 2017-05-10 13:58:27.000000000 +0200 +++ new/rfc3986-1.1.0/tests/test_validators.py 2017-07-17 23:21:23.000000000 +0200 @@ -52,6 +52,12 @@ validators.Validator().require_presence_of('frob') +def test_checking_validity_of_component(): + """Verify that we validate components we're validating.""" + with pytest.raises(ValueError): + validators.Validator().check_validity_of('frob') + + def test_use_of_password(): """Verify the behaviour of {forbid,allow}_use_of_password.""" validator = validators.Validator() @@ -182,6 +188,22 @@ rfc3986.uri_reference('ssh://git.openstack.org/sigmavirus24'), rfc3986.uri_reference('ssh://[email protected]:22/sigmavirus24'), rfc3986.uri_reference('https://git.openstack.org:443/sigmavirus24'), + rfc3986.uri_reference( + 'ssh://[email protected]:22/sigmavirus24?foo=bar#fragment' + ), + rfc3986.uri_reference( + 'ssh://git.openstack.org:22/sigmavirus24?foo=bar#fragment' + ), + rfc3986.uri_reference('ssh://git.openstack.org:22/?foo=bar#fragment'), + rfc3986.uri_reference('ssh://git.openstack.org:22/sigmavirus24#fragment'), + rfc3986.uri_reference('ssh://git.openstack.org:22/#fragment'), + rfc3986.uri_reference('ssh://git.openstack.org:22/'), + rfc3986.uri_reference('ssh://[email protected]:22/?foo=bar#fragment'), + rfc3986.uri_reference( + 'ssh://[email protected]:22/sigmavirus24#fragment' + ), + rfc3986.uri_reference('ssh://[email protected]:22/#fragment'), + rfc3986.uri_reference('ssh://[email protected]:22/'), ]) def test_successful_complex_validation(uri): """Verify we do not raise ValidationErrors for good URIs.""" @@ -193,4 +215,23 @@ '22', '443', ).require_presence_of( 'scheme', 'host', 'path', + ).check_validity_of( + 'scheme', 'userinfo', 'host', 'port', 'path', 'query', 'fragment', ).validate(uri) + + +def test_invalid_uri_generates_error(invalid_uri): + """Verify we catch invalid URIs.""" + uri = rfc3986.uri_reference(invalid_uri) + with pytest.raises(exceptions.InvalidComponentsError): + validators.Validator().check_validity_of('host').validate(uri) + + +def test_invalid_uri_with_invalid_path(invalid_uri): + """Verify we catch multiple invalid components.""" + uri = rfc3986.uri_reference(invalid_uri) + uri = uri.copy_with(path='#foobar') + with pytest.raises(exceptions.InvalidComponentsError): + validators.Validator().check_validity_of( + 'host', 'path', + ).validate(uri)
