Last active
April 6, 2024 11:37
-
-
Save rnag/ddd678b42af0ed97193c8b763d216d58 to your computer and use it in GitHub Desktop.
field/key remapping
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dataclasses import dataclass | |
from .remappers import Alias, remapper # see module `remappers.py` below | |
@dataclass | |
class DiveSpot(metaclass=remapper): | |
id: str = Alias('_id') | |
name: str = Alias('divespot') | |
# stub to satisfy external linters and type checkers | |
def __init__(self, **kwargs): ... | |
ds = DiveSpot() | |
print(ds) # DiveSpot(id=None, name=None) | |
data = {'_id': '5719fdf6edf5136d37aaf562', 'divespot': 'The Tugs', 'divesite': 'Fathom Five National Park', 'region': 'Ontario', 'country': 'Canada'} | |
ds = DiveSpot(**data) | |
print(ds) # DiveSpot(id='5719fdf6edf5136d37aaf562', name='The Tugs') | |
ds = DiveSpot(id='test', name='my name') | |
print(ds) # DiveSpot(id='test', name='my name') | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dataclasses import _create_fn | |
def remapper(name, bases, cls_dict): | |
def __init__(self, **kwargs): | |
cls = self.__class__ | |
# create a sentinel "missing" type, as `dataclasses` also does | |
class _MISSING_TYPE: | |
... | |
lines = ['_get = kwargs.get'] | |
lines.extend(f'r = _get("{other_key}", _MISSING); ' | |
f'self.{attr} = _get("{attr}") if r is _MISSING else r' | |
for other_key, attr in cls.__remapping__.items()) | |
init_fn = cls.__init__ = _create_fn('__init__', ('self', '**kwargs'), lines, | |
locals={'_MISSING': _MISSING_TYPE()}) | |
return init_fn(self, **kwargs) | |
cls_dict.update( | |
__init__=__init__, | |
__remapping__={}, | |
) | |
cls = type(name, bases, cls_dict) | |
return cls | |
class Alias: | |
__slots__ = ('_other_name', ) | |
def __init__(self, other_name: str): | |
self._other_name = other_name | |
def __set_name__(self, owner, name): | |
owner.__remapping__[self._other_name] = name |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment