Merge pull request #143 from CyrilRoelandteNovance/clean_py3
Python 3 support
This commit is contained in:
@@ -166,6 +166,10 @@ class HTTPrettyRequest(BaseHTTPRequestHandler, BaseClass):
|
||||
# Now 2 convenient attributes for the HTTPretty API:
|
||||
|
||||
# `querystring` holds a dictionary with the parsed query string
|
||||
try:
|
||||
self.path = self.path.encode('iso-8859-1')
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
self.path = decode_utf8(self.path)
|
||||
|
||||
qstring = self.path.split("?", 1)[-1]
|
||||
@@ -187,7 +191,7 @@ class HTTPrettyRequest(BaseHTTPRequestHandler, BaseClass):
|
||||
parsed = parse_qs(expanded)
|
||||
result = {}
|
||||
for k in parsed:
|
||||
result[k] = map(decode_utf8, parsed[k])
|
||||
result[k] = list(map(decode_utf8, parsed[k]))
|
||||
|
||||
return result
|
||||
|
||||
@@ -204,6 +208,7 @@ class HTTPrettyRequest(BaseHTTPRequestHandler, BaseClass):
|
||||
content_type = self.headers.get('content-type', '')
|
||||
|
||||
do_parse = PARSING_FUNCTIONS.get(content_type, FALLBACK_FUNCTION)
|
||||
body = decode_utf8(body)
|
||||
try:
|
||||
return do_parse(body)
|
||||
except:
|
||||
@@ -343,8 +348,8 @@ class fakesock(object):
|
||||
self._sent_data.append(data)
|
||||
|
||||
try:
|
||||
requestline, _ = data.split('\r\n', 1)
|
||||
method, path, version = parse_requestline(requestline)
|
||||
requestline, _ = data.split(b'\r\n', 1)
|
||||
method, path, version = parse_requestline(decode_utf8(requestline))
|
||||
is_parsing_headers = True
|
||||
except ValueError:
|
||||
is_parsing_headers = False
|
||||
@@ -358,10 +363,10 @@ class fakesock(object):
|
||||
if not is_parsing_headers:
|
||||
if len(self._sent_data) > 1:
|
||||
headers = utf8(last_requestline(self._sent_data))
|
||||
meta = dict(self._entry.request.headers)
|
||||
meta = self._entry.request.headers
|
||||
body = utf8(self._sent_data[-1])
|
||||
if meta.get('transfer-encoding', '') == 'chunked':
|
||||
if not body.isdigit() and body != '\r\n' and body != '0\r\n\r\n':
|
||||
if not body.isdigit() and body != b'\r\n' and body != b'0\r\n\r\n':
|
||||
self._entry.request.body += body
|
||||
else:
|
||||
self._entry.request.body += body
|
||||
@@ -372,7 +377,7 @@ class fakesock(object):
|
||||
# path might come with
|
||||
s = urlsplit(path)
|
||||
POTENTIAL_HTTP_PORTS.add(int(s.port or 80))
|
||||
headers, body = map(utf8, data.split('\r\n\r\n', 1))
|
||||
headers, body = list(map(utf8, data.split(b'\r\n\r\n', 1)))
|
||||
|
||||
request = httpretty.historify_request(headers, body)
|
||||
|
||||
@@ -393,7 +398,7 @@ class fakesock(object):
|
||||
def debug(self, func, *a, **kw):
|
||||
if self.is_http:
|
||||
frame = inspect.stack()[0][0]
|
||||
lines = map(utf8, traceback.format_stack(frame))
|
||||
lines = list(map(utf8, traceback.format_stack(frame)))
|
||||
|
||||
message = [
|
||||
"HTTPretty intercepted and unexpected socket method call.",
|
||||
@@ -807,12 +812,12 @@ class httpretty(HttpBaseClass):
|
||||
'uri': uri,
|
||||
'method': request.method,
|
||||
'headers': dict(request.headers),
|
||||
'body': request.body,
|
||||
'body': decode_utf8(request.body),
|
||||
'querystring': request.querystring
|
||||
},
|
||||
'response': {
|
||||
'status': response.status,
|
||||
'body': response.data,
|
||||
'body': decode_utf8(response.data),
|
||||
'headers': dict(response.headers)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -27,6 +27,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import re
|
||||
from .compat import BaseClass
|
||||
from .utils import decode_utf8
|
||||
|
||||
|
||||
STATUSES = {
|
||||
@@ -109,14 +110,14 @@ STATUSES = {
|
||||
|
||||
|
||||
class HttpBaseClass(BaseClass):
|
||||
GET = b'GET'
|
||||
PUT = b'PUT'
|
||||
POST = b'POST'
|
||||
DELETE = b'DELETE'
|
||||
HEAD = b'HEAD'
|
||||
PATCH = b'PATCH'
|
||||
OPTIONS = b'OPTIONS'
|
||||
CONNECT = b'CONNECT'
|
||||
GET = 'GET'
|
||||
PUT = 'PUT'
|
||||
POST = 'POST'
|
||||
DELETE = 'DELETE'
|
||||
HEAD = 'HEAD'
|
||||
PATCH = 'PATCH'
|
||||
OPTIONS = 'OPTIONS'
|
||||
CONNECT = 'CONNECT'
|
||||
METHODS = (GET, PUT, POST, DELETE, HEAD, PATCH, OPTIONS, CONNECT)
|
||||
|
||||
|
||||
@@ -133,8 +134,8 @@ def parse_requestline(s):
|
||||
...
|
||||
ValueError: Not a Request-Line
|
||||
"""
|
||||
methods = b'|'.join(HttpBaseClass.METHODS)
|
||||
m = re.match(br'(' + methods + b')\s+(.*)\s+HTTP/(1.[0|1])', s, re.I)
|
||||
methods = '|'.join(HttpBaseClass.METHODS)
|
||||
m = re.match(r'(' + methods + ')\s+(.*)\s+HTTP/(1.[0|1])', s, re.I)
|
||||
if m:
|
||||
return m.group(1).upper(), m.group(2), m.group(3)
|
||||
else:
|
||||
@@ -147,7 +148,7 @@ def last_requestline(sent_data):
|
||||
"""
|
||||
for line in reversed(sent_data):
|
||||
try:
|
||||
parse_requestline(line)
|
||||
parse_requestline(decode_utf8(line))
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
|
||||
@@ -32,10 +32,12 @@ import re
|
||||
import json
|
||||
import requests
|
||||
from sure import within, microseconds, expect
|
||||
from tornado import version as tornado_version
|
||||
from httpretty import HTTPretty, httprettified
|
||||
from httpretty.compat import text_type
|
||||
from httpretty.core import decode_utf8
|
||||
|
||||
from base import FIXTURE_FILE, use_tornado_server
|
||||
from .base import FIXTURE_FILE, use_tornado_server
|
||||
from tornado import version as tornado_version
|
||||
|
||||
try:
|
||||
@@ -573,7 +575,7 @@ def test_httpretty_should_allow_registering_regexes_with_streaming_responses():
|
||||
os.environ['DEBUG'] = 'true'
|
||||
|
||||
def my_callback(request, url, headers):
|
||||
request.body.should.equal('hithere')
|
||||
request.body.should.equal(b'hithere')
|
||||
return 200, headers, "Received"
|
||||
|
||||
HTTPretty.register_uri(
|
||||
@@ -590,7 +592,7 @@ def test_httpretty_should_allow_registering_regexes_with_streaming_responses():
|
||||
'https://api.yipit.com/v1/deal;brand=gap?first_name=chuck&last_name=norris',
|
||||
data=gen(),
|
||||
)
|
||||
expect(response.content).to.equal("Received")
|
||||
expect(response.content).to.equal(b"Received")
|
||||
expect(HTTPretty.last_request.method).to.equal('POST')
|
||||
expect(HTTPretty.last_request.path).to.equal('/v1/deal;brand=gap?first_name=chuck&last_name=norris')
|
||||
|
||||
@@ -697,7 +699,7 @@ def test_recording_calls():
|
||||
]
|
||||
})
|
||||
response['response'].should.have.key("status").being.equal(200)
|
||||
response['response'].should.have.key("body").being.an(unicode)
|
||||
response['response'].should.have.key("body").being.an(text_type)
|
||||
response['response'].should.have.key("headers").being.a(dict)
|
||||
response['response']["headers"].should.have.key("server").being.equal("TornadoServer/" + tornado_version)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from datetime import datetime
|
||||
from mock import Mock, patch, call
|
||||
from sure import expect
|
||||
|
||||
from httpretty.compat import StringIO
|
||||
from httpretty.core import HTTPrettyRequest, FakeSSLSocket, fakesock, httpretty
|
||||
|
||||
|
||||
@@ -23,11 +24,11 @@ def test_request_stubs_internals():
|
||||
# Given a valid HTTP request header string
|
||||
headers = "\r\n".join([
|
||||
'POST /somewhere/?name=foo&age=bar HTTP/1.1',
|
||||
'Accept-Encoding: identity',
|
||||
'Host: github.com',
|
||||
'Content-Type: application/json',
|
||||
'Connection: close',
|
||||
'User-Agent: Python-urllib/2.7',
|
||||
'accept-encoding: identity',
|
||||
'host: github.com',
|
||||
'content-type: application/json',
|
||||
'connection: close',
|
||||
'user-agent: Python-urllib/2.7',
|
||||
])
|
||||
|
||||
# When I create a HTTPrettyRequest with an empty body
|
||||
@@ -43,10 +44,12 @@ def test_request_stubs_internals():
|
||||
})
|
||||
|
||||
# And the `rfile` should be a StringIO
|
||||
request.should.have.property('rfile').being.a('StringIO.StringIO')
|
||||
type_as_str = StringIO.__module__ + '.' + StringIO.__name__
|
||||
|
||||
request.should.have.property('rfile').being.a(type_as_str)
|
||||
|
||||
# And the `wfile` should be a StringIO
|
||||
request.should.have.property('wfile').being.a('StringIO.StringIO')
|
||||
request.should.have.property('wfile').being.a(type_as_str)
|
||||
|
||||
# And the `method` should be available
|
||||
request.should.have.property('method').being.equal('POST')
|
||||
@@ -301,16 +304,16 @@ def test_fakesock_socket_real_sendall(old_socket):
|
||||
# Background: the real socket will stop returning bytes after the
|
||||
# first call
|
||||
real_socket = old_socket.return_value
|
||||
real_socket.recv.side_effect = ['response from server', ""]
|
||||
real_socket.recv.side_effect = [b'response from server', b""]
|
||||
|
||||
# Given a fake socket
|
||||
socket = fakesock.socket()
|
||||
|
||||
# When I call real_sendall with data, some args and kwargs
|
||||
socket.real_sendall("SOMEDATA", 'some extra args...', foo='bar')
|
||||
socket.real_sendall(b"SOMEDATA", b'some extra args...', foo=b'bar')
|
||||
|
||||
# Then it should have called sendall in the real socket
|
||||
real_socket.sendall.assert_called_once_with("SOMEDATA", 'some extra args...', foo='bar')
|
||||
real_socket.sendall.assert_called_once_with(b"SOMEDATA", b'some extra args...', foo=b'bar')
|
||||
|
||||
# And the timeout was set to 0
|
||||
real_socket.settimeout.assert_called_once_with(0)
|
||||
@@ -322,7 +325,7 @@ def test_fakesock_socket_real_sendall(old_socket):
|
||||
])
|
||||
|
||||
# And the buffer should contain the data from the server
|
||||
socket.fd.getvalue().should.equal("response from server")
|
||||
socket.fd.getvalue().should.equal(b"response from server")
|
||||
|
||||
# And connect was never called
|
||||
real_socket.connect.called.should.be.false
|
||||
@@ -336,17 +339,17 @@ def test_fakesock_socket_real_sendall_continue_eagain(socket, old_socket):
|
||||
# Background: the real socket will stop returning bytes after the
|
||||
# first call
|
||||
real_socket = old_socket.return_value
|
||||
real_socket.recv.side_effect = [SocketErrorStub(errno.EAGAIN), 'after error', ""]
|
||||
real_socket.recv.side_effect = [SocketErrorStub(errno.EAGAIN), b'after error', b""]
|
||||
|
||||
# Given a fake socket
|
||||
socket = fakesock.socket()
|
||||
|
||||
|
||||
# When I call real_sendall with data, some args and kwargs
|
||||
socket.real_sendall("SOMEDATA", 'some extra args...', foo='bar')
|
||||
socket.real_sendall(b"SOMEDATA", b'some extra args...', foo=b'bar')
|
||||
|
||||
# Then it should have called sendall in the real socket
|
||||
real_socket.sendall.assert_called_once_with("SOMEDATA", 'some extra args...', foo='bar')
|
||||
real_socket.sendall.assert_called_once_with(b"SOMEDATA", b'some extra args...', foo=b'bar')
|
||||
|
||||
# And the timeout was set to 0
|
||||
real_socket.settimeout.assert_called_once_with(0)
|
||||
@@ -358,7 +361,7 @@ def test_fakesock_socket_real_sendall_continue_eagain(socket, old_socket):
|
||||
])
|
||||
|
||||
# And the buffer should contain the data from the server
|
||||
socket.fd.getvalue().should.equal("after error")
|
||||
socket.fd.getvalue().should.equal(b"after error")
|
||||
|
||||
# And connect was never called
|
||||
real_socket.connect.called.should.be.false
|
||||
@@ -372,16 +375,16 @@ def test_fakesock_socket_real_sendall_socket_error(socket, old_socket):
|
||||
# Background: the real socket will stop returning bytes after the
|
||||
# first call
|
||||
real_socket = old_socket.return_value
|
||||
real_socket.recv.side_effect = [SocketErrorStub(42), 'after error', ""]
|
||||
real_socket.recv.side_effect = [SocketErrorStub(42), b'after error', ""]
|
||||
|
||||
# Given a fake socket
|
||||
socket = fakesock.socket()
|
||||
|
||||
# When I call real_sendall with data, some args and kwargs
|
||||
socket.real_sendall("SOMEDATA", 'some extra args...', foo='bar')
|
||||
socket.real_sendall(b"SOMEDATA", b'some extra args...', foo=b'bar')
|
||||
|
||||
# Then it should have called sendall in the real socket
|
||||
real_socket.sendall.assert_called_once_with("SOMEDATA", 'some extra args...', foo='bar')
|
||||
real_socket.sendall.assert_called_once_with(b"SOMEDATA", b'some extra args...', foo=b'bar')
|
||||
|
||||
# And the timeout was set to 0
|
||||
real_socket.settimeout.assert_called_once_with(0)
|
||||
@@ -390,7 +393,7 @@ def test_fakesock_socket_real_sendall_socket_error(socket, old_socket):
|
||||
real_socket.recv.assert_called_once_with(16)
|
||||
|
||||
# And the buffer should contain the data from the server
|
||||
socket.fd.getvalue().should.equal("")
|
||||
socket.fd.getvalue().should.equal(b"")
|
||||
|
||||
# And connect was never called
|
||||
real_socket.connect.called.should.be.false
|
||||
@@ -403,7 +406,7 @@ def test_fakesock_socket_real_sendall_when_http(POTENTIAL_HTTP_PORTS, old_socket
|
||||
# Background: the real socket will stop returning bytes after the
|
||||
# first call
|
||||
real_socket = old_socket.return_value
|
||||
real_socket.recv.side_effect = ['response from foobar :)', ""]
|
||||
real_socket.recv.side_effect = [b'response from foobar :)', b""]
|
||||
|
||||
# And the potential http port is 4000
|
||||
POTENTIAL_HTTP_PORTS.__contains__.side_effect = lambda other: int(other) == 4000
|
||||
@@ -415,7 +418,7 @@ def test_fakesock_socket_real_sendall_when_http(POTENTIAL_HTTP_PORTS, old_socket
|
||||
socket.connect(('foobar.com', 4000))
|
||||
|
||||
# And send some data
|
||||
socket.real_sendall("SOMEDATA")
|
||||
socket.real_sendall(b"SOMEDATA")
|
||||
|
||||
# Then connect should have been called
|
||||
real_socket.connect.assert_called_once_with(('foobar.com', 4000))
|
||||
@@ -430,7 +433,7 @@ def test_fakesock_socket_real_sendall_when_http(POTENTIAL_HTTP_PORTS, old_socket
|
||||
])
|
||||
|
||||
# And the buffer should contain the data from the server
|
||||
socket.fd.getvalue().should.equal("response from foobar :)")
|
||||
socket.fd.getvalue().should.equal(b"response from foobar :)")
|
||||
|
||||
|
||||
@patch('httpretty.core.old_socket')
|
||||
@@ -456,7 +459,7 @@ def test_fakesock_socket_sendall_with_valid_requestline(POTENTIAL_HTTP_PORTS, ht
|
||||
socket.connect(('foo.com', 80))
|
||||
|
||||
# When I try to send data
|
||||
socket.sendall("GET /foobar HTTP/1.1\r\nContent-Type: application/json\r\n\r\n")
|
||||
socket.sendall(b"GET /foobar HTTP/1.1\r\nContent-Type: application/json\r\n\r\n")
|
||||
|
||||
|
||||
@patch('httpretty.core.old_socket')
|
||||
@@ -482,7 +485,7 @@ def test_fakesock_socket_sendall_with_valid_requestline(POTENTIAL_HTTP_PORTS, ht
|
||||
socket.connect(('foo.com', 80))
|
||||
|
||||
# When I try to send data
|
||||
socket.sendall("GET /foobar HTTP/1.1\r\nContent-Type: application/json\r\n\r\n")
|
||||
socket.sendall(b"GET /foobar HTTP/1.1\r\nContent-Type: application/json\r\n\r\n")
|
||||
|
||||
|
||||
@patch('httpretty.core.old_socket')
|
||||
@@ -493,7 +496,7 @@ def test_fakesock_socket_sendall_with_body_data_no_entry(POTENTIAL_HTTP_PORTS, o
|
||||
# Using a subclass of socket that mocks out real_sendall
|
||||
class MySocket(fakesock.socket):
|
||||
def real_sendall(self, data):
|
||||
data.should.equal('BLABLABLABLA')
|
||||
data.should.equal(b'BLABLABLABLA')
|
||||
return 'cool'
|
||||
|
||||
# Given an instance of that socket
|
||||
@@ -504,7 +507,7 @@ def test_fakesock_socket_sendall_with_body_data_no_entry(POTENTIAL_HTTP_PORTS, o
|
||||
socket.connect(('foo.com', 80))
|
||||
|
||||
# When I try to send data
|
||||
result = socket.sendall("BLABLABLABLA")
|
||||
result = socket.sendall(b"BLABLABLABLA")
|
||||
|
||||
# Then the result should be the return value from real_sendall
|
||||
result.should.equal('cool')
|
||||
@@ -522,7 +525,7 @@ def test_fakesock_socket_sendall_with_body_data_with_entry(POTENTIAL_HTTP_PORTS,
|
||||
# Using a mocked entry
|
||||
entry = Mock()
|
||||
entry.request.headers = {}
|
||||
entry.request.body = ''
|
||||
entry.request.body = b''
|
||||
|
||||
# Given an instance of that socket
|
||||
socket = MySocket()
|
||||
@@ -533,10 +536,10 @@ def test_fakesock_socket_sendall_with_body_data_with_entry(POTENTIAL_HTTP_PORTS,
|
||||
socket.connect(('foo.com', 80))
|
||||
|
||||
# When I try to send data
|
||||
socket.sendall("BLABLABLABLA")
|
||||
socket.sendall(b"BLABLABLABLA")
|
||||
|
||||
# Then the entry should have that body
|
||||
entry.request.body.should.equal('BLABLABLABLA')
|
||||
entry.request.body.should.equal(b'BLABLABLABLA')
|
||||
|
||||
|
||||
@patch('httpretty.core.old_socket')
|
||||
@@ -553,7 +556,7 @@ def test_fakesock_socket_sendall_with_body_data_with_chunked_entry(POTENTIAL_HTT
|
||||
entry.request.headers = {
|
||||
'transfer-encoding': 'chunked',
|
||||
}
|
||||
entry.request.body = ''
|
||||
entry.request.body = b''
|
||||
|
||||
# Given an instance of that socket
|
||||
socket = MySocket()
|
||||
@@ -563,7 +566,7 @@ def test_fakesock_socket_sendall_with_body_data_with_chunked_entry(POTENTIAL_HTT
|
||||
socket.connect(('foo.com', 80))
|
||||
|
||||
# When I try to send data
|
||||
socket.sendall("BLABLABLABLA")
|
||||
socket.sendall(b"BLABLABLABLA")
|
||||
|
||||
# Then the entry should have that body
|
||||
httpretty.last_request.body.should.equal('BLABLABLABLA')
|
||||
httpretty.last_request.body.should.equal(b'BLABLABLABLA')
|
||||
|
||||
Reference in New Issue
Block a user