From 8792e5a813e23ed87bf8003d88551018bf6101af Mon Sep 17 00:00:00 2001 From: Richard Iannone Date: Thu, 27 Mar 2025 17:26:36 -0400 Subject: [PATCH 1/3] Enable display of brief in validation report --- pointblank/validate.py | 283 +++++++++++++++++++++++++++++++---------- 1 file changed, 218 insertions(+), 65 deletions(-) diff --git a/pointblank/validate.py b/pointblank/validate.py index ce0d9aabb..7481e7936 100644 --- a/pointblank/validate.py +++ b/pointblank/validate.py @@ -1944,7 +1944,7 @@ def col_vals_gt( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -1986,8 +1986,11 @@ def col_vals_gt( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -2086,6 +2089,9 @@ def col_vals_gt( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -2112,7 +2118,7 @@ def col_vals_lt( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -2154,8 +2160,11 @@ def col_vals_lt( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -2253,6 +2262,9 @@ def col_vals_lt( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -2279,7 +2291,7 @@ def col_vals_eq( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -2321,8 +2333,11 @@ def col_vals_eq( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -2419,6 +2434,9 @@ def col_vals_eq( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -2445,7 +2463,7 @@ def col_vals_ne( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -2487,8 +2505,11 @@ def col_vals_ne( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -2583,6 +2604,9 @@ def col_vals_ne( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -2609,7 +2633,7 @@ def col_vals_ge( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -2651,8 +2675,11 @@ def col_vals_ge( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -2751,6 +2778,9 @@ def col_vals_ge( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -2777,7 +2807,7 @@ def col_vals_le( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -2819,8 +2849,11 @@ def col_vals_le( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -2919,6 +2952,9 @@ def col_vals_le( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -2947,7 +2983,7 @@ def col_vals_between( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -2998,8 +3034,11 @@ def col_vals_between( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -3110,6 +3149,9 @@ def col_vals_between( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -3139,7 +3181,7 @@ def col_vals_outside( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -3190,8 +3232,11 @@ def col_vals_outside( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -3305,6 +3350,9 @@ def col_vals_outside( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -3331,7 +3379,7 @@ def col_vals_in_set( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -3366,8 +3414,11 @@ def col_vals_in_set( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -3459,6 +3510,9 @@ def col_vals_in_set( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -3483,7 +3537,7 @@ def col_vals_not_in_set( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -3518,10 +3572,15 @@ def col_vals_not_in_set( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` + will make the validation step inactive (still reporting its presence and keeping indexes + for the steps unchanged). Returns ------- @@ -3610,6 +3669,9 @@ def col_vals_not_in_set( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -3633,7 +3695,7 @@ def col_vals_null( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -3665,8 +3727,11 @@ def col_vals_null( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -3755,6 +3820,9 @@ def col_vals_null( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -3777,7 +3845,7 @@ def col_vals_not_null( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -3809,8 +3877,11 @@ def col_vals_not_null( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -3899,6 +3970,9 @@ def col_vals_not_null( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -3923,7 +3997,7 @@ def col_vals_regex( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -3961,8 +4035,11 @@ def col_vals_regex( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -4054,6 +4131,9 @@ def col_vals_regex( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -4078,7 +4158,7 @@ def col_vals_expr( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -4111,8 +4191,11 @@ def col_vals_expr( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -4180,6 +4263,9 @@ def col_vals_expr( self.thresholds if thresholds is None else _normalize_thresholds_creation(thresholds) ) + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + val_info = _ValidationInfo( assertion_type=assertion_type, column=None, @@ -4200,7 +4286,7 @@ def col_exists( columns: str | list[str] | Column | ColumnSelector | ColumnSelectorNarwhals, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -4229,8 +4315,11 @@ def col_exists( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -4320,6 +4409,9 @@ def col_exists( if isinstance(columns, (Column, str)): columns = [columns] + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + # Iterate over the columns and create a validation step for each for column in columns: val_info = _ValidationInfo( @@ -4342,7 +4434,7 @@ def rows_distinct( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -4374,8 +4466,11 @@ def rows_distinct( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -4464,6 +4559,9 @@ def rows_distinct( # TODO: incorporate Column object + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + val_info = _ValidationInfo( assertion_type=assertion_type, column=columns_subset, @@ -4489,7 +4587,7 @@ def col_schema_match( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -4542,8 +4640,11 @@ def col_schema_match( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -4640,6 +4741,9 @@ def col_schema_match( "full_match_dtypes": full_match_dtypes, } + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + val_info = _ValidationInfo( assertion_type=assertion_type, values=values, @@ -4662,7 +4766,7 @@ def row_count_match( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -4708,8 +4812,11 @@ def row_count_match( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -4811,6 +4918,9 @@ def row_count_match( # Package up the `count=` and boolean params into a dictionary for later interrogation values = {"count": count, "inverse": inverse, "abs_tol_bounds": bounds} + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + val_info = _ValidationInfo( assertion_type=assertion_type, values=values, @@ -4832,7 +4942,7 @@ def col_count_match( pre: Callable | None = None, thresholds: int | float | bool | tuple | dict | Thresholds = None, actions: Actions | None = None, - brief: str | None = None, + brief: str | bool | None = None, active: bool = True, ) -> Validate: """ @@ -4870,8 +4980,11 @@ def col_count_match( levels. If provided, the [`Actions`](`pointblank.Actions`) class should be used to define the actions. brief - An optional brief description of the validation step. The templating elements `"{col}"` - and `"{step}"` can be used to insert the column name and step number, respectively. + An optional brief description of the validation step that will be displayed in the + reporting table. You can use the templating elements like `"{step}"` to insert + the step number, or `"{auto}"` to include an automatically generated brief. If `True` + the entire brief will be automatically generated. If `None` (the default) then there + won't be a brief. active A boolean value indicating whether the validation step should be active. Using `False` will make the validation step inactive (still reporting its presence and keeping indexes @@ -4939,6 +5052,9 @@ def col_count_match( # Package up the `count=` and boolean params into a dictionary for later interrogation values = {"count": count, "inverse": inverse} + # Transform any shorthands of `brief=` to string representations + brief = _transform_auto_brief(brief=brief) + val_info = _ValidationInfo( assertion_type=assertion_type, values=values, @@ -7003,9 +7119,17 @@ def get_tabular_report( # Add the `type_upd` entry to the dictionary validation_info_dict["type_upd"] = _transform_assertion_str( - assertion_str=validation_info_dict["assertion_type"] + assertion_str=validation_info_dict["assertion_type"], + brief_str=validation_info_dict["brief"], + autobrief_str=validation_info_dict["autobrief"], ) + # Remove the `brief` entry from the dictionary + validation_info_dict.pop("brief") + + # Remove the `autobrief` entry from the dictionary + validation_info_dict.pop("autobrief") + # ------------------------------------------------ # Process the `columns_upd` entry # ------------------------------------------------ @@ -7328,7 +7452,6 @@ def get_tabular_report( # Drop other keys from the dictionary validation_info_dict.pop("na_pass") validation_info_dict.pop("label") - validation_info_dict.pop("brief") validation_info_dict.pop("active") validation_info_dict.pop("all_passed") @@ -7955,6 +8078,16 @@ def _process_brief(brief: str | None, step: int, col: str | list[str] | None) -> return brief +def _transform_auto_brief(brief: str | bool | None) -> str | None: + if isinstance(brief, bool): + if brief: + return "{auto}" + else: + return None + else: + return brief + + def _process_action_str( action_str: str, step: int, @@ -8386,6 +8519,7 @@ def _validation_info_as_dict(validation_info: _ValidationInfo) -> dict: "pre", "label", "brief", + "autobrief", "active", "eval_error", "all_passed", @@ -8600,13 +8734,29 @@ def _transform_w_s_n(values, color, interrogation_performed): ] -def _transform_assertion_str(assertion_str: list[str]) -> list[str]: +def _transform_assertion_str( + assertion_str: list[str], brief_str: list[str | None], autobrief_str: list[str] +) -> list[str]: # Get the SVG icons for the assertion types svg_icon = _get_assertion_icon(icon=assertion_str) - # Append `()` to the `assertion_str` assertion_str = [x + "()" for x in assertion_str] + # Make every None value in `brief_str` an empty string + brief_str = ["" if x is None else x for x in brief_str] + + # If the template text `{auto}` is in the `brief_str` then replace it with the corresponding + # `autobrief_str` entry + brief_str = [ + brief_str[i].replace("{auto}", autobrief_str[i]) + if "{auto}" in brief_str[i] + else brief_str[i] + for i in range(len(brief_str)) + ] + + # Use Markdown-to-HTML conversion to format the `brief_str` text + brief_str = [commonmark.commonmark(x) for x in brief_str] + # Obtain the number of characters contained in the assertion # string; this is important for sizing components appropriately assertion_type_nchar = [len(x) for x in assertion_str] @@ -8617,12 +8767,15 @@ def _transform_assertion_str(assertion_str: list[str]) -> list[str]: # Create the assertion type update using a list comprehension type_upd = [ f""" -
- {svg} +
+ {svg} +
+
+
{assertion}
- {assertion} +
{brief}
""" - for assertion, svg, size in zip(assertion_str, svg_icon, text_size) + for assertion, svg, size, brief in zip(assertion_str, svg_icon, text_size, brief_str) ] return type_upd From 3994772637951f4b08dc0945f1a5f43ae0a0ef9a Mon Sep 17 00:00:00 2001 From: Richard Iannone Date: Thu, 27 Mar 2025 17:26:50 -0400 Subject: [PATCH 2/3] Update test snapshots --- .../comprehensive_validation_report.html | 225 ++++++++++++------ .../no_interrogation_validation_report.html | 153 ++++++++---- .../selector_helper_functions_no_match.html | 27 ++- .../selector_helper_functions_no_match.html | 27 ++- .../selector_helper_functions_no_match.html | 27 ++- 5 files changed, 306 insertions(+), 153 deletions(-) diff --git a/tests/snapshots/test_validate/test_comprehensive_validation_report_html_snap/comprehensive_validation_report.html b/tests/snapshots/test_validate/test_comprehensive_validation_report_html_snap/comprehensive_validation_report.html index da5227db5..05ae52a07 100644 --- a/tests/snapshots/test_validate/test_comprehensive_validation_report_html_snap/comprehensive_validation_report.html +++ b/tests/snapshots/test_validate/test_comprehensive_validation_report_html_snap/comprehensive_validation_report.html @@ -96,8 +96,8 @@ #4CA64C 1 -
- +
+ col_vals_gt @@ -108,7 +108,10 @@
- col_vals_gt() +
+
col_vals_gt()
+
+
d 100 @@ -134,8 +137,8 @@ #FF3300 2 -
- +
+ col_vals_lt @@ -146,7 +149,10 @@
- col_vals_lt() +
+
col_vals_lt()
+
+
c 5 @@ -172,8 +178,8 @@ #FF3300 3 -
- +
+ col_vals_equal @@ -184,7 +190,10 @@
- col_vals_eq() +
+
col_vals_eq()
+
+
a 3 @@ -210,8 +219,8 @@ #4CA64C 4 -
- +
+ col_vals_not_equal @@ -222,7 +231,10 @@
- col_vals_ne() +
+
col_vals_ne()
+
+
c 10 @@ -248,8 +260,8 @@ #4CA64C66 5 -
- +
+ col_vals_lte @@ -260,7 +272,10 @@
- col_vals_le() +
+
col_vals_le()
+
+
a 7 @@ -286,8 +301,8 @@ #AAAAAA 6 -
- +
+ col_vals_gte @@ -298,7 +313,10 @@
- col_vals_ge() +
+
col_vals_ge()
+
+
d 500 @@ -324,8 +342,8 @@ #4CA64C 7 -
- +
+ col_vals_between @@ -336,7 +354,10 @@
- col_vals_between() +
+
col_vals_between()
+
+
c [0, 10] @@ -362,8 +383,8 @@ #4CA64C 8 -
- +
+ col_vals_not_between @@ -378,7 +399,10 @@
- col_vals_outside() +
+
col_vals_outside()
+
+
a (8, 9] @@ -404,8 +428,8 @@ #4CA64C66 9 -
- +
+ col_vals_equal @@ -416,7 +440,10 @@
- col_vals_eq() +
+
col_vals_eq()
+
+
a 10 @@ -442,8 +469,8 @@ #4CA64C 10 -
- +
+ col_vals_gte @@ -454,7 +481,10 @@
- col_vals_ge() +
+
col_vals_ge()
+
+
a 20 @@ -482,8 +512,8 @@ #4CA64C66 11 -
- +
+ col_vals_gt @@ -494,7 +524,10 @@
- col_vals_gt() +
+
col_vals_gt()
+
+
new 20 @@ -522,8 +555,8 @@ #4CA64C 12 -
- +
+ col_vals_in_set @@ -534,7 +567,10 @@
- col_vals_in_set() +
+
col_vals_in_set()
+
+
f low, mid, high @@ -560,8 +596,8 @@ #4CA64C 13 -
- +
+ col_vals_not_in_set @@ -574,7 +610,10 @@
- col_vals_not_in_set() +
+
col_vals_not_in_set()
+
+
f l, h, m @@ -600,8 +639,8 @@ #FF3300 14 -
- +
+ col_vals_null @@ -612,7 +651,10 @@
- col_vals_null() +
+
col_vals_null()
+
+
c — @@ -638,8 +680,8 @@ #4CA64C 15 -
- +
+ col_vals_not_null @@ -652,7 +694,10 @@
- col_vals_not_null() +
+
col_vals_not_null()
+
+
date_time — @@ -678,8 +723,8 @@ #4CA64C 16 -
- +
+ col_vals_regex @@ -693,7 +738,10 @@
- col_vals_regex() +
+
col_vals_regex()
+
+
b [0-9]-[a-z]{3}-[0-9]{3} @@ -719,8 +767,8 @@ #FF3300 17 -
- +
+ col_exists @@ -732,7 +780,10 @@
- col_exists() +
+
col_exists()
+
+
z — @@ -758,8 +809,8 @@ #4CA64C 18 -
- +
+ col_schema_match @@ -775,7 +826,10 @@
- col_schema_match() +
+
col_schema_match()
+
+
— SCHEMA @@ -801,8 +855,8 @@ #4CA64C 19 -
- +
+ row_count_match @@ -818,7 +872,10 @@
- row_count_match() +
+
row_count_match()
+
+
— 13 @@ -844,8 +901,8 @@ #4CA64C 20 -
- +
+ row_count_match @@ -861,7 +918,10 @@
- row_count_match() +
+
row_count_match()
+
+
— ≠ 2 @@ -887,8 +947,8 @@ #4CA64C 21 -
- +
+ col_count_match @@ -904,7 +964,10 @@
- col_count_match() +
+
col_count_match()
+
+
— 8 @@ -930,8 +993,8 @@ #4CA64C 22 -
- +
+ col_count_match @@ -947,7 +1010,10 @@
- col_count_match() +
+
col_count_match()
+
+
— ≠ 2 @@ -973,8 +1039,8 @@ #AAAAAA 23 -
- +
+ rows_distinct @@ -989,7 +1055,10 @@
- rows_distinct() +
+
rows_distinct()
+
+
ALL COLUMNS — @@ -1015,8 +1084,8 @@ #AAAAAA 24 -
- +
+ rows_distinct @@ -1031,7 +1100,10 @@
- rows_distinct() +
+
rows_distinct()
+
+
a, b, c — @@ -1057,8 +1129,8 @@ #4CA64C 25 -
- +
+ col_vals_expr @@ -1069,7 +1141,10 @@
- col_vals_expr() +
+
col_vals_expr()
+
+
— COLUMN EXPR diff --git a/tests/snapshots/test_validate/test_no_interrogation_validation_report_html_snap/no_interrogation_validation_report.html b/tests/snapshots/test_validate/test_no_interrogation_validation_report_html_snap/no_interrogation_validation_report.html index c22b7a3b3..a73c62720 100644 --- a/tests/snapshots/test_validate/test_no_interrogation_validation_report_html_snap/no_interrogation_validation_report.html +++ b/tests/snapshots/test_validate/test_no_interrogation_validation_report_html_snap/no_interrogation_validation_report.html @@ -96,8 +96,8 @@ #4CA64C66 1 -
- +
+ col_vals_gt @@ -108,7 +108,10 @@
- col_vals_gt() +
+
col_vals_gt()
+
+
d 100 @@ -126,8 +129,8 @@ #4CA64C66 2 -
- +
+ col_vals_lt @@ -138,7 +141,10 @@
- col_vals_lt() +
+
col_vals_lt()
+
+
c 5 @@ -156,8 +162,8 @@ #4CA64C66 3 -
- +
+ col_vals_equal @@ -168,7 +174,10 @@
- col_vals_eq() +
+
col_vals_eq()
+
+
a 3 @@ -186,8 +195,8 @@ #4CA64C66 4 -
- +
+ col_vals_not_equal @@ -198,7 +207,10 @@
- col_vals_ne() +
+
col_vals_ne()
+
+
c 10 @@ -216,8 +228,8 @@ #4CA64C66 5 -
- +
+ col_vals_lte @@ -228,7 +240,10 @@
- col_vals_le() +
+
col_vals_le()
+
+
a 7 @@ -246,8 +261,8 @@ #4CA64C66 6 -
- +
+ col_vals_gte @@ -258,7 +273,10 @@
- col_vals_ge() +
+
col_vals_ge()
+
+
d 500 @@ -276,8 +294,8 @@ #4CA64C66 7 -
- +
+ col_vals_between @@ -288,7 +306,10 @@
- col_vals_between() +
+
col_vals_between()
+
+
c [0, 10] @@ -306,8 +327,8 @@ #4CA64C66 8 -
- +
+ col_vals_not_between @@ -322,7 +343,10 @@
- col_vals_outside() +
+
col_vals_outside()
+
+
a (8, 9] @@ -340,8 +364,8 @@ #4CA64C66 9 -
- +
+ col_vals_equal @@ -352,7 +376,10 @@
- col_vals_eq() +
+
col_vals_eq()
+
+
a 10 @@ -370,8 +397,8 @@ #4CA64C66 10 -
- +
+ col_vals_gte @@ -382,7 +409,10 @@
- col_vals_ge() +
+
col_vals_ge()
+
+
a 20 @@ -400,8 +430,8 @@ #4CA64C66 11 -
- +
+ col_vals_gt @@ -412,7 +442,10 @@
- col_vals_gt() +
+
col_vals_gt()
+
+
new 20 @@ -430,8 +463,8 @@ #4CA64C66 12 -
- +
+ col_vals_in_set @@ -442,7 +475,10 @@
- col_vals_in_set() +
+
col_vals_in_set()
+
+
f low, mid, high @@ -460,8 +496,8 @@ #4CA64C66 13 -
- +
+ col_vals_not_in_set @@ -474,7 +510,10 @@
- col_vals_not_in_set() +
+
col_vals_not_in_set()
+
+
f l, h, m @@ -492,8 +531,8 @@ #4CA64C66 14 -
- +
+ col_vals_null @@ -504,7 +543,10 @@
- col_vals_null() +
+
col_vals_null()
+
+
c — @@ -522,8 +564,8 @@ #4CA64C66 15 -
- +
+ col_vals_not_null @@ -536,7 +578,10 @@
- col_vals_not_null() +
+
col_vals_not_null()
+
+
date_time — @@ -554,8 +599,8 @@ #4CA64C66 16 -
- +
+ col_vals_regex @@ -569,7 +614,10 @@
- col_vals_regex() +
+
col_vals_regex()
+
+
b [0-9]-[a-z]{3}-[0-9]{3} @@ -587,8 +635,8 @@ #4CA64C66 17 -
- +
+ col_exists @@ -600,7 +648,10 @@
- col_exists() +
+
col_exists()
+
+
z — diff --git a/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_memtable_variable_names/selector_helper_functions_no_match.html b/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_memtable_variable_names/selector_helper_functions_no_match.html index 37b544abf..4db3109e1 100644 --- a/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_memtable_variable_names/selector_helper_functions_no_match.html +++ b/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_memtable_variable_names/selector_helper_functions_no_match.html @@ -96,8 +96,8 @@ #4CA64C 1 -
- +
+ col_vals_lte @@ -108,7 +108,10 @@
- col_vals_le() +
+
col_vals_le()
+
+
high_floats 100 @@ -134,8 +137,8 @@ #4CA64C66 2 -
- +
+ col_vals_gt @@ -146,7 +149,10 @@
- col_vals_gt() +
+
col_vals_gt()
+
+
Contains(text='not_present', case_sensitive=False) 10 @@ -172,8 +178,8 @@ #4CA64C 3 -
- +
+ col_vals_lt @@ -184,7 +190,10 @@
- col_vals_lt() +
+
col_vals_lt()
+
+
low_numbers 5 diff --git a/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pd_variable_names/selector_helper_functions_no_match.html b/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pd_variable_names/selector_helper_functions_no_match.html index b0882ceb6..a81aa96be 100644 --- a/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pd_variable_names/selector_helper_functions_no_match.html +++ b/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pd_variable_names/selector_helper_functions_no_match.html @@ -96,8 +96,8 @@ #4CA64C 1 -
- +
+ col_vals_lte @@ -108,7 +108,10 @@
- col_vals_le() +
+
col_vals_le()
+
+
high_floats 100 @@ -134,8 +137,8 @@ #4CA64C66 2 -
- +
+ col_vals_gt @@ -146,7 +149,10 @@
- col_vals_gt() +
+
col_vals_gt()
+
+
Contains(text='not_present', case_sensitive=False) 10 @@ -172,8 +178,8 @@ #4CA64C 3 -
- +
+ col_vals_lt @@ -184,7 +190,10 @@
- col_vals_lt() +
+
col_vals_lt()
+
+
low_numbers 5 diff --git a/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pl_variable_names/selector_helper_functions_no_match.html b/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pl_variable_names/selector_helper_functions_no_match.html index cdf01087b..57cd57c55 100644 --- a/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pl_variable_names/selector_helper_functions_no_match.html +++ b/tests/snapshots/test_validate/test_validation_with_selector_helper_functions_no_match_snap/tbl_pl_variable_names/selector_helper_functions_no_match.html @@ -96,8 +96,8 @@ #4CA64C 1 -
- +
+ col_vals_lte @@ -108,7 +108,10 @@
- col_vals_le() +
+
col_vals_le()
+
+
high_floats 100 @@ -134,8 +137,8 @@ #4CA64C66 2 -
- +
+ col_vals_gt @@ -146,7 +149,10 @@
- col_vals_gt() +
+
col_vals_gt()
+
+
Contains(text='not_present', case_sensitive=False) 10 @@ -172,8 +178,8 @@ #4CA64C 3 -
- +
+ col_vals_lt @@ -184,7 +190,10 @@
- col_vals_lt() +
+
col_vals_lt()
+
+
low_numbers 5 From ae4827aa5a8a488ea474cbe2a011d5a37cd87a5c Mon Sep 17 00:00:00 2001 From: Richard Iannone Date: Thu, 27 Mar 2025 18:01:20 -0400 Subject: [PATCH 3/3] Add new snapshot tests --- .../validation_report_with_briefs.html | 309 ++++++++++++++++++ tests/test_validate.py | 28 ++ 2 files changed, 337 insertions(+) create mode 100644 tests/snapshots/test_validate/test_validation_report_briefs_html/validation_report_with_briefs.html diff --git a/tests/snapshots/test_validate/test_validation_report_briefs_html/validation_report_with_briefs.html b/tests/snapshots/test_validate/test_validation_report_briefs_html/validation_report_with_briefs.html new file mode 100644 index 000000000..71701737a --- /dev/null +++ b/tests/snapshots/test_validate/test_validation_report_briefs_html/validation_report_with_briefs.html @@ -0,0 +1,309 @@ +
+ + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Pointblank Validation
Validation example with briefs
Polarssmall_tableWARNING0.1ERROR0.25CRITICAL0.35
STEPCOLUMNSVALUESTBLEVALUNITSPASSFAILWECEXT
#FF33001 +
+ + + col_vals_equal + + + + + + + +
+
+
col_vals_eq()
+
+
+
a3 + + + + + + + +133
0.23
10
0.77
#FF33002 +
+ + + col_vals_lt + + + + + + + +
+
+
col_vals_lt()
+
+
+
c5 + + + + + + + +135
0.38
8
0.62
#4CA64C3 +
+ + + col_vals_gt + + + + + + + +
+
+
col_vals_gt()
+
+

Expect that values in d should be > 100.

+
+
d100 + + + + + + + +1313
1.00
0
0.00
#4CA64C664 +
+ + + col_vals_lte + + + + + + + +
+
+
col_vals_le()
+
+

This is a custom brief for the assertion

+
+
a7 + + + + + + + +1312
0.92
1
0.08
#AAAAAA5 +
+ + + col_vals_gte + + + + + + + +
+
+
col_vals_ge()
+
+

Step 5: {brief}

+
+
d500 + + + + + + + +1311
0.85
2
0.15
+ +
+ \ No newline at end of file diff --git a/tests/test_validate.py b/tests/test_validate.py index 326cf49d7..1f2d0bae4 100644 --- a/tests/test_validate.py +++ b/tests/test_validate.py @@ -5403,6 +5403,34 @@ def test_comprehensive_validation_report_html_snap(snapshot): snapshot.assert_match(edited_report_html_str, "comprehensive_validation_report.html") +def test_validation_report_briefs_html(snapshot): + validation = ( + Validate( + data=load_dataset(), + tbl_name="small_table", + label="Validation example with briefs", + thresholds=Thresholds(warning=0.10, error=0.25, critical=0.35), + ) + .col_vals_eq(columns="a", value=3) # no brief + .col_vals_lt(columns="c", value=5, brief=False) # same as `brief=None` (no brief) + .col_vals_gt(columns="d", value=100, brief=True) # automatically generated brief + .col_vals_le(columns="a", value=7, brief="This is a custom brief for the assertion") + .col_vals_ge(columns="d", value=500, na_pass=True, brief="**Step** {step}: {brief}") + .interrogate() + ) + + html_str = validation.get_tabular_report().as_raw_html() + + # Define the regex pattern to match the entire tag with class "gt_sourcenote" + pattern = r'.*?' + + # Use re.sub to remove the tag + edited_report_html_str = re.sub(pattern, "", html_str, flags=re.DOTALL) + + # Use the snapshot fixture to create and save the snapshot + snapshot.assert_match(edited_report_html_str, "validation_report_with_briefs.html") + + def test_no_interrogation_validation_report_html_snap(snapshot): validation = ( Validate(