Skip to content

Commit

Permalink
Fix unserializable parameters value (#2122)
Browse files Browse the repository at this point in the history
* sync remote

* custom resolver fix initial draft

* fix lint

* fix lint

* update release note

* use json_encoder
  • Loading branch information
ravi-kumar-pilla authored Oct 7, 2024
1 parent 34bcb55 commit ed0e6aa
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 3 deletions.
3 changes: 3 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Please follow the established format:

- Update Kedro-Viz telemetry for opt-out model (#2022)

## Bug fixes and other changes

- Fix unserializable parameters value (#2122)

# Release 10.0.0

Expand Down
2 changes: 1 addition & 1 deletion package/kedro_viz/data_access/repositories/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def get_dataset(self, dataset_name: str) -> Optional["AbstractDataset"]:
else: # pragma: no cover
dataset_obj = self._catalog._get_dataset(dataset_name)
except DatasetNotFoundError:
dataset_obj = MemoryDataset() # pylint: disable=abstract-class-instantiated
dataset_obj = MemoryDataset()

return dataset_obj

Expand Down
17 changes: 16 additions & 1 deletion package/kedro_viz/models/flowchart.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from types import FunctionType
from typing import Any, ClassVar, Dict, List, Optional, Set, Union, cast

from fastapi.encoders import jsonable_encoder
from kedro.pipeline.node import Node as KedroNode
from pydantic import (
BaseModel,
Expand Down Expand Up @@ -861,7 +862,13 @@ def parameter_value(self) -> Any:
return None

try:
return self.kedro_obj.load()
actual_parameter_value = self.kedro_obj.load()
# Return only json serializable value
return jsonable_encoder(actual_parameter_value)
except (TypeError, ValueError, RecursionError):
# In case the parameter is not JSON serializable,
# return the string representation
return str(actual_parameter_value)
except (AttributeError, DatasetError):
# This except clause triggers if the user passes a parameter that is not
# defined in the catalog (DatasetError) it also catches any case where
Expand All @@ -870,6 +877,14 @@ def parameter_value(self) -> Any:
"Cannot find parameter `%s` in the catalog.", self.parameter_name
)
return None
# pylint: disable=broad-exception-caught
except Exception as exc: # pragma: no cover
logger.error(
"An error occurred when loading parameter `%s` in the catalog :: %s",
self.parameter_name,
exc,
)
return None


class ParametersNodeMetadata(GraphNodeMetadata):
Expand Down
1 change: 1 addition & 0 deletions package/kedro_viz/models/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""`kedro_viz.models.utils` contains utility functions used in the `kedro_viz.models` package"""

import logging
from typing import TYPE_CHECKING

Expand Down
42 changes: 41 additions & 1 deletion package/tests/test_models/test_flowchart.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from functools import partial
from pathlib import Path
from textwrap import dedent
from unittest.mock import call, patch
from unittest.mock import Mock, call, patch

import pytest
from kedro.io import MemoryDataset
Expand Down Expand Up @@ -215,6 +215,46 @@ def test_create_parameters_node_single_parameter(
assert parameters_node.parameter_value == 0.3
assert parameters_node.modular_pipelines == expected_modular_pipelines

def test_create_single_parameter_with_complex_type(self):
parameters_dataset = MemoryDataset(data=object())
parameters_node = GraphNode.create_parameters_node(
dataset_id="params:test_split_ratio",
dataset_name="params:test_split_ratio",
layer=None,
tags=set(),
parameters=parameters_dataset,
modular_pipelines=set(),
)
assert isinstance(parameters_node, ParametersNode)
assert parameters_node.kedro_obj is parameters_dataset
assert not parameters_node.is_all_parameters()
assert parameters_node.is_single_parameter()
assert isinstance(parameters_node.parameter_value, str)

def test_create_all_parameters_with_complex_type(self):
mock_object = Mock()
parameters_dataset = MemoryDataset(
data={
"test_split_ratio": 0.3,
"num_epochs": 1000,
"complex_param": mock_object,
}
)
parameters_node = GraphNode.create_parameters_node(
dataset_id="parameters",
dataset_name="parameters",
layer=None,
tags=set(),
parameters=parameters_dataset,
modular_pipelines=set(),
)
assert isinstance(parameters_node, ParametersNode)
assert parameters_node.kedro_obj is parameters_dataset
assert parameters_node.id == "parameters"
assert parameters_node.is_all_parameters()
assert not parameters_node.is_single_parameter()
assert isinstance(parameters_node.parameter_value, str)

def test_create_non_existing_parameter_node(self):
"""Test the case where ``parameters`` is equal to None"""
parameters_node = GraphNode.create_parameters_node(
Expand Down

0 comments on commit ed0e6aa

Please sign in to comment.