Skip to content

Commit

Permalink
add docstring to the DataBlockINIBasedModel class
Browse files Browse the repository at this point in the history
  • Loading branch information
MAfarrag committed Jan 14, 2025
1 parent 74503f6 commit 8d721a6
Showing 1 changed file with 82 additions and 2 deletions.
84 changes: 82 additions & 2 deletions hydrolib/core/dflowfm/ini/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,47 @@ def _value_is_not_none_or_type_is_filemodel(field_type: type, value: Any) -> boo
class DataBlockINIBasedModel(INIBasedModel):
"""DataBlockINIBasedModel defines the base model for ini models with datablocks.
This class extends the functionality of INIBasedModel to handle structured data blocks
commonly found in INI files. It provides validation, serialization, and conversion methods
for working with these data blocks.
Attributes:
datablock (Datablock): (class attribute) the actual data columns.
Attributes:
datablock (List[List[Union[float, str]]]):
A two-dimensional list representing the data block. Each sub-list corresponds to
a row in the data block, and the values can be either floats or strings.
Args:
datablock (List[List[Union[float, str]]], optional):
The initial data block for the model. Defaults to an empty list.
Returns:
None
Raises:
ValueError: If a NaN value is found within the data block.
See Also:
INIBasedModel: The parent class for models representing INI-based configurations.
INISerializerConfig: Provides configuration for INI serialization.
Examples:
Create a model and validate its data block:
>>> from hydrolib.core.dflowfm.ini.models import DataBlockINIBasedModel
>>> model = DataBlockINIBasedModel(datablock=[[1.0, 2.0], [3.0, 4.0]])
>>> print(model.datablock)
[[1.0, 2.0], [3.0, 4.0]]
Attempt to create a model with invalid data:
>>> model = DataBlockINIBasedModel(datablock=[[1.0, None]])
ValueError: NaN is not supported in datablocks.
Notes:
- The class includes a validator to ensure that no NaN values are present in the data block.
- Data blocks are converted to a serialized format for writing to INI files.
"""

datablock: Datablock = Field(default_factory=list)
Expand All @@ -302,6 +341,9 @@ class DataBlockINIBasedModel(INIBasedModel):
def _get_unknown_keyword_error_manager(cls) -> Optional[UnknownKeywordErrorManager]:
"""
The DataBlockINIBasedModel does not need to raise an error on unknown keywords.
Returns:
Optional[UnknownKeywordErrorManager]: Returns None as unknown keywords are ignored.
"""
return None

Expand All @@ -310,11 +352,30 @@ def _to_section(
config: DataBlockINIBasedSerializerConfig,
save_settings: ModelSaveSettings,
) -> Section:
"""
Converts the current model to an INI Section representation.
Args:
config (DataBlockINIBasedSerializerConfig): Configuration for serializing the data block.
save_settings (ModelSaveSettings): Settings for saving the model.
Returns:
Section: The INI Section containing serialized data and the data block.
"""
section = super()._to_section(config, save_settings)
section.datablock = self._to_datablock(config)
return section

def _to_datablock(self, config: DataBlockINIBasedSerializerConfig) -> List[List]:
"""
Converts the data block to a serialized format based on the configuration.
Args:
config (DataBlockINIBasedSerializerConfig): Configuration for serializing the data block.
Returns:
List[List]: A serialized representation of the data block.
"""
converted_datablock = []

for row in self.datablock:
Expand All @@ -329,6 +390,16 @@ def _to_datablock(self, config: DataBlockINIBasedSerializerConfig) -> List[List]
def convert_value(
cls, value: Union[float, str], config: DataBlockINIBasedSerializerConfig
) -> str:
"""
Converts a value in the data block to its serialized string representation.
Args:
value (Union[float, str]): The value to be converted.
config (DataBlockINIBasedSerializerConfig): Configuration for the conversion.
Returns:
str: The serialized string representation of the value.
"""
if isinstance(value, float):
return f"{value:{config.float_format_datablock}}"

Expand All @@ -339,21 +410,30 @@ def _validate_no_nans_are_present(cls, datablock: Datablock) -> Datablock:
"""Validate that the datablock does not have any NaN values.
Args:
datablock (Datablock): The datablock to verify.
datablock (Datablock): The datablock to validate.
Raises:
ValueError: When a NaN is present in the datablock.
Returns:
Datablock: The validated datablock.
"""
if any(cls._is_float_and_nan(value) for list in datablock for value in list):
if any(cls._is_float_and_nan(value) for row in datablock for value in row):
raise ValueError("NaN is not supported in datablocks.")

return datablock

@staticmethod
def _is_float_and_nan(value: float) -> bool:
"""
Determines whether a value is a float and is NaN.
Args:
value (float): The value to check.
Returns:
bool: True if the value is a NaN float; otherwise, False.
"""
return isinstance(value, float) and isnan(value)


Expand Down

0 comments on commit 8d721a6

Please sign in to comment.