Skip to content

Commit

Permalink
Merge pull request #75 from bpicolo/67_utf8_encode_params
Browse files Browse the repository at this point in the history
UTF8 encode url params
  • Loading branch information
Ben Picolo committed Dec 16, 2014
2 parents 2044baa + 3bdedb3 commit 4ac6cf0
Show file tree
Hide file tree
Showing 27 changed files with 136 additions and 18 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
0.7.4 (2014-12-11)
------------------
- Requests urlencode params as utf8
- Docs related to 0.7.2
- Declare utf-8 encoding for all files

0.7.3 (2014-12-11)
------------------
- request logging is now done on the debug level instead of
- request logging is now done on the debug level instead of
info level.

0.7.2 (2014-12-11)
------------------
- Allow headers to be passed in the api_docs request

0.7.1 (2014-12-11)
------------------
- Requests no longer mutate clients

0.7.0 (2014-11-26)
------------------
- headers are no longer cached and required as part of async and
Expand Down
12 changes: 12 additions & 0 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,18 @@ Wrapping HTTP response error with custom class
"http://petstore.swagger.wordnik.com/api/api-docs",
raise_with=MyAwesomeException)
Passing Headers to the api-docs requests
----------------------------------------------

``swagger-py`` provides an option to pass custom headers with requests to
api-docs

.. code-block:: python
swagger_client = client.get_client(
"http://petstore.swagger.wordnik.com/api/api-docs",
api_doc_request_headers={'foo': 'bar'})
Docstrings
----------

Expand Down
15 changes: 8 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name="swaggerpy",
version="0.7.3",
version="0.7.4",
license="BSD 3-Clause License",
description="Library for accessing Swagger-enabled API's",
long_description=open(os.path.join(os.path.dirname(__file__),
Expand All @@ -28,17 +28,18 @@
"Programming Language :: Python",
],
tests_require=[
"nose",
"tissue",
"bottle",
"coverage",
"ordereddict",
"httpretty",
"bottle"
"nose",
"ordereddict",
"tissue",
],
install_requires=[
"requests",
"python-dateutil",
"crochet",
"python-dateutil",
"requests",
"twisted",
"yelp_uri",
],
)
15 changes: 8 additions & 7 deletions swaggerpy/async_http_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand All @@ -10,21 +11,21 @@
from cStringIO import StringIO
import json
import logging
import urllib

import crochet

import twisted.internet.error
import twisted.web.client
from swaggerpy import http_client
from swaggerpy.exception import HTTPError
from swaggerpy.multipart_response import create_multipart_content
from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.internet.protocol import Protocol
from twisted.web.client import Agent
from twisted.web.client import FileBodyProducer
from twisted.web.http_headers import Headers
from yelp_uri import urllib_utf8

from swaggerpy import http_client
from swaggerpy.exception import HTTPError
from swaggerpy.multipart_response import create_multipart_content

log = logging.getLogger(__name__)

Expand All @@ -47,7 +48,7 @@ def start_request(self, request_params):
'method': str(request_params['method']),
'bodyProducer': stringify_body(request_params),
'headers': listify_headers(request_params['headers']),
'uri': str(request_params['url'] + '?' + urllib.urlencode(
'uri': str(request_params['url'] + '?' + urllib_utf8.urlencode(
request_params['params'], True))
}

Expand Down Expand Up @@ -169,7 +170,7 @@ def stringify_body(request_params):
if 'files' in request_params:
data = create_multipart_content(request_params, headers)
elif headers.get('content-type') == http_client.APP_FORM:
data = urllib.urlencode(request_params.get('data', {}))
data = urllib_utf8.urlencode(request_params.get('data', {}))
else:
http_client.stringify_body(request_params)
data = request_params.get('data')
Expand Down
8 changes: 6 additions & 2 deletions swaggerpy/client.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013, Digium, Inc.
# Copyright (c) 2014, Yelp, Inc.
#

"""Swagger client library.
"""

Expand All @@ -14,6 +14,8 @@
from collections import namedtuple
from urlparse import urlparse

from yelp_uri import urllib_utf8

import swagger_type
from swaggerpy.http_client import APP_FORM, APP_JSON, SynchronousHttpClient
from swaggerpy.processors import SwaggerProcessor
Expand Down Expand Up @@ -170,7 +172,7 @@ def _construct_request(self, **kwargs):
def __call__(self, **kwargs):
log.debug(u"%s?%r" % (
self._json[u'nickname'],
urllib.urlencode(kwargs)
urllib_utf8.urlencode(kwargs)
))
request = self._construct_request(**kwargs)

Expand Down Expand Up @@ -290,6 +292,8 @@ class SwaggerClient(object):
:type api_base_path: str
:param raise_with: Custom Exception to wrap the response error with
:type raise_with: type
:params api_doc_request_headers: Headers to pass with api docs requests
:type: dict
"""

def __init__(self, url_or_resource, http_client=None,
Expand Down
1 change: 1 addition & 0 deletions swaggerpy/exception.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
1 change: 1 addition & 0 deletions swaggerpy/http_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2013, Digium, Inc.
Expand Down
2 changes: 2 additions & 0 deletions swaggerpy/multipart_response.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

from uuid import uuid4
from swaggerpy import http_client

Expand Down
2 changes: 2 additions & 0 deletions swaggerpy/processors.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

#
# Copyright (c) 2013, Digium, Inc.
#
Expand Down
2 changes: 2 additions & 0 deletions swaggerpy/response.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

#
# Copyright (c) Yelp, Inc.
#
Expand Down
2 changes: 2 additions & 0 deletions swaggerpy/swagger_model.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

#
# Copyright (c) 2013, Digium, Inc.
#
Expand Down
2 changes: 2 additions & 0 deletions swaggerpy/swagger_type.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

#
# Copyright (c) Yelp, Inc.
#
Expand Down
45 changes: 45 additions & 0 deletions tests/async_http_client_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand All @@ -18,6 +19,7 @@

from crochet._eventloop import EventualResult
from twisted.internet.defer import Deferred
from twisted.web.http_headers import Headers

import swaggerpy.async_http_client
import swaggerpy.exception
Expand All @@ -34,6 +36,16 @@ def test_stringify_body_converts_dict_to_str(self):
self.assertEqual({"foo": "bar", "bar": 42},
json.loads(request_params['data']))

def test_stringify_body_encode_params_to_utf8(self):
request_params = {
'headers': {'content-type': 'application/json'},
'data': {'foo': 'bar', 'bar': 42},
'params': {'bar': u'酒場'},
}
swaggerpy.http_client.stringify_body(request_params)
self.assertEqual({"foo": "bar", "bar": 42},
json.loads(request_params['data']))

def test_stringify_body_ignores_data_if_header_content_type_not_json(self):
request_params = {'headers': {}, 'data': 'foo'}
swaggerpy.http_client.stringify_body(request_params)
Expand Down Expand Up @@ -132,6 +144,39 @@ def test_success_AsyncHTTP_response(self):
resp = async_client.wait(5, eventual)
self.assertEqual(2, resp.code)

def test_url_encode_async_request(self):
Response = namedtuple("MyResponse",
"version code phrase headers length deliverBody")
with patch.object(
swaggerpy.async_http_client.AsynchronousHttpClient,
'fetch_deferred',
return_value=Mock(
autospec=EventualResult,
_deferred=Mock(autospec=Deferred),
),
) as mock_fetch_deferred:
req = {
'method': 'GET',
'url': 'foo',
'data': None,
'headers': {'foo': 'bar'},
'params': {'bar': u'酒場'},
}
mock_fetch_deferred.return_value.wait.return_value = Response(
1, 2, 3, 4, 5, 6)

async_client = swaggerpy.async_http_client.AsynchronousHttpClient()
async_client.start_request(req)

mock_fetch_deferred.assert_called_once_with(
{
'headers': Headers({'foo': ['bar']}),
'method': 'GET',
'bodyProducer': None,
'uri': 'foo?bar=%E9%85%92%E5%A0%B4'
}
)


class HTTPBodyFetcherTest(unittest.TestCase):

Expand Down
1 change: 1 addition & 0 deletions tests/client_http_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2013, Digium, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/client_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2013, Digium, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/exception_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
16 changes: 16 additions & 0 deletions tests/http_client_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import base64
import unittest

Expand All @@ -23,6 +25,20 @@ def test_simple_get(self):
self.assertEqual({'foo': ['bar']},
httpretty.last_request().querystring)

@httpretty.activate
def test_unicode_to_utf8_encode_params(self):
httpretty.register_uri(
httpretty.GET, "http://swagger.py/client-test",
body='expected')

uut = SynchronousHttpClient()
resp = uut.request('GET', "http://swagger.py/client-test",
params={'foo': u'酒場'})
self.assertEqual(200, resp.status_code)
self.assertEqual('expected', resp.text)
self.assertEqual({'foo': [u'酒場']},
httpretty.last_request().querystring)

@httpretty.activate
def test_real_post(self):
httpretty.register_uri(
Expand Down
2 changes: 2 additions & 0 deletions tests/integration/async_http_client_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

import socket
import threading
import time
Expand Down
1 change: 1 addition & 0 deletions tests/loader_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2013, Digium, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/resource_api_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/resource_listing_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/resource_model_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/resource_operation_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/resource_response_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/resource_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2014, Yelp, Inc.
Expand Down
1 change: 1 addition & 0 deletions tests/util_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2013, Digium, Inc.
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ deps =
mock
ordereddict
commands =
nosetests
nosetests {posargs}

[testenv:flake8]
deps=
Expand Down

0 comments on commit 4ac6cf0

Please sign in to comment.