Repository: kevin1024/vcrpy
Pull request #530 (2020-05-25 03:21:23)

Enumerate Record Mode Values
The possible values for `record_mode` could be communicated better. The core change is in `record_mode.py`.

Because either the `Enum` (`vcr.mode.NONE`) or the string value can be used (`none`), this change is backwards compatible. Imported in `vcr/__init__.py` to allow for semantic access.

I'm not sure what the `ANY` mode is used for? Docs could be clearer.


Patch:
diff --git a/vcr/__init__.py b/vcr/__init__.py
index 070d3e9..c456960 100644
--- a/vcr/__init__.py
+++ b/vcr/__init__.py
@@ -1,6 +1,7 @@
 import logging
 from .config import VCR
 from logging import NullHandler
+from .record_mode import RecordMode as mode  # noqa import is not used in this file
 
 __version__ = "4.0.2"
 
diff --git a/vcr/cassette.py b/vcr/cassette.py
index 662c2d2..826a68b 100644
--- a/vcr/cassette.py
+++ b/vcr/cassette.py
@@ -14,6 +14,7 @@ from .serializers import yamlserializer
 from .persisters.filesystem import FilesystemPersister
 from .util import partition_dict
 from ._handle_coroutine import handle_coroutine
+from .record_mode import RecordMode
 
 try:
     from asyncio import iscoroutinefunction
@@ -175,7 +176,7 @@ class Cassette:
         path,
         serializer=None,
         persister=None,
-        record_mode="once",
+        record_mode=RecordMode.ONCE,
         match_on=(uri, method),
         before_record_request=None,
         before_record_response=None,
@@ -218,7 +219,7 @@ class Cassette:
 
     @property
     def write_protected(self):
-        return self.rewound and self.record_mode == "once" or self.record_mode == "none"
+        return self.rewound and self.record_mode == RecordMode.ONCE or self.record_mode == RecordMode.NONE
 
     def append(self, request, response):
         """Add a request, response pair to this cassette"""
@@ -250,7 +251,7 @@ class Cassette:
 
     def can_play_response_for(self, request):
         request = self._before_record_request(request)
-        return request and request in self and self.record_mode != "all" and self.rewound
+        return request and request in self and self.record_mode != RecordMode.ALL and self.rewound
 
     def play_response(self, request):
         """
diff --git a/vcr/config.py b/vcr/config.py
index ce41978..7dfd1a8 100644
--- a/vcr/config.py
+++ b/vcr/config.py
@@ -12,6 +12,7 @@ from .cassette import Cassette
 from .serializers import yamlserializer, jsonserializer
 from .persisters.filesystem import FilesystemPersister
 from .util import compose, auto_decorate
+from .record_mode import RecordMode
 from . import matchers
 from . import filters
 
@@ -37,7 +38,7 @@ class VCR:
         custom_patches=(),
         filter_query_parameters=(),
         ignore_hosts=(),
-        record_mode="once",
+        record_mode=RecordMode.ONCE,
         ignore_localhost=False,
         filter_headers=(),
         before_record_response=None,
diff --git a/vcr/record_mode.py b/vcr/record_mode.py
new file mode 100644
index 0000000..c25cf14
--- /dev/null
+++ b/vcr/record_mode.py
@@ -0,0 +1,23 @@
+from enum import Enum
+
+
+class RecordMode(str, Enum):
+    """
+    Configues when VCR will record to the cassette.
+
+    Can be declared by either using the enumerated value (`vcr.mode.ONCE`)
+    or by simply using the defined string (`once`).
+
+    `ALL`: Every request is recorded.
+    `ANY`: ?
+    `NEW_EPISODES`: Any request not found in the cassette is recorded.
+    `NONE`: No requests are recorded.
+    `ONCE`:  First set of requests is recorded, all others are replayed.
+    Attempting to add a new episode fails.
+    """
+
+    ALL = "all"
+    ANY = "any"
+    NEW_EPISODES = "new_episodes"
+    NONE = "none"
+    ONCE = "once"


Test patch:
diff --git a/tests/integration/test_disksaver.py b/tests/integration/test_disksaver.py
index c26e13a..9868555 100644
--- a/tests/integration/test_disksaver.py
+++ b/tests/integration/test_disksaver.py
@@ -45,7 +45,7 @@ def test_disk_saver_write(tmpdir, httpbin):
     # the mtime doesn't change
     time.sleep(1)
 
-    with vcr.use_cassette(fname, record_mode="any") as cass:
+    with vcr.use_cassette(fname, record_mode=vcr.mode.ANY) as cass:
         urlopen(httpbin.url).read()
         urlopen(httpbin.url + "/get").read()
         assert cass.play_count == 1
diff --git a/tests/integration/test_matchers.py b/tests/integration/test_matchers.py
index c555e5c..1ed550b 100644
--- a/tests/integration/test_matchers.py
+++ b/tests/integration/test_matchers.py
@@ -19,7 +19,7 @@ def cassette(tmpdir, httpbin, httpbin_secure):
     default_uri = _replace_httpbin(DEFAULT_URI, httpbin, httpbin_secure)
 
     cassette_path = str(tmpdir.join("test.yml"))
-    with vcr.use_cassette(cassette_path, record_mode="all"):
+    with vcr.use_cassette(cassette_path, record_mode=vcr.mode.ALL):
         urlopen(default_uri)
     return cassette_path
 
diff --git a/tests/integration/test_record_mode.py b/tests/integration/test_record_mode.py
index 38abce5..c5109ad 100644
--- a/tests/integration/test_record_mode.py
+++ b/tests/integration/test_record_mode.py
@@ -5,11 +5,11 @@ from urllib.request import urlopen
 
 def test_once_record_mode(tmpdir, httpbin):
     testfile = str(tmpdir.join("recordmode.yml"))
-    with vcr.use_cassette(testfile, record_mode="once"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ONCE):
         # cassette file doesn't exist, so create.
         urlopen(httpbin.url).read()
 
-    with vcr.use_cassette(testfile, record_mode="once"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ONCE):
         # make the same request again
         urlopen(httpbin.url).read()
 
@@ -22,12 +22,12 @@ def test_once_record_mode(tmpdir, httpbin):
 
 def test_once_record_mode_two_times(tmpdir, httpbin):
     testfile = str(tmpdir.join("recordmode.yml"))
-    with vcr.use_cassette(testfile, record_mode="once"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ONCE):
         # get two of the same file
         urlopen(httpbin.url).read()
         urlopen(httpbin.url).read()
 
-    with vcr.use_cassette(testfile, record_mode="once"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ONCE):
         # do it again
         urlopen(httpbin.url).read()
         urlopen(httpbin.url).read()
@@ -35,7 +35,7 @@ def test_once_record_mode_two_times(tmpdir, httpbin):
 
 def test_once_mode_three_times(tmpdir, httpbin):
     testfile = str(tmpdir.join("recordmode.yml"))
-    with vcr.use_cassette(testfile, record_mode="once"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ONCE):
         # get three of the same file
         urlopen(httpbin.url).read()
         urlopen(httpbin.url).read()
@@ -45,11 +45,11 @@ def test_once_mode_three_times(tmpdir, httpbin):
 def test_new_episodes_record_mode(tmpdir, httpbin):
     testfile = str(tmpdir.join("recordmode.yml"))
 
-    with vcr.use_cassette(testfile, record_mode="new_episodes"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.NEW_EPISODES):
         # cassette file doesn't exist, so create.
         urlopen(httpbin.url).read()
 
-    with vcr.use_cassette(testfile, record_mode="new_episodes") as cass:
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.NEW_EPISODES) as cass:
         # make the same request again
         urlopen(httpbin.url).read()
 
@@ -66,7 +66,7 @@ def test_new_episodes_record_mode(tmpdir, httpbin):
         # not all responses have been played
         assert not cass.all_played
 
-    with vcr.use_cassette(testfile, record_mode="new_episodes") as cass:
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.NEW_EPISODES) as cass:
         # the cassette should now have 2 responses
         assert len(cass.responses) == 2
 
@@ -74,11 +74,11 @@ def test_new_episodes_record_mode(tmpdir, httpbin):
 def test_new_episodes_record_mode_two_times(tmpdir, httpbin):
     testfile = str(tmpdir.join("recordmode.yml"))
     url = httpbin.url + "/bytes/1024"
-    with vcr.use_cassette(testfile, record_mode="new_episodes"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.NEW_EPISODES):
         # cassette file doesn't exist, so create.
         original_first_response = urlopen(url).read()
 
-    with vcr.use_cassette(testfile, record_mode="new_episodes"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.NEW_EPISODES):
         # make the same request again
         assert urlopen(url).read() == original_first_response
 
@@ -86,7 +86,7 @@ def test_new_episodes_record_mode_two_times(tmpdir, httpbin):
         # to the cassette without repercussions
         original_second_response = urlopen(url).read()
 
-    with vcr.use_cassette(testfile, record_mode="once"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ONCE):
         # make the same request again
         assert urlopen(url).read() == original_first_response
         assert urlopen(url).read() == original_second_response
@@ -99,11 +99,11 @@ def test_new_episodes_record_mode_two_times(tmpdir, httpbin):
 def test_all_record_mode(tmpdir, httpbin):
     testfile = str(tmpdir.join("recordmode.yml"))
 
-    with vcr.use_cassette(testfile, record_mode="all"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ALL):
         # cassette file doesn't exist, so create.
         urlopen(httpbin.url).read()
 
-    with vcr.use_cassette(testfile, record_mode="all") as cass:
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ALL) as cass:
         # make the same request again
         urlopen(httpbin.url).read()
 
@@ -121,7 +121,7 @@ def test_none_record_mode(tmpdir, httpbin):
     # Cassette file doesn't exist, yet we are trying to make a request.
     # raise hell.
     testfile = str(tmpdir.join("recordmode.yml"))
-    with vcr.use_cassette(testfile, record_mode="none"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.NONE):
         with pytest.raises(Exception):
             urlopen(httpbin.url).read()
 
@@ -130,11 +130,11 @@ def test_none_record_mode_with_existing_cassette(tmpdir, httpbin):
     # create a cassette file
     testfile = str(tmpdir.join("recordmode.yml"))
 
-    with vcr.use_cassette(testfile, record_mode="all"):
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.ALL):
         urlopen(httpbin.url).read()
 
     # play from cassette file
-    with vcr.use_cassette(testfile, record_mode="none") as cass:
+    with vcr.use_cassette(testfile, record_mode=vcr.mode.NONE) as cass:
         urlopen(httpbin.url).read()
         assert cass.play_count == 1
         # but if I try to hit the net, raise an exception.
diff --git a/tests/unit/test_stubs.py b/tests/unit/test_stubs.py
index ee05134..c952fad 100644
--- a/tests/unit/test_stubs.py
+++ b/tests/unit/test_stubs.py
@@ -1,5 +1,6 @@
 from unittest import mock
 
+from vcr import mode
 from vcr.stubs import VCRHTTPSConnection
 from vcr.cassette import Cassette
 
@@ -13,6 +14,6 @@ class TestVCRConnection:
     @mock.patch("vcr.cassette.Cassette.can_play_response_for", return_value=False)
     def testing_connect(*args):
         vcr_connection = VCRHTTPSConnection("www.google.com")
-        vcr_connection.cassette = Cassette("test", record_mode="all")
+        vcr_connection.cassette = Cassette("test", record_mode=mode.ALL)
         vcr_connection.real_connection.connect()
         assert vcr_connection.real_connection.sock is not None
diff --git a/tests/unit/test_vcr.py b/tests/unit/test_vcr.py
index c49a4b9..1eb8c69 100644
--- a/tests/unit/test_vcr.py
+++ b/tests/unit/test_vcr.py
@@ -4,7 +4,7 @@ import os
 import pytest
 import http.client as httplib
 
-from vcr import VCR, use_cassette
+from vcr import VCR, mode, use_cassette
 from vcr.request import Request
 from vcr.stubs import VCRHTTPSConnection
 from vcr.patch import _HTTPConnection, force_reset
@@ -188,11 +188,11 @@ def test_custom_patchers():
 def test_inject_cassette():
     vcr = VCR(inject_cassette=True)
 
-    @vcr.use_cassette("test", record_mode="once")
+    @vcr.use_cassette("test", record_mode=mode.ONCE)
     def with_cassette_injected(cassette):
-        assert cassette.record_mode == "once"
+        assert cassette.record_mode == mode.ONCE
 
-    @vcr.use_cassette("test", record_mode="once", inject_cassette=False)
+    @vcr.use_cassette("test", record_mode=mode.ONCE, inject_cassette=False)
     def without_cassette_injected():
         pass
 
@@ -201,7 +201,7 @@ def test_inject_cassette():
 
 
 def test_with_current_defaults():
-    vcr = VCR(inject_cassette=True, record_mode="once")
+    vcr = VCR(inject_cassette=True, record_mode=mode.ONCE)
 
     @vcr.use_cassette("test", with_current_defaults=False)
     def changing_defaults(cassette, checks):
@@ -212,10 +212,10 @@ def test_with_current_defaults():
         checks(cassette)
 
     def assert_record_mode_once(cassette):
-        assert cassette.record_mode == "once"
+        assert cassette.record_mode == mode.ONCE
 
     def assert_record_mode_all(cassette):
-        assert cassette.record_mode == "all"
+        assert cassette.record_mode == mode.ALL
 
     changing_defaults(assert_record_mode_once)
     current_defaults(assert_record_mode_once)