mappr
Easily convert between arbitrary types.
Goals
mappr's goal is to make it as easy as possible to define custom converters between arbitrary types in python. It does not concern itself with validation or coercion. It only provides a simple way to define a mapping between two types + some extra functionality to automatically generate converters for simple cases (off by default).
Links
Installation
uv
pip
poetry
If you'd like to setup the project locally for development, see Contribute for more details.
Quick Example
See the Documentation for more examples.
Assume we have a following types in our app. They represent pretty much the same thing, but different views of it.
from dataclasses import dataclass
import mappr
@dataclass
class User:
username: str
first_name: str
last_name: str
email: str
class Person:
def __init__(self, nick, name, email):
self.nick = nick
self.name = name
self.email = email
# Since we're not using any base class supported out of the box by mappr
# we need to define a field_iterator for our Person class. mappr
# comes bundled with ones for dataclasses, pydantic (ptional) and
# SQLAlchemy (optional). field_iterators are very easy to implement so more
# will follow. Of course you can also use field iterators defined by 3rd
# party packages. Just needs to be imported prior to converting any objects.
@mappr.field_iterator(test=lambda target_cls: isinstance(target_cls, Person))
def iter_person(model_cls: Type) -> mappr.FieldIterator:
yield from ['nick', 'name', 'email']
# register User -> Person converter ('email' matches by name so can be skipped)
mappr.register(User, Person, mapping=dict(
nick=lambda obj, name: obj.username,
name=lambda obj, name: f"{obj.first_name} {obj.last_name}",
))
# register Person -> User converter
mappr.register(User, Person, mapping=dict(
username=lambda obj, name: obj.nick,
first_name=lambda obj, name: obj.name and obj.name.split()[0],
last_name=lambda obj, name: obj.name and obj.name.split()[-1],
))
user = User(
username='john.doe',
first_name='John',
last_name='Doe',
email='john.doe@example.com',
)
person = mappr.convert(Person, user)
assert person == Person(
name='John Doe',
email='john.doe@example.com',
nick='john.doe',
)
user2 = mappr.Convert(User, person)
assert user2 == user