dataclass-mapper
================
|pypi| |support| |licence| |readthedocs| |build| |coverage|
.. |pypi| image:: https://img.shields.io/pypi/v/dataclass-mapper.svg?style=flat-square
:target: https://pypi.org/project/dataclass-mapper/
:alt: pypi version
.. |support| image:: https://img.shields.io/pypi/pyversions/dataclass-mapper.svg?style=flat-square
:target: https://pypi.org/project/dataclass-mapper/
:alt: supported Python version
.. |build| image:: https://github.com/dataclass-mapper/dataclass-mapper/actions/workflows/test.yml/badge.svg
:target: https://github.com/dataclass-mapper/dataclass-mapper/actions
:alt: build status
.. |coverage| image:: https://codecov.io/gh/dataclass-mapper/dataclass-mapper/branch/main/graphs/badge.svg?branch=main
:target: https://codecov.io/gh/dataclass-mapper/dataclass-mapper?branch=main
:alt: Code coverage
.. |licence| image:: https://img.shields.io/pypi/l/dataclass-mapper.svg?style=flat-square
:target: https://pypi.org/project/dataclass-mapper/
:alt: licence
.. |readthedocs| image:: https://img.shields.io/readthedocs/dataclass-mapper/latest.svg?style=flat-square&label=Read%20the%20Docs
:alt: Read the documentation at https://dataclass-mapper.readthedocs.io/en/latest/
:target: https://dataclass-mapper.readthedocs.io/en/latest/
Writing mapper methods between two similar dataclasses is boring, need to be actively maintained and are error-prone.
Much better to let this library auto-generate them for you.
The focus of this library is:
- **Concise and easy syntax:**
- using it has to be a lot less overhead than writing the mappers by hand
- trivial mappings should not require code
- identical syntax for mapping between dataclasses and Pydantic models
- **Safety:**
- using this library must give equal or more type safety than writing the mappers by hand
- the types between source and target classes must matches (including optional checks)
- all target fields must be actually initialized
- mappings cannot reference non-existing fields
- in case of an error a clean exception must be raised
- **Performance:**
- mapping an object using this library must be the same speed than mapping using a custom mapper function
- the type checks shouldn't slow down the program
- because of the first two points, all type checks and the generation of the mapper functions happen during the definition of the classes
Motivation
----------
A couple of example usecases, that show why this library might be useful.
* Given an API with multiple, different interfaces (e.g. different API versions), that are all connected to a common algorithm with some common datamodel.
All the different API models needs to be mapped to the common datamodel, and afterwards mapped back to the API model.
* Given an API that has a ``POST`` and a ``GET`` endpoint.
Both models (``POST`` request body model and ``GET`` response body model) are almost the same, but there are some minor differences.
E.g. response model has an additional ``id`` parameter.
You need a way of mapping the request model to a response model.
Installation
------------
``dataclass-mapper`` can be installed using:
.. code-block:: bash
pip install dataclass-mapper
# or for Pydantic support
pip install 'dataclass-mapper[pydantic]'
Example
-------
We have the following target data structure, a class called ``Person``.
.. code-block:: python
>>> from dataclasses import dataclass
>>> @dataclass
... class Person:
... first_name: str
... second_name: str
... age: int
We want to have a mapper from the source data structure, a class called ``ContactInfo``.
Notice that the attribute ``second_name`` of ``Person`` is called ``surname`` in ``ContactInfo``.
Other than that, all the attribute names are the same.
Instead of writing a mapper function by hand, you can let it autogenerate one using this library:
.. code-block:: python
>>> from dataclass_mapper import map_to, mapper
>>>
>>> @mapper(Person, {"second_name": "surname"})
... @dataclass
... class ContactInfo:
... first_name: str
... surname: str
... age: int
>>>
>>> contact = ContactInfo(first_name="Henry", surname="Kaye", age=42)
>>> map_to(contact, Person)
Person(first_name='Henry', second_name='Kaye', age=42)
The ``dataclass-mapper`` library autogenerated a mapper, that can be used with the ``map_to`` function.
All we had to specify was the name of the target class, and optionally specify which fields map to which other fields.
Notice that we only had to specify that the ``second_name`` field has to be mapped to ``surname``,
all other fields were mapped automatically because the field names didn't change.
And the ``dataclass-mapper`` library will perform a lot of checks around this mapping.
It will check if the data types match, if some fields would be left uninitialized, etc.
Features
--------
The current version has support for:
* Python's ``dataclass`` (with recursive models, custom initializers, optional types, extra-context, ...): see `Supported features <https://dataclass-mapper.readthedocs.io/en/latest/features.html>`_ for the full list and examples
* Mappings between Enum classes: see `Enum mappings <https://dataclass-mapper.readthedocs.io/en/latest/enums.html>`_
* Pydantic models: see `Pydantic support <https://dataclass-mapper.readthedocs.io/en/latest/pydantic.html>`_
* Type/Value checks: see `Type safety <https://dataclass-mapper.readthedocs.io/en/latest/type_safety.html>`_
Contributing
------------
See `CONTRIBUTING.rst <https://github.com/dataclass-mapper/dataclass-mapper/blob/main/CONTRIBUTING.rst>`_.
License
-------
The project is released under the `MIT license <https://github.com/dataclass-mapper/dataclass-mapper/blob/main/LICENSE.md>`_.
Raw data
{
"_id": null,
"home_page": "https://dataclass-mapper.readthedocs.io",
"name": "dataclass-mapper",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "dataclass,pydantic,python,automation",
"author": "Jakob Kogler",
"author_email": "jakob.kogler@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/b7/ba/8202e478dbfb6ab558254942648a6f141a082cf6f14089497018bc05c45f/dataclass_mapper-1.9.3.tar.gz",
"platform": null,
"description": "dataclass-mapper\n================\n\n|pypi| |support| |licence| |readthedocs| |build| |coverage|\n\n.. |pypi| image:: https://img.shields.io/pypi/v/dataclass-mapper.svg?style=flat-square\n :target: https://pypi.org/project/dataclass-mapper/\n :alt: pypi version\n\n.. |support| image:: https://img.shields.io/pypi/pyversions/dataclass-mapper.svg?style=flat-square\n :target: https://pypi.org/project/dataclass-mapper/\n :alt: supported Python version\n\n.. |build| image:: https://github.com/dataclass-mapper/dataclass-mapper/actions/workflows/test.yml/badge.svg\n :target: https://github.com/dataclass-mapper/dataclass-mapper/actions\n :alt: build status\n\n.. |coverage| image:: https://codecov.io/gh/dataclass-mapper/dataclass-mapper/branch/main/graphs/badge.svg?branch=main\n :target: https://codecov.io/gh/dataclass-mapper/dataclass-mapper?branch=main\n :alt: Code coverage\n\n.. |licence| image:: https://img.shields.io/pypi/l/dataclass-mapper.svg?style=flat-square\n :target: https://pypi.org/project/dataclass-mapper/\n :alt: licence\n\n.. |readthedocs| image:: https://img.shields.io/readthedocs/dataclass-mapper/latest.svg?style=flat-square&label=Read%20the%20Docs\n :alt: Read the documentation at https://dataclass-mapper.readthedocs.io/en/latest/\n :target: https://dataclass-mapper.readthedocs.io/en/latest/\n\nWriting mapper methods between two similar dataclasses is boring, need to be actively maintained and are error-prone.\nMuch better to let this library auto-generate them for you.\n\nThe focus of this library is:\n\n- **Concise and easy syntax:**\n \n - using it has to be a lot less overhead than writing the mappers by hand\n - trivial mappings should not require code\n - identical syntax for mapping between dataclasses and Pydantic models\n\n- **Safety:**\n\n - using this library must give equal or more type safety than writing the mappers by hand\n - the types between source and target classes must matches (including optional checks)\n - all target fields must be actually initialized\n - mappings cannot reference non-existing fields\n - in case of an error a clean exception must be raised\n\n- **Performance:**\n\n - mapping an object using this library must be the same speed than mapping using a custom mapper function\n - the type checks shouldn't slow down the program\n - because of the first two points, all type checks and the generation of the mapper functions happen during the definition of the classes\n\nMotivation\n----------\n\nA couple of example usecases, that show why this library might be useful.\n\n* Given an API with multiple, different interfaces (e.g. different API versions), that are all connected to a common algorithm with some common datamodel.\n All the different API models needs to be mapped to the common datamodel, and afterwards mapped back to the API model.\n* Given an API that has a ``POST`` and a ``GET`` endpoint.\n Both models (``POST`` request body model and ``GET`` response body model) are almost the same, but there are some minor differences.\n E.g. response model has an additional ``id`` parameter.\n You need a way of mapping the request model to a response model.\n\nInstallation\n------------\n\n``dataclass-mapper`` can be installed using:\n\n.. code-block:: bash\n\n pip install dataclass-mapper\n # or for Pydantic support\n pip install 'dataclass-mapper[pydantic]'\n\nExample\n-------\n\nWe have the following target data structure, a class called ``Person``.\n\n.. code-block:: python\n\n >>> from dataclasses import dataclass\n\n >>> @dataclass\n ... class Person:\n ... first_name: str\n ... second_name: str\n ... age: int\n\n\nWe want to have a mapper from the source data structure, a class called ``ContactInfo``.\nNotice that the attribute ``second_name`` of ``Person`` is called ``surname`` in ``ContactInfo``.\nOther than that, all the attribute names are the same.\n\nInstead of writing a mapper function by hand, you can let it autogenerate one using this library:\n\n.. code-block:: python\n\n >>> from dataclass_mapper import map_to, mapper\n >>>\n >>> @mapper(Person, {\"second_name\": \"surname\"})\n ... @dataclass\n ... class ContactInfo:\n ... first_name: str\n ... surname: str\n ... age: int\n >>>\n >>> contact = ContactInfo(first_name=\"Henry\", surname=\"Kaye\", age=42)\n >>> map_to(contact, Person)\n Person(first_name='Henry', second_name='Kaye', age=42)\n\nThe ``dataclass-mapper`` library autogenerated a mapper, that can be used with the ``map_to`` function.\nAll we had to specify was the name of the target class, and optionally specify which fields map to which other fields.\nNotice that we only had to specify that the ``second_name`` field has to be mapped to ``surname``,\nall other fields were mapped automatically because the field names didn't change.\n\nAnd the ``dataclass-mapper`` library will perform a lot of checks around this mapping.\nIt will check if the data types match, if some fields would be left uninitialized, etc.\n\nFeatures\n--------\n\nThe current version has support for:\n\n* Python's ``dataclass`` (with recursive models, custom initializers, optional types, extra-context, ...): see `Supported features <https://dataclass-mapper.readthedocs.io/en/latest/features.html>`_ for the full list and examples\n* Mappings between Enum classes: see `Enum mappings <https://dataclass-mapper.readthedocs.io/en/latest/enums.html>`_\n* Pydantic models: see `Pydantic support <https://dataclass-mapper.readthedocs.io/en/latest/pydantic.html>`_\n* Type/Value checks: see `Type safety <https://dataclass-mapper.readthedocs.io/en/latest/type_safety.html>`_\n\nContributing\n------------\n\nSee `CONTRIBUTING.rst <https://github.com/dataclass-mapper/dataclass-mapper/blob/main/CONTRIBUTING.rst>`_.\n\nLicense\n-------\n\nThe project is released under the `MIT license <https://github.com/dataclass-mapper/dataclass-mapper/blob/main/LICENSE.md>`_.\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Autogenerate mappings between dataclasses",
"version": "1.9.3",
"project_urls": {
"Documentation": "https://dataclass-mapper.readthedocs.io",
"Homepage": "https://dataclass-mapper.readthedocs.io",
"Repository": "https://github.com/dataclass-mapper/dataclass-mapper"
},
"split_keywords": [
"dataclass",
"pydantic",
"python",
"automation"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ab23d556ed541e8c26dcaec12184a29f6a839587be89f6d2e70792af276b0e28",
"md5": "1d6e0fcc709e174381b35781992636b6",
"sha256": "c47519b57743983cba799d94fbbbd47e2584c8f1002c8390069eedb88efadfb8"
},
"downloads": -1,
"filename": "dataclass_mapper-1.9.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1d6e0fcc709e174381b35781992636b6",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 22776,
"upload_time": "2024-02-10T16:57:12",
"upload_time_iso_8601": "2024-02-10T16:57:12.812585Z",
"url": "https://files.pythonhosted.org/packages/ab/23/d556ed541e8c26dcaec12184a29f6a839587be89f6d2e70792af276b0e28/dataclass_mapper-1.9.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b7ba8202e478dbfb6ab558254942648a6f141a082cf6f14089497018bc05c45f",
"md5": "d5e339cfcc9878c201f3ffaa2c31ce63",
"sha256": "d2ee99c68f474500ed258a03815449cda958dd08f961288481bdebd17c714a5d"
},
"downloads": -1,
"filename": "dataclass_mapper-1.9.3.tar.gz",
"has_sig": false,
"md5_digest": "d5e339cfcc9878c201f3ffaa2c31ce63",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 17688,
"upload_time": "2024-02-10T16:57:14",
"upload_time_iso_8601": "2024-02-10T16:57:14.563062Z",
"url": "https://files.pythonhosted.org/packages/b7/ba/8202e478dbfb6ab558254942648a6f141a082cf6f14089497018bc05c45f/dataclass_mapper-1.9.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-02-10 16:57:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "dataclass-mapper",
"github_project": "dataclass-mapper",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "dataclass-mapper"
}