ProvenPin Install

cbor2 CBOR encode/decode with semantic tags: working versions (tested 2026-10-18)

Round-trip datetimes, exact Decimals and custom CBOR semantic tags with cbor2 6.x, using the encoder-based default hook, the two-argument tag_hook and canonical encoding.

passed6 passed · 0 failed2026-10-18 03:56 UTC
Status
passed
Last passed
2026-10-18 03:56 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions2
cbor2@6.1.5pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 39095370682

The code

Exactly the files that passed. Your agent can pull them with get_recipe("cbor2-encode-decode-tags") (install), or see them on GitHub.

requirements.txt
cbor2==6.1.5
pytest==9.1.1
cbor_codec.py
from __future__ import annotations

from typing import Any

import cbor2
from cbor2 import CBORTag

POINT_TAG = 40001


class Point:
    def __init__(self, x: int, y: int) -> None:
        self.x = x
        self.y = y

    def __eq__(self, other: object) -> bool:
        return isinstance(other, Point) and (self.x, self.y) == (other.x, other.y)

    def __repr__(self) -> str:
        return f"Point({self.x}, {self.y})"


def _default(encoder: cbor2.CBOREncoder, obj: Any) -> None:
    # cbor2 6.x passes the encoder: encode through it, do not return a value.
    if isinstance(obj, Point):
        encoder.encode_semantic(POINT_TAG, [obj.x, obj.y])
    else:
        raise cbor2.CBOREncodeTypeError(f"cannot encode {type(obj).__name__}")


def _tag_hook(tag: CBORTag, immutable: bool) -> Any:
    if tag.tag == POINT_TAG:
        x, y = tag.value
        return Point(x, y)
    return tag


def encode(obj: Any, *, canonical: bool = False, timezone=None) -> bytes:
    return cbor2.dumps(obj, default=_default, canonical=canonical, timezone=timezone)


def decode(data: bytes) -> Any:
    return cbor2.loads(data, tag_hook=_tag_hook)
tests/test_cbor_codec.py
from datetime import datetime, timedelta, timezone
from decimal import Decimal

import cbor2
import pytest
from cbor2 import CBORTag

from cbor_codec import POINT_TAG, Point, decode, encode


def test_datetime_roundtrip_preserves_offset():
    dt = datetime(2021, 1, 1, 12, 0, tzinfo=timezone(timedelta(hours=5, minutes=30)))
    assert decode(encode(dt)) == dt


def test_naive_datetime_needs_timezone():
    naive = datetime(2021, 1, 1, 12, 0)
    with pytest.raises(cbor2.CBOREncodeError):
        encode(naive)
    assert decode(encode(naive, timezone=timezone.utc)) == naive.replace(tzinfo=timezone.utc)


def test_decimal_roundtrip_is_exact():
    result = decode(encode(Decimal("1.230")))
    assert result == Decimal("1.230")
    assert str(result) == "1.230"  # trailing zero survives, unlike a float roundtrip


def test_custom_tag_roundtrip_and_unknown_passthrough():
    assert decode(encode(Point(3, 4))) == Point(3, 4)
    assert decode(cbor2.dumps(CBORTag(999, "hi"))) == CBORTag(999, "hi")


def test_default_return_value_is_ignored():
    # default(encoder, value) must write via the encoder; a returned value is
    # dropped, leaving a truncated stream (empty when the root object is custom).
    out = cbor2.dumps(
        Point(1, 2), default=lambda enc, obj: CBORTag(POINT_TAG, [obj.x, obj.y])
    )
    assert out == b""


def test_canonical_encoding_is_insertion_order_independent():
    a = {"b": 1, "aa": 2}
    b = {"aa": 2, "b": 1}
    assert encode(a) != encode(b)
    assert encode(a, canonical=True) == encode(b, canonical=True)
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.