{"id":8428,"library":"placebo","title":"Placebo","description":"Placebo is a Python library designed to mock `boto3` calls, allowing developers to record actual AWS service responses and replay them later without interacting with real AWS endpoints. This is particularly useful for unit testing, offline development, and creating consistent test environments. The current version is 0.10.0. Releases have been sporadic, with a significant update to 0.10.0 after a nearly three-year gap, indicating active maintenance but not a fixed cadence.","status":"active","version":"0.10.0","language":"en","source_language":"en","source_url":"https://github.com/garnaat/placebo","tags":["boto3","testing","mocking","aws","offline","sdk"],"install":[{"cmd":"pip install placebo","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Placebo's purpose is to mock boto3 calls; it does not install boto3 itself, but its functionality is entirely dependent on boto3 being present in the environment where AWS calls are made.","package":"boto3","optional":true}],"imports":[{"symbol":"attach","correct":"from placebo import attach"},{"note":"While `boto3.DEFAULT_SESSION` exists, it must be explicitly set up with `boto3.setup_default_session()` for Placebo to attach correctly, otherwise, directly creating a `boto3.Session()` is more reliable for explicit control.","wrong":"import boto3; session = boto3.DEFAULT_SESSION","symbol":"Session","correct":"import boto3; boto3.Session()"}],"quickstart":{"code":"import boto3\nimport placebo\nimport os\n\ndata_path = os.path.join(os.path.dirname(__file__), 'placebo_data')\nos.makedirs(data_path, exist_ok=True)\n\nsession = boto3.Session(region_name='us-east-1')\npill = placebo.attach(session, data_path=data_path)\n\n# --- Recording mode ---\n# Set PLACEBO_MODE=record in environment variables to enable recording\n# e.g., PLACEBO_MODE=record python your_script.py\nif os.environ.get('PLACEBO_MODE') == 'record':\n    print(\"Recording AWS calls...\")\n    pill.record()\n    s3 = session.client('s3')\n    try:\n        s3.list_buckets()\n        print(\"Buckets listed and recorded.\")\n    except Exception as e:\n        print(f\"Error during recording: {e}\")\n\n# --- Playback mode ---\n# Default behavior, or set PLACEBO_MODE=playback\n# e.g., PLACEBO_MODE=playback python your_script.py\nelse:\n    print(\"Playing back recorded AWS calls...\")\n    pill.playback()\n    s3 = session.client('s3')\n    try:\n        response = s3.list_buckets()\n        print(\"Buckets listed from recording:\")\n        for bucket in response.get('Buckets', []):\n            print(f\" - {bucket['Name']}\")\n    except Exception as e:\n        print(f\"Error during playback: {e}\")\n\n# Clean up (optional, for demonstration purposes)\n# import shutil\n# if os.path.exists(data_path):\n#     shutil.rmtree(data_path)\n","lang":"python","description":"This example demonstrates how to set up Placebo for both recording and playing back AWS API calls using `boto3`. It creates a `boto3` session, attaches Placebo to it with a specified data directory, and then, based on an environment variable, either records S3 `list_buckets` calls or plays them back from previously recorded JSON files."},"warnings":[{"fix":"Upgrade your Python environment to Python 3.x (e.g., Python 3.6+ is recommended by Placebo's PyPI classifiers).","message":"Placebo version 0.10.0, released in September 2021, officially dropped support for Python 2.x. Codebases still on Python 2.x will need to upgrade to Python 3.x to use this and future versions.","severity":"breaking","affected_versions":">=0.10.0"},{"fix":"Upgrade to Placebo version 0.10.0 or later to ensure correct handling of binary response bodies.","message":"Older versions of Placebo (prior to 0.10.0) had a bug handling binary response bodies from AWS services, which could lead to incorrect data or errors during playback.","severity":"gotcha","affected_versions":"<0.10.0"},{"fix":"Explicitly initialize the default session with `boto3.setup_default_session()` before attaching Placebo, or, preferably, create and pass a named `boto3.Session()` object to `placebo.attach()` for clearer scope.","message":"When using `boto3.DEFAULT_SESSION`, Placebo may not correctly attach unless `boto3.setup_default_session()` is explicitly called beforehand. If you create `boto3` clients from a default session that hasn't been set up, Placebo might not intercept calls.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always call `pill.record()` or `pill.playback()` on the `Pill` object *before* creating any `boto3` clients from the associated session that you intend to mock.","message":"Clients created from a `boto3.Session` *before* `pill.record()` or `pill.playback()` is called might not be 'placebo-aware' and will still make live AWS calls. This was a bug fixed in 0.7.2, but misunderstanding the order of operations can still cause issues.","severity":"gotcha","affected_versions":"<0.7.2, and a potential user error in later versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Install `boto3` alongside Placebo: `pip install boto3 placebo`.","cause":"Placebo is designed to mock `boto3` interactions but does not include `boto3` as a direct installation dependency. This error occurs if `boto3` is not installed in your environment.","error":"ModuleNotFoundError: No module named 'boto3'"},{"fix":"Ensure you are reading the `botocore.response.StreamingBody` as bytes or handling compression correctly. For example, `response['Body'].read()` will return bytes. If you need to decompress, use `gzip.GzipFile` with `io.BytesIO`.","cause":"This typically indicates an attempt to process binary response data (e.g., from S3 `get_object` calls) as a string. Older Placebo versions had issues with binary responses, and even with 0.10.0+, incorrect handling of the `StreamingBody` can lead to this.","error":"TypeError: a bytes-like object is required, not 'str' (or similar errors when processing binary data)"},{"fix":"Verify that `pill.record()` or `pill.playback()` is explicitly called on the correct `Pill` instance, and that all `boto3` clients intended for mocking are instantiated *after* Placebo has been activated for that session.","cause":"This can happen if `pill.record()` or `pill.playback()` was not called on the `Pill` object, if `boto3` clients were created before these methods were invoked, or if Placebo was attached to a different `boto3.Session` than the one being used.","error":"AWS calls are still being made to real endpoints even when Placebo is supposedly active."}]}