Skip to content

Commit

Permalink
Merge branch 'tidy/mdformat' of https://github.com/mckinsey/vizro int…
Browse files Browse the repository at this point in the history
…o tidy/mdformat
  • Loading branch information
stichbury committed Dec 3, 2024
2 parents add8a5a + 96a7147 commit e9e61e8
Show file tree
Hide file tree
Showing 21 changed files with 417 additions and 91 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ repos:
--wrap=no,
--align-semantic-breaks-in-lists,
]
exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference|vizro-core/docs/pages/user-guides/custom-components.md
exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference|vizro-core/docs/pages/user-guides/custom-components.md|^vizro-core/changelog.d|^vizro-ai/changelog.d
additional_dependencies:
- mdformat-mkdocs[recommended]==3.1.1

Expand Down
54 changes: 54 additions & 0 deletions vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!--
A new scriv changelog fragment.
Uncomment the section that is right (remove the HTML comment wrapper).
-->

<!--
### Highlights ✨
- A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Removed
- A bullet item for the Removed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Added
- A bullet item for the Added category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Changed
- A bullet item for the Changed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Deprecated
- A bullet item for the Deprecated category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Fixed
- A bullet item for the Fixed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Security
- A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
54 changes: 54 additions & 0 deletions vizro-core/changelog.d/20241203_145221_antony.milne_mdformat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!--
A new scriv changelog fragment.
Uncomment the section that is right (remove the HTML comment wrapper).
-->

<!--
### Highlights ✨
- A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Removed
- A bullet item for the Removed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Added
- A bullet item for the Added category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Changed
- A bullet item for the Changed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Deprecated
- A bullet item for the Deprecated category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Fixed
- A bullet item for the Fixed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Security
- A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
54 changes: 54 additions & 0 deletions vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!--
A new scriv changelog fragment.
Uncomment the section that is right (remove the HTML comment wrapper).
-->

<!--
### Highlights ✨
- A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Removed
- A bullet item for the Removed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Added
- A bullet item for the Added category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Changed
- A bullet item for the Changed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Deprecated
- A bullet item for the Deprecated category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Fixed
- A bullet item for the Fixed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->

<!--
### Security
- A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
2 changes: 1 addition & 1 deletion vizro-core/src/vizro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

__all__ = ["Vizro"]

__version__ = "0.1.30.dev0"
__version__ = "0.1.29.dev0"


# For the below _css_dist and _js_dist to be used by Dash, they must be retrieved by dash.resources.Css.get_all_css().
Expand Down
56 changes: 38 additions & 18 deletions vizro-core/src/vizro/actions/_actions_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,18 @@ def _get_component_actions(component) -> list[Action]:


def _apply_filter_controls(
data_frame: pd.DataFrame, ctds_filters: list[CallbackTriggerDict], target: ModelID
data_frame: pd.DataFrame, ctds_filter: list[CallbackTriggerDict], target: ModelID
) -> pd.DataFrame:
"""Applies filters from a vm.Filter model in the controls.
Args:
data_frame: unfiltered DataFrame.
ctds_filters: list of CallbackTriggerDict for filters.
ctds_filter: list of CallbackTriggerDict for filters.
target: id of targeted Figure.
Returns: filtered DataFrame.
"""
for ctd in ctds_filters:
for ctd in ctds_filter:
selector_value = ctd["value"]
selector_value = selector_value if isinstance(selector_value, list) else [selector_value]
selector_actions = _get_component_actions(model_manager[ctd["id"]])
Expand Down Expand Up @@ -162,12 +162,12 @@ def _update_nested_figure_properties(


def _get_parametrized_config(
ctd_parameters: list[CallbackTriggerDict], target: ModelID, data_frame: bool
ctds_parameter: list[CallbackTriggerDict], target: ModelID, data_frame: bool
) -> dict[str, Any]:
"""Convert parameters into a keyword-argument dictionary.
Args:
ctd_parameters: list of CallbackTriggerDicts for vm.Parameter.
ctds_parameter: list of CallbackTriggerDicts for vm.Parameter.
target: id of targeted figure.
data_frame: whether to return only DataFrame parameters starting "data_frame." or only non-DataFrame parameters.
Expand All @@ -185,7 +185,7 @@ def _get_parametrized_config(
config = deepcopy(model_manager[target].figure._arguments)
del config["data_frame"]

for ctd in ctd_parameters:
for ctd in ctds_parameter:
# TODO: needs to be refactored so that it is independent of implementation details
parameter_value = ctd["value"]

Expand Down Expand Up @@ -221,25 +221,25 @@ def _apply_filters(
# Takes in just one target, so dataframe is filtered repeatedly for every target that uses it.
# Potentially this could be de-duplicated but it's not so important since filtering is a relatively fast
# operation (compared to data loading).
filtered_data = _apply_filter_controls(data_frame=data, ctds_filters=ctds_filter, target=target)
filtered_data = _apply_filter_controls(data_frame=data, ctds_filter=ctds_filter, target=target)
filtered_data = _apply_filter_interaction(
data_frame=filtered_data, ctds_filter_interaction=ctds_filter_interaction, target=target
)
return filtered_data


def _get_unfiltered_data(
ctds_parameters: list[CallbackTriggerDict], targets: list[ModelID]
ctds_parameter: list[CallbackTriggerDict], targets: list[ModelID]
) -> dict[ModelID, pd.DataFrame]:
# Takes in multiple targets to ensure that data can be loaded efficiently using _multi_load and not repeated for
# every single target.
# Getting unfiltered data requires data frame parameters. We pass in all ctd_parameters and then find the
# Getting unfiltered data requires data frame parameters. We pass in all ctds_parameter and then find the
# data_frame ones by passing data_frame=True in the call to _get_paramaterized_config. Static data is also
# handled here and will just have empty dictionary for its kwargs.
multi_data_source_name_load_kwargs: list[tuple[DataSourceName, dict[str, Any]]] = []
for target in targets:
dynamic_data_load_params = _get_parametrized_config(
ctd_parameters=ctds_parameters, target=target, data_frame=True
ctds_parameter=ctds_parameter, target=target, data_frame=True
)
data_source_name = model_manager[target]["data_frame"]
multi_data_source_name_load_kwargs.append((data_source_name, dynamic_data_load_params["data_frame"]))
Expand All @@ -250,25 +250,45 @@ def _get_unfiltered_data(
def _get_modified_page_figures(
ctds_filter: list[CallbackTriggerDict],
ctds_filter_interaction: list[dict[str, CallbackTriggerDict]],
ctds_parameters: list[CallbackTriggerDict],
ctds_parameter: list[CallbackTriggerDict],
targets: list[ModelID],
) -> dict[ModelID, Any]:
from vizro.models import Filter

outputs: dict[ModelID, Any] = {}

control_targets = []
figure_targets = []
for target in targets:
if isinstance(model_manager[target], Filter):
control_targets.append(target)
else:
figure_targets.append(target)

# TODO-NEXT: Add fetching unfiltered data for the Filter.targets as well, once dynamic filters become "targetable"
# from other actions too. For example, in future, if Parameter is targeting only a single Filter.
# Currently, it only works for the on_page_load because Filter.targets are indeed the part of the actions' targets.
# More about the limitation: https://github.com/mckinsey/vizro/pull/879/files#r1863535516
target_to_data_frame = _get_unfiltered_data(ctds_parameter=ctds_parameter, targets=figure_targets)

# TODO: the structure here would be nicer if we could get just the ctds for a single target at one time,
# so you could do apply_filters on a target a pass only the ctds relevant for that target.
# Consider restructuring ctds to a more convenient form to make this possible.

for target, unfiltered_data in _get_unfiltered_data(ctds_parameters, targets).items():
for target, unfiltered_data in target_to_data_frame.items():
filtered_data = _apply_filters(unfiltered_data, ctds_filter, ctds_filter_interaction, target)
outputs[target] = model_manager[target](
data_frame=filtered_data,
**_get_parametrized_config(ctd_parameters=ctds_parameters, target=target, data_frame=False),
**_get_parametrized_config(ctds_parameter=ctds_parameter, target=target, data_frame=False),
)

# TODO NEXT: will need to pass unfiltered_data into Filter.__call__.
# This dictionary is filtered for correct targets already selected in Filter.__call__ or that could be done here
# instead.
# {target: data_frame for target, data_frame in unfiltered_data.items() if target in self.targets}
for target in control_targets:
ctd_filter = [item for item in ctds_filter if item["id"] == model_manager[target].selector.id]

# This only covers the case of cross-page actions when Filter in an output, but is not an input of the action.
current_value = ctd_filter[0]["value"] if ctd_filter else None

# target_to_data_frame contains all targets, including some which might not be relevant for the filter in
# question. We filter to use just the relevant targets in Filter.__call__.
outputs[target] = model_manager[target](target_to_data_frame=target_to_data_frame, current_value=current_value)

return outputs
2 changes: 1 addition & 1 deletion vizro-core/src/vizro/actions/_filter_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ def _filter(
return _get_modified_page_figures(
ctds_filter=ctx.args_grouping["external"]["filters"],
ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"],
ctds_parameters=ctx.args_grouping["external"]["parameters"],
ctds_parameter=ctx.args_grouping["external"]["parameters"],
targets=targets,
)
2 changes: 1 addition & 1 deletion vizro-core/src/vizro/actions/_on_page_load_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ def _on_page_load(targets: list[ModelID], **inputs: dict[str, Any]) -> dict[Mode
return _get_modified_page_figures(
ctds_filter=ctx.args_grouping["external"]["filters"],
ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"],
ctds_parameters=ctx.args_grouping["external"]["parameters"],
ctds_parameter=ctx.args_grouping["external"]["parameters"],
targets=targets,
)
2 changes: 1 addition & 1 deletion vizro-core/src/vizro/actions/_parameter_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ def _parameter(targets: list[str], **inputs: dict[str, Any]) -> dict[ModelID, An
return _get_modified_page_figures(
ctds_filter=ctx.args_grouping["external"]["filters"],
ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"],
ctds_parameters=ctx.args_grouping["external"]["parameters"],
ctds_parameter=ctx.args_grouping["external"]["parameters"],
targets=target_ids,
)
2 changes: 1 addition & 1 deletion vizro-core/src/vizro/actions/filter_interaction_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ def filter_interaction(targets: Optional[list[ModelID]] = None, **inputs: dict[s
return _get_modified_page_figures(
ctds_filter=ctx.args_grouping["external"]["filters"],
ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"],
ctds_parameters=ctx.args_grouping["external"]["parameters"],
ctds_parameter=ctx.args_grouping["external"]["parameters"],
targets=targets or [],
)
3 changes: 3 additions & 0 deletions vizro-core/src/vizro/models/_components/form/_form_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def validate_value(cls, value, values):
[entry["value"] for entry in values["options"]] if isinstance(values["options"][0], dict) else values["options"]
)

if hasattr(value, "__iter__") and ALL_OPTION in value:
return value

if value and not is_value_contained(value, possible_values):
raise ValueError("Please provide a valid value from `options`.")

Expand Down
17 changes: 14 additions & 3 deletions vizro-core/src/vizro/models/_components/form/checklist.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class Checklist(VizroBaseModel):
title: str = Field("", description="Title to be displayed")
actions: list[Action] = []

_dynamic: bool = PrivateAttr(False)

# Component properties for actions and interactions
_input_property: str = PrivateAttr("value")

Expand All @@ -46,9 +48,8 @@ class Checklist(VizroBaseModel):
_validate_options = root_validator(allow_reuse=True, pre=True)(validate_options_dict)
_validate_value = validator("value", allow_reuse=True, always=True)(validate_value)

@_log_call
def build(self):
full_options, default_value = get_options_and_default(options=self.options, multi=True)
def __call__(self, options):
full_options, default_value = get_options_and_default(options=options, multi=True)

return html.Fieldset(
children=[
Expand All @@ -62,3 +63,13 @@ def build(self):
),
]
)

def _build_dynamic_placeholder(self):
if self.value is None:
self.value = [get_options_and_default(self.options, multi=True)[1]]

return self.__call__(self.options)

@_log_call
def build(self):
return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options)
Loading

0 comments on commit e9e61e8

Please sign in to comment.