diff --git a/.gitignore b/.gitignore
index a88aff4..cd55f92 100644
--- a/.gitignore
+++ b/.gitignore
@@ -176,5 +176,5 @@ pyrightconfig.json
# End of https://www.toptal.com/developers/gitignore/api/python
# file generated by setuptools_scm
-/jsont/_version.py
+/jsonype/_version.py
diff --git a/.idea/jsont.iml b/.idea/jsonype.iml
similarity index 100%
rename from .idea/jsont.iml
rename to .idea/jsonype.iml
diff --git a/.idea/misc.xml b/.idea/misc.xml
index a85b351..fae8e54 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 7dd5928..98f7f69 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/README.md b/README.md
index f6c38b7..598240f 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-# json-t
+# jsonype
## Usage
-See [documentation](https://json-t.readthedocs.io).
+See [documentation](https://jsonype.readthedocs.io).
## Similar tools
@@ -11,7 +11,7 @@ See [documentation](https://json-t.readthedocs.io).
a less permissive license.
- [Pydantic](https://docs.pydantic.dev) is a widely used data validation library for Python.
It is often used for converting to and from JSON, but offers much more than that. Unlike in case of
- json-t classes that should be converted from/to JSON need to inherit from a base class (`BaseModel`).
+ jsonype classes that should be converted from/to JSON need to inherit from a base class (`BaseModel`).
## Development
@@ -56,5 +56,5 @@ current directory is set to the project's root folder.
```bash
cd docs
-sphinx-apidoc -o source ../jsont/
+sphinx-apidoc -o source ../jsonype/
```
diff --git a/check.sh b/check.sh
index 9fd13aa..46c614e 100755
--- a/check.sh
+++ b/check.sh
@@ -2,4 +2,7 @@
pylama
ruff check
+mypy
pytest
+[ -f jsonype/_version.py ] || echo "__version__='0'" > jsonype/_version.py
+(cd docs && make doctest)
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 562b124..f695922 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -8,12 +8,12 @@
sys.path.insert(0, os.path.abspath("../../"))
-from jsont._version import __version__
+from jsonype._version import __version__
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
-project = 'json-t'
+project = 'jsonype'
# noinspection PyShadowingBuiltins
copyright = '2023, Volker Stampa'
author = 'Volker Stampa'
diff --git a/docs/source/index.rst b/docs/source/index.rst
index d6bb2b9..3614918 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -1,5 +1,5 @@
-Welcome to json-t's documentation!
-==================================
+Welcome to jsonype's documentation!
+===================================
.. toctree::
:maxdepth: 1
@@ -7,7 +7,7 @@ Welcome to json-t's documentation!
modules
-json-t is a package for converting Python's
+jsonype is a package for converting Python's
`JSON representation `_
to (or from) a Python object of a given
type if possible (i.e. a suitable converter is available).
@@ -17,11 +17,11 @@ This is most useful when the given type contains type-hints such that this type-
Getting Started
---------------
-Add ``json-t`` to your dependencies or install with pip::
+Add ``jsonype`` to your dependencies or install with pip::
- pip install json-t
+ pip install jsonype
-For details on how to use it see :class:`jsont.typed_json.TypedJson`.
+For details on how to use it see :class:`jsonype.TypedJson`.
diff --git a/docs/source/jsont.rst b/docs/source/jsonype.rst
similarity index 67%
rename from docs/source/jsont.rst
rename to docs/source/jsonype.rst
index 57f89ef..094903b 100644
--- a/docs/source/jsont.rst
+++ b/docs/source/jsonype.rst
@@ -1,10 +1,10 @@
-jsont package
-=============
+jsonype package
+===============
Module contents
---------------
-.. automodule:: jsont
+.. automodule:: jsonype
:members:
:special-members: __init__
:undoc-members:
diff --git a/docs/source/modules.rst b/docs/source/modules.rst
index 18e51c7..9ed47d7 100644
--- a/docs/source/modules.rst
+++ b/docs/source/modules.rst
@@ -1,7 +1,7 @@
-jsont
-=====
+jsonype
+=======
.. toctree::
:maxdepth: 3
- jsont
+ jsonype
diff --git a/jsont/__init__.py b/jsonype/__init__.py
similarity index 79%
rename from jsont/__init__.py
rename to jsonype/__init__.py
index eee2ed7..3e290ab 100644
--- a/jsont/__init__.py
+++ b/jsonype/__init__.py
@@ -1,5 +1,10 @@
# pylint: disable=C0414
from .base_types import Json as Json # noqa: W0611
+
+# isort: off
+from .basic_from_json_converters import (FromJsonConversionError # noqa: W0611
+ as FromJsonConversionError)
+# isort: on
from .basic_from_json_converters import FromJsonConverter as FromJsonConverter # noqa: W0611
from .basic_from_json_converters import ToAny as ToAny # noqa: W0611
from .basic_from_json_converters import ToList as ToList # noqa: W0611
@@ -10,6 +15,11 @@
from .basic_from_json_converters import ToTuple as ToTuple # noqa: W0611
from .basic_from_json_converters import ToTypedMapping as ToTypedMapping # noqa: W0611
from .basic_from_json_converters import ToUnion as ToUnion # noqa: W0611
+
+# isort: off
+from .basic_from_json_converters import (UnsupportedTargetTypeError # noqa: W0611
+ as UnsupportedTargetTypeError)
+# isort: on
from .basic_to_json_converters import FromMapping as FromMapping # noqa: W0611
from .basic_to_json_converters import FromNone as FromNone # noqa: W0611
from .basic_to_json_converters import FromSequence as FromSequence # noqa: W0611
diff --git a/jsont/base_types.py b/jsonype/base_types.py
similarity index 100%
rename from jsont/base_types.py
rename to jsonype/base_types.py
diff --git a/jsont/basic_from_json_converters.py b/jsonype/basic_from_json_converters.py
similarity index 99%
rename from jsont/basic_from_json_converters.py
rename to jsonype/basic_from_json_converters.py
index 23cbc0a..984f47e 100644
--- a/jsont/basic_from_json_converters.py
+++ b/jsonype/basic_from_json_converters.py
@@ -4,7 +4,7 @@
from typing import (Any, Callable, Generic, Iterable, Literal, Mapping, Optional, Protocol,
Sequence, TypeVar, Union, cast, get_args, runtime_checkable)
-from jsont.base_types import Json, JsonSimple
+from jsonype.base_types import Json, JsonSimple
TargetType = TypeVar("TargetType")
ContainedTargetType = TypeVar("ContainedTargetType")
@@ -343,7 +343,7 @@ def type_for_key(k: str) -> type[TargetType]:
items = js.items() if self.strict \
else [(k, v) for k, v in js.items() if k in annotations]
return {k: from_json(v, type_for_key(k)) for k, v in items}
- raise FromJsonConversionError(js, target_type,
+ raise FromJsonConversionError(js, cast(type, target_type),
f"Required key missing: {target_type.__required_keys__}")
raise FromJsonConversionError(js, target_type)
diff --git a/jsont/basic_to_json_converters.py b/jsonype/basic_to_json_converters.py
similarity index 98%
rename from jsont/basic_to_json_converters.py
rename to jsonype/basic_to_json_converters.py
index ec22704..22cb4ff 100644
--- a/jsont/basic_to_json_converters.py
+++ b/jsonype/basic_to_json_converters.py
@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from typing import Any, Callable, Generic, Mapping, Sequence, TypeVar, get_args
-from jsont.base_types import Json, JsonNull, JsonSimple
+from jsonype.base_types import Json, JsonNull, JsonSimple
SourceType_contra = TypeVar("SourceType_contra", contravariant=True)
diff --git a/jsont/typed_json.py b/jsonype/typed_json.py
similarity index 85%
rename from jsont/typed_json.py
rename to jsonype/typed_json.py
index ceb2723..c93daa7 100644
--- a/jsont/typed_json.py
+++ b/jsonype/typed_json.py
@@ -1,12 +1,12 @@
from inspect import get_annotations
from typing import Any, TypeVar, cast, get_origin
-from jsont.base_types import Json
-from jsont.basic_from_json_converters import (FromJsonConverter, ToAny, ToList, ToLiteral,
- ToMapping, ToNone, ToSimple, ToTuple, ToTypedMapping,
- ToUnion, UnsupportedTargetTypeError)
-from jsont.basic_to_json_converters import (FromMapping, FromNone, FromSequence, FromSimple,
- ToJsonConverter, UnsupportedSourceTypeError)
+from jsonype.base_types import Json
+from jsonype.basic_from_json_converters import (FromJsonConverter, ToAny, ToList, ToLiteral,
+ ToMapping, ToNone, ToSimple, ToTuple,
+ ToTypedMapping, ToUnion, UnsupportedTargetTypeError)
+from jsonype.basic_to_json_converters import (FromMapping, FromNone, FromSequence, FromSimple,
+ ToJsonConverter, UnsupportedSourceTypeError)
TargetType = TypeVar("TargetType")
@@ -22,7 +22,7 @@ class TypedJson:
Example:
>>> from typing import TypedDict
- >>> from jsont import TypedJson
+ >>> from jsonype import TypedJson
>>> from json import loads
>>>
>>> typed_json = TypedJson()
@@ -59,9 +59,9 @@ class TypedJson:
>>> try:
... person = TypedJson(strict=True).from_json(js, Person)
... except ValueError as e:
- ... print(e)
- Cannot convert {'street': '...', ..., 'zip': 'ignored'}
- to as it contains unknown key zip
+ ... print(e) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
+ ("Cannot convert {'street': '...', ..., 'zip': 'ignored'}
+ to : Unknown key: zip", ...
"""
def __init__(self, strict: bool = False) -> None:
diff --git a/pyproject.toml b/pyproject.toml
index 7e132fc..99b20bf 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,9 +1,8 @@
[tool.poetry]
-name = "json-t"
+name = "jsonype"
version = "0" # ignored
description = "A package for converting classes with type hints to/from JSON"
-homepage = "https://github.com/volkerstampa/json-t"
-packages = [{include = "jsont"}]
+homepage = "https://github.com/volkerstampa/jsonype"
authors = ["Volker Stampa "]
maintainers = ["Volker Stampa "]
readme = "README.md"
@@ -22,27 +21,34 @@ requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.setuptools_scm]
-version_file = "jsont/_version.py"
+version_file = "jsonype/_version.py"
local_scheme = "poetry_setuptools_scm_plugin:no_local_scheme"
[tool.pylama]
-linters = "eradicate,mccabe,mypy,pycodestyle,pydocstyle,pyflakes,pylint,radon,vulture,isort"
+# dont run mypy through pylama because of:
+# https://github.com/klen/pylama/issues/163
+linters = "eradicate,mccabe,pycodestyle,pydocstyle,pyflakes,pylint,radon,vulture,isort"
skip = "docs/*"
[tool.pylama.linter.pydocstyle]
ignore = "D100,D101,D102,D103,D104,D107,D203,D213,D410,D411,D406,D413,D407"
+[tool.pylama.linter.mypy]
+cache_dir = "build/.mypy_cache"
+strict = "True"
+files = "jsonype,tests"
+
[tool.pydocstyle]
ignore = "D100,D101,D102,D103,D104,D107,D203,D213,D410,D411,D406,D413,D407"
[tool.mypy]
cache_dir = "build/.mypy_cache"
strict = "True"
-files = "jsont,tests"
+files = "jsonype,tests"
[tool.isort]
line_length = 100
-src_paths = ["jsont", "tests"]
+src_paths = ["jsonype", "tests"]
[tool.pylint."messages control"]
disable = ["invalid-name", "missing-module-docstring", "missing-function-docstring", "missing-class-docstring"]
@@ -55,7 +61,7 @@ cc_min = "C"
[tool.vulture]
min_confidence = 61
-paths = ["jsont", "tests"]
+paths = ["jsonype", "tests"]
[tool.ruff]
line-length = 100
diff --git a/tests/jsont/__init__.py b/tests/jsonype/__init__.py
similarity index 100%
rename from tests/jsont/__init__.py
rename to tests/jsonype/__init__.py
diff --git a/tests/jsont/test_typed_json.py b/tests/jsonype/test_typed_json.py
similarity index 95%
rename from tests/jsont/test_typed_json.py
rename to tests/jsonype/test_typed_json.py
index ffde401..1cbe13b 100644
--- a/tests/jsont/test_typed_json.py
+++ b/tests/jsonype/test_typed_json.py
@@ -6,9 +6,9 @@
from typing import (Any, Callable, Iterable, List, Mapping, Optional, Sequence, Tuple, TypeAlias,
TypedDict, TypeVar, Union, cast)
-from pytest import mark
+from pytest import mark, raises
-from jsont import TypedJson
+from jsonype import FromJsonConversionError, TypedJson
_T = TypeVar("_T")
@@ -19,7 +19,7 @@
strict_typed_json = TypedJson(strict=True)
-@mark.parametrize( # type: ignore [misc]
+@mark.parametrize(
"simple_obj",
[0, -1, 2, 0.0, 1.0, -2.0, True, False, "Hello", "", None],
)
@@ -27,14 +27,14 @@ def test_simple(simple_obj: Any) -> None:
assert_can_convert_from_to_json(simple_obj, type(simple_obj))
-@mark.parametrize("simple_obj", [0, "Hello", None]) # type: ignore [misc]
+@mark.parametrize("simple_obj", [0, "Hello", None])
def test_simple_with_union_type(simple_obj: Union[int, str, None]) -> None:
# Union is a type-special-form so cast to type explicitly
assert_can_convert_from_to_json(
simple_obj, cast(type[Optional[Union[int, str]]], Optional[Union[int, str]]))
-@mark.parametrize( # type: ignore [misc]
+@mark.parametrize(
("li", "ty"),
[
([0, -1, 2], int),
@@ -48,7 +48,7 @@ def test_homogeneous_list(li: Sequence[Any], ty: TypeAlias) -> None:
assert_can_convert_from_to_json(li, list[ty])
-@mark.parametrize("li", [[1], ["Hi"]]) # type: ignore [misc]
+@mark.parametrize("li", [[1], ["Hi"]])
def test_untyped_list(li: Sequence[Any]) -> None:
assert_can_convert_from_to_json(li, list)
@@ -67,7 +67,7 @@ def test_empty_tuple() -> None:
assert_can_convert_from_to_json((), tuple[()])
-@mark.parametrize( # type: ignore [misc]
+@mark.parametrize(
("m", "ty"),
[({"k1": 1}, int), ({"k1": True, "k2": False}, bool), ({"k1": None}, NoneType)],
)
@@ -97,6 +97,16 @@ class Map(TypedDict):
assert_can_convert_from_to_json({"k1": 1., "k2": 2}, Map)
+def test_typed_dict_fail_if_key_missing() -> None:
+ class Map(TypedDict):
+ k1: float
+ k2: int
+
+ with raises(FromJsonConversionError) as exc_info:
+ typed_json.from_json({"k1": 1.}, Map)
+ assert "k2" in str(exc_info.value)
+
+
def test_random_objects() -> None:
for _ in range(500):
assert_can_convert_from_to_json(*(_random_typed_object(8)))