# API

class betamax.Betamax(session, cassette_library_dir=None, default_cassette_options={})

  This object contains the main API of the request-vcr library.

  This object is entirely a context manager so all you have to do is:

      s = requests.Session()
      with Betamax(s) as vcr:
          vcr.use_cassette('example')
          r = s.get('https://httpbin.org/get')

  Or more concisely, you can do:

      s = requests.Session()
      with Betamax(s).use_cassette('example') as vcr:
          r = s.get('https://httpbin.org/get')

  This object allows for the user to specify the cassette library directory and default cassette options.

      s = requests.Session()
      with Betamax(s, cassette_library_dir='tests/cassettes') as vcr:
          vcr.use_cassette('example')
          r = s.get('https://httpbin.org/get')

      with Betamax(s, default_cassette_options={
              're_record_interval': 1000
              }) as vcr:
          vcr.use_cassette('example')
          r = s.get('https://httpbin.org/get')

  betamax_adapter

    Create a new adapter to replace the existing ones

  static configure()

    Help to configure the library as a whole.

        with Betamax.configure() as config:
            config.cassette_library_dir = 'tests/cassettes/'
            config.default_cassette_options['match_options'] = [
                'method', 'uri', 'headers'
                ]

  property current_cassette

    Return the cassette that is currently in use.

    Returns:

      `Cassette`

  http_adapters

    Store the session’s original adapters.

  static register_request_matcher(matcher_class)

    Register a new request matcher.

    Parameters:

      matcher_class – (required), this must sub-class `BaseMatcher`

  static register_serializer(serializer_class)

    Register a new serializer.

    Parameters:

      matcher_class – (required), this must sub-class `BaseSerializer`

  session

    Store the requests.Session object being wrapped.

  start()

    Start recording or replaying interactions.

  stop()

    Stop recording or replaying interactions.

  use_cassette(cassette_name, **kwargs)

    Tell Betamax which cassette you wish to use for the context.

    Parameters:

      - cassette_name (str) – relative name, without the serialization format, of the cassette you wish Betamax would use

      - serialize_with (str) – the format you want Betamax to serialize the cassette with

      - serialize (str) – DEPRECATED the format you want Betamax to serialize the request and response data to and from

betamax.decorator.use_cassette(cassette_name, cassette_library_dir=None, default_cassette_options={}, **use_cassette_kwargs)

  Provide a Betamax-wrapped Session for convenience.

  Added in version 0.5.0.

  This decorator can be used to get a plain Session that has been wrapped in Betamax. For example,

      from betamax.decorator import use_cassette

      @use_cassette('example-decorator', cassette_library_dir='.')
      def test_get(session):
          # do things with session

  Parameters:

    - cassette_name (str) – Name of the cassette file in which interactions will be stored.

    - cassette_library_dir (str) – Directory in which cassette files will be stored.

    - default_cassette_options (dict) – Dictionary of default cassette options to set for the cassette used when recording these interactions.

    - **use_cassette_kwargs – Keyword arguments passed to `use_cassette()`

class betamax.configure.Configuration

  This object acts as a proxy to configure different parts of Betamax.

  You should only ever encounter this object when configuring the library as a whole. For example:

      with Betamax.configure() as config:
          config.cassette_library_dir = 'tests/cassettes/'
          config.default_cassette_options['record_mode'] = 'once'
          config.default_cassette_options['match_requests_on'] = ['uri']
          config.define_cassette_placeholder('<URI>', 'http://httpbin.org')
          config.preserve_exact_body_bytes = True

  after_start(callback=None)

    Register a function to call after Betamax is started.

    Example usage:

        def on_betamax_start(cassette):
            if cassette.is_recording():
                print("Setting up authentication...")

        with Betamax.configure() as config:
            config.cassette_load(callback=on_cassette_load)

    Parameters:

      callback (callable) – The function which accepts a cassette and might mutate it before returning.

  before_playback(tag=None, callback=None)

    Register a function to call before playing back an interaction.

    Example usage:

        def before_playback(interaction, cassette):
            pass

        with Betamax.configure() as config:
            config.before_playback(callback=before_playback)

    Parameters:

      - tag (str) – Limits the interactions passed to the function based on the interaction’s tag (currently unsupported).

      - callback (callable) – The function which either accepts just an interaction or an interaction and a cassette and mutates the interaction before returning.

  before_record(tag=None, callback=None)

    Register a function to call before recording an interaction.

    Example usage:

        def before_record(interaction, cassette):
            pass

        with Betamax.configure() as config:
            config.before_record(callback=before_record)

    Parameters:

      - tag (str) – Limits the interactions passed to the function based on the interaction’s tag (currently unsupported).

      - callback (callable) – The function which either accepts just an interaction or an interaction and a cassette and mutates the interaction before returning.

  before_stop(callback=None)

    Register a function to call before Betamax stops.

    Example usage:

        def on_betamax_stop(cassette):
            if not cassette.is_recording():
                print("Playback completed.")

        with Betamax.configure() as config:
            config.cassette_eject(callback=on_betamax_stop)

    Parameters:

      callback (callable) – The function which accepts a cassette and might mutate it before returning.

  property cassette_library_dir

    Retrieve and set the directory to store the cassettes in.

  property default_cassette_options

    Retrieve and set the default cassette options.

    The options include:

    - `match_requests_on`

    - `placeholders`

    - `re_record_interval`

    - `record_mode`

    - `preserve_exact_body_bytes`

    Other options will be ignored.

  define_cassette_placeholder(placeholder, replace)

    Define a placeholder value for some text.

    This also will replace the placeholder text with the text you wish it to use when replaying interactions from cassettes.

    Parameters:

      - placeholder (str) – (required), text to be used as a placeholder

      - replace (str) – (required), text to be replaced or replacing the placeholder

A set of fixtures to integrate Betamax with py.test.

betamax.fixtures.pytest.betamax_session(betamax_recorder)

  Generate a session that has Betamax already installed.

  See betamax_recorder fixture.

  Parameters:

    betamax_recorder – A recorder fixture with a configured request session.

  Returns:

    An instantiated requests Session wrapped by Betamax.

Minimal `unittest.TestCase` subclass adding Betamax integration.

class betamax.fixtures.unittest.BetamaxTestCase(methodName='runTest')

  Betamax integration for unittest.

  Added in version 0.5.0.

  CASSETTE_LIBRARY_DIR = None

    Custom path to save cassette.

  SESSION_CLASS

    Class that is a subclass of `requests.Session`

    alias of `Session`

  generate_cassette_name()

    Generates a cassette name for the current test.

    The default format is “%(classname)s.%(testMethodName)s”

    To change the default cassette format, override this method in a subclass.

    Returns:

      Cassette name for the current test.

    Return type:

      str

  setUp()

    Betamax-ified setUp fixture.

    This will call the superclass’ setUp method first and then it will create a new `requests.Session` and wrap that in a Betamax object to record it. At the end of `setUp`, it will start recording.

  tearDown()

    Betamax-ified tearDown fixture.

    This will call the superclass’ tearDown method first and then it will stop recording interactions.

When using Betamax with unittest, you can use the traditional style of Betamax covered in the documentation thoroughly, or you can use your fixture methods, `unittest.TestCase.setUp()` and `unittest.TestCase.tearDown()` to wrap entire tests in Betamax.

Here’s how you might use it:

    from betamax.fixtures import unittest

    from myapi import SessionManager

    class TestMyApi(unittest.BetamaxTestCase):
        def setUp(self):
            # Call BetamaxTestCase's setUp first to get a session
            super(TestMyApi, self).setUp()

            self.manager = SessionManager(self.session)

        def test_all_users(self):
            """Retrieve all users from the API."""
            for user in self.manager:
                # Make assertions or something

Alternatively, if you are subclassing a `requests.Session` to provide extra functionality, you can do something like this:

    from betamax.fixtures import unittest

    from myapi import Session, SessionManager

    class TestMyApi(unittest.BetamaxTestCase):
        SESSION_CLASS = Session

        # See above ...

## Examples

### Basic Usage

Let example.json be a file in a directory called cassettes with the content:

    {
      "http_interactions": [
        {
          "request": {
            "body": {
              "string": "",
              "encoding": "utf-8"
            },
            "headers": {
              "User-Agent": ["python-requests/v1.2.3"]
            },
            "method": "GET",
            "uri": "https://httpbin.org/get"
          },
          "response": {
            "body": {
              "string": "example body",
              "encoding": "utf-8"
            },
            "headers": {},
            "status": {
              "code": 200,
              "message": "OK"
            },
            "url": "https://httpbin.org/get"
          }
        }
      ],
      "recorded_with": "betamax"
    }

The following snippet will not raise any exceptions

    from betamax import Betamax
    from requests import Session

    s = Session()

    with Betamax(s, cassette_library_dir='cassettes') as betamax:
        betamax.use_cassette('example', record='none')
        r = s.get("https://httpbin.org/get")

On the other hand, this will raise an exception:

    from betamax import Betamax
    from requests import Session

    s = Session()

    with Betamax(s, cassette_library_dir='cassettes') as betamax:
        betamax.use_cassette('example', record='none')
        r = s.post("https://httpbin.org/post",
                   data={"key": "value"})

Finally, we can also use a decorator in order to simplify things:

    import unittest

    from betamax.decorator import use_cassette

    class TestExample(unittest.TestCase):
        @use_cassette('example', cassette_library_dir='cassettes')
        def test_example(self, session):
            session.get('https://httpbin.org/get')

    # Or if you're using something like py.test
    @use_cassette('example', cassette_library_dir='cassettes')
    def test_example_pytest(session):
        session.get('https://httpbin.org/get')

## Opinions at Work

If you use `requests`’s default `Accept-Encoding` header, servers that support gzip content encoding will return responses that Betamax cannot serialize in a human-readable format. In this event, the cassette will look like this:

    {
      "http_interactions": [
        {
          "request": {
            "body": {
              "base64_string": "",
              "encoding": "utf-8"
            },
            "headers": {
              "User-Agent": ["python-requests/v1.2.3"]
            },
            "method": "GET",
            "uri": "https://httpbin.org/get"
          },
          "response": {
            "body": {
              "base64_string": "Zm9vIGJhcgo=",
              "encoding": "utf-8"
            },
            "headers": {
              "Content-Encoding": ["gzip"]
            },
            "status": {
              "code": 200,
              "message": "OK"
            },
            "url": "https://httpbin.org/get"
          }
        }
      ],
      "recorded_with": "betamax"
    }

## Forcing bytes to be preserved

You may want to force betamax to preserve the exact bytes in the body of a response (or request) instead of relying on the opinions held by the library. In this case you have two ways of telling betamax to do this.

The first, is on a per-cassette basis, like so:

    from betamax import Betamax
    import requests

    session = Session()

    with Betamax.configure() as config:
        c.cassette_library_dir = '.'

    with Betamax(session).use_cassette('some_cassette',
                                       preserve_exact_body_bytes=True):
        r = session.get('http://example.com')

On the other hand, you may want to preserve exact body bytes for all cassettes. In this case, you can do:

    from betamax import Betamax
    import requests

    session = Session()

    with Betamax.configure() as config:
        config.cassette_library_dir = '.'
        config.preserve_exact_body_bytes = True

    with Betamax(session).use_cassette('some_cassette'):
        r = session.get('http://example.com')