hexdoc.patchouli.page
1__all__ = [ 2 "BlastingPage", 3 "CampfireCookingPage", 4 "CraftingPage", 5 "EmptyPage", 6 "EntityPage", 7 "ImagePage", 8 "LinkPage", 9 "Multiblock", 10 "MultiblockPage", 11 "Page", 12 "PageWithText", 13 "PageWithTitle", 14 "QuestPage", 15 "RelationsPage", 16 "SmeltingPage", 17 "SmithingPage", 18 "SmokingPage", 19 "SpotlightPage", 20 "StonecuttingPage", 21 "TextPage", 22] 23 24from .abstract_pages import Page, PageWithText, PageWithTitle 25from .pages import ( 26 BlastingPage, 27 CampfireCookingPage, 28 CraftingPage, 29 EmptyPage, 30 EntityPage, 31 ImagePage, 32 LinkPage, 33 Multiblock, 34 MultiblockPage, 35 QuestPage, 36 RelationsPage, 37 SmeltingPage, 38 SmithingPage, 39 SmokingPage, 40 SpotlightPage, 41 StonecuttingPage, 42 TextPage, 43)
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
52class CampfireCookingPage( 53 PageWithDoubleRecipe[CampfireCookingRecipe], type="patchouli:campfire_cooking" 54): 55 pass
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
58class CraftingPage( 59 PageWithDoubleRecipeAccumulator[CraftingRecipe], type="patchouli:crafting" 60): 61 @classmethod 62 @override 63 def accumulator_type(cls): 64 return CraftingAccumulatorPage
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
73class EmptyPage(Page, type="patchouli:empty", template_type="patchouli:page"): 74 draw_filler: bool = True
Base class for Patchouli page types.
See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
77class EntityPage(PageWithText, type="patchouli:entity"): 78 _entity_name: LocalizedStr = PrivateAttr() 79 _texture: PNGTexture = PrivateAttr() 80 81 entity: Entity 82 scale: float = 1 83 offset: float = 0 84 rotate: bool = True 85 default_rotation: float = -45 86 name_field: LocalizedStr | None = Field(default=None, serialization_alias="name") 87 88 @property 89 def entity_name(self): 90 return self._entity_name 91 92 @property 93 def name(self): 94 if self.name_field is None or not self.name_field.value: 95 return self._entity_name 96 return self.name_field 97 98 @property 99 def texture(self): 100 return self._texture 101 102 @model_validator(mode="after") 103 def _get_texture(self, info: ValidationInfo) -> Self: 104 # can't be on Entity's validator because it's frozen and 105 # causes circular references with the PNGTexture 106 assert info.context is not None 107 i18n = I18n.of(info) 108 self._entity_name = i18n.localize_entity(self.entity.id) 109 self._texture = PNGTexture.load_id( 110 id="textures/entities" / self.entity.id + ".png", context=info.context 111 ) 112 return self
Base class for a Page with optional text.
If text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
115class ImagePage(PageWithTitle, type="patchouli:image"): 116 images: list[Texture] 117 border: bool = False 118 119 @property 120 def images_with_alt(self): 121 for image in self.images: 122 if self.title: 123 yield image, self.title 124 else: 125 yield image, str(image)
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
Base class for Patchouli page types.
See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
133class Multiblock(HexdocModel): 134 """https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/multiblocks/""" 135 136 mapping: dict[str, ItemWithTexture | TagWithTexture] 137 pattern: list[list[str]] 138 symmetrical: bool = False 139 offset: tuple[int, int, int] | None = None 140 141 def bill_of_materials(self): 142 character_counts = defaultdict[str, int](int) 143 144 for layer in self.pattern: 145 for row in layer: 146 for character in row: 147 match character: 148 case str() if character in self.mapping: 149 character_counts[character] += 1 150 case " " | "0": # air 151 pass 152 case _: 153 raise ValueError( 154 f"Character not found in multiblock mapping: `{character}`" 155 ) 156 157 materials = [ 158 (self.mapping[character], count) 159 for character, count in character_counts.items() 160 ] 161 162 # sort by descending count, break ties by ascending name 163 materials.sort(key=lambda v: v[0].name.value) 164 materials.sort(key=lambda v: v[1], reverse=True) 165 166 return materials 167 168 @field_validator("mapping", mode="after") 169 @classmethod 170 def _add_default_mapping( 171 cls, 172 mapping: dict[str, ItemWithTexture | TagWithTexture], 173 info: ValidationInfo, 174 ): 175 i18n = I18n.of(info) 176 return { 177 "_": ItemWithTexture( 178 id=ItemStack("hexdoc", "any"), 179 name=i18n.localize("hexdoc.any_block"), 180 texture=PNGTexture.load_id( 181 ResourceLocation("hexdoc", "textures/gui/any_block.png"), 182 context=info, 183 ), 184 ), 185 } | mapping
141 def bill_of_materials(self): 142 character_counts = defaultdict[str, int](int) 143 144 for layer in self.pattern: 145 for row in layer: 146 for character in row: 147 match character: 148 case str() if character in self.mapping: 149 character_counts[character] += 1 150 case " " | "0": # air 151 pass 152 case _: 153 raise ValueError( 154 f"Character not found in multiblock mapping: `{character}`" 155 ) 156 157 materials = [ 158 (self.mapping[character], count) 159 for character, count in character_counts.items() 160 ] 161 162 # sort by descending count, break ties by ascending name 163 materials.sort(key=lambda v: v[0].name.value) 164 materials.sort(key=lambda v: v[1], reverse=True) 165 166 return materials
188class MultiblockPage(PageWithText, type="patchouli:multiblock"): 189 name: LocalizedStr 190 multiblock_id: ResourceLocation | None = None 191 multiblock: Multiblock | None = None 192 enable_visualize: bool = True 193 194 _texture: ImageTexture | None = PrivateAttr(None) 195 196 @property 197 def texture(self): 198 return self._texture 199 200 @property 201 def _texture_id(self): 202 if self.multiblock_id: 203 return self.multiblock_id.with_path( 204 f"textures/multiblock/hexdoc/{self.multiblock_id.path}.png" 205 ) 206 207 @model_validator(mode="after") 208 def _check_multiblock(self, info: ValidationInfo) -> Self: 209 if self.multiblock_id is None and self.multiblock is None: 210 raise ValueError(f"One of multiblock_id or multiblock must be set\n{self}") 211 212 if texture_id := self._texture_id: 213 self._texture = validate_texture( 214 texture_id, 215 context=info, 216 model_type=ImageTexture, 217 ) 218 219 return self
Base class for a Page with optional text.
If text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
35class Page(TypeTaggedTemplate, AdvancementSpoilered, Flagged, type=None): 36 """Base class for Patchouli page types. 37 38 See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types 39 """ 40 41 advancement: ResourceLocation | None = None 42 anchor: str | None = None 43 44 def __init_subclass__( 45 cls, 46 *, 47 type: str | InheritType | None = Inherit, 48 template_type: str | None = None, 49 **kwargs: Unpack[ConfigDict], 50 ) -> None: 51 super().__init_subclass__(type=type, template_type=template_type, **kwargs) 52 53 @classproperty 54 @classmethod 55 def type(cls) -> ResourceLocation | None: 56 assert cls._type is not NoValue 57 return cls._type 58 59 @model_validator(mode="wrap") 60 @classmethod 61 def _pre_root(cls, value: str | Any, handler: ModelWrapValidatorHandler[Self]): 62 match value: 63 case str(text): 64 # treat a plain string as a text page 65 value = {"type": "patchouli:text", "text": text} 66 case {"type": str(raw_type)} if ":" not in raw_type: 67 # default to the patchouli namespace if not specified 68 # see: https://github.com/VazkiiMods/Patchouli/blob/b87e91a5a08d/Xplat/src/main/java/vazkii/patchouli/client/book/ClientBookRegistry.java#L110 69 value["type"] = f"patchouli:{raw_type}" 70 case _: 71 pass 72 return handler(value) 73 74 @classproperty 75 @classmethod 76 def template(cls) -> str: 77 return cls.template_id.template_path("pages") 78 79 def book_link_key(self, entry_key: str): 80 """Key to look up this page in `BookContext.book_links`, or `None` if this page 81 has no anchor.""" 82 if self.anchor is not None: 83 return f"{entry_key}#{self.anchor}" 84 85 def fragment(self, entry_fragment: str): 86 """URL fragment for this page in `BookContext.book_links`, or `None` if this 87 page has no anchor.""" 88 if self.anchor is not None: 89 return f"{entry_fragment}@{self.anchor}" 90 91 def redirect_path(self, entry_path: str): 92 """Path to this page when generating redirect pages, or `None` if this page has 93 no anchor.""" 94 if self.anchor is not None: 95 return f"{entry_path}/{self.anchor}" 96 97 def _get_advancement(self): 98 # implements AdvancementSpoilered 99 return self.advancement
Base class for Patchouli page types.
See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types
Equivalent of classmethod(property(...)).
Use @classproperty. Do not instantiate this class directly.
Equivalent of classmethod(property(...)).
Use @classproperty. Do not instantiate this class directly.
79 def book_link_key(self, entry_key: str): 80 """Key to look up this page in `BookContext.book_links`, or `None` if this page 81 has no anchor.""" 82 if self.anchor is not None: 83 return f"{entry_key}#{self.anchor}"
Key to look up this page in BookContext.book_links, or None if this page
has no anchor.
85 def fragment(self, entry_fragment: str): 86 """URL fragment for this page in `BookContext.book_links`, or `None` if this 87 page has no anchor.""" 88 if self.anchor is not None: 89 return f"{entry_fragment}@{self.anchor}"
URL fragment for this page in BookContext.book_links, or None if this
page has no anchor.
91 def redirect_path(self, entry_path: str): 92 """Path to this page when generating redirect pages, or `None` if this page has 93 no anchor.""" 94 if self.anchor is not None: 95 return f"{entry_path}/{self.anchor}"
Path to this page when generating redirect pages, or None if this page has
no anchor.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
102class PageWithText(Page, type=None): 103 """Base class for a `Page` with optional text. 104 105 If text is required, do not subclass this type. 106 """ 107 108 text: FormatTree | None = None
Base class for a Page with optional text.
If text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
111class PageWithTitle(PageWithText, type=None): 112 """Base class for a `Page` with optional title and text. 113 114 If title and/or text is required, do not subclass this type. 115 """ 116 117 title: LocalizedStr | None = None
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
222class QuestPage(PageWithText, type="patchouli:quest"): 223 trigger: ResourceLocation | None = None 224 title: LocalizedStr = LocalizedStr.with_value("Objective")
Base class for a Page with optional text.
If text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
227class RelationsPage(PageWithText, type="patchouli:relations"): 228 entries: list[ResourceLocation] 229 title: LocalizedStr = LocalizedStr.with_value("Related Chapters") 230 231 @pass_context 232 def get_entries(self, context: Context) -> list[ResourceLocation]: 233 for entry in self.entries: 234 if entry not in context["book"].all_entries: 235 raise ValueError(f"Broken entry reference in relations: {entry}") 236 return self.entries
Base class for a Page with optional text.
If text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
257class SpotlightPage(PageWithText, type="patchouli:spotlight"): 258 title_field: LocalizedStr | None = Field(default=None, alias="title") 259 item: ItemWithTexture 260 link_recipe: bool = False 261 262 @property 263 def title(self) -> LocalizedStr | None: 264 return self.title_field or self.item.name
Base class for a Page with optional text.
If text is required, do not subclass this type.
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.
251class StonecuttingPage( 252 PageWithDoubleRecipe[StonecuttingRecipe], type="patchouli:stonecutting" 253): 254 pass
Base class for a Page with optional title and text.
If title and/or text is required, do not subclass this type.
43class TextPage(Page, type="patchouli:text"): 44 title: LocalizedStr | None = None 45 text: FormatTree
Base class for Patchouli page types.
See: https://vazkiimods.github.io/Patchouli/docs/patchouli-basics/page-types
365def init_private_attributes(self: BaseModel, context: Any, /) -> None: 366 """This function is meant to behave like a BaseModel method to initialize private attributes. 367 368 It takes context as an argument since that's what pydantic-core passes when calling it. 369 370 Args: 371 self: The BaseModel instance. 372 context: The context. 373 """ 374 if getattr(self, '__pydantic_private__', None) is None: 375 pydantic_private = {} 376 for name, private_attr in self.__private_attributes__.items(): 377 # Avoid needlessly creating a new dict for the validated data: 378 if private_attr.default_factory_takes_validated_data: 379 default = private_attr.get_default( 380 call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} 381 ) 382 else: 383 default = private_attr.get_default(call_default_factory=True) 384 if default is not PydanticUndefined: 385 pydantic_private[name] = default 386 object_setattr(self, '__pydantic_private__', pydantic_private)
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args: self: The BaseModel instance. context: The context.