Python six.moves.urllib.parse.parse_qs() Examples

The following are 30 code examples of six.moves.urllib.parse.parse_qs(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module six.moves.urllib.parse , or try the search function .
Example #1
Source File: spider.py    From collectors with MIT License 6 votes vote down vote up
def _process_url(page_from, page_to, url):

    # Get url page
    query = urlparse(url).query
    query = parse_qs(query)
    page = query.get('page')

    # Preserve if match
    if page:
        page_from = int(page_from)
        page_to = int(page_to)
        page = int(page[0])
        if page >= page_from and page <= page_to:
            return url

    return None 
Example #2
Source File: quota_sets.py    From manila with Apache License 2.0 6 votes vote down vote up
def _delete(self, req, id):
        context = req.environ['manila.context']
        params = parse.parse_qs(req.environ.get('QUERY_STRING', ''))
        user_id = params.get('user_id', [None])[0]
        share_type = params.get('share_type', [None])[0]
        self._validate_user_id_and_share_type_args(user_id, share_type)
        try:
            db.authorize_project_context(context, id)
            if user_id:
                QUOTAS.destroy_all_by_project_and_user(context, id, user_id)
            elif share_type:
                share_type_id = self._get_share_type_id(context, share_type)
                QUOTAS.destroy_all_by_project_and_share_type(
                    context, id, share_type_id)
            else:
                QUOTAS.destroy_all_by_project(context, id)
            return webob.Response(status_int=http_client.ACCEPTED)
        except exception.NotAuthorized:
            raise webob.exc.HTTPForbidden() 
Example #3
Source File: quota_sets.py    From manila with Apache License 2.0 6 votes vote down vote up
def _show(self, req, id, detail=False):
        context = req.environ['manila.context']
        params = parse.parse_qs(req.environ.get('QUERY_STRING', ''))
        user_id = params.get('user_id', [None])[0]
        share_type = params.get('share_type', [None])[0]
        try:
            db.authorize_project_context(context, id)
            # _get_quotas use 'usages' to indicate whether retrieve additional
            # attributes, so pass detail to the argument.
            share_type_id = self._get_share_type_id(context, share_type)
            quotas = self._get_quotas(
                context, id, user_id, share_type_id, usages=detail)
            return self._view_builder.detail_list(
                req, quotas, id, share_type_id)
        except exception.NotAuthorized:
            raise webob.exc.HTTPForbidden() 
Example #4
Source File: test_tableau.py    From luigi-td with Apache License 2.0 6 votes vote down vote up
def test_default(self):
        target = TestTableauServerResultTarget(test_config.get_tmp_path('result.job'))
        target.datasource = 'test-datasource'
        url = urlparse(target.get_result_url())
        params = parse_qs(url.query)
        eq_(url.scheme, 'tableau')
        eq_(url.hostname, 'tableau.example.com')
        eq_(url.path, '/' + target.datasource)
        eq_(url_unquote(url.username), TestTableauServerResultTarget.username)
        eq_(url_unquote(url.password), TestTableauServerResultTarget.password)
        eq_(params.get('ssl'), ['true'])
        eq_(params.get('ssl_verify'), ['true'])
        eq_(params.get('server_version'), None)
        eq_(params.get('site'), None)
        eq_(params.get('project'), None)
        eq_(params.get('mode'), ['replace']) 
Example #5
Source File: test_flask_oidc.py    From flask-oidc with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def test_refresh():
    """
    Test token expiration and refresh.
    """
    test_client = make_test_client()

    with patch('time.time', Mock(return_value=time.time())) as time_1:
        # authenticate and get an ID token cookie
        auth_redirect = test_client.get('/')
        callback_redirect = test_client.get(callback_url_for(auth_redirect))
        actual_page = test_client.get(callback_redirect.headers['Location'])
        page_text = ''.join(codecs.iterdecode(actual_page.response, 'utf-8'))
        assert page_text == 'too many secrets', "Authentication failed"

    # app should now try to use the refresh token
    with patch('time.time', Mock(return_value=time.time() + 10)) as time_2:
        test_client.get('/')
        body = parse_qs(last_request['body'])
        assert body.get('refresh_token') == ['mock_refresh_token'],\
            "App should have tried to refresh credentials" 
Example #6
Source File: __init__.py    From pyspider with Apache License 2.0 6 votes vote down vote up
def _connect_elasticsearch(parsed, dbtype):
    # in python 2.6 url like "http://host/?query", query will not been splitted
    if parsed.path.startswith('/?'):
        index = parse_qs(parsed.path[2:])
    else:
        index = parse_qs(parsed.query)
    if 'index' in index and index['index']:
        index = index['index'][0]
    else:
        index = 'pyspider'

    if dbtype == 'projectdb':
        from .elasticsearch.projectdb import ProjectDB
        return ProjectDB([parsed.netloc], index=index)
    elif dbtype == 'resultdb':
        from .elasticsearch.resultdb import ResultDB
        return ResultDB([parsed.netloc], index=index)
    elif dbtype == 'taskdb':
        from .elasticsearch.taskdb import TaskDB
        return TaskDB([parsed.netloc], index=index) 
Example #7
Source File: test_auth.py    From allura with Apache License 2.0 6 votes vote down vote up
def test_access_token_ok(self, Request, Server):
        Request.from_request.return_value = {
            'oauth_consumer_key': 'api_key',
            'oauth_token': 'api_key',
            'oauth_verifier': 'good',
        }
        user = M.User.by_username('test-admin')
        ctok = M.OAuthConsumerToken(
            api_key='api_key',
            user_id=user._id,
            description='ctok_desc',
        )
        M.OAuthRequestToken(
            api_key='api_key',
            consumer_token_id=ctok._id,
            callback='http://my.domain.com/callback?myparam=foo',
            user_id=user._id,
            validation_pin='good',
        )
        ThreadLocalORMSession.flush_all()
        r = self.app.get('/rest/oauth/access_token')
        atok = parse_qs(r.text)
        assert_equal(len(atok['oauth_token']), 1)
        assert_equal(len(atok['oauth_token_secret']), 1) 
Example #8
Source File: referrer.py    From pyreferrer with MIT License 6 votes vote down vote up
def parse_query_string(url, parameters):
        if not parameters:
            return ''

        url_query = url.query
        if six.PY2:
            url_query = url_query.encode('utf-8')
        query_params = parse_qs(url_query, keep_blank_values=True)
        query_common = set.intersection(set(query_params.keys()), set(parameters))
        fragment_params = parse_qs(url.fragment, keep_blank_values=True)
        fragment_common = set.intersection(set(fragment_params.keys()), set(parameters))
        query = ''
        if len(query_common) > 0:
            query = query_params[list(query_common)[0]][0]
        elif len(fragment_common) > 0:
            query = fragment_params[list(fragment_common)[0]][0]
        elif '*' in parameters:
            query = ''

        if six.PY2:
            return query.decode('utf-8')
        return query 
Example #9
Source File: mediawiki.py    From Dailyfresh-B2C with Apache License 2.0 6 votes vote down vote up
def access_token(self, token):
        """
        Fetches the Mediawiki access token.
        """
        auth_token = self.oauth_auth(token)

        response = requests.post(
            url=self.setting('MEDIAWIKI_URL'),
            params={'title': 'Special:Oauth/token'},
            auth=auth_token
        )
        credentials = parse_qs(response.content)
        oauth_token_key = credentials.get(b('oauth_token'))[0]
        oauth_token_secret = credentials.get(b('oauth_token_secret'))[0]
        oauth_token_key = oauth_token_key.decode()
        oauth_token_secret = oauth_token_secret.decode()

        return {
            'oauth_token': oauth_token_key,
            'oauth_token_secret': oauth_token_secret
        } 
Example #10
Source File: codec.py    From pwnypack with MIT License 6 votes vote down vote up
def deurlform(d):
    """
    Convert a URL encoded query string to a dictionary.

    Args:
        d(str): The URL encoded query string.

    Returns:
        dict: A dictionary containing each key and all its values as a list.

    Example:
        >>> from pwny import *
        >>> deurlform('foo=bar&baz=quux&baz=corge')
        {'foo': ['bar'], 'baz': ['quux', 'corge']}
    """
    return parse_qs(d) 
Example #11
Source File: functions.py    From python-mwoauth with MIT License 6 votes vote down vote up
def process_request_token(content):
    if content.startswith("Error: "):
        raise OAuthException(content[len("Error: "):])

    credentials = parse_qs(content)

    if credentials is None or credentials == {}:
        raise OAuthException(
            "Expected x-www-form-urlencoded response from " +
            "MediaWiki, but got something else: " +
            "{0}".format(repr(content)))
    elif 'oauth_token' not in credentials or \
         'oauth_token_secret' not in credentials:
        raise OAuthException(
            "MediaWiki response lacks token information: "
            "{0}".format(repr(credentials)))
    else:
        return RequestToken(
            credentials.get('oauth_token')[0],
            credentials.get('oauth_token_secret')[0]
        ) 
Example #12
Source File: tests.py    From monasca-ui with Apache License 2.0 6 votes vote down vote up
def test_get_relative_url_with_unicode(self):
        """Tests if it properly converts multibyte characters."""
        from six.moves.urllib import parse as urlparse

        self.view.request = self.request_factory.get(
            '/', data={'a': 1, 'b': 2}
        )
        expected_path = ('/elasticsearch/.kibana/search'
                         '/New-Saved-Search%E3%81%82')
        expected_qs = {'a': ['1'], 'b': ['2']}

        url = self.view.get_relative_url(
            u'/elasticsearch/.kibana/search/New-Saved-Searchあ'
        )
        # order of query params may change
        parsed_url = urlparse.urlparse(url)
        actual_path = parsed_url.path
        actual_qs = urlparse.parse_qs(parsed_url.query)

        self.assertEqual(actual_path, expected_path)
        self.assertEqual(actual_qs, expected_qs) 
Example #13
Source File: utils.py    From edx-enterprise with GNU Affero General Public License v3.0 6 votes vote down vote up
def update_query_parameters(url, query_parameters):
    """
    Return url with updated query parameters.

    Arguments:
        url (str): Original url whose query parameters need to be updated.
        query_parameters (dict): A dictionary containing query parameters to be added to course selection url.

    Returns:
        (slug): slug identifier for the identity provider that can be used for identity verification of
            users associated the enterprise customer of the given user.

    """
    scheme, netloc, path, query_string, fragment = urlsplit(url)
    url_params = parse_qs(query_string)

    # Update url query parameters
    url_params.update(query_parameters)

    return urlunsplit(
        (scheme, netloc, path, urlencode(sorted(url_params.items()), doseq=True), fragment),
    ) 
Example #14
Source File: utils.py    From edx-enterprise with GNU Affero General Public License v3.0 6 votes vote down vote up
def traverse_pagination(response, endpoint):
    """
    Traverse a paginated API response.

    Extracts and concatenates "results" (list of dict) returned by DRF-powered
    APIs.

    Arguments:
        response (Dict): Current response dict from service API
        endpoint (slumber Resource object): slumber Resource object from edx-rest-api-client

    Returns:
        list of dict.

    """
    results = response.get('results', [])

    next_page = response.get('next')
    while next_page:
        querystring = parse_qs(urlparse(next_page).query, keep_blank_values=True)
        response = endpoint.get(**querystring)
        results += response.get('results', [])
        next_page = response.get('next')

    return results 
Example #15
Source File: niji_tags.py    From niji with MIT License 6 votes vote down vote up
def change_url(request, kwargs=None, query=None):
    kwargs = kwargs or {}
    query = query or {}
    rm = request.resolver_match
    _kwargs = rm.kwargs.copy()
    _kwargs.update(kwargs)
    if _kwargs.get("page") == 1:
        _kwargs.pop('page', None)
    qs = parse_qs(urlparse(request.get_full_path()).query)
    qs.update(query)
    path = reverse(
        '%s:%s' % (rm.namespace, rm.url_name),
        args=rm.args,
        kwargs=_kwargs,
    )
    if (qs):
        return "%s?%s" % (path, urlencode(qs, True))
    else:
        return path 
Example #16
Source File: test_spid_testenv.py    From spid-testenv2 with GNU Affero General Public License v3.0 6 votes vote down vote up
def test_logout_response_http_redirect(self, unravel, verified):
        # See: https://github.com/italia/spid-testenv2/issues/88
        with patch('testenv.server.IdpServer._sp_single_logout_service', return_value=_sp_single_logout_service(self.idp_server, 'https://spid.test:8000', BINDING_HTTP_REDIRECT)) as mocked:  # noqa: F841
            response = self.test_client.get(
                '/slo-test?SAMLRequest=b64encodedrequest&SigAlg={}&Signature=sign'.format(
                    quote(SIG_RSA_SHA256)), follow_redirects=False)
            self.assertEqual(response.status_code, 302)
            response_location = response.headers.get('Location')
            url = urlparse(response_location)
            query = parse_qs(url.query)
            self.assertIn(
                'Signature',
                query
            )
            saml_response = query.get('SAMLResponse')[0]
            response = decode_base64_and_inflate(saml_response)
            xml = ET.fromstring(response)
            signatures = xml.findall(
                './/{http://www.w3.org/2000/09/xmldsig#}Signature')
            self.assertEqual(0, len(signatures))
            self.assertEqual(len(self.idp_server.ticket), 0)
            self.assertEqual(len(self.idp_server.responses), 0) 
Example #17
Source File: test_signature.py    From mediafire-python-open-sdk with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def test_signature_values(self):
        """Test signature generation and update"""

        body = """
        {"response": {
            "user_info": {}, "new_key": "yes", "result": "Success"}
        }
        """

        responses.add(responses.POST, self.url, body=body, status=200,
                      content_type="application/json")
        # original secret key
        self.api.user_get_info()
        # secret key is (1000000000 * 16807) % 2147483647 = 792978578
        self.api.user_get_info()

        query = responses.calls[0].request.body.decode('utf-8')
        params = parse_qs(query)

        self.assertEqual(params['signature'][0], CALL_SIGNATURES[0])

        query = responses.calls[1].request.body.decode('utf-8')
        params = parse_qs(query)

        self.assertEqual(params['signature'][0], CALL_SIGNATURES[1]) 
Example #18
Source File: client.py    From eclcli with Apache License 2.0 6 votes vote down vote up
def _pagination(self, collection, path, **params):
        if params.get('page_reverse', False):
            linkrel = 'previous'
        else:
            linkrel = 'next'
        next = True
        while next:
            res = self.get(path, params=params)
            yield res
            next = False
            try:
                for link in res['%s_links' % collection]:
                    if link['rel'] == linkrel:
                        query_str = urlparse.urlparse(link['href']).query
                        params = urlparse.parse_qs(query_str)
                        next = True
                        break
            except KeyError:
                break 
Example #19
Source File: client.py    From eclcli with Apache License 2.0 6 votes vote down vote up
def _pagination(self, collection, path, **params):
        if params.get('page_reverse', False):
            linkrel = 'previous'
        else:
            linkrel = 'next'
        next = True
        while next:
            res = self.get(path, params=params)
            yield res
            next = False
            try:
                for link in res['%s_links' % collection]:
                    if link['rel'] == linkrel:
                        query_str = urlparse.urlparse(link['href']).query
                        params = urlparse.parse_qs(query_str)
                        next = True
                        break
            except KeyError:
                break 
Example #20
Source File: client.py    From eclcli with Apache License 2.0 6 votes vote down vote up
def _pagination(self, collection, path, **params):
        if params.get('page_reverse', False):
            linkrel = 'previous'
        else:
            linkrel = 'next'
        next = True
        while next:
            res = self.get(path, params=params)
            yield res
            next = False
            try:
                for link in res['%s_links' % collection]:
                    if link['rel'] == linkrel:
                        query_str = urlparse.urlparse(link['href']).query
                        params = urlparse.parse_qs(query_str)
                        next = True
                        break
            except KeyError:
                break 
Example #21
Source File: test_api_v2.py    From tacker with Apache License 2.0 6 votes vote down vote up
def test_list_pagination_with_empty_page(self):
        return_value = []
        instance = self.plugin.return_value
        instance.get_networks.return_value = return_value
        params = {'limit': ['2'],
                  'marker': str(_uuid())}
        res = self.api.get(_get_path('networks'),
                           params=params).json

        self.assertEqual([], res['networks'])

        previous_links = []
        if 'networks_links' in res:
            for r in res['networks_links']:
                self.assertNotEqual(r['rel'], 'next')
                if r['rel'] == 'previous':
                    previous_links.append(r)
        self.assertEqual(1, len(previous_links))

        url = urlparse.urlparse(previous_links[0]['href'])
        self.assertEqual(_get_path('networks'), url.path)
        expect_params = params.copy()
        del expect_params['marker']
        expect_params['page_reverse'] = ['True']
        self.assertEqual(expect_params, urlparse.parse_qs(url.query)) 
Example #22
Source File: test_api_v2.py    From tacker with Apache License 2.0 6 votes vote down vote up
def test_list_pagination_reverse_with_empty_page(self):
        return_value = []
        instance = self.plugin.return_value
        instance.get_networks.return_value = return_value
        params = {'limit': ['2'],
                  'marker': [str(_uuid())],
                  'page_reverse': ['True']}
        res = self.api.get(_get_path('networks'),
                           params=params).json
        self.assertEqual([], res['networks'])

        next_links = []
        if 'networks_links' in res:
            for r in res['networks_links']:
                self.assertNotEqual(r['rel'], 'previous')
                if r['rel'] == 'next':
                    next_links.append(r)
        self.assertEqual(1, len(next_links))

        url = urlparse.urlparse(next_links[0]['href'])
        self.assertEqual(_get_path('networks'), url.path)
        expect_params = params.copy()
        del expect_params['marker']
        del expect_params['page_reverse']
        self.assertEqual(expect_params, urlparse.parse_qs(url.query)) 
Example #23
Source File: mediawiki.py    From Dailyfresh-B2C with Apache License 2.0 6 votes vote down vote up
def oauth_authorization_request(self, token):
        """
        Generates the URL for the authorization link
        """
        if not isinstance(token, dict):
            token = parse_qs(token)

        oauth_token = token.get(self.OAUTH_TOKEN_PARAMETER_NAME)[0]
        state = self.get_or_create_state()
        base_url = self.setting('MEDIAWIKI_URL')

        return '{0}?{1}'.format(base_url, urlencode({
            'title': 'Special:Oauth/authenticate',
            self.OAUTH_TOKEN_PARAMETER_NAME: oauth_token,
            self.REDIRECT_URI_PARAMETER_NAME: self.get_redirect_uri(state)
        })) 
Example #24
Source File: test_client.py    From python-storage with Apache License 2.0 5 votes vote down vote up
def test_list_buckets_explicit_project(self):
        from six.moves.urllib.parse import parse_qs
        from six.moves.urllib.parse import urlparse

        PROJECT = "PROJECT"
        OTHER_PROJECT = "OTHER_PROJECT"
        CREDENTIALS = _make_credentials()
        client = self._make_one(project=PROJECT, credentials=CREDENTIALS)

        http = _make_requests_session([_make_json_response({})])
        client._http_internal = http

        buckets = list(client.list_buckets(project=OTHER_PROJECT))

        self.assertEqual(len(buckets), 0)

        http.request.assert_called_once_with(
            method="GET",
            url=mock.ANY,
            data=mock.ANY,
            headers=mock.ANY,
            timeout=mock.ANY,
        )

        requested_url = http.request.mock_calls[0][2]["url"]
        expected_base_url = "/".join(
            [
                client._connection.API_BASE_URL,
                "storage",
                client._connection.API_VERSION,
                "b",
            ]
        )
        self.assertTrue(requested_url.startswith(expected_base_url))

        expected_query = {"project": [OTHER_PROJECT], "projection": ["noAcl"]}
        uri_parts = urlparse(requested_url)
        self.assertEqual(parse_qs(uri_parts.query), expected_query) 
Example #25
Source File: test_sqlalchemy_data_layer.py    From flask-rest-jsonapi with MIT License 5 votes vote down vote up
def test_add_pagination_links(app):
    with app.app_context():
        qs = {'page[number]': '2', 'page[size]': '10'}
        qsm = QSManager(qs, None)
        pagination_dict = dict()
        add_pagination_links(pagination_dict, 43, qsm, str())
        last_page_dict = parse_qs(pagination_dict['links']['last'][1:])
        assert len(last_page_dict['page[number]']) == 1
        assert last_page_dict['page[number]'][0] == '5' 
Example #26
Source File: test_client.py    From python-storage with Apache License 2.0 5 votes vote down vote up
def test_list_buckets_empty(self):
        from six.moves.urllib.parse import parse_qs
        from six.moves.urllib.parse import urlparse

        PROJECT = "PROJECT"
        CREDENTIALS = _make_credentials()
        client = self._make_one(project=PROJECT, credentials=CREDENTIALS)

        http = _make_requests_session([_make_json_response({})])
        client._http_internal = http

        buckets = list(client.list_buckets())

        self.assertEqual(len(buckets), 0)

        http.request.assert_called_once_with(
            method="GET",
            url=mock.ANY,
            data=mock.ANY,
            headers=mock.ANY,
            timeout=mock.ANY,
        )

        requested_url = http.request.mock_calls[0][2]["url"]
        expected_base_url = "/".join(
            [
                client._connection.API_BASE_URL,
                "storage",
                client._connection.API_VERSION,
                "b",
            ]
        )
        self.assertTrue(requested_url.startswith(expected_base_url))

        expected_query = {"project": [PROJECT], "projection": ["noAcl"]}
        uri_parts = urlparse(requested_url)
        self.assertEqual(parse_qs(uri_parts.query), expected_query) 
Example #27
Source File: client.py    From python-saml with MIT License 5 votes vote down vote up
def receive(method, query_string, body):
    # Determine the protocol used and pare the appropriate data.
    method = method.upper()
    if method == 'GET':
        data = parse_qs(_text(query_string))
        binding = 'artifact' if 'SAMLArtifact' in data else 'redirect'

    elif method == 'POST':
        data = parse_qs(_text(body))
        binding = 'post'

    else:
        # Unknown method used.
        return None

    if binding in ('redirect', 'post'):
        # Pull the text out of the query.
        encoded = data.get('SAMLResponse', data.get('SAMLRequest'))
        if not encoded:
            # No SAML message found.
            return None

        # Decode the text.
        text = base64.b64decode(encoded[0])
        if binding == "redirect":
            text = zlib.decompress(text, -15)

        # Parse the text into xml.
        message = etree.XML(text)

        # Get the relay state if present.
        relay_state = data.get('RelayState')
        if relay_state:
            relay_state = unquote_plus(relay_state[0])

        # Return the message and the relay state.
        return message, relay_state 
Example #28
Source File: test_api_v2.py    From tacker with Apache License 2.0 5 votes vote down vote up
def test_list_pagination_with_last_page(self):
        id = str(_uuid())
        input_dict = {'id': id,
                      'name': 'net1',
                      'admin_state_up': True,
                      'status': "ACTIVE",
                      'tenant_id': '',
                      'shared': False,
                      'subnets': []}
        return_value = [input_dict]
        instance = self.plugin.return_value
        instance.get_networks.return_value = return_value
        params = {'limit': ['2'],
                  'marker': str(_uuid())}
        res = self.api.get(_get_path('networks'),
                           params=params).json

        self.assertEqual(1, len(res['networks']))
        self.assertEqual(id, res['networks'][0]['id'])

        self.assertIn('networks_links', res)
        previous_links = []
        for r in res['networks_links']:
            self.assertNotEqual(r['rel'], 'next')
            if r['rel'] == 'previous':
                previous_links.append(r)
        self.assertEqual(1, len(previous_links))

        url = urlparse.urlparse(previous_links[0]['href'])
        self.assertEqual(_get_path('networks'), url.path)
        expect_params = params.copy()
        expect_params['marker'] = [id]
        expect_params['page_reverse'] = ['True']
        self.assertEqual(expect_params, urlparse.parse_qs(url.query)) 
Example #29
Source File: test_oauth.py    From spotipy with MIT License 5 votes vote down vote up
def test_get_authorize_url_shows_dialog_when_requested(self):
        oauth = SpotifyOAuth("CLID", "CLISEC", "REDIR", show_dialog=True)

        url = oauth.get_authorize_url()

        parsed_url = urllibparse.urlparse(url)
        parsed_qs = urllibparse.parse_qs(parsed_url.query)
        self.assertTrue(parsed_qs['show_dialog']) 
Example #30
Source File: demo_theme.py    From ttrv with MIT License 5 votes vote down vote up
def initialize_vcr():

    def auth_matcher(r1, r2):
        return (r1.headers.get('authorization') ==
                r2.headers.get('authorization'))

    def uri_with_query_matcher(r1, r2):
        p1,  p2 = urlparse(r1.uri), urlparse(r2.uri)
        return (p1[:3] == p2[:3] and
                parse_qs(p1.query, True) == parse_qs(p2.query, True))

    cassette_dir = os.path.join(os.path.dirname(__file__), 'cassettes')
    if not os.path.exists(cassette_dir):
        os.makedirs(cassette_dir)

    filename = os.path.join(cassette_dir, 'demo_theme.yaml')
    if os.path.exists(filename):
        record_mode = 'none'
    else:
        record_mode = 'once'
    vcr = VCR(
        record_mode=record_mode,
        filter_headers=[('Authorization', '**********')],
        filter_post_data_parameters=[('refresh_token', '**********')],
        match_on=['method', 'uri_with_query', 'auth', 'body'],
        cassette_library_dir=cassette_dir)
    vcr.register_matcher('auth', auth_matcher)
    vcr.register_matcher('uri_with_query', uri_with_query_matcher)

    return vcr


# Patch the getch method so we can display multiple notifications or
# other elements that require a keyboard input on the screen at the
# same time without blocking the main thread.