1
0
mirror of https://github.com/kevin1024/vcrpy.git synced 2025-12-09 17:15:35 +00:00

Added migration script for old cassettes

This commit is contained in:
Max Shytikov
2014-04-22 01:00:02 +02:00
parent 5354ef781c
commit ee28768a31
7 changed files with 239 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
[
{
"request": {
"body": null,
"method": "GET",
"headers": {
"Accept-Encoding": "gzip, deflate, compress",
"Accept": "*/*",
"User-Agent": "python-requests/2.2.1 CPython/2.6.1 Darwin/10.8.0"
},
"uri" : "http://httpbin.org:80/ip"
},
"response": {
"status": {
"message": "OK",
"code": 200
},
"headers": [
"Access-Control-Allow-Origin: *\r\n",
"Content-Type: application/json\r\n",
"Date: Mon, 21 Apr 2014 23:13:40 GMT\r\n",
"Server: gunicorn/0.17.4\r\n",
"Content-Length: 32\r\n",
"Connection: keep-alive\r\n"
],
"body": {
"string": "{\n \"origin\": \"217.122.164.194\"\n}"
}
}
}
]

View File

@@ -0,0 +1,15 @@
- request: !!python/object:vcr.request.Request
body: null
headers: !!python/object/apply:__builtin__.frozenset
- - !!python/tuple [Accept-Encoding, 'gzip, deflate, compress']
- !!python/tuple [User-Agent, python-requests/2.2.1 CPython/2.6.1 Darwin/10.8.0]
- !!python/tuple [Accept, '*/*']
method: GET
uri: http://httpbin.org:80/ip
response:
body: {string: !!python/unicode "{\n \"origin\": \"217.122.164.194\"\n}"}
headers: [!!python/unicode "Access-Control-Allow-Origin: *\r\n", !!python/unicode "Content-Type:
application/json\r\n", !!python/unicode "Date: Mon, 21 Apr 2014 23:06:09 GMT\r\n",
!!python/unicode "Server: gunicorn/0.17.4\r\n", !!python/unicode "Content-Length:
32\r\n", !!python/unicode "Connection: keep-alive\r\n"]
status: {code: 200, message: OK}

View File

@@ -0,0 +1 @@
This is not a cassette

View File

@@ -0,0 +1,34 @@
[
{
"request": {
"body": null,
"protocol": "http",
"method": "GET",
"headers": {
"Accept-Encoding": "gzip, deflate, compress",
"Accept": "*/*",
"User-Agent": "python-requests/2.2.1 CPython/2.6.1 Darwin/10.8.0"
},
"host": "httpbin.org",
"path": "/ip",
"port": 80
},
"response": {
"status": {
"message": "OK",
"code": 200
},
"headers": [
"Access-Control-Allow-Origin: *\r\n",
"Content-Type: application/json\r\n",
"Date: Mon, 21 Apr 2014 23:13:40 GMT\r\n",
"Server: gunicorn/0.17.4\r\n",
"Content-Length: 32\r\n",
"Connection: keep-alive\r\n"
],
"body": {
"string": "{\n \"origin\": \"217.122.164.194\"\n}"
}
}
}
]

View File

@@ -0,0 +1,18 @@
- request: !!python/object:vcr.request.Request
body: null
headers: !!python/object/apply:__builtin__.frozenset
- - !!python/tuple [Accept-Encoding, 'gzip, deflate, compress']
- !!python/tuple [User-Agent, python-requests/2.2.1 CPython/2.6.1 Darwin/10.8.0]
- !!python/tuple [Accept, '*/*']
host: httpbin.org
method: GET
path: /ip
port: 80
protocol: http
response:
body: {string: !!python/unicode "{\n \"origin\": \"217.122.164.194\"\n}"}
headers: [!!python/unicode "Access-Control-Allow-Origin: *\r\n", !!python/unicode "Content-Type:
application/json\r\n", !!python/unicode "Date: Mon, 21 Apr 2014 23:06:09 GMT\r\n",
!!python/unicode "Server: gunicorn/0.17.4\r\n", !!python/unicode "Content-Length:
32\r\n", !!python/unicode "Connection: keep-alive\r\n"]
status: {code: 200, message: OK}

View File

@@ -0,0 +1,36 @@
import filecmp
import json
import shutil
import vcr.migration
def test_try_migrate_with_json(tmpdir):
cassette = tmpdir.join('cassette').strpath
shutil.copy('tests/fixtures/migration/old_cassette.json', cassette)
assert vcr.migration.try_migrate(cassette)
with open('tests/fixtures/migration/new_cassette.json', 'r') as f:
expected_json = json.load(f)
with open(cassette, 'r') as f:
actual_json = json.load(f)
assert actual_json == expected_json
def test_try_migrate_with_yaml(tmpdir):
cassette = tmpdir.join('cassette').strpath
shutil.copy('tests/fixtures/migration/old_cassette.yaml', cassette)
assert vcr.migration.try_migrate(cassette)
assert filecmp.cmp(cassette, 'tests/fixtures/migration/new_cassette.yaml')
def test_try_migrate_with_invalid_or_new_cassettes(tmpdir):
cassette = tmpdir.join('cassette').strpath
files = [
'tests/fixtures/migration/not_cassette.txt',
'tests/fixtures/migration/new_cassette.yaml',
'tests/fixtures/migration/new_cassette.json',
]
for file_path in files:
shutil.copy(file_path, cassette)
assert not vcr.migration.try_migrate(cassette)
assert filecmp.cmp(cassette, file_path) # shold not change file

104
vcr/migration.py Normal file
View File

@@ -0,0 +1,104 @@
"""
Migration script for old 'yaml' and 'json' cassettes
.. warning:: Backup your cassettes files before migration.
It merges and deletes the request obsolete keys (protocol, host, port, path)
into new 'uri' key.
Usage::
python -m vcr.migration PATH
The PATH can be path to the directory with cassettes or cassette itself
"""
from contextlib import closing
import json
import os
import re
import shutil
import sys
import tempfile
PARTS = [
'protocol',
'host',
'port',
'path',
]
def build_uri(**parts):
return "{protocol}://{host}:{port}{path}".format(**parts)
def migrate_json(in_fp, out_fp):
data = json.load(in_fp)
for item in data:
req = item['request']
uri = {k: req.pop(k) for k in PARTS}
req['uri'] = build_uri(**uri)
json.dump(data, out_fp, indent=4)
def migrate_yml(in_fp, out_fp):
migrated = False
uri = dict.fromkeys(PARTS, None)
for line in in_fp:
for part in uri:
match = re.match('\s+{}:\s(.*)'.format(part), line)
if match:
uri[part] = match.group(1)
break
else:
out_fp.write(line)
if None not in uri.values(): # if all uri parts are collected
out_fp.write(" uri: {}\n".format(build_uri(**uri)))
uri = dict.fromkeys(PARTS, None) # reset dict
migrated = True
if not migrated:
raise RuntimeError("migration failed")
def migrate(file_path, migration_fn):
# because we assume that original files can be reverted
# we will try to copy the content. (os.rename not needed)
with closing(tempfile.TemporaryFile()) as out_fp:
with open(file_path, 'r') as in_fp:
migration_fn(in_fp, out_fp)
with open(file_path, 'w') as in_fp:
out_fp.seek(0)
shutil.copyfileobj(out_fp, in_fp)
def try_migrate(path):
try: # try to migrate as json
migrate(path, migrate_json)
except: # probably the file is not a json
try: # let's try to migrate as yaml
migrate(path, migrate_yml)
except: # oops probably the file is not a cassette
return False
return True
def main():
if len(sys.argv) != 2:
raise SystemExit("Please provide path to cassettes directory or file. "
"Usage: python -m vcr.migration PATH")
path = sys.argv[1]
if not os.path.isabs(path):
path = os.path.abspath(path)
for root, dirs, files in os.walk(path):
for file_name in files:
file_path = os.path.join(root, file_name)
migrated = try_migrate(file_path)
status = 'OK' if migrated else 'FAIL'
sys.stderr.write("[{}] {}\n".format(status, file_path))
sys.stderr.write("Done.\n")
if __name__ == '__main__':
main()