mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-08 16:53:23 +00:00
Split persister errors into CassetteNotFoundError and CassetteDecodeError (#681)
This commit is contained in:
@@ -136,7 +136,8 @@ Create your own persistence class, see the example below:
|
|||||||
|
|
||||||
Your custom persister must implement both ``load_cassette`` and ``save_cassette``
|
Your custom persister must implement both ``load_cassette`` and ``save_cassette``
|
||||||
methods. The ``load_cassette`` method must return a deserialized cassette or raise
|
methods. The ``load_cassette`` method must return a deserialized cassette or raise
|
||||||
``ValueError`` if no cassette is found.
|
either ``CassetteNotFoundError`` if no cassette is found, or ``CassetteDecodeError``
|
||||||
|
if the cassette cannot be successfully deserialized.
|
||||||
|
|
||||||
Once the persister class is defined, register with VCR like so...
|
Once the persister class is defined, register with VCR like so...
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
import os
|
import os
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
# Internal imports
|
# Internal imports
|
||||||
import vcr
|
import vcr
|
||||||
from vcr.persisters.filesystem import FilesystemPersister
|
from vcr.persisters.filesystem import CassetteDecodeError, CassetteNotFoundError, FilesystemPersister
|
||||||
|
|
||||||
|
|
||||||
class CustomFilesystemPersister:
|
class CustomFilesystemPersister:
|
||||||
@@ -25,6 +27,19 @@ class CustomFilesystemPersister:
|
|||||||
FilesystemPersister.save_cassette(cassette_path, cassette_dict, serializer)
|
FilesystemPersister.save_cassette(cassette_path, cassette_dict, serializer)
|
||||||
|
|
||||||
|
|
||||||
|
class BadPersister(FilesystemPersister):
|
||||||
|
"""A bad persister that raises different errors."""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load_cassette(cassette_path, serializer):
|
||||||
|
if "nonexistent" in cassette_path:
|
||||||
|
raise CassetteNotFoundError()
|
||||||
|
elif "encoding" in cassette_path:
|
||||||
|
raise CassetteDecodeError()
|
||||||
|
else:
|
||||||
|
raise ValueError("buggy persister")
|
||||||
|
|
||||||
|
|
||||||
def test_save_cassette_with_custom_persister(tmpdir, httpbin):
|
def test_save_cassette_with_custom_persister(tmpdir, httpbin):
|
||||||
"""Ensure you can save a cassette using custom persister"""
|
"""Ensure you can save a cassette using custom persister"""
|
||||||
my_vcr = vcr.VCR()
|
my_vcr = vcr.VCR()
|
||||||
@@ -53,3 +68,22 @@ def test_load_cassette_with_custom_persister(tmpdir, httpbin):
|
|||||||
with my_vcr.use_cassette(test_fixture, serializer="json"):
|
with my_vcr.use_cassette(test_fixture, serializer="json"):
|
||||||
response = urlopen(httpbin.url).read()
|
response = urlopen(httpbin.url).read()
|
||||||
assert b"difficult sometimes" in response
|
assert b"difficult sometimes" in response
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_cassette_persister_exception_handling(tmpdir, httpbin):
|
||||||
|
"""
|
||||||
|
Ensure expected errors from persister are swallowed while unexpected ones
|
||||||
|
are passed up the call stack.
|
||||||
|
"""
|
||||||
|
my_vcr = vcr.VCR()
|
||||||
|
my_vcr.register_persister(BadPersister)
|
||||||
|
|
||||||
|
with my_vcr.use_cassette("bad/nonexistent") as cass:
|
||||||
|
assert len(cass) == 0
|
||||||
|
|
||||||
|
with my_vcr.use_cassette("bad/encoding") as cass:
|
||||||
|
assert len(cass) == 0
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
with my_vcr.use_cassette("bad/buggy") as cass:
|
||||||
|
pass
|
||||||
|
|||||||
@@ -29,6 +29,19 @@ def test_cassette_load(tmpdir):
|
|||||||
assert len(a_cassette) == 1
|
assert len(a_cassette) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_cassette_load_nonexistent():
|
||||||
|
a_cassette = Cassette.load(path="something/nonexistent.yml")
|
||||||
|
assert len(a_cassette) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_cassette_load_invalid_encoding(tmpdir):
|
||||||
|
a_file = tmpdir.join("invalid_encoding.yml")
|
||||||
|
with open(a_file, "wb") as fd:
|
||||||
|
fd.write(b"\xda")
|
||||||
|
a_cassette = Cassette.load(path=str(a_file))
|
||||||
|
assert len(a_cassette) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_cassette_not_played():
|
def test_cassette_not_played():
|
||||||
a = Cassette("test")
|
a = Cassette("test")
|
||||||
assert not a.play_count
|
assert not a.play_count
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from ._handle_coroutine import handle_coroutine
|
|||||||
from .errors import UnhandledHTTPRequestError
|
from .errors import UnhandledHTTPRequestError
|
||||||
from .matchers import get_matchers_results, method, requests_match, uri
|
from .matchers import get_matchers_results, method, requests_match, uri
|
||||||
from .patch import CassettePatcherBuilder
|
from .patch import CassettePatcherBuilder
|
||||||
from .persisters.filesystem import FilesystemPersister
|
from .persisters.filesystem import CassetteDecodeError, CassetteNotFoundError, FilesystemPersister
|
||||||
from .record_mode import RecordMode
|
from .record_mode import RecordMode
|
||||||
from .serializers import yamlserializer
|
from .serializers import yamlserializer
|
||||||
from .util import partition_dict
|
from .util import partition_dict
|
||||||
@@ -352,7 +352,7 @@ class Cassette:
|
|||||||
self.append(request, response)
|
self.append(request, response)
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
self.rewound = True
|
self.rewound = True
|
||||||
except ValueError:
|
except (CassetteDecodeError, CassetteNotFoundError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@@ -5,17 +5,25 @@ from pathlib import Path
|
|||||||
from ..serialize import deserialize, serialize
|
from ..serialize import deserialize, serialize
|
||||||
|
|
||||||
|
|
||||||
|
class CassetteNotFoundError(FileNotFoundError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CassetteDecodeError(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FilesystemPersister:
|
class FilesystemPersister:
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_cassette(cls, cassette_path, serializer):
|
def load_cassette(cls, cassette_path, serializer):
|
||||||
cassette_path = Path(cassette_path) # if cassette path is already Path this is no operation
|
cassette_path = Path(cassette_path) # if cassette path is already Path this is no operation
|
||||||
if not cassette_path.is_file():
|
if not cassette_path.is_file():
|
||||||
raise ValueError("Cassette not found.")
|
raise CassetteNotFoundError()
|
||||||
try:
|
try:
|
||||||
with cassette_path.open() as f:
|
with cassette_path.open() as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
except UnicodeEncodeError as err:
|
except UnicodeDecodeError as err:
|
||||||
raise ValueError("Can't read Cassette, Encoding is broken") from err
|
raise CassetteDecodeError("Can't read Cassette, Encoding is broken") from err
|
||||||
|
|
||||||
return deserialize(data, serializer)
|
return deserialize(data, serializer)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user