======
Svarog
======
.. image:: https://img.shields.io/pypi/v/svarog.svg
:target: https://pypi.python.org/pypi/svarog
.. image:: https://github.com/dswistowski/svarog/actions/workflows/tests.yml/badge.svg
:target: https://github.com/dswistowski/svarog/actions/workflows/tests.yml
.. image:: https://readthedocs.org/projects/svarog/badge/?version=latest
:target: https://svarog.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
Svarog allow to create object from non typed data. All it need is annotated `__init__` method:
>>> from svarog import forge
... class A:
... def __init__(self, a: int, b: str):
... self._a = a
... self._b = b
... def __repr__(self):
... return f'A(a={self._a}, b="{self._b}")'
>>> forge(A, {"a": 1, "b": "3"})
A(a=1, b="3")
More complicated types as `Sequence`, `Mapping`, `Optional` are possible
>>> class A:
... def __init__(self, b: Sequence[int]):
... self._b = b
... def __repr__(self):
... return f'A(b={self._b})'
>>> forge(A, {"b": "3213"})
A(b=[3, 2, 1, 3])
You can use forward refs:
>>> class WithRef:
... def __init__(self, child: Optional['WithRef']):
... self._child = child
... def __repr__(self):
... return f"WithRef({self._child!r})"
>>> forge(WithRef(WithRef(WithRef())))
WithRef(WithRef(WithRef(None)))
Objects are forged recursively:
>>> @dataclass
... class A:
... b: 'B'
... c: 'C'
... @dataclass
... class B:
... number: int
... @dataclass
... class C:
... string: str
>>> forge(A, {'b': {'number': 42}, 'c': {'string': 'the-string'}})
A(b=B(number=42), c=C(string='the-string'))
You can register own forge for your classes:
>>> class FooType(Enum):
... LOREM = "lorem"
... IPSUM = "ipsum"
...
... class FooParams:
... types: ClassVar[Mapping[FooType, "FooParams"]] = {}
... def __init_subclass__(cls, type: FooType):
... cls.types[type] = cls
...
... @classmethod
... def for_type(cls, type):
... return cls.types[type]
...
... @dataclass
... class LoremFooParams(FooParams, type=FooType.LOREM):
... lorem: str
...
... @dataclass
... class IpsumFooParams(FooParams, type=FooType.IPSUM):
... ipsum: int
...
... @dataclass
... class Foo:
... type: FooType
... params: FooParams
...
... @classmethod
... def forge(cls, _, data, forge):
... foo_type = forge(FooType, data["type"])
... return Foo(
... type=forge(FooType, foo_type),
... params=forge(FooParams.for_type(foo_type), data["params"])
... )
...
>>> register_forge(Foo, Foo.forge)
>>> forge(Foo, {"type": "lorem", "params": {"lorem": "foo-bar"}})
Foo(type=<FooType.LOREM: 'lorem'>, params=LoremFooParams(lorem='foo-bar'))
>>> forge(Foo, {"type": "ipsum", "params": {"ipsum": 42}})
Foo(type=<FooType.IPSUM: 'ipsum'>, params=IpsumFooParams(ipsum=42))
Support for CamelCase to snake_case convertion:
>>> class Snake:
... lorem_ipsum: int
>>> forge = Svarog(snake_case=True).forge
>>> forge(Snake, {"LoremIpsum": 42})
Snake(lorem_ipsum=42)
* Free software: MIT license
* Documentation: https://svarog.readthedocs.io.
Features
--------
* Converts unstructured data into structured recursively
* Works with `dataclasses`
* Works with `Sequence`, `Mapping`, `Optional`
* Special conventers for types can be registered with
Credits
-------
Some parts of this code, and concept borrowed from cattrs_ project
.. _Cattrs: https://github.com/Tinche/cattrs
This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
Raw data
{
"_id": null,
"home_page": "https://gitlab.com/dswistowski/svarog/",
"name": "svarog",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "svarog,json,structure,typing",
"author": "Damian \u015awistowski",
"author_email": "damian@swistowski.org",
"download_url": "https://files.pythonhosted.org/packages/be/6a/accd525bec44a94b1ecb548e9895781b84a77b94b144fe9b65351f51380e/svarog-0.3.1.tar.gz",
"platform": null,
"description": "======\nSvarog\n======\n\n\n.. image:: https://img.shields.io/pypi/v/svarog.svg\n :target: https://pypi.python.org/pypi/svarog\n\n.. image:: https://github.com/dswistowski/svarog/actions/workflows/tests.yml/badge.svg\n :target: https://github.com/dswistowski/svarog/actions/workflows/tests.yml\n\n.. image:: https://readthedocs.org/projects/svarog/badge/?version=latest\n :target: https://svarog.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n\n\n\nSvarog allow to create object from non typed data. All it need is annotated `__init__` method:\n\n\n>>> from svarog import forge\n... class A:\n... def __init__(self, a: int, b: str):\n... self._a = a\n... self._b = b\n... def __repr__(self):\n... return f'A(a={self._a}, b=\"{self._b}\")'\n>>> forge(A, {\"a\": 1, \"b\": \"3\"})\nA(a=1, b=\"3\")\n\n\nMore complicated types as `Sequence`, `Mapping`, `Optional` are possible\n\n>>> class A:\n... def __init__(self, b: Sequence[int]):\n... self._b = b\n... def __repr__(self):\n... return f'A(b={self._b})'\n>>> forge(A, {\"b\": \"3213\"})\nA(b=[3, 2, 1, 3])\n\nYou can use forward refs:\n\n>>> class WithRef:\n... def __init__(self, child: Optional['WithRef']):\n... self._child = child\n... def __repr__(self):\n... return f\"WithRef({self._child!r})\"\n>>> forge(WithRef(WithRef(WithRef())))\nWithRef(WithRef(WithRef(None)))\n\n\nObjects are forged recursively:\n\n\n>>> @dataclass\n... class A:\n... b: 'B'\n... c: 'C'\n... @dataclass\n... class B:\n... number: int\n... @dataclass\n... class C:\n... string: str\n>>> forge(A, {'b': {'number': 42}, 'c': {'string': 'the-string'}})\nA(b=B(number=42), c=C(string='the-string'))\n\n\nYou can register own forge for your classes:\n\n>>> class FooType(Enum):\n... LOREM = \"lorem\"\n... IPSUM = \"ipsum\"\n...\n... class FooParams:\n... types: ClassVar[Mapping[FooType, \"FooParams\"]] = {}\n... def __init_subclass__(cls, type: FooType):\n... cls.types[type] = cls\n...\n... @classmethod\n... def for_type(cls, type):\n... return cls.types[type]\n...\n... @dataclass\n... class LoremFooParams(FooParams, type=FooType.LOREM):\n... lorem: str\n...\n... @dataclass\n... class IpsumFooParams(FooParams, type=FooType.IPSUM):\n... ipsum: int\n...\n... @dataclass\n... class Foo:\n... type: FooType\n... params: FooParams\n...\n... @classmethod\n... def forge(cls, _, data, forge):\n... foo_type = forge(FooType, data[\"type\"])\n... return Foo(\n... type=forge(FooType, foo_type),\n... params=forge(FooParams.for_type(foo_type), data[\"params\"])\n... )\n...\n>>> register_forge(Foo, Foo.forge)\n>>> forge(Foo, {\"type\": \"lorem\", \"params\": {\"lorem\": \"foo-bar\"}})\nFoo(type=<FooType.LOREM: 'lorem'>, params=LoremFooParams(lorem='foo-bar'))\n\n>>> forge(Foo, {\"type\": \"ipsum\", \"params\": {\"ipsum\": 42}})\nFoo(type=<FooType.IPSUM: 'ipsum'>, params=IpsumFooParams(ipsum=42))\n\n\nSupport for CamelCase to snake_case convertion:\n\n>>> class Snake:\n... lorem_ipsum: int\n>>> forge = Svarog(snake_case=True).forge\n>>> forge(Snake, {\"LoremIpsum\": 42})\nSnake(lorem_ipsum=42)\n\n* Free software: MIT license\n* Documentation: https://svarog.readthedocs.io.\n\n\nFeatures\n--------\n\n* Converts unstructured data into structured recursively\n\n * Works with `dataclasses`\n * Works with `Sequence`, `Mapping`, `Optional`\n * Special conventers for types can be registered with\n\nCredits\n-------\n\nSome parts of this code, and concept borrowed from cattrs_ project\n\n.. _Cattrs: https://github.com/Tinche/cattrs\n\nThis package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.\n\n.. _Cookiecutter: https://github.com/audreyr/cookiecutter\n.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Svarog allow to create object from non typed data",
"version": "0.3.1",
"split_keywords": [
"svarog",
"json",
"structure",
"typing"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d7f4ac89eb7350ace43a564143f14aed8fdafa526831be80b9a8b51193647727",
"md5": "ffd65cf64f3cf821389874c18684a4b3",
"sha256": "c67598593b3bf91f1ae1a8e0120b66ca0114c46c53e3c1d86d0f83ea71ccfd45"
},
"downloads": -1,
"filename": "svarog-0.3.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ffd65cf64f3cf821389874c18684a4b3",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 9185,
"upload_time": "2023-02-02T14:52:57",
"upload_time_iso_8601": "2023-02-02T14:52:57.039287Z",
"url": "https://files.pythonhosted.org/packages/d7/f4/ac89eb7350ace43a564143f14aed8fdafa526831be80b9a8b51193647727/svarog-0.3.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "be6aaccd525bec44a94b1ecb548e9895781b84a77b94b144fe9b65351f51380e",
"md5": "f3aa22a551c2f998669318f6d6b3bb26",
"sha256": "81de509f0c4994546b42a4bbf0ac49440ed81914f2fa2257e71b8fb3c7d09576"
},
"downloads": -1,
"filename": "svarog-0.3.1.tar.gz",
"has_sig": false,
"md5_digest": "f3aa22a551c2f998669318f6d6b3bb26",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 8795,
"upload_time": "2023-02-02T14:52:58",
"upload_time_iso_8601": "2023-02-02T14:52:58.575892Z",
"url": "https://files.pythonhosted.org/packages/be/6a/accd525bec44a94b1ecb548e9895781b84a77b94b144fe9b65351f51380e/svarog-0.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-02-02 14:52:58",
"github": false,
"gitlab": true,
"bitbucket": false,
"gitlab_user": "dswistowski",
"gitlab_project": "svarog",
"lcname": "svarog"
}