Use dynamic defaults for Python's attr package when creating model

54 views Asked by At

I am working with attr to create a meta-model (showing a subset to give the idea),


import abc, attr
from attrs import validators
from delensalot.lerepi.core.validator import model

@attr.s
class DLENSALOT_Data:
    """A root model element of the Dlensalot formalism.

    Attributes:
        beam: 
    """

    beam = attr.ib(default=None)



@attr.s
class DLENSALOT_Model:
    """A root model element of the Dlensalot formalism.

    Attributes:
        data: 
    """
    
    data  = attr.ib(default=DLENSALOT_Data(), validator=model.data)

A model, DLENSALOT_Model() then defaults to it's default values as expected.

I would like to have a different default-configuration depending on the user choice, in the sense of the following:

DLENSALOT_Model(defaultsto='A').data.beam
>>> <beam value for default A>
DLENSALOT_Model(defaultsto='B').data.beam
>>> <beam value for default B>

In other words, I'd like to have a way of configuring my meta-model. I am thinking of something like (which doesn't work but I hope it gives the idea),


import abc, attr
from attrs import validators
from delensalot.lerepi.core.validator import model

default_dict = {
    'A' : ...,
    'B': ...
}


@attr.s
class DLENSALOT_Data:
    """A root model element of the Dlensalot formalism.

    Attributes:
        beam: 
    """
    defaultsto = attr.ib()
    beam = attr.ib(default=default_dict[defaultsto]['data']['beam'])



@attr.s
class DLENSALOT_Model(DLENSALOT_Concept):
    """A root model element of the Dlensalot formalism.

    Attributes:
        data: 
    """
    defaultsto = attr.ib()
    data  = attr.ib(default=DLENSALOT_Data(defaultsto=defaultsto), validator=model.data)

Any suggestions appreciated

I've tried attr.Factory(lambda self: .., takes_self = True), decorators to post-set defaults, and it's just not working for me..

1

There are 1 answers

1
Kuroneko On

You can use __attrs_post_init__

import attr

default_dict = {
    'A': {'data': {'beam': 'yummy'}},
    'B': {'data': {'beam': 'spicy'}}
}


@attr.s
class DLENSALOT_Data():
    """A root model element of the Dlensalot formalism.

    Attributes:
        data: 
    """
    defaultsto = attr.ib()
    data = attr.ib(default=None, init=False)

    def __attrs_post_init__(self):
        self.data = default_dict[self.defaultsto]['data']['beam']


print(DLENSALOT_Data(defaultsto='A').data)

Output:

yummy