Lazy initialization¶
If you want to create some class instance with filled required data during init,
and then populated with config values, you can use the parameter lazy_init for this purpose.
All file constants will be injected after calling the method init_props. Example of work:
application.yml:
default_text_style:
size: 14
weight: bold
font: "Times New Roman"
color:
- 128
- 128
- 128
language_greetings:
- language: english
text: hello
- language: german
text: hallo
- language: french
text: bonjour
wellcome_message: "{greeting}! Thank you for registration, {username}!"
mailing_frequency:
days: 5
hours: 12
lazy_init_demo.py:
from typing import List, Optional, Tuple, TypedDict, Union
from dataclasses import dataclass
from datetime import timedelta
from conjector import properties
@dataclass
class TextStyle:
size: int
weight: str
font: str
color: Union[Tuple[int, int, int], str]
class GreetingDict(TypedDict):
language: str
text: str
@properties(lazy_init=True)
@dataclass
class EmailMessageServiceConfig:
default_text_style: TextStyle
language_greetings: List[GreetingDict]
mailing_frequency: Optional[timedelta] = None
wellcome_message: str = "some_default_message"
email_config = EmailMessageServiceConfig(
default_text_style=TextStyle(
size=16, weight="normal", font="Arial", color="black"
),
language_greetings=[GreetingDict(language="english", text="hello")],
)
# it works like a normal dataclass instance
assert email_config.default_text_style == TextStyle(
size=16, weight="normal", font="Arial", color="black"
)
assert email_config.mailing_frequency is None
assert email_config.wellcome_message == "some_default_message"
# after calling `init_props`, config values will be injected.
# It also overrides all values that we set during initialize before.
email_config.init_props()
assert email_config.default_text_style == TextStyle(
size=14, weight="bold", font="Times New Roman", color=(128, 128, 128)
)
assert email_config.mailing_frequency == timedelta(days=5, hours=12)
assert email_config.wellcome_message == (
"{greeting}! Thank you for registration, {username}!"
)
Because there are 3 sources of data (default values, values passed during initialization, and config file values),
it could be hard to understand how we can resolve this conflict.
Bellow is the table to clarify the behavior of the init_props method.
init |
default |
config |
will be used |
|---|---|---|---|
- |
+ |
- |
default |
- |
+ |
+ |
config |
+ |
~ |
- |
init |
+ |
~ |
+ |
init \ config |
+- provided; -- missing; ~- not affect.
How you can see, when both init and config values provided, they are equally important,
but, by default, config have higher priority and overrides init.
If you, for some reason, don’t want to override already initialized values, only defaults,
it’s also possible with init_props(override_init=False)