Skip to content

Commit

Permalink
Merge branch 'pr/99'
Browse files Browse the repository at this point in the history
  • Loading branch information
sigmavirus24 committed Apr 7, 2016
2 parents f08afda + 5fce8aa commit f67b2cb
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 8 deletions.
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ Contributors

- Marc Abramowitz (@msabramo)
- Bryce Boe <bbzbryce@gmail.com> (@bboe)
- Alex Richard-Hoyling <@arhoyling)
1 change: 0 additions & 1 deletion betamax/cassette/cassette.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ def load_interactions(self):

for i in self.interactions:
i.replace_all(self.placeholders, ('placeholder', 'replace'))
i.deserialize() # this needs to happen *after* replace_all

def sanitize_interactions(self):
for i in self.interactions:
Expand Down
14 changes: 8 additions & 6 deletions betamax/cassette/interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,27 @@ class Interaction(object):
"""

def __init__(self, interaction, response=None):
self.recorded_at = None
self.json = interaction
self.orig_response = response
self.used = False
self.deserialize()
self.recorded_response = self.deserialize()
self.used = False

def as_response(self):
"""Return the Interaction as a Response object."""
self.recorded_response = self.deserialize()
return self.recorded_response

@property
def recorded_at(self):
return datetime.strptime(self.json['recorded_at'], '%Y-%m-%dT%H:%M:%S')

def deserialize(self):
"""Turn a serialized interaction into a Response."""
r = util.deserialize_response(self.json['response'])
r.request = util.deserialize_prepared_request(self.json['request'])
extract_cookies_to_jar(r.cookies, r.request, r.raw)
self.recorded_at = datetime.strptime(
self.json['recorded_at'], '%Y-%m-%dT%H:%M:%S'
)
self.recorded_response = r
return r

def match(self, matchers):
"""Return whether this interaction is a match."""
Expand Down
1 change: 1 addition & 0 deletions tests/cassettes/replay_multiple_times.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"http_interactions": [{"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Connection": ["keep-alive"], "Accept-Encoding": ["gzip, deflate"], "Accept": ["*/*"], "User-Agent": ["python-requests/2.9.1"]}, "method": "GET", "uri": "http://httpbin.org/stream/5"}, "response": {"body": {"string": "{\"url\": \"http://httpbin.org/stream/5\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 0, \"origin\": \"188.39.80.202\"}\n{\"url\": \"http://httpbin.org/stream/5\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 1, \"origin\": \"188.39.80.202\"}\n{\"url\": \"http://httpbin.org/stream/5\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 2, \"origin\": \"188.39.80.202\"}\n{\"url\": \"http://httpbin.org/stream/5\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 3, \"origin\": \"188.39.80.202\"}\n{\"url\": \"http://httpbin.org/stream/5\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 4, \"origin\": \"188.39.80.202\"}\n", "encoding": null}, "headers": {"Transfer-Encoding": ["chunked"], "Server": ["nginx"], "Connection": ["keep-alive"], "Access-Control-Allow-Credentials": ["true"], "Date": ["Fri, 25 Mar 2016 17:06:34 GMT"], "Access-Control-Allow-Origin": ["*"], "Content-Type": ["application/json"]}, "status": {"message": "OK", "code": 200}, "url": "http://httpbin.org/stream/5"}, "recorded_at": "2016-03-25T17:06:34"}, {"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Connection": ["keep-alive"], "Accept-Encoding": ["gzip, deflate"], "Accept": ["*/*"], "User-Agent": ["python-requests/2.9.1"]}, "method": "GET", "uri": "http://httpbin.org/stream/1"}, "response": {"body": {"string": "{\"url\": \"http://httpbin.org/stream/1\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 0, \"origin\": \"188.39.80.202\"}\n", "encoding": null}, "headers": {"Transfer-Encoding": ["chunked"], "Server": ["nginx"], "Connection": ["keep-alive"], "Access-Control-Allow-Credentials": ["true"], "Date": ["Fri, 25 Mar 2016 17:20:38 GMT"], "Access-Control-Allow-Origin": ["*"], "Content-Type": ["application/json"]}, "status": {"message": "OK", "code": 200}, "url": "http://httpbin.org/stream/1"}, "recorded_at": "2016-03-25T17:20:38"}, {"request": {"body": {"string": "", "encoding": "utf-8"}, "headers": {"Connection": ["keep-alive"], "Accept-Encoding": ["gzip, deflate"], "Accept": ["*/*"], "User-Agent": ["python-requests/2.9.1"]}, "method": "GET", "uri": "http://httpbin.org/stream/3"}, "response": {"body": {"string": "{\"url\": \"http://httpbin.org/stream/3\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 0, \"origin\": \"188.39.80.202\"}\n{\"url\": \"http://httpbin.org/stream/3\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 1, \"origin\": \"188.39.80.202\"}\n{\"url\": \"http://httpbin.org/stream/3\", \"headers\": {\"Host\": \"httpbin.org\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"User-Agent\": \"python-requests/2.9.1\"}, \"args\": {}, \"id\": 2, \"origin\": \"188.39.80.202\"}\n", "encoding": null}, "headers": {"Transfer-Encoding": ["chunked"], "Server": ["nginx"], "Connection": ["keep-alive"], "Access-Control-Allow-Credentials": ["true"], "Date": ["Fri, 25 Mar 2016 17:37:06 GMT"], "Access-Control-Allow-Origin": ["*"], "Content-Type": ["application/json"]}, "status": {"message": "OK", "code": 200}, "url": "http://httpbin.org/stream/3"}, "recorded_at": "2016-03-25T17:37:06"}], "recorded_with": "betamax/0.5.1"}
2 changes: 2 additions & 0 deletions tests/integration/test_record_modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ def test_replays_response_from_cassette(self):
assert r1.status_code == 200
r0_headers = r0.headers.copy()
r0_headers.pop('Date')
r0_headers.pop('Age')
r1_headers = r1.headers.copy()
r1_headers.pop('Date')
r1_headers.pop('Age')
# NOTE(sigmavirus24): This fails if the second request is
# technically a second later. Ignoring the Date headers allows
# this test to succeed.
Expand Down
19 changes: 19 additions & 0 deletions tests/regression/test_can_replay_interactions_multiple_times.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import unittest

from betamax import Betamax
from requests import Session


class TestReplayInteractionMultipleTimes(unittest.TestCase):
"""
Test that an Interaction can be replayed multiple times within the same
betamax session.
"""
def test_replay_interaction_more_than_once(self):
s = Session()

with Betamax(s).use_cassette('replay_multiple_times', record='once',
allow_playback_repeats=True):
for k in range(1, 5):
r = s.get('http://httpbin.org/stream/3', stream=True)
assert r.raw.read(1028), "Stream already consumed. Try: %d" % k
6 changes: 5 additions & 1 deletion tests/unit/test_cassette.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ def setUp(self):
self.date = datetime(2013, 8, 31)
self.cassette.save_interaction(self.response, self.response.request)
self.interaction = self.cassette.interactions[0]
self.interaction.recorded_at = self.date

def tearDown(self):
try:
Expand Down Expand Up @@ -333,6 +332,11 @@ def test_as_response(self):
r = self.interaction.as_response()
assert isinstance(r, Response)

def test_as_response_returns_new_instance(self):
r1 = self.interaction.as_response()
r2 = self.interaction.as_response()
assert r1 is not r2

def test_deserialized_response(self):
def check_uri(attr):
# Necessary since PreparedRequests do not have a uri attr
Expand Down

0 comments on commit f67b2cb

Please sign in to comment.