Ejemplo n.º 1
0
def test_unregister() -> None:
	# Create and register a custom encoder for Decimal that turns it into a string
	@sdjson.encoders.register(Decimal)
	def encode_str(obj):
		return str(obj)

	# Test that we get the expected output from the first encoder
	assert sdjson.dumps(Decimal(1)) == '"1"'

	# Unregister that encoder
	sdjson.unregister_encoder(Decimal)

	# We should now get an error
	with pytest.raises(TypeError, match="Object of type [']*Decimal[']* is not JSON serializable") as e:
		sdjson.dumps(Decimal(2))
	assert e.type is TypeError
def test_custom_class() -> None:
    # Create and register the custom encoders
    # In this example we create three separate encoders even though all three classes
    #  actually share a common subclass. In real usage they might not be.
    @sdjson.encoders.register(Character)
    def encode_character(obj):
        return dict(obj)

    @sdjson.encoders.register(Cheese)
    def encode_cheese(obj):
        return dict(obj)

    @sdjson.encoders.register(Shop)
    def encode_shop(obj):
        return dict(obj)

    # Create instances of classes
    runny_camembert = Cheese("Camembert", ["Very runny"])
    shopkeeper = Character("Mr Wensleydale", "Michael Palin")
    customer = Character("The Customer", "John Cleese")
    cheese_shop = Shop(
        "The National Cheese Emporium",
        address="""12 Some Street
Some Town
England""",
        staff=[shopkeeper],
        customers=[customer],
        current_stock=[runny_camembert],
        music=False,
        dancing=False,
    )

    expected_json = (
        '{"name": "The National Cheese Emporium", "address": "12 Some Street\\n'
        'Some Town\\nEngland", "is_open": true, "music": false, "dancing": false, '
        '"staff": [{"name": "Mr Wensleydale", "actor": "Michael Palin", "armed": false}], '
        '"customers": [{"name": "The Customer", "actor": "John Cleese", "armed": false}], '
        '"current_stock": [{"name": "Camembert", "properties": ["Very runny"]}]}'
    )

    with TemporaryPathPlus() as tmpdir:
        tmpfile = tmpdir / "output.json"

        with open(tmpfile, 'w', encoding="UTF-8") as fp:
            sdjson.dump(cheese_shop, fp)

        with open(tmpfile, encoding="UTF-8") as fp:
            assert fp.read() == expected_json

    assert sdjson.dumps(cheese_shop) == expected_json

    # Cleanup
    sdjson.unregister_encoder(Character)
    sdjson.unregister_encoder(Cheese)
    sdjson.unregister_encoder(Shop)
Ejemplo n.º 3
0
def test_protocols() -> None:
    class Integer:
        def __int__(self):
            return 42

    class Float:
        def __float__(self):
            return 42.0

    class Bytes:
        def __bytes__(self):
            return b"42"

    with pytest.raises(
            TypeError,
            match="Object of type '?Integer'? is not JSON serializable"):
        sdjson.dumps(Integer())

    with pytest.raises(
            TypeError,
            match="Object of type '?Float'? is not JSON serializable"):
        sdjson.dumps(Float())

    with pytest.raises(
            TypeError,
            match="Object of type '?Bytes'? is not JSON serializable"):
        sdjson.dumps(Bytes())

    @sdjson.encoders.register(SupportsInt)
    def supports_int_encoder(obj):
        return int(obj)

    @sdjson.encoders.register(SupportsFloat)
    def supports_float_encoder(obj):
        return float(obj)

    @sdjson.encoders.register(SupportsBytes)
    def supports_bytes_encoder(obj):
        return bytes(obj)

    assert sdjson.dumps(Integer()) == "42"
    assert sdjson.dumps(Float()) == "42.0"

    # To prove the protocols don't take precedence
    assert sdjson.dumps(123) == "123"

    with pytest.raises(
            TypeError,
            match="Object of type '?bytes'? is not JSON serializable"):
        sdjson.dumps(Bytes())

    @sdjson.encoders.register(bytes)
    def bytes_encoder(obj):
        return obj.decode("UTF-8")

    assert sdjson.dumps(Bytes()) == '"42"'

    sdjson.unregister_encoder(SupportsInt)
    sdjson.unregister_encoder(SupportsFloat)
    sdjson.unregister_encoder(SupportsBytes)
    sdjson.unregister_encoder(bytes)

    with pytest.raises(KeyError):
        sdjson.unregister_encoder(bytes)

    with pytest.raises(TypeError,
                       match="Protocols must be @runtime_checkable"):
        sdjson.register_encoder(SupportsBizBaz, supports_bytes_encoder)