]> review.fuel-infra Code Review - packages/trusty/python-pysaml2.git/commitdiff
Added debian/patches/using-correct-urllib.parse-instead-of-urlparse.patch
authorThomas Goirand <zigo@debian.org>
Fri, 24 Apr 2015 12:51:40 +0000 (14:51 +0200)
committerThomas Goirand <zigo@debian.org>
Fri, 24 Apr 2015 12:51:40 +0000 (14:51 +0200)
Rewritten-From: f442ffe9b8580ef5ccbdab60ab29b35c964d4821

debian/patches/series
debian/patches/using-correct-urllib.parse-instead-of-urlparse.patch [new file with mode: 0644]

index 052b7be5c21d08d9f6ae68c6894c4d4b51a9a9ef..566194efaac68116070bf0589446e4f8c1710fe3 100644 (file)
@@ -1 +1,2 @@
 fixed-python3-support.patch
+using-correct-urllib.parse-instead-of-urlparse.patch
diff --git a/debian/patches/using-correct-urllib.parse-instead-of-urlparse.patch b/debian/patches/using-correct-urllib.parse-instead-of-urlparse.patch
new file mode 100644 (file)
index 0000000..46beef3
--- /dev/null
@@ -0,0 +1,728 @@
+Description: Using correct urllib.parse
+ Make it work with Python 3.
+Author: Thomas Goirand <zigo@debian.org>
+Forwarded: no
+Last-Update: 2015-04-24
+
+--- python-pysaml2-2.0.0.orig/example/idp2/idp.py
++++ python-pysaml2-2.0.0/example/idp2/idp.py
+@@ -1,5 +1,4 @@
+ #!/usr/bin/env python
+-import argparse
+ import base64
+ import xmldsig as ds
+ import re
+@@ -7,7 +6,8 @@ import logging
+ import time
+ from hashlib import sha1
+-from urlparse import parse_qs
++import urllib
++import urllib.parse
+ from Cookie import SimpleCookie
+ import os
+@@ -90,12 +90,12 @@ class Service(object):
+     def unpack_redirect(self):
+         if "QUERY_STRING" in self.environ:
+             _qs = self.environ["QUERY_STRING"]
+-            return dict([(k, v[0]) for k, v in parse_qs(_qs).items()])
++            return dict([(k, v[0]) for k, v in urllib.parse.parse_qs(_qs).items()])
+         else:
+             return None
+     
+     def unpack_post(self):
+-        _dict = parse_qs(get_post(self.environ))
++        _dict = urllib.parse.parse_qs(get_post(self.environ))
+         logger.debug("unpack_post:: %s" % _dict)
+         try:
+             return dict([(k, v[0]) for k, v in _dict.items()])
+@@ -193,7 +193,7 @@ class Service(object):
+     #     :return:
+     #     """
+     #     loc = "http://%s/login" % (self.environ["HTTP_HOST"])
+-    #     loc += "?%s" % urllib.urlencode({"came_from": self.environ[
++    #     loc += "?%s" % urllib.parse.urlencode({"came_from": self.environ[
+     #         "PATH_INFO"], "key": key})
+     #     headers = [('Content-Type', 'text/plain')]
+     #
+@@ -490,7 +490,7 @@ def verify_username_and_password(dic):
+ def do_verify(environ, start_response, _):
+-    query = parse_qs(get_post(environ))
++    query = urllib.parse.parse_qs(get_post(environ))
+     logger.debug("do_verify: %s" % query)
+@@ -893,7 +893,7 @@ def application(environ, start_response)
+         environ["idp.authn_ref"] = authn_ref
+     else:
+         try:
+-            query = parse_qs(environ["QUERY_STRING"])
++            query = urllib.parse.parse_qs(environ["QUERY_STRING"])
+             logger.debug("QUERY: %s" % query)
+             user = IDP.cache.uid2user[query["id"][0]]
+         except KeyError:
+--- python-pysaml2-2.0.0.orig/example/idp2_repoze/idp.py
++++ python-pysaml2-2.0.0/example/idp2_repoze/idp.py
+@@ -1,5 +1,4 @@
+ #!/usr/bin/env python
+-import argparse
+ import base64
+ import re
+@@ -7,7 +6,7 @@ import logging
+ import time
+ from hashlib import sha1
+-from urlparse import parse_qs
++from urllib.parse import parse_qs
+ from Cookie import SimpleCookie
+ import os
+@@ -191,7 +190,7 @@ class Service(object):
+     #     :return:
+     #     """
+     #     loc = "http://%s/login" % (self.environ["HTTP_HOST"])
+-    #     loc += "?%s" % urllib.urlencode({"came_from": self.environ[
++    #     loc += "?%s" % urllib.parse.urlencode({"came_from": self.environ[
+     #         "PATH_INFO"], "key": key})
+     #     headers = [('Content-Type', 'text/plain')]
+     #
+--- python-pysaml2-2.0.0.orig/example/sp-repoze/sp.py
++++ python-pysaml2-2.0.0/example/sp-repoze/sp.py
+@@ -6,8 +6,8 @@ import os
+ from sp_conf import CONFIG
+ import re
+ import subprocess
+-from urlparse import parse_qs
+-import argparse
++import urllib
++import urllib.parse
+ from saml2 import BINDING_HTTP_REDIRECT, time_util
+ from saml2.httputil import Response
+ from saml2.httputil import Unauthorized
+@@ -127,7 +127,7 @@ def slo(environ, start_response, user):
+     sc = client.saml_client
+     if "QUERY_STRING" in environ:
+-        query = parse_qs(environ["QUERY_STRING"])
++        query = urllib.parse.parse_qs(environ["QUERY_STRING"])
+         logger.info("query: %s" % query)
+         try:
+             response = sc.parse_logout_request_response(
+--- python-pysaml2-2.0.0.orig/example/sp-wsgi/sp.py
++++ python-pysaml2-2.0.0/example/sp-wsgi/sp.py
+@@ -1,11 +1,10 @@
+ #!/usr/bin/env python
+ import logging
+ import re
+-import argparse
+ import service_conf
+ from Cookie import SimpleCookie
+-from urlparse import parse_qs
++from urllib.parse import parse_qs
+ import sys
+ from saml2 import BINDING_HTTP_REDIRECT
+--- python-pysaml2-2.0.0.orig/src/s2repoze/plugins/formswithhidden.py
++++ python-pysaml2-2.0.0/src/s2repoze/plugins/formswithhidden.py
+@@ -69,7 +69,7 @@ class FormHiddenPlugin(FormPlugin):
+                 return None
+             del query[self.login_form_qs]
+             query.update(qinfo)
+-            environ['QUERY_STRING'] = urllib.urlencode(query)
++            environ['QUERY_STRING'] = urllib.parse.urlencode(query)
+             environ['repoze.who.application'] = HTTPFound(
+                                                     construct_url(environ))
+             credentials = {'login':login, 'password':password}
+--- python-pysaml2-2.0.0.orig/src/s2repoze/plugins/sp.py
++++ python-pysaml2-2.0.0/src/s2repoze/plugins/sp.py
+@@ -25,7 +25,8 @@ import platform
+ import shelve
+ import traceback
+ import saml2
+-from urlparse import parse_qs, urlparse
++import urllib
++import urllib.parse
+ from saml2.md import Extensions
+ import xmldsig as ds
+@@ -137,7 +138,7 @@ class SAML2Plugin(object):
+         self.cache = cache
+         self.discosrv = discovery
+         self.idp_query_param = idp_query_param
+-        self.logout_endpoints = [urlparse(ep)[2] for ep in config.endpoint(
++        self.logout_endpoints = [urllib.parse.urlparse(ep)[2] for ep in config.endpoint(
+             "single_logout_service")]
+         try:
+             self.metadata = self.conf.metadata
+@@ -252,7 +253,7 @@ class SAML2Plugin(object):
+             query = environ.get(key)
+             if query:
+                 try:
+-                    _idp_entity_id = dict(parse_qs(query))[
++                    _idp_entity_id = dict(urllib.parse.parse_qs(query))[
+                         self.idp_query_param][0]
+                     if _idp_entity_id in idps:
+                         idp_entity_id = _idp_entity_id
+@@ -274,7 +275,7 @@ class SAML2Plugin(object):
+                 if self.wayf:
+                     if query:
+                         try:
+-                            wayf_selected = dict(parse_qs(query))[
++                            wayf_selected = dict(urllib.parse.parse_qs(query))[
+                                 "wayf_selected"][0]
+                         except KeyError:
+                             return self._wayf_redirect(came_from)
+@@ -410,7 +411,7 @@ class SAML2Plugin(object):
+                     "endpoints","sp")["discovery_response"][0][0]
+                 if (environ["PATH_INFO"]) in ret and ret.split(
+                         environ["PATH_INFO"])[1] == "":
+-                    query = parse_qs(environ["QUERY_STRING"])
++                    query = urllib.parse.parse_qs(environ["QUERY_STRING"])
+                     sid = query["sid"][0]
+                     came_from = self.outstanding_queries[sid]
+             except:
+--- python-pysaml2-2.0.0.orig/src/saml2/authn.py
++++ python-pysaml2-2.0.0/src/saml2/authn.py
+@@ -1,7 +1,6 @@
+ import logging
+-from urllib import urlencode
+-from urlparse import parse_qs
+-from urlparse import urlsplit
++import urllib
++import urllib.parse
+ import time
+ import ldap
+ from saml2 import SAMLError
+@@ -48,7 +47,7 @@ def url_encode_params(params=None):
+             params_list.extend([(k, x) for x in v])
+         else:
+             params_list.append((k, v))
+-    return urlencode(params_list)
++    return urllib.parse.urlencode(params_list)
+ def create_return_url(base, query, **kwargs):
+@@ -61,11 +60,11 @@ def create_return_url(base, query, **kwa
+     :param kwargs: extra query parameters
+     :return:
+     """
+-    part = urlsplit(base)
++    part = urllib.parse.urlsplit(base)
+     if part.fragment:
+         raise ValueError("Base URL contained parts it shouldn't")
+-    for key, values in parse_qs(query).items():
++    for key, values in urllib.parse.parse_qs(query).items():
+         if key in kwargs:
+             if isinstance(kwargs[key], basestring):
+                 kwargs[key] = [kwargs[key]]
+@@ -74,7 +73,7 @@ def create_return_url(base, query, **kwa
+             kwargs[key] = values
+     if part.query:
+-        for key, values in parse_qs(part.query).items():
++        for key, values in urllib.parse.parse_qs(part.query).items():
+             if key in kwargs:
+                 if isinstance(kwargs[key], basestring):
+                     kwargs[key] = [kwargs[key]]
+@@ -151,7 +150,7 @@ class UsernamePasswordMako(UserAuthnMeth
+         logger.debug("verify(%s)" % request)
+         if isinstance(request, basestring):
+-            _dict = parse_qs(request)
++            _dict = urllib.parse.parse_qs(request)
+         elif isinstance(request, dict):
+             _dict = request
+         else:
+--- python-pysaml2-2.0.0.orig/src/saml2/client.py
++++ python-pysaml2-2.0.0/src/saml2/client.py
+@@ -42,7 +42,7 @@ from saml2.client_base import NoServiceD
+ from saml2.mdstore import destinations
+ try:
+-    from urlparse import parse_qs
++    from urllib.parse import parse_qs
+ except ImportError:
+     # Compatibility with Python <= 2.5
+     from cgi import parse_qs
+--- python-pysaml2-2.0.0.orig/src/saml2/client_base.py
++++ python-pysaml2-2.0.0/src/saml2/client_base.py
+@@ -19,8 +19,6 @@
+ to conclude its tasks.
+ """
+ import threading
+-from urllib import urlencode
+-from urlparse import urlparse
+ from saml2.entity import Entity
+@@ -37,7 +35,8 @@ import saml2
+ import time
+ from saml2.soap import make_soap_enveloped_saml_thingy
+-from urlparse import parse_qs
++import urllib
++import urllib.parse
+ from saml2.s_utils import signature, UnravelError
+ from saml2.s_utils import do_attributes
+@@ -756,7 +755,7 @@ class Base(Entity):
+             else:
+                 args["isPassive"] = "false"
+-        params = urlencode(args)
++        params = urllib.parse.urlencode(args)
+         return "%s?%s" % (url, params)
+     @staticmethod
+@@ -773,10 +772,10 @@ class Base(Entity):
+         """
+         if url:
+-            part = urlparse(url)
+-            qsd = parse_qs(part[4])
++            part = urllib.parse.urlparse(url)
++            qsd = urllib.parse.parse_qs(part[4])
+         elif query:
+-            qsd = parse_qs(query)
++            qsd = urllib.parse.parse_qs(query)
+         else:
+             qsd = {}
+--- python-pysaml2-2.0.0.orig/src/saml2/discovery.py
++++ python-pysaml2-2.0.0/src/saml2/discovery.py
+@@ -1,5 +1,5 @@
+-from urllib import urlencode
+-from urlparse import urlparse, parse_qs
++import urllib
++import urllib.parse
+ from saml2.entity import Entity
+ from saml2.response import VerificationError
+@@ -14,10 +14,10 @@ class DiscoveryServer(Entity):
+     def parse_discovery_service_request(self, url="", query=""):
+         if url:
+-            part = urlparse(url)
+-            dsr = parse_qs(part[4])
++            part = urllib.parse.urlparse(url)
++            dsr = urllib.parse.parse_qs(part[4])
+         elif query:
+-            dsr = parse_qs(query)
++            dsr = urllib.parse.parse_qs(query)
+         else:
+             dsr = {}
+@@ -31,9 +31,9 @@ class DiscoveryServer(Entity):
+                 pass
+         if "return" in dsr:
+-            part = urlparse(dsr["return"])
++            part = urllib.parse.urlparse(dsr["return"])
+             if part.query:
+-                qp = parse_qs(part.query)
++                qp = urllib.parse.parse_qs(part.query)
+                 if "returnIDParam" in dsr:
+                     assert dsr["returnIDParam"] not in qp.keys()
+                 else:
+@@ -69,9 +69,9 @@ class DiscoveryServer(Entity):
+             return_url = kwargs["return"]
+             
+         if entity_id:
+-            qp = urlencode({returnIDParam: entity_id})
++            qp = urllib.parse.urlencode({returnIDParam: entity_id})
+-            part = urlparse(return_url)
++            part = urllib.parse.urlparse(return_url)
+             if part.query:
+                 # Iff there is a query part add the new info at the end
+                 return_url = "%s&%s" % (return_url, qp)
+--- python-pysaml2-2.0.0.orig/src/saml2/httpbase.py
++++ python-pysaml2-2.0.0/src/saml2/httpbase.py
+@@ -3,7 +3,7 @@ import cookielib
+ import copy
+ import re
+ import urllib
+-import urlparse
++import urllib.parse as urlparse
+ import requests
+ import time
+ from Cookie import SimpleCookie
+@@ -109,7 +109,7 @@ class HTTPBase(object):
+         :param url:
+         :return:
+         """
+-        part = urlparse.urlparse(url)
++        part = urllib.parse.urlparse(url)
+         #if part.port:
+         #    _domain = "%s:%s" % (part.hostname, part.port)
+@@ -139,7 +139,7 @@ class HTTPBase(object):
+         if not kaka:
+             return
+-        part = urlparse.urlparse(request.url)
++        part = urllib.parse.urlparse(request.url)
+         _domain = part.hostname
+         logger.debug("%s: '%s'" % (_domain, kaka))
+@@ -274,10 +274,10 @@ class HTTPBase(object):
+     def use_http_artifact(self, message, destination="", relay_state=""):
+         if relay_state:
+-            query = urllib.urlencode({"SAMLart": message,
++            query = urllib.parse.urlencode({"SAMLart": message,
+                                       "RelayState": relay_state})
+         else:
+-            query = urllib.urlencode({"SAMLart": message})
++            query = urllib.parse.urlencode({"SAMLart": message})
+         info = {
+             "data": "",
+             "url": "%s?%s" % (destination, query)
+@@ -297,10 +297,10 @@ class HTTPBase(object):
+         elif typ == "SAMLRequest":
+             # msg should be an identifier
+             if relay_state:
+-                query = urllib.urlencode({"ID": message,
++                query = urllib.parse.urlencode({"ID": message,
+                                           "RelayState": relay_state})
+             else:
+-                query = urllib.urlencode({"ID": message})
++                query = urllib.parse.urlencode({"ID": message})
+             info = {
+                 "data": "",
+                 "url": "%s?%s" % (destination, query)
+--- python-pysaml2-2.0.0.orig/src/saml2/httputil.py
++++ python-pysaml2-2.0.0/src/saml2/httputil.py
+@@ -4,8 +4,8 @@ import logging
+ import time
+ import cgi
+-from urllib import quote
+-from urlparse import parse_qs
++import urllib
++import urllib.parse
+ from Cookie import SimpleCookie
+ from saml2 import BINDING_HTTP_ARTIFACT, SAMLError
+@@ -188,8 +188,8 @@ def geturl(environ, query=True, path=Tru
+ def getpath(environ):
+     """Builds a path."""
+-    return ''.join([quote(environ.get('SCRIPT_NAME', '')),
+-                    quote(environ.get('PATH_INFO', ''))])
++    return ''.join([urllib.parse.quote(environ.get('SCRIPT_NAME', '')),
++                    urllib.parse.quote(environ.get('PATH_INFO', ''))])
+ def get_post(environ):
+@@ -220,14 +220,14 @@ def get_response(environ, start_response
+ def unpack_redirect(environ):
+     if "QUERY_STRING" in environ:
+         _qs = environ["QUERY_STRING"]
+-        return dict([(k, v[0]) for k, v in parse_qs(_qs).items()])
++        return dict([(k, v[0]) for k, v in urllib.parse.parse_qs(_qs).items()])
+     else:
+         return None
+ def unpack_post(environ):
+     try:
+-        return dict([(k, v[0]) for k, v in parse_qs(get_post(environ))])
++        return dict([(k, v[0]) for k, v in urllib.parse.parse_qs(get_post(environ))])
+     except Exception:
+         return None
+--- python-pysaml2-2.0.0.orig/src/saml2/ident.py
++++ python-pysaml2-2.0.0/src/saml2/ident.py
+@@ -3,8 +3,8 @@ import shelve
+ import logging
+ from hashlib import sha256
+-from urllib import quote
+-from urllib import unquote
++import urllib
++import urllib.parse
+ from saml2 import SAMLError
+ from saml2.s_utils import rndstr
+ from saml2.s_utils import PolicyError
+@@ -31,7 +31,7 @@ def code(item):
+     for attr in ATTR:
+         val = getattr(item, attr)
+         if val:
+-            _res.append("%d=%s" % (i, quote(val)))
++            _res.append("%d=%s" % (i, urllib.parse.quote(val)))
+         i += 1
+     return ",".join(_res)
+@@ -40,7 +40,7 @@ def decode(txt):
+     _nid = NameID()
+     for part in txt.split(","):
+         i, val = part.split("=")
+-        setattr(_nid, ATTR[int(i)], unquote(val))
++        setattr(_nid, ATTR[int(i)], urllib.parse.unquote(val))
+     return _nid
+--- python-pysaml2-2.0.0.orig/src/saml2/pack.py
++++ python-pysaml2-2.0.0/src/saml2/pack.py
+@@ -23,7 +23,8 @@ Bindings normally consists of three part
+ - how to package the information
+ - which protocol to use
+ """
+-import urlparse
++import urllib
++import urllib.parse
+ import saml2
+ import base64
+ import urllib
+@@ -136,13 +137,13 @@ def http_redirect_message(message, locat
+         except:
+             raise Unsupported("Signing algorithm")
+         else:
+-            string = "&".join([urllib.urlencode({k: args[k]}) for k in _order if k in args])
++            string = "&".join([urllib.parse.urlencode({k: args[k]}) for k in _order if k in args])
+             args["Signature"] = base64.b64encode(signer.sign(string, key))
+-            string = urllib.urlencode(args)
++            string = urllib.parse.urlencode(args)
+     else:
+-        string = urllib.urlencode(args)
++        string = urllib.parse.urlencode(args)
+-    glue_char = "&" if urlparse.urlparse(location).query else "?"
++    glue_char = "&" if urllib.parse.urlparse(location).query else "?"
+     login_url = glue_char.join([location, string])
+     headers = [('Location', str(login_url))]
+     body = []
+--- python-pysaml2-2.0.0.orig/src/saml2/sigver.py
++++ python-pysaml2-2.0.0/src/saml2/sigver.py
+@@ -630,7 +630,7 @@ def verify_redirect_signature(info, cert
+             args = info.copy()
+             del args["Signature"]  # everything but the signature
+             string = "&".join(
+-                [urllib.urlencode({k: args[k][0]}) for k in _order])
++                [urllib.parse.urlencode({k: args[k][0]}) for k in _order])
+             _key = extract_rsa_key_from_x509_cert(pem_format(cert))
+             _sign = base64.b64decode(info["Signature"][0])
+             try:
+--- python-pysaml2-2.0.0.orig/src/saml2/validate.py
++++ python-pysaml2-2.0.0/src/saml2/validate.py
+@@ -1,5 +1,5 @@
+ import calendar
+-import urlparse
++import urllib.parse
+ import re
+ import time_util
+ import struct
+@@ -46,7 +46,7 @@ def valid_id(oid):
+ def valid_any_uri(item):
+     """very simplistic, ..."""
+     try:
+-        part = urlparse.urlparse(item)
++        part = urllib.parse.urlparse(item)
+     except Exception:
+         raise NotValid("AnyURI")
+@@ -68,7 +68,7 @@ def valid_date_time(item):
+ def valid_url(url):
+     try:
+-        _ = urlparse.urlparse(url)
++        _ = urllib.parse.urlparse(url)
+     except Exception:
+         raise NotValid("URL")
+         
+--- python-pysaml2-2.0.0.orig/tests/fakeIDP.py
++++ python-pysaml2-2.0.0/tests/fakeIDP.py
+@@ -1,4 +1,5 @@
+-from urlparse import parse_qs
++import urllib
++import urllib.parse
+ from saml2.authn_context import INTERNETPROTOCOLPASSWORD
+ from saml2.samlp import attribute_query_from_string, logout_request_from_string
+ from saml2 import BINDING_HTTP_REDIRECT, pack
+@@ -66,14 +67,14 @@ class FakeIDP(Server):
+         if method == "GET":
+             path, query = url.split("?")
+-            qs_dict = parse_qs(kwargs["data"])
++            qs_dict = urllib.parse.parse_qs(kwargs["data"])
+             req = qs_dict["SAMLRequest"][0]
+             rstate = qs_dict["RelayState"][0]
+         else:
+             # Could be either POST or SOAP
+             path = url
+             try:
+-                qs_dict = parse_qs(kwargs["data"])
++                qs_dict = urllib.parse.parse_qs(kwargs["data"])
+                 req = qs_dict["SAMLRequest"][0]
+                 rstate = qs_dict["RelayState"][0]
+             except KeyError:
+--- python-pysaml2-2.0.0.orig/tests/test_50_server.py
++++ python-pysaml2-2.0.0/tests/test_50_server.py
+@@ -1,7 +1,8 @@
+ #!/usr/bin/env python
+ # -*- coding: utf-8 -*-
+ import base64
+-from urlparse import parse_qs
++import urllib
++import urllib.parse
+ from saml2.assertion import Policy
+ from saml2.authn_context import INTERNETPROTOCOLPASSWORD
+ from saml2.saml import NameID, NAMEID_FORMAT_TRANSIENT
+@@ -131,7 +132,7 @@ class TestServer1():
+         binding = BINDING_HTTP_REDIRECT
+         htargs = self.client.apply_binding(
+             binding, "%s" % authn_request, "http://www.example.com", "abcd")
+-        _dict = parse_qs(htargs["headers"][0][1].split('?')[1])
++        _dict = urllib.parse.parse_qs(htargs["headers"][0][1].split('?')[1])
+         print(_dict)
+         raises(OtherError, self.server.parse_authn_request,
+                _dict["SAMLRequest"][0], binding)
+@@ -143,7 +144,7 @@ class TestServer1():
+         binding = BINDING_HTTP_REDIRECT
+         htargs = self.client.apply_binding(binding, "%s" % authn_request,
+                                            "http://www.example.com", "abcd")
+-        _dict = parse_qs(htargs["headers"][0][1].split('?')[1])
++        _dict = urllib.parse.parse_qs(htargs["headers"][0][1].split('?')[1])
+         print(_dict)
+         try:
+@@ -170,7 +171,7 @@ class TestServer1():
+         binding = BINDING_HTTP_REDIRECT
+         htargs = self.client.apply_binding(binding, "%s" % authn_request,
+                                            "http://www.example.com", "abcd")
+-        _dict = parse_qs(htargs["headers"][0][1].split('?')[1])
++        _dict = urllib.parse.parse_qs(htargs["headers"][0][1].split('?')[1])
+         print(_dict)
+         req = self.server.parse_authn_request(_dict["SAMLRequest"][0], binding)
+--- python-pysaml2-2.0.0.orig/tests/test_51_client.py
++++ python-pysaml2-2.0.0/tests/test_51_client.py
+@@ -3,7 +3,7 @@
+ import base64
+ import urllib
+-import urlparse
++import urllib.parse
+ from saml2.authn_context import INTERNETPROTOCOLPASSWORD
+ from saml2.response import LogoutResponse
+@@ -368,8 +368,8 @@ class TestClientWithDummy():
+         assert http_args["headers"][0][0] == "Location"
+         assert http_args["data"] == []
+         redirect_url = http_args["headers"][0][1]
+-        _, _, _, _, qs, _ = urlparse.urlparse(redirect_url)
+-        qs_dict = urlparse.parse_qs(qs)
++        _, _, _, _, qs, _ = urllib.parse.urlparse(redirect_url)
++        qs_dict = urllib.parse.parse_qs(qs)
+         req = self.server.parse_authn_request(qs_dict["SAMLRequest"][0],
+                                               binding)
+         resp_args = self.server.response_args(req.message, [response_binding])
+@@ -422,7 +422,7 @@ class TestClientWithDummy():
+         # Here I fake what the client will do
+         # create the form post
+-        http_args["data"] = urllib.urlencode(_dic)
++        http_args["data"] = urllib.parse.urlencode(_dic)
+         http_args["method"] = "POST"
+         http_args["dummy"] = _dic["SAMLRequest"]
+         http_args["headers"] = [('Content-type',
+--- python-pysaml2-2.0.0.orig/tests/test_64_artifact.py
++++ python-pysaml2-2.0.0/tests/test_64_artifact.py
+@@ -1,7 +1,7 @@
+ import base64
+ from hashlib import sha1
+-from urlparse import urlparse
+-from urlparse import parse_qs
++import urllib
++import urllib.parse
+ from saml2 import BINDING_HTTP_ARTIFACT
+ from saml2 import BINDING_SOAP
+ from saml2 import BINDING_HTTP_POST
+@@ -42,11 +42,11 @@ def get_msg(hinfo, binding, response=Fal
+             j = _inp.find('"', i)
+             msg = _inp[i:j]
+         else:
+-            parts = urlparse(hinfo["url"])
+-            msg = parse_qs(parts.query)["SAMLart"][0]
++            parts = urllib.parse.urlparse(hinfo["url"])
++            msg = urllib.parse.parse_qs(parts.query)["SAMLart"][0]
+     else: # BINDING_HTTP_REDIRECT
+-        parts = urlparse(hinfo["headers"][0][1])
+-        msg = parse_qs(parts.query)["SAMLRequest"][0]
++        parts = urllib.parse.urlparse(hinfo["headers"][0][1])
++        msg = urllib.parse.parse_qs(parts.query)["SAMLRequest"][0]
+     return msg
+--- python-pysaml2-2.0.0.orig/tests/test_65_authn_query.py
++++ python-pysaml2-2.0.0/tests/test_65_authn_query.py
+@@ -1,4 +1,5 @@
+-from urlparse import urlparse, parse_qs
++import urllib
++import urllib.parse
+ from saml2 import BINDING_SOAP, BINDING_HTTP_POST
+ __author__ = 'rolandh'
+@@ -33,8 +34,8 @@ def get_msg(hinfo, binding):
+         j = _inp.find('"', i)
+         xmlstr = _inp[i:j]
+     else:  # BINDING_HTTP_REDIRECT
+-        parts = urlparse(hinfo["headers"][0][1])
+-        xmlstr = parse_qs(parts.query)["SAMLRequest"][0]
++        parts = urllib.parse.urlparse(hinfo["headers"][0][1])
++        xmlstr = urllib.parse.parse_qs(parts.query)["SAMLRequest"][0]
+     return xmlstr
+--- python-pysaml2-2.0.0.orig/tests/test_68_assertion_id.py
++++ python-pysaml2-2.0.0/tests/test_68_assertion_id.py
+@@ -1,5 +1,5 @@
+-from urlparse import parse_qs
+-from urlparse import urlparse
++from urllib.parse import parse_qs
++from urllib.parse import urlparse
+ from saml2.authn_context import INTERNETPROTOCOLPASSWORD
+ from saml2.samlp import AuthnRequest
+ from saml2.samlp import NameIDPolicy
+@@ -36,10 +36,10 @@ def get_msg(hinfo, binding, response=Fal
+             msg = hinfo["data"]
+         else:
+             msg = ""
+-            return parse_qs(hinfo["url"].split("?")[1])["ID"][0]
++            return urllib.parse.parse_qs(hinfo["url"].split("?")[1])["ID"][0]
+     else:  # BINDING_HTTP_REDIRECT
+-        parts = urlparse(hinfo["headers"][0][1])
+-        msg = parse_qs(parts.query)["SAMLRequest"][0]
++        parts = urllib.parse.urlparse(hinfo["headers"][0][1])
++        msg = urllib.parse.parse_qs(parts.query)["SAMLRequest"][0]
+     return msg
+--- python-pysaml2-2.0.0.orig/tests/test_70_redirect_signing.py
++++ python-pysaml2-2.0.0/tests/test_70_redirect_signing.py
+@@ -6,7 +6,8 @@ from saml2.server import Server
+ from saml2 import BINDING_HTTP_REDIRECT
+ from saml2.client import Saml2Client
+ from saml2.config import SPConfig
+-from urlparse import parse_qs
++import urllib
++import urllib.parse
+ from pathutils import dotname
+@@ -38,7 +39,7 @@ def test():
+     for param, val in info["headers"]:
+         if param == "Location":
+-            _dict = parse_qs(val.split("?")[1])
++            _dict = urllib.parse.parse_qs(val.split("?")[1])
+             _certs = idp.metadata.certs(sp.config.entityid, "any", "signing")
+             for cert in _certs:
+                 if verify_redirect_signature(_dict, cert):