# advanced-automapper
Object automapper based on type hints.
## Installation
Using pip:
```bash
pip install advanced-automapper
```
Using poetry
```bash
poetry add advanced-automapper
```
## Get started
It is important to note that PyAutomapper requieres that both origin and destination classes have have type hints to define the type for every field.
Let's say you have a Pydantic model called Person, and you need to map it to a SqlAlchmey model to save it to a database:
```python
from enum import Enum
from typing import Dict, List, Optional
from pydantic import BaseModel
from sqlalchemy import Enum as SqlEnum
from sqlalchemy import ForeignKey, Integer, String
from sqlalchemy.orm import Mapped, declarative_base, mapped_column, relationship
class GenderPydantic(Enum):
MALE = 1
FEMALE = 2
FURRY = 3
OTHER = 4
class PersonPydantic(BaseModel):
name: str
age: int
gender: GenderPydantic
Base = declarative_base()
class GenderAlchemy(Enum):
MALE = 1
FEMALE = 2
FURRY = 3
OTHER = 4
class PersonAlchemy(Base):
__tablename__ = "persons"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String(50), nullable=False)
age: Mapped[int] = mapped_column(Integer)
gender: Mapped[GenderAlchemy] = mapped_column(
SqlEnum(GenderAlchemy), nullable=False
)
def __repr__(self):
return f"<PersonAlchemy(name='{self.name}', age={self.age}, gender='{self.gender}')>"
# Create a person
person = PersonPydantic(name="John", age=25, gender=GenderPydantic.MALE)
```
To create a PersonAlchemy object:
```python
from automapper import mapper
mapped_person = mapper.map(person, PersonAlchemy)
print(mapped_person)
```
## Add custom mapping
PyAutomapper allows to map fields with different names between them using custom mapping.
Imagine that, in the previous SqlAlchemy class the gender field is called "genero":
```python
from enum import Enum
from typing import Dict, List, Optional
from pydantic import BaseModel
from sqlalchemy import Enum as SqlEnum
from sqlalchemy import ForeignKey, Integer, String
from sqlalchemy.orm import Mapped, declarative_base, mapped_column, relationship
class GenderPydantic(Enum):
MALE = 1
FEMALE = 2
FURRY = 3
OTHER = 4
class PersonPydantic(BaseModel):
name: str
age: int
gender: GenderPydantic
Base = declarative_base()
class GenderAlchemy(Enum):
MALE = 1
FEMALE = 2
FURRY = 3
OTHER = 4
class PersonAlchemy(Base):
__tablename__ = "persons"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String(50), nullable=False)
age: Mapped[int] = mapped_column(Integer)
# Let's rename this field
genero: Mapped[GenderAlchemy] = mapped_column(
SqlEnum(GenderAlchemy), nullable=False
)
def __repr__(self):
return f"<PersonAlchemy(name='{self.name}', age={self.age}, gender='{self.gender}')>"
# Create a person
person = PersonPydantic(name="John", age=25, gender=GenderPydantic.MALE)
```
The solution is to add a cutom mapping in the Mapper relating the field "gender", in the source class, with "genero" in the target.
```python
from automapper import mapper
mapper.add_custom_mapping(PersonPydantic, "gender", "genero")
mapped_person = mapper.map(person, PersonAlchemy)
print(mapped_person)
```
## More examples
The tests folder in the code repository contains examples of mapping between different python objects.
Raw data
{
"_id": null,
"home_page": "https://impalah.github.io/advanced-automapper/",
"name": "advanced-automapper",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "mapper, typehints, python",
"author": "impalah",
"author_email": "impalah@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/64/39/4cd923607ce0c1cded90b7a1591539aa37bf949731198bbc91065b6a5067/advanced_automapper-0.1.15.tar.gz",
"platform": null,
"description": "# advanced-automapper\n\nObject automapper based on type hints.\n\n## Installation\n\nUsing pip:\n\n```bash\npip install advanced-automapper\n```\n\nUsing poetry\n\n```bash\npoetry add advanced-automapper\n```\n\n## Get started\n\nIt is important to note that PyAutomapper requieres that both origin and destination classes have have type hints to define the type for every field.\n\nLet's say you have a Pydantic model called Person, and you need to map it to a SqlAlchmey model to save it to a database:\n\n```python\n\nfrom enum import Enum\nfrom typing import Dict, List, Optional\n\nfrom pydantic import BaseModel\n\nfrom sqlalchemy import Enum as SqlEnum\nfrom sqlalchemy import ForeignKey, Integer, String\nfrom sqlalchemy.orm import Mapped, declarative_base, mapped_column, relationship\n\n\nclass GenderPydantic(Enum):\n MALE = 1\n FEMALE = 2\n FURRY = 3\n OTHER = 4\n\nclass PersonPydantic(BaseModel):\n name: str\n age: int\n gender: GenderPydantic\n\n\n\nBase = declarative_base()\n\n\nclass GenderAlchemy(Enum):\n MALE = 1\n FEMALE = 2\n FURRY = 3\n OTHER = 4\n\nclass PersonAlchemy(Base):\n __tablename__ = \"persons\"\n id: Mapped[int] = mapped_column(Integer, primary_key=True)\n name: Mapped[str] = mapped_column(String(50), nullable=False)\n age: Mapped[int] = mapped_column(Integer)\n gender: Mapped[GenderAlchemy] = mapped_column(\n SqlEnum(GenderAlchemy), nullable=False\n )\n\n def __repr__(self):\n return f\"<PersonAlchemy(name='{self.name}', age={self.age}, gender='{self.gender}')>\"\n\n# Create a person\nperson = PersonPydantic(name=\"John\", age=25, gender=GenderPydantic.MALE)\n\n\n```\n\nTo create a PersonAlchemy object:\n\n```python\nfrom automapper import mapper\n\nmapped_person = mapper.map(person, PersonAlchemy)\n\nprint(mapped_person)\n\n```\n\n## Add custom mapping\n\nPyAutomapper allows to map fields with different names between them using custom mapping.\n\nImagine that, in the previous SqlAlchemy class the gender field is called \"genero\":\n\n```python\n\nfrom enum import Enum\nfrom typing import Dict, List, Optional\n\nfrom pydantic import BaseModel\n\nfrom sqlalchemy import Enum as SqlEnum\nfrom sqlalchemy import ForeignKey, Integer, String\nfrom sqlalchemy.orm import Mapped, declarative_base, mapped_column, relationship\n\n\nclass GenderPydantic(Enum):\n MALE = 1\n FEMALE = 2\n FURRY = 3\n OTHER = 4\n\nclass PersonPydantic(BaseModel):\n name: str\n age: int\n gender: GenderPydantic\n\n\n\nBase = declarative_base()\n\n\nclass GenderAlchemy(Enum):\n MALE = 1\n FEMALE = 2\n FURRY = 3\n OTHER = 4\n\nclass PersonAlchemy(Base):\n __tablename__ = \"persons\"\n id: Mapped[int] = mapped_column(Integer, primary_key=True)\n name: Mapped[str] = mapped_column(String(50), nullable=False)\n age: Mapped[int] = mapped_column(Integer)\n # Let's rename this field\n genero: Mapped[GenderAlchemy] = mapped_column(\n SqlEnum(GenderAlchemy), nullable=False\n )\n\n def __repr__(self):\n return f\"<PersonAlchemy(name='{self.name}', age={self.age}, gender='{self.gender}')>\"\n\n# Create a person\nperson = PersonPydantic(name=\"John\", age=25, gender=GenderPydantic.MALE)\n\n```\n\nThe solution is to add a cutom mapping in the Mapper relating the field \"gender\", in the source class, with \"genero\" in the target.\n\n```python\n\nfrom automapper import mapper\n\nmapper.add_custom_mapping(PersonPydantic, \"gender\", \"genero\")\n\nmapped_person = mapper.map(person, PersonAlchemy)\n\nprint(mapped_person)\n\n```\n\n## More examples\n\nThe tests folder in the code repository contains examples of mapping between different python objects.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Object mapper based on type hints",
"version": "0.1.15",
"project_urls": {
"Documentation": "https://impalah.github.io/advanced-automapper/",
"Homepage": "https://impalah.github.io/advanced-automapper/",
"Repository": "https://github.com/impalah/advanced-automapper",
"Source": "https://github.com/impalah/advanced-automapper"
},
"split_keywords": [
"mapper",
" typehints",
" python"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "748d57d06f0895f785320e5d158092c4974fb500c3f836b0698fcf59badbfab6",
"md5": "e74e9c8efaeba04cd7f34c5570780322",
"sha256": "9d289db08fc5d9ceb59783f62e5c9125abaec9e5c3883fea4ee329dacf6ce9c7"
},
"downloads": -1,
"filename": "advanced_automapper-0.1.15-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e74e9c8efaeba04cd7f34c5570780322",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 7863,
"upload_time": "2024-09-21T18:32:48",
"upload_time_iso_8601": "2024-09-21T18:32:48.768164Z",
"url": "https://files.pythonhosted.org/packages/74/8d/57d06f0895f785320e5d158092c4974fb500c3f836b0698fcf59badbfab6/advanced_automapper-0.1.15-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "64394cd923607ce0c1cded90b7a1591539aa37bf949731198bbc91065b6a5067",
"md5": "795cb363ff4dd868fbf3f3a37dba82e1",
"sha256": "feb7d085aab547ed146896d5b724a05507020a615ce3c165a340af8849560a9d"
},
"downloads": -1,
"filename": "advanced_automapper-0.1.15.tar.gz",
"has_sig": false,
"md5_digest": "795cb363ff4dd868fbf3f3a37dba82e1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 5782,
"upload_time": "2024-09-21T18:32:50",
"upload_time_iso_8601": "2024-09-21T18:32:50.277496Z",
"url": "https://files.pythonhosted.org/packages/64/39/4cd923607ce0c1cded90b7a1591539aa37bf949731198bbc91065b6a5067/advanced_automapper-0.1.15.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-21 18:32:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "impalah",
"github_project": "advanced-automapper",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "advanced-automapper"
}