commit 65f0647521a7e6f42cd26e79b82357f74fb63448 Author: CentOS Sources Date: Tue May 7 08:30:52 2019 -0400 import python-httpretty-0.8.14-9.20161011git70af1f8.el8 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc5a5d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/HTTPretty-70af1f8.tar.gz diff --git a/.python-httpretty.metadata b/.python-httpretty.metadata new file mode 100644 index 0000000..8099d30 --- /dev/null +++ b/.python-httpretty.metadata @@ -0,0 +1 @@ +399312527a1edb0226c0a2941856d03de6443850 SOURCES/HTTPretty-70af1f8.tar.gz diff --git a/SOURCES/0001-Call-reset-from-setUp-and-tearDown-in-addition-to-en.patch b/SOURCES/0001-Call-reset-from-setUp-and-tearDown-in-addition-to-en.patch new file mode 100644 index 0000000..9d5912f --- /dev/null +++ b/SOURCES/0001-Call-reset-from-setUp-and-tearDown-in-addition-to-en.patch @@ -0,0 +1,37 @@ +From 01474bf64e0434881059a3638abff5bb62eaedb1 Mon Sep 17 00:00:00 2001 +From: Scott Moser +Date: Tue, 24 Jan 2017 12:30:47 -0500 +Subject: [PATCH] Call reset from setUp and tearDown in addition to enable and + disable. + +When decorating a class via setUp and tearDown, reset() was not being +called. That was an unintentional change in behavior from previous versions. + +Addresses #316. +--- + httpretty/core.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/httpretty/core.py b/httpretty/core.py +index 34d1ed1..c408c38 100644 +--- a/httpretty/core.py ++++ b/httpretty/core.py +@@ -1189,6 +1189,7 @@ def httprettified(test): + if hasattr(klass, 'setUp') + else None) + def new_setUp(self): ++ httpretty.reset() + httpretty.enable() + if use_addCleanup: + self.addCleanup(httpretty.disable) +@@ -1202,6 +1203,7 @@ def httprettified(test): + else None) + def new_tearDown(self): + httpretty.disable() ++ httpretty.reset() + if original_tearDown: + original_tearDown(self) + klass.tearDown = new_tearDown +-- +2.9.3 + diff --git a/SOURCES/0001-Handle-bugs-in-older-urllib3-versions-in-one-of-the-.patch b/SOURCES/0001-Handle-bugs-in-older-urllib3-versions-in-one-of-the-.patch new file mode 100644 index 0000000..eb4ca43 --- /dev/null +++ b/SOURCES/0001-Handle-bugs-in-older-urllib3-versions-in-one-of-the-.patch @@ -0,0 +1,66 @@ +From 5d2f8d99c28519fe0cf47ebf5f043928d422b757 Mon Sep 17 00:00:00 2001 +From: Adam Williamson +Date: Fri, 6 Jan 2017 17:56:43 -0800 +Subject: [PATCH] Handle bugs in older urllib3 versions in one of the tests + +Older urllib3 versions had a bug where they lower-cased header +names (in response header dicts). That makes one of our tests +fail with older urllib3, because the test expects a 'Server' +header. As this isn't our fault at all, just have the test cope +with it by checking if the header dict has a 'server' key and +replacing it with a 'Server' key with the same value. + +urllib3 1.10 also had a bug when you called dict() on its +HTTPHeaderDict class; it would turn this: + +{'headername': 'value'} + +Into this: + +{'headername': ['headername', 'value']} + +That was fixed in 1.11, but RHEL 6 still has 1.10, so let's +work with that by doing dict(headerdict.items()) instead of +just dict(headerdict) (when we're recording the calls). +--- + httpretty/core.py | 7 ++++++- + tests/functional/test_requests.py | 5 +++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/httpretty/core.py b/httpretty/core.py +index 34d1ed1..0c2d334 100644 +--- a/httpretty/core.py ++++ b/httpretty/core.py +@@ -971,7 +971,12 @@ class httpretty(HttpBaseClass): + 'response': { + 'status': response.status, + 'body': decode_utf8(response.data), +- 'headers': dict(response.headers) ++ # urllib3 1.10 had a bug if you just did: ++ # dict(response.headers) ++ # which would cause all the values to become lists ++ # with the header name as the first item and the ++ # true value as the second item. Workaround that ++ 'headers': dict(response.headers.items()) + } + }) + cls.enable() +diff --git a/tests/functional/test_requests.py b/tests/functional/test_requests.py +index 4e2063e..18c89f8 100644 +--- a/tests/functional/test_requests.py ++++ b/tests/functional/test_requests.py +@@ -742,6 +742,11 @@ def test_recording_calls(port): + response['response'].should.have.key("status").being.equal(200) + response['response'].should.have.key("body").being.an(text_type) + response['response'].should.have.key("headers").being.a(dict) ++ # older urllib3 had a bug where header keys were lower-cased: ++ # https://github.com/shazow/urllib3/issues/236 ++ # cope with that ++ if 'server' in response['response']["headers"]: ++ response['response']["headers"]["Server"] = response['response']["headers"].pop("server") + response['response']["headers"].should.have.key("Server").being.equal("TornadoServer/" + tornado_version) + + # And When I playback the previously recorded calls +-- +2.11.0 + diff --git a/SOURCES/314.patch b/SOURCES/314.patch new file mode 100644 index 0000000..db41a09 --- /dev/null +++ b/SOURCES/314.patch @@ -0,0 +1,31 @@ +From f642a108a5eb199665a39830f095073bd2406003 Mon Sep 17 00:00:00 2001 +From: Shaform +Date: Tue, 20 Dec 2016 20:26:36 +0800 +Subject: [PATCH] fix test on python3 + +--- + tests/functional/base.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/functional/base.py b/tests/functional/base.py +index b8355f0..6f143f6 100644 +--- a/tests/functional/base.py ++++ b/tests/functional/base.py +@@ -37,7 +37,7 @@ + from functools import wraps + + from os.path import abspath, dirname, join +-from httpretty.core import POTENTIAL_HTTP_PORTS, old_socket ++from httpretty.core import POTENTIAL_HTTP_PORTS, old_socket, decode_utf8 + + + def get_free_tcp_port(): +@@ -63,7 +63,7 @@ def post(self, matched): + payload = dict(self.request.arguments) + self.write(json.dumps({ + matched or 'index': payload, +- 'req_body': self.request.body, ++ 'req_body': decode_utf8(self.request.body), + 'req_headers': dict(self.request.headers.items()), + }, indent=4)) + diff --git a/SOURCES/pr313.patch b/SOURCES/pr313.patch new file mode 100644 index 0000000..22bfa0b --- /dev/null +++ b/SOURCES/pr313.patch @@ -0,0 +1,528 @@ +diff --git a/.gitignore b/.gitignore +index f465139..761556d 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -13,3 +13,4 @@ _public/ + tests/functional/fixtures/recording-*.json + #* + *#* ++.idea/ +diff --git a/development.txt b/development.txt +index 6b7a5a4..5a8ff32 100644 +--- a/development.txt ++++ b/development.txt +@@ -6,9 +6,9 @@ mock==1.3.0 + nose==1.3.7 + nose-randomly==1.2.0 + rednose==0.4.3 +-requests==2.8.1 ++requests[security]==2.11.1 + sure==1.2.24 +-urllib3==1.12 ++urllib3==1.19 + tornado==4.3 + coverage==4.0.3 + Sphinx==1.3.3 +diff --git a/httpretty/core.py b/httpretty/core.py +index 34d1ed1..8ece7fe 100644 +--- a/httpretty/core.py ++++ b/httpretty/core.py +@@ -30,6 +30,7 @@ import codecs + import inspect + import socket + import functools ++from functools import partial + import itertools + import warnings + import traceback +@@ -38,7 +39,6 @@ import contextlib + import threading + import tempfile + +- + from .compat import ( + PY3, + StringIO, +@@ -99,17 +99,16 @@ try: # pragma: no cover + if not PY3: + old_sslwrap_simple = ssl.sslwrap_simple + old_sslsocket = ssl.SSLSocket ++ #old_sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + except ImportError: # pragma: no cover + ssl = None + + +-# used to handle error caused by ndg-httpsclient +-try: # pragma: no cover +- from requests.packages.urllib3.contrib.pyopenssl import inject_into_urllib3, extract_from_urllib3 +- pyopenssl_override = True +-except ImportError: # pragma: no cover +- pyopenssl_override = False +- ++try: ++ import requests.packages.urllib3.connection as requests_urllib3_connection ++ old_requests_ssl_wrap_socket = requests_urllib3_connection.ssl_wrap_socket ++except ImportError: ++ requests_urllib3_connection = None + + DEFAULT_HTTP_PORTS = frozenset([80]) + POTENTIAL_HTTP_PORTS = set(DEFAULT_HTTP_PORTS) +@@ -298,6 +297,7 @@ class fakesock(object): + self.truesock = (old_socket(family, type, protocol) + if httpretty.allow_net_connect + else None) ++ self._connected_truesock = False + self._closed = True + self.fd = FakeSockFile() + self.fd.socket = _sock or self +@@ -354,10 +354,16 @@ class fakesock(object): + self.is_http = self._port in ports_to_check + + if not self.is_http: +- if self.truesock: ++ if self.truesock and not self._connected_truesock: + self.truesock.connect(self._address) ++ self._connected_truesock = True + else: + raise UnmockedError() ++ elif self.truesock is not None and not self._connected_truesock: ++ matcher = httpretty.match_http_address(self._host, self._port) ++ if matcher is None: ++ self.truesock.connect(self._address) ++ self._connected_truesock = True + + def fileno(self): + if self.truesock: +@@ -365,9 +371,9 @@ class fakesock(object): + return self.fd.fileno() + + def close(self): +- if not (self.is_http and self._closed): +- if self.truesock: +- self.truesock.close() ++ if self._connected_truesock: ++ self.truesock.close() ++ self._connected_truesock = False + self._closed = True + + def makefile(self, mode='r', bufsize=-1): +@@ -404,22 +410,27 @@ class fakesock(object): + buffer so that HTTPretty can return it accordingly when + necessary. + """ +- + if not self.truesock: + raise UnmockedError() + + if not self.is_http: + return self.truesock.sendall(data, *args, **kw) + +- self.truesock.connect(self._address) ++ if self._address[1] == 443 and old_sslsocket: ++ sock = old_sslsocket(self.truesock) ++ else: ++ sock = self.truesock ++ ++ if not self._connected_truesock: ++ sock.connect(self._address) + +- self.truesock.setblocking(1) +- self.truesock.sendall(data, *args, **kw) ++ sock.setblocking(1) ++ sock.sendall(data, *args, **kw) + + should_continue = True + while should_continue: + try: +- received = self.truesock.recv(self._bufsize) ++ received = sock.recv(self._bufsize) + self.fd.write(received) + should_continue = bool(received.strip()) + +@@ -544,8 +555,17 @@ class fakesock(object): + return getattr(self.truesock, name) + + +-def fake_wrap_socket(s, *args, **kw): +- return s ++def fake_wrap_socket(orig_wrap_socket_fn, sock, *args, **kw): ++ server_hostname = kw.get('server_hostname') ++ if server_hostname is not None: ++ matcher = httpretty.match_https_hostname(server_hostname) ++ if matcher is None: ++ return orig_wrap_socket_fn( ++ sock, ++ *args, ++ **kw ++ ) ++ return sock + + + def create_fake_connection( +@@ -937,6 +957,53 @@ class httpretty(HttpBaseClass): + return (None, []) + + @classmethod ++ def match_https_hostname(cls, hostname): ++ items = sorted( ++ cls._entries.items(), ++ key=lambda matcher_entries: matcher_entries[0].priority, ++ reverse=True, ++ ) ++ for matcher, value in items: ++ if matcher.info is None: ++ pattern_with_port = "https://{0}:".format(hostname) ++ pattern_without_port = "https://{0}/".format(hostname) ++ for pattern in [pattern_with_port, pattern_without_port]: ++ if matcher.regex.search(pattern) is not None \ ++ or matcher.regex.pattern.startswith(pattern): ++ return matcher ++ ++ elif matcher.info.hostname == hostname: ++ return matcher ++ return None ++ ++ @classmethod ++ def match_http_address(cls, hostname, port): ++ items = sorted( ++ cls._entries.items(), ++ key=lambda matcher_entries: matcher_entries[0].priority, ++ reverse=True, ++ ) ++ for matcher, value in items: ++ if matcher.info is None: ++ if port in POTENTIAL_HTTPS_PORTS: ++ scheme = 'https://' ++ else: ++ scheme = 'http://' ++ ++ pattern_without_port = "{0}{1}/".format(scheme, hostname) ++ pattern_with_port = "{0}{1}:{2}/".format(scheme, hostname, port) ++ for pattern in [pattern_with_port, pattern_without_port]: ++ if matcher.regex.search(pattern_without_port) is not None \ ++ or matcher.regex.pattern.startswith(pattern): ++ return matcher ++ ++ elif matcher.info.hostname == hostname \ ++ and matcher.info.port == port: ++ return matcher ++ ++ return None ++ ++ @classmethod + @contextlib.contextmanager + def record(cls, filename, indentation=4, encoding='utf-8'): + try: +@@ -1112,9 +1179,11 @@ class httpretty(HttpBaseClass): + ssl.sslwrap_simple = old_sslwrap_simple + ssl.__dict__['sslwrap_simple'] = old_sslwrap_simple + +- if pyopenssl_override: +- # Replace PyOpenSSL Monkeypatching +- inject_into_urllib3() ++ if requests_urllib3_connection is not None: ++ requests_urllib3_connection.ssl_wrap_socket = \ ++ old_requests_ssl_wrap_socket ++ requests_urllib3_connection.__dict__['ssl_wrap_socket'] = \ ++ old_requests_ssl_wrap_socket + + @classmethod + def is_enabled(cls): +@@ -1152,19 +1221,22 @@ class httpretty(HttpBaseClass): + socks.__dict__['socksocket'] = fakesock.socket + + if ssl: +- ssl.wrap_socket = fake_wrap_socket ++ new_wrap = partial(fake_wrap_socket, old_ssl_wrap_socket) ++ ssl.wrap_socket = new_wrap + ssl.SSLSocket = FakeSSLSocket + +- ssl.__dict__['wrap_socket'] = fake_wrap_socket ++ ssl.__dict__['wrap_socket'] = new_wrap + ssl.__dict__['SSLSocket'] = FakeSSLSocket + + if not PY3: +- ssl.sslwrap_simple = fake_wrap_socket +- ssl.__dict__['sslwrap_simple'] = fake_wrap_socket ++ ssl.sslwrap_simple = new_wrap ++ ssl.__dict__['sslwrap_simple'] = new_wrap ++ ++ if requests_urllib3_connection is not None: ++ new_wrap = partial(fake_wrap_socket, old_requests_ssl_wrap_socket) ++ requests_urllib3_connection.ssl_wrap_socket = new_wrap ++ requests_urllib3_connection.__dict__['ssl_wrap_socket'] = new_wrap + +- if pyopenssl_override: +- # Remove PyOpenSSL monkeypatch - use the default implementation +- extract_from_urllib3() + + class httprettized(object): + +diff --git a/test-requirements.txt b/test-requirements.txt +index bda473e..46f1062 100644 +--- a/test-requirements.txt ++++ b/test-requirements.txt +@@ -1,4 +1,4 @@ +--r dev.txt ++-r development.txt + httplib2==0.9 + requests==2.5.1 + tornado==4.0.2 +diff --git a/tests/functional/test_requests.py b/tests/functional/test_requests.py +index 4e2063e..91baefd 100644 +--- a/tests/functional/test_requests.py ++++ b/tests/functional/test_requests.py +@@ -37,7 +37,7 @@ 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 tests.functional.base import FIXTURE_FILE, use_tornado_server + from tornado import version as tornado_version + + try: +@@ -567,7 +567,12 @@ def test_httpretty_provides_easy_access_to_querystrings_with_regexes(): + }) + + ++try: ++ from unittest import skip ++except ImportError: ++ from unittest2 import skip + @httprettified ++@skip + def test_httpretty_allows_to_chose_if_querystring_should_be_matched(): + "HTTPretty should provide a way to not match regexes that have a different querystring" + +@@ -580,13 +582,9 @@ def test_httpretty_allows_to_chose_if_querystring_should_be_matched(): + + response = requests.get('https://example.org/what/') + expect(response.text).to.equal('Nudge, nudge, wink, wink. Know what I mean?') +- try: +- requests.get('https://example.org/what/?flying=coconuts') +- raised = False +- except requests.ConnectionError: +- raised = True + +- assert raised is True ++ response = requests.get('https://example.org/what/?flying=coconuts') ++ expect(response.text).to.not_be.equal('Nudge, nudge, wink, wink. Know what I mean?') + + + @httprettified +diff --git a/tests/pyopenssl/test_mock.py b/tests/pyopenssl/test_mock.py +index 1de759a..cfa5143 100644 +--- a/tests/pyopenssl/test_mock.py ++++ b/tests/pyopenssl/test_mock.py +@@ -31,19 +31,10 @@ import requests + from httpretty import HTTPretty, httprettified + from sure import expect + +-from requests.packages.urllib3.contrib.pyopenssl import inject_into_urllib3, extract_from_urllib3 +- + + @httprettified + def test_httpretty_overrides_when_pyopenssl_installed(): + ('HTTPretty should remove PyOpenSSLs urllib3 mock if it is installed') +- +- # When we run Httpretty with PyOpenSSL and ndg-httpsclient installed +- from httpretty.core import pyopenssl_override +- +- # Then we override pyopenssl +- pyopenssl_override.should.be.true +- + # And HTTPretty works successfully + HTTPretty.register_uri(HTTPretty.GET, "https://yipit.com/", + body="Find the best daily deals") +@@ -53,20 +44,3 @@ def test_httpretty_overrides_when_pyopenssl_installed(): + expect(HTTPretty.last_request.method).to.equal('GET') + expect(HTTPretty.last_request.path).to.equal('/') + +- +-@httprettified +-def test_httpretty_fails_when_pyopenssl_is_not_replaced(): +- ('HTTPretty should fail if PyOpenSSL is installed and we do not remove the monkey patch') +- +- # When we don't replace the PyOpenSSL monkeypatch +- inject_into_urllib3() +- +- # And we use HTTPretty on as ssl site +- HTTPretty.register_uri(HTTPretty.GET, "https://yipit.com/", +- body="Find the best daily deals") +- +- # Then we get an SSL error +- requests.get.when.called_with('https://yipit.com').should.throw(requests.exceptions.SSLError) +- +- # Undo injection after test +- extract_from_urllib3() +\ No newline at end of file +diff --git a/tests/unit/test_core.py b/tests/unit/test_core.py +index e28404f..b87d2aa 100644 +--- a/tests/unit/test_core.py ++++ b/tests/unit/test_core.py +@@ -263,6 +263,7 @@ def test_fakesock_socket_close(old_socket): + # Given a fake socket instance that is synthetically open + socket = fakesock.socket() + socket._closed = False ++ socket._connected_truesock = True + + # When I close it + socket.close() +diff --git a/tests/unit/test_fakesocket.py b/tests/unit/test_fakesocket.py +new file mode 100644 +index 0000000..8b84d99 +--- /dev/null ++++ b/tests/unit/test_fakesocket.py +@@ -0,0 +1,72 @@ ++# #!/usr/bin/env python ++# -*- coding: utf-8 -*- ++ ++# ++# Copyright (C) <2011-2012> Gabriel Falcão ++# ++# Permission is hereby granted, free of charge, to any person ++# obtaining a copy of this software and associated documentation ++# files (the "Software"), to deal in the Software without ++# restriction, including without limitation the rights to use, ++# copy, modify, merge, publish, distribute, sublicense, and/or sell ++# copies of the Software, and to permit persons to whom the ++# Software is furnished to do so, subject to the following ++# conditions: ++# ++# The above copyright notice and this permission notice shall be ++# included in all copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++# OTHER DEALINGS IN THE SOFTWARE. ++ ++import functools ++import socket ++ ++import mock ++ ++ ++class FakeSocket(socket.socket): ++ """ ++ Just an editable socket factory ++ It allows mock to patch readonly functions ++ """ ++ connect = sendall = lambda *args, **kw: None ++ ++ ++fake_socket_interupter_flag = {} ++ ++def recv(flag, size): ++ """ ++ Two pass recv implementation ++ ++ This implementation will for the first time send something that is smaller than ++ the asked size passed in argument. ++ Any further call will just raise RuntimeError ++ """ ++ if 'was_here' in flag: ++ raise RuntimeError('Already sent everything') ++ else: ++ flag['was_here'] = None ++ return 'a'* (size - 1) ++ ++recv = functools.partial(recv, fake_socket_interupter_flag) ++ ++@mock.patch('httpretty.old_socket', new=FakeSocket) ++def _test_shorten_response(): ++ u"HTTPretty shouldn't try to read from server when communication is over" ++ from sure import expect ++ import httpretty ++ ++ fakesocket = httpretty.fakesock.socket(socket.AF_INET, ++ socket.SOCK_STREAM) ++ with mock.patch.object(fakesocket.truesock, 'recv', recv): ++ fakesocket.connect(('localhost', 80)) ++ fakesocket._true_sendall('WHATEVER') ++ expect(fakesocket.fd.read()).to.equal( ++ 'a' * (httpretty.socket_buffer_size - 1)) +diff --git a/tests/unit/test_passthrough.py b/tests/unit/test_passthrough.py +new file mode 100644 +index 0000000..1162638 +--- /dev/null ++++ b/tests/unit/test_passthrough.py +@@ -0,0 +1,74 @@ ++# #!/usr/bin/env python ++# -*- coding: utf-8 -*- ++ ++# ++# Copyright (C) <2011-2012> Gabriel Falcão ++# ++# Permission is hereby granted, free of charge, to any person ++# obtaining a copy of this software and associated documentation ++# files (the "Software"), to deal in the Software without ++# restriction, including without limitation the rights to use, ++# copy, modify, merge, publish, distribute, sublicense, and/or sell ++# copies of the Software, and to permit persons to whom the ++# Software is furnished to do so, subject to the following ++# conditions: ++# ++# The above copyright notice and this permission notice shall be ++# included in all copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++# OTHER DEALINGS IN THE SOFTWARE. ++import requests ++from sure import expect ++ ++from httpretty import ( ++ HTTPretty, ++ httprettified, ++) ++ ++ ++@httprettified ++def test_http_passthrough(): ++ url = 'http://ip4.me/' ++ response1 = requests.get(url) ++ ++ HTTPretty.enable() ++ HTTPretty.register_uri(HTTPretty.GET, 'http://google.com/', body="Not Google") ++ ++ response2 = requests.get('http://google.com/') ++ expect(response2.content).to.equal(b'Not Google') ++ ++ response3 = requests.get(url) ++ expect(response3.content).to.equal(response1.content) ++ ++ HTTPretty.disable() ++ ++ response4 = requests.get(url) ++ expect(response4.content).to.equal(response1.content) ++ ++ ++@httprettified ++def test_https_passthrough(): ++ url = 'https://www.cloudflare.com/ips-v4' ++ ++ response1 = requests.get(url) ++ ++ HTTPretty.enable() ++ HTTPretty.register_uri(HTTPretty.GET, 'http://google.com/', body="Not Google") ++ ++ response2 = requests.get('http://google.com/') ++ expect(response2.content).to.equal(b'Not Google') ++ ++ response3 = requests.get(url) ++ expect(response3.content).to.equal(response1.content) ++ ++ HTTPretty.disable() ++ ++ response4 = requests.get(url) ++ expect(response4.content).to.equal(response1.content) diff --git a/SOURCES/python-httpretty-fakesock_getpeercert_noconnect.patch b/SOURCES/python-httpretty-fakesock_getpeercert_noconnect.patch new file mode 100644 index 0000000..bab9419 --- /dev/null +++ b/SOURCES/python-httpretty-fakesock_getpeercert_noconnect.patch @@ -0,0 +1,64 @@ +--- HTTPretty/tests/unit/test_core.py 2017-01-06 15:04:06.030520764 -0800 ++++ HTTPretty/tests/unit/test_core.py.new 2017-01-06 15:37:17.932752818 -0800 +@@ -192,31 +192,37 @@ + @patch('httpretty.core.datetime') + def test_fakesock_socket_getpeercert(dt): + ("fakesock.socket#getpeercert should return a hardcoded fake certificate") +- # Background: +- dt.now.return_value = datetime(2013, 10, 4, 4, 20, 0) ++ # Don't bother with an actual remote roundtrip ++ httpretty.allow_net_connect = False + +- # Given a fake socket instance +- socket = fakesock.socket() +- +- # And that it's bound to some host and port +- socket.connect(('somewhere.com', 80)) +- +- # When I retrieve the peer certificate +- certificate = socket.getpeercert() +- +- # Then it should return a hardcoded value +- certificate.should.equal({ +- u'notAfter': 'Sep 29 04:20:00 GMT', +- u'subject': ( +- ((u'organizationName', u'*.somewhere.com'),), +- ((u'organizationalUnitName', u'Domain Control Validated'),), +- ((u'commonName', u'*.somewhere.com'),)), +- u'subjectAltName': ( +- (u'DNS', u'*somewhere.com'), +- (u'DNS', u'somewhere.com'), +- (u'DNS', u'*') +- ) +- }) ++ try: ++ # Background: ++ dt.now.return_value = datetime(2013, 10, 4, 4, 20, 0) ++ ++ # Given a fake socket instance ++ socket = fakesock.socket() ++ ++ # And that it's bound to some host and port ++ socket.connect(('somewhere.com', 80)) ++ ++ # When I retrieve the peer certificate ++ certificate = socket.getpeercert() ++ ++ # Then it should return a hardcoded value ++ certificate.should.equal({ ++ u'notAfter': 'Sep 29 04:20:00 GMT', ++ u'subject': ( ++ ((u'organizationName', u'*.somewhere.com'),), ++ ((u'organizationalUnitName', u'Domain Control Validated'),), ++ ((u'commonName', u'*.somewhere.com'),)), ++ u'subjectAltName': ( ++ (u'DNS', u'*somewhere.com'), ++ (u'DNS', u'somewhere.com'), ++ (u'DNS', u'*') ++ ) ++ }) ++ finally: ++ httpretty.allow_net_connect = True + + + def test_fakesock_socket_ssl(): diff --git a/SPECS/python-httpretty.spec b/SPECS/python-httpretty.spec new file mode 100644 index 0000000..5551ecc --- /dev/null +++ b/SPECS/python-httpretty.spec @@ -0,0 +1,278 @@ +%if 0%{?fedora} || 0%{?rhel} > 7 +# escaping for EPEL. +%global with_python3 1 +%endif + +%if 0%{?rhel} > 7 +# Disable python2 build by default +%bcond_with python2 +%else +%bcond_without python2 +%endif + +%global github_owner gabrielfalcao +%global github_name HTTPretty +%global modname httpretty +# define these only if actually building from a GH snapshot not a release tarball +%global github_commit 70af1f8cf925ef50cb5e72212fb0aa46e1451dc3 +%global shortcommit %(c=%{github_commit}; echo ${c:0:7}) +%global github_date 20161011 + +%global run_tests 1 + +Name: python-httpretty +Version: 0.8.14 +# If github_date is defined, assume a post-release snapshot +Release: 9%{?github_date:.%{github_date}git%{shortcommit}}%{?dist} +Summary: HTTP request mock tool for Python + +License: MIT +URL: http://falcao.it/HTTPretty/ +Source0: https://github.com/%{github_owner}/%{github_name}/archive/%{github_commit}/%{github_name}-%{shortcommit}.tar.gz +# Alternative for building from a release tarball +#Source0: https://files.pythonhosted.org/packages/source/h/httpretty/httpretty-%%{version}.tar.gz + +# Fix HTTPS with recent openssl +# This is https://github.com/gabrielfalcao/HTTPretty/pull/313 +# Squashed by checking the PR branch out from git and doing: +# git diff master > pr313.patch (because just getting 313.patch from github +# results in a patch that doesn't apply) +# I edited the patch to apply several fixes: +# 1. Rename the `_socket` arg of the `fake_wrap_socket` function to `sock` +# (as otherwise it breaks due to urllib3 calling `wrap_socket` with the +# socket arg named as `sock`) +# 2. In test_passthrough.py, correct the type of the expected response +# (requests `Response.content` is a bytestring, not a string) +# 3. Remove the addition of `test_httpretty_should_passthrough_for_ssl`, +# as it requires a remote trip +# 4. Use {0} ({1}, {2}...) in format strings, not just {}, as {} doesn't +# work in Python 2.6 (EPEL 6) +# 5. Try importing skip from unittest2 if it's not available from unittest +# (Python 2.6 unittest didn't have it) +# I've noted all these issues in comments on the PR +Patch0: pr313.patch + +# Fix tests with Python 3 +Patch1: https://github.com/gabrielfalcao/HTTPretty/pull/314.patch + +# Avoid unnecessary remote access requirement (note: test only actually +# does a remote connection after PR #313) +Patch2: python-httpretty-fakesock_getpeercert_noconnect.patch + +# Fix a couple of issues with urllib 1.10 (as found in RHEL 6) +# https://github.com/gabrielfalcao/HTTPretty/pull/315 +Patch3: 0001-Handle-bugs-in-older-urllib3-versions-in-one-of-the-.patch + +# Fix setUp and tearDown not calling reset +# https://github.com/gabrielfalcao/HTTPretty/pull/317 +Patch4: 0001-Call-reset-from-setUp-and-tearDown-in-addition-to-en.patch + +BuildArch: noarch + +%global _description\ +Once upon a time a python developer wanted to use a RESTful API, everything was\ +fine but until the day he needed to test the code that hits the RESTful API:\ +what if the API server is down? What if its content has changed?\ +\ +Don't worry, HTTPretty is here for you. + +%description %_description + +%if %{with python2} +%package -n python2-httpretty +Summary: %summary + +BuildRequires: python2-devel +BuildRequires: python2-setuptools +# For tests +BuildRequires: python2-httplib2 +BuildRequires: python2-mock +BuildRequires: python2-nose +BuildRequires: python2-requests +BuildRequires: python2-sure +BuildRequires: python2-urllib3 +%if 0%{?epel} == 6 +# Need unittest2 to get the 'skip' decorator +BuildRequires: python-unittest2 +%endif + +Requires: python2-urllib3 +%{?python_provide:%python_provide python2-httpretty} + +%description -n python2-httpretty %_description +%endif # with python2 + +%if 0%{?with_python3} +%package -n python3-httpretty +Summary: HTTP request mock tool for Python 3 +Requires: python3-urllib3 + +BuildRequires: python3-devel +BuildRequires: python3-setuptools +# For tests +BuildRequires: python3-httplib2 +BuildRequires: python3-mock +BuildRequires: python3-nose +BuildRequires: python3-requests +BuildRequires: python3-sure +BuildRequires: python3-urllib3 + +%description -n python3-httpretty +Once upon a time a python developer wanted to use a RESTful API, everything was +fine but until the day he needed to test the code that hits the RESTful API: +what if the API server is down? What if its content has changed? + +Don't worry, HTTPretty is here for you. +%endif + +%prep +%autosetup -n %{github_name}-%{github_commit} -p1 + +# Alternative for building from a release tarball +#autosetup -n httpretty-%{version} -p1 + +# un-pin requirements +sed -i -e 's/==.*//g' development.txt test-requirements.txt requirements.txt +sed -i -e 's/requests\[security\]/requests/g' development.txt +# remove some 'requirements' that aren't actually needed just for us to run tests +sed -i -e '/^coverage/d' development.txt test-requirements.txt +sed -i -e '/^tornado/d' development.txt test-requirements.txt +sed -i -r -e '/^(S|s)phinx/d' development.txt +sed -i -e '/^rednose/d' development.txt +sed -i -e '/^nose-randomly/d' development.txt +sed -i -e '/^flake8/d' development.txt +sed -i -e '/^ipdb/d' development.txt +# These tests require a remote roundtrip, so remove them +rm tests/unit/test_passthrough.py +# Remove tests that require python-tornado +rm tests/functional/test_bypass.py +rm tests/functional/base.py +rm tests/functional/test_requests.py +rm tests/functional/testserver.py + +%if 0%{?with_python3} +rm -rf %{py3dir} +cp -a . %{py3dir} +%endif + +%build +# setup.py contains non-ASCII characters; in Koji build environment +# default encoding is ASCII and this will choke, so set a UTF-8 locale +%if %{with python2} +LANG=en_US.UTF-8 %py2_build +%endif # with python2 + +%if 0%{?with_python3} +pushd %{py3dir} +LANG=en_US.UTF-8 %py3_build +popd +%endif + +%install +%if %{with python2} +LANG=en_US.UTF-8 %py2_install +%endif # with python2 + +%if 0%{?with_python3} +pushd %{py3dir} +LANG=en_US.UTF-8 %py3_install +popd +%endif + + +%check +%if %{run_tests} +%if %{with python2} +LANG=en_US.UTF-8 %{__python2} setup.py test +%endif # with python2 + +%if 0%{?with_python3} +pushd %{py3dir} +LANG=en_US.UTF-8 %{__python3} setup.py test +popd +%endif +%endif + + +%if %{with python2} +%files -n python2-httpretty +%doc README.md +%license COPYING +%{python2_sitelib}/httpretty +%{python2_sitelib}/httpretty-%{version}-py2.?.egg-info +%endif # with python2 + +%if 0%{?with_python3} +%files -n python3-httpretty +%doc README.md +%license COPYING +%{python3_sitelib}/httpretty +%{python3_sitelib}/httpretty-%{version}-py3.?.egg-info +%endif + + +%changelog +* Wed Aug 22 2018 Eduardo Otubo - 0.8.14-9.20161011git70af1f8 +- Remove dependency to python-tornado and its related tests +- Resolves: rhbz#1615783 + +* Mon May 21 2018 Charalampos Stratakis - 0.8.14-8.20161011git70af1f8 +- Conditionalize the python2 subpackage + +* Fri Feb 09 2018 Fedora Release Engineering - 0.8.14-7.20161011git70af1f8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Fri Sep 29 2017 Troy Dawson - 0.8.14-6.20161011git70af1f8 +- Cleanup spec file conditionals + +* Sat Aug 19 2017 Zbigniew Jędrzejewski-Szmek - 0.8.14-5.20161011git70af1f8 +- Python 2 binary package renamed to python2-httpretty + See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3 + +* Thu Jul 27 2017 Fedora Release Engineering - 0.8.14-4.20161011git70af1f8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sat Feb 11 2017 Fedora Release Engineering - 0.8.14-3.20161011git70af1f8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Fri Jan 27 2017 Adam Williamson - 0.8.14-2.20161011git70af1f8 +- Backport PR #317 (call reset from setUp / tearDown) - thanks gholms + +* Fri Jan 06 2017 Adam Williamson - 0.8.14-1.20161011git70af1f8 +- Update to current git master (as a 0.8.14 post-release snapshot) +- Backport PR #313 (fix with recent OpenSSL, requests and urllib3) +- Backport PR #314 (fix a test with Python 3) +- Backport PR #315 (fix some issues with urllib 1.10, as found in RHEL 6) +- Avoid an unnecessary remote roundtrip in one of the tests +- Replace dependency 'un-pinning' patch with some sed commands in the spec +- Replace ASCII patch by running setup.py with a UTF-8 LANG +- Enable the tests, with necessary buildrequires + +* Tue Dec 13 2016 Charalampos Stratakis - 0.8.3-8 +- Rebuild for Python 3.6 + +* Tue Jul 19 2016 Fedora Release Engineering - 0.8.3-7 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Thu Feb 04 2016 Fedora Release Engineering - 0.8.3-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Nov 10 2015 Fedora Release Engineering - 0.8.3-5 +- Rebuilt for https://fedoraproject.org/wiki/Changes/python3.5 + +* Thu Jun 18 2015 Fedora Release Engineering - 0.8.3-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon Mar 02 2015 Jamie Lennox - 0.8.3-3 +- Added conditional __python2 macros for building on RHEL 6. + +* Tue Feb 24 2015 Jamie Lennox - 0.8.3-2 +- Added with_python3 build flags to enable building on EPEL. + +* Mon Jul 28 2014 Jamie Lennox - 0.8.3-1 +- Updated to new version. +- Removed check, there are simply too many problems upstream. + +* Mon Mar 10 2014 Jamie Lennox - 0.8.0-1 +- Initial package. +