Skip to main content

Normalise any API response into a consistent envelope: ok, data, error, status, meta

Project description

unwrapr

Stop writing the same API response unwrapping code in every project.

pip install unwrapr

Requires Python 3.9+ · Zero dependencies


The problem

Every API you call returns a different shape:

{"data": {...}, "error": null}           # some APIs
{"success": True, "result": {...}}       # other APIs
{"status": 200, "payload": {...}}        # yet others
[{"id": 1}, {"id": 2}]                  # or just raw lists

You end up writing custom unwrapping logic for every single one.

unwrapr fixes that. One function. Any shape. Consistent output.


Quick start

from unwrapr import unwrap

# Works with any API response shape
env = unwrap({"success": True, "data": {"id": 1, "name": "Alice"}})

env.ok      # True
env.data    # {"id": 1, "name": "Alice"}
env.error   # None
env.status  # None
env.meta    # {}

Supported shapes

unwrapr auto-detects the response shape and normalises it:

# { data, error }
unwrap({"data": {"id": 1}, "error": None})

# { success, data }
unwrap({"success": True, "result": {"id": 1}})

# { status, payload }
unwrap({"status": 200, "payload": {"id": 1}})

# JSON:API
unwrap({"data": [...], "included": [], "meta": {"total": 5}})

# Plain dict or list
unwrap({"id": 1, "name": "Alice"})
unwrap([1, 2, 3])

HTTP status override

Pass the HTTP status code to let it override the body:

env = unwrap(response.json(), status=response.status_code)
env.ok      # True if 2xx, False otherwise
env.status  # the actual HTTP status code

Safe data access

env = unwrap({"success": False, "error": "Not found"})

# Raises UnwraprError if not ok
data = env.unwrap()

# Returns default if not ok — never raises
data = env.unwrap_or([])
data = env.unwrap_or(None)

# Use as a boolean
if env:
    print(env.data)

Custom strategies

Add your own shape detection logic:

from unwrapr import unwrap, DEFAULT_STRATEGIES

def my_api_strategy(raw):
    if isinstance(raw, dict) and "response" in raw:
        return {
            "ok": raw["response"]["success"],
            "data": raw["response"]["body"],
            "error": raw["response"].get("error"),
            "status": None,
            "meta": {},
        }
    return None  # return None to try the next strategy

env = unwrap(response, strategies=[my_api_strategy] + DEFAULT_STRATEGIES)

Works great with petchr

from petchr import petch
from unwrapr import unwrap

resp = petch("https://api.example.com/users/1")
env = unwrap(resp.data, status=resp.status_code)

if env:
    print(env.data)
else:
    print(f"Error: {env.error}")

The Envelope

Every call returns an Envelope:

Field Type Description
ok bool True if response is successful
data Any The extracted payload
error `str None`
status `int None`
meta dict Extra fields (pagination, links etc)
raw Any Original response before normalising

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unwrapr-1.0.0.tar.gz (8.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unwrapr-1.0.0-py3-none-any.whl (7.1 kB view details)

Uploaded Python 3

File details

Details for the file unwrapr-1.0.0.tar.gz.

File metadata

  • Download URL: unwrapr-1.0.0.tar.gz
  • Upload date:
  • Size: 8.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for unwrapr-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e023fc28bb91c818398981109841d098b78a8f1d0e50a7fa91d0acd41a3b57f0
MD5 672474df52d9652a91ab41e12aa0fb68
BLAKE2b-256 73a59ad1834de0981dab061959f1049cc1a6067c84a8885db37e695f0a56a51e

See more details on using hashes here.

File details

Details for the file unwrapr-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: unwrapr-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 7.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for unwrapr-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f00c58682bf2bca5e8f64582f6371482c04adf8f0585b0b04fa4aa4bda7ee36b
MD5 27f011872ec098bf673e8bab6daf2f28
BLAKE2b-256 ec72bf9c4d6c5c3fe48fa808d8a0cefd0ff80218a86fce585f211a67f50f27c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page