From 647d36f7cdb214b82ef5023385f7be136f369423 Mon Sep 17 00:00:00 2001 From: Ben Jeffery Date: Wed, 20 Oct 2021 14:33:19 +0100 Subject: [PATCH] Improve JSON encoding error message --- python/CHANGELOG.rst | 3 +++ python/tests/test_metadata.py | 8 ++++++++ python/tskit/exceptions.py | 6 ++++++ python/tskit/metadata.py | 7 ++++++- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/python/CHANGELOG.rst b/python/CHANGELOG.rst index 569f8a4309..d11ecf1a60 100644 --- a/python/CHANGELOG.rst +++ b/python/CHANGELOG.rst @@ -31,6 +31,9 @@ ``TableCollection.sort`` no longer sorts individuals. (:user:`benjeffery`, :issue:`1774`, :pr:`1789`) +- Metadata encoding errors now raise ``MetadataEncodingError`` + (:user:`benjeffery`, :issue:`1505`, :pr:`1827`). + **Features** - Add ``TableCollection.sort_individuals`` to sort the individuals as this is no longer done by the diff --git a/python/tests/test_metadata.py b/python/tests/test_metadata.py index dc5695e40e..8d4aef0df7 100644 --- a/python/tests/test_metadata.py +++ b/python/tests/test_metadata.py @@ -566,6 +566,14 @@ def test_nested_default_error(self): ): tskit.MetadataSchema(schema) + def test_bad_type_error(self): + ms = tskit.MetadataSchema({"codec": "json"}) + with pytest.raises( + exceptions.MetadataEncodingError, + match="Could not encode metadata of type TableCollection", + ): + ms.validate_and_encode_row(tskit.TableCollection(1)) + class TestStructCodec: def encode_decode(self, method_name, sub_schema, obj, buffer): diff --git a/python/tskit/exceptions.py b/python/tskit/exceptions.py index 7c83c4244a..c688a0e7ba 100644 --- a/python/tskit/exceptions.py +++ b/python/tskit/exceptions.py @@ -54,3 +54,9 @@ class MetadataSchemaValidationError(TskitException): """ A metadata schema object did not validate against the metaschema. """ + + +class MetadataEncodingError(TskitException): + """ + A metadata object was of a type that could not be encoded + """ diff --git a/python/tskit/metadata.py b/python/tskit/metadata.py index 50f0b1c23d..3cc452fcf3 100644 --- a/python/tskit/metadata.py +++ b/python/tskit/metadata.py @@ -144,7 +144,12 @@ def __init__(self, schema: Mapping[str, Any]) -> None: } def encode(self, obj: Any) -> bytes: - return tskit.canonical_json(obj).encode() + try: + return tskit.canonical_json(obj).encode() + except TypeError as e: + raise exceptions.MetadataEncodingError( + f"Could not encode metadata of type {str(e).split()[3]}" + ) def decode(self, encoded: bytes) -> Any: result = json.loads(encoded.decode())