python-attrs / attrs

Python Classes Without Boilerplate
https://www.attrs.org/
MIT License
5.31k stars 374 forks source link

How to derive multiple fields from one complex input dict? #1262

Closed 4l1fe closed 8 months ago

4l1fe commented 8 months ago

I'm writing the class with fields that takes and convert their values from the same input subdict


def _get_contact(cont_type, seq: list[dict], max_length=13) -> Optional[str]:
    filtered = [d for d in seq
                if d.get('type', {}).get('id') == cont_type]
    if not filtered:
        return None

    contact = filtered[0]
    if cont_type == 'cell':
        return contact['value']['number']

    if cont_type == 'email':
        return contact['value']

get_cell_phone = partial(_get_contact, 'cell')
get_email = partial(_get_contact, 'email')

@define
class Info:   
    contact_phone = field(alias='contact', converter=get_cell_phone)
    contact_email = field(alias='contact', converter=get_email)

The input subdict

{
 'contact': [{'comment': 'comment',
   'need_verification': True,
   'preferred': False,
   'type': {'id': 'cell', 'name': 'Mobile'},
   'value': {'city': '11',
    'country': '66',
    'formatted': '+66 (111) 808-12-51',
    'number': '111111'},
   'verified': False},
  {'preferred': True,
   'type': {'id': 'email', 'name': 'Email'},
   'value': 'my-email@example.com'}]
}

I've already figured out that alias logic is quite straight and wrong to take for the case

import Info

SyntaxError: duplicate argument 'contact' in function definition

How would i extract values for the fields from one subdict?

Info(**subdict)

Or should i make an extension something like?

contact_phone = field(from_field='contact')
4l1fe commented 8 months ago

The answer is Derived Attributes