def expect_column_values_to_not_be_null(cls, ge_object): return [[ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Missing (n)", "tooltip": { "content": "expect_column_values_to_not_be_null" } } }), ge_object.result["unexpected_count"] if "unexpected_count" in ge_object.result and ge_object.result["unexpected_count"] is not None else "--", ], [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Missing (%)", "tooltip": { "content": "expect_column_values_to_not_be_null" } } }), "%.1f%%" % ge_object.result["unexpected_percent"] if "unexpected_percent" in ge_object.result and ge_object.result["unexpected_percent"] is not None else "--", ]]
def _render_dataset_info(cls, evrs, content_blocks) -> None: expect_table_row_count_to_be_between_evr = cls._find_evr_by_type( evrs["results"], "expect_table_row_count_to_be_between") table_rows = [] table_rows.append([ "Number of variables", len(cls._get_column_list_from_evrs(evrs)), ]) table_rows.append([ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Number of observations", "tooltip": { "content": "expect_table_row_count_to_be_between" }, "params": { "tooltip_text": "Number of observations" }, }, }), "--" if not expect_table_row_count_to_be_between_evr else expect_table_row_count_to_be_between_evr.result["observed_value"], ]) table_rows += [ [ "Missing cells", cls._get_percentage_missing_cells_str(evrs), ], # ["Duplicate rows", "0 (0.0%)", ], #TODO: bring back when we have an expectation for this ] content_blocks.append( RenderedTableContent( **{ "content_block_type": "table", "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Dataset info", "tag": "h6", }, }), "table": table_rows, "styling": { "classes": ["col-6", "mt-1", "p-1"], "body": { "classes": ["table", "table-sm"] }, }, }))
def test_ValidationResultsTableContentBlockRenderer_get_content_block_fn( evr_success): content_block_fn = ValidationResultsTableContentBlockRenderer._get_content_block_fn( "expect_table_row_count_to_be_between") content_block_fn_output = content_block_fn(evr_success) content_block_fn_expected_output = [[ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "$icon", "params": { "icon": "", "markdown_status_icon": "✅" }, "styling": { "params": { "icon": { "classes": [ "fas", "fa-check-circle", "text-success", ], "tag": "i", } } }, }, "styling": { "parent": { "classes": ["hide-succeeded-validation-target-child"] } }, }), RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Must have greater than or equal to $min_value rows.", "params": { "min_value": 0, "max_value": None, "result_format": "SUMMARY", "row_condition": None, "condition_parser": None, "strict_max": None, "strict_min": None, }, "styling": None, }, }), "1,313", ]] assert content_block_fn_output == content_block_fn_expected_output
def _render_header(cls, evrs, column_type=None): # NOTE: This logic is brittle try: column_name = evrs[0].expectation_config.kwargs["column"] except KeyError: column_name = "Table-level expectations" return RenderedHeaderContent( **{ "content_block_type": "header", "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": convert_to_string_and_escape( column_name), "tooltip": { "content": "expect_column_to_exist", "placement": "top" }, "tag": "h5", "styling": { "classes": ["m-0", "p-0"] } } }), "subheader": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Type: {column_type}".format( column_type=column_type), "tooltip": { "content": "expect_column_values_to_be_of_type <br>expect_column_values_to_be_in_type_list", }, "tag": "h6", "styling": { "classes": ["mt-1", "mb-0"] } } }), # { # "template": column_type, # }, "styling": { "classes": ["col-12", "p-0"], "header": { "classes": ["alert", "alert-secondary"] } } })
def _missing_content_block_fn(cls, evr, styling=None, include_column_name=True): # Only render EVR objects for which an exception was raised if evr.exception_info["raised_exception"] is True: template_str = "$expectation_type raised an exception: $exception_message" if include_column_name: template_str = "$column: " + template_str try: column = evr.expectation_config.kwargs["column"] except KeyError: column = None return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": { "column": column, "expectation_type": evr.expectation_config.expectation_type, "exception_message": evr.exception_info["exception_message"], }, "styling": styling, }, }) ]
def _descriptive_histogram_renderer( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs ): assert result, "Must pass in result." observed_partition_object = result.result["details"]["observed_partition"] weights = observed_partition_object["weights"] if len(weights) > 60: return None header = RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Histogram", "tooltip": { "content": "expect_column_kl_divergence_to_be_less_than" }, "tag": "h6", }, } ) return cls._get_kl_divergence_chart(observed_partition_object, header)
def _render_properties_table(self, evrs): evr_list = [ self._find_evr_by_type( evrs, "expect_column_unique_value_count_to_be_between" ), self._find_evr_by_type( evrs, "expect_column_proportion_of_unique_values_to_be_between" ), self._find_evr_by_type(evrs, "expect_column_values_to_not_be_null"), self._find_evr_by_type(evrs, "expect_column_values_to_not_match_regex"), ] evrs = [evr for evr in evr_list if (evr is not None)] if len(evrs) > 0: new_content_block = self._properties_table_renderer.render(evrs) new_content_block.header = RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": {"template": "Properties", "tag": "h6"}, } ) new_content_block.styling = { "classes": ["col-3", "mt-1", "pl-1", "pr-1"], "body": { "classes": ["table", "table-sm", "table-unbordered"], "styles": {"width": "100%"}, }, } return new_content_block
def _render_validation_success_cell(cls, validation_success): return RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "$validation_success", "params": { "validation_success": "" }, "styling": { "params": { "validation_success": { "tag": "i", "classes": [ "fas", "fa-check-circle", "text-success", "ge-success-icon", ] if validation_success else [ "fas", "fa-times", "text-danger", "ge-failed-icon", ], } }, "classes": ["ge-index-page-table-validation-links-item"], }, }, })
def _get_kl_divergence_observed_value(cls, evr): if not evr.result.get("details"): return "--" observed_partition_object = evr.result["details"]["observed_partition"] observed_distribution = super()._get_kl_divergence_chart( observed_partition_object) observed_value = (num_to_str(evr.result.get("observed_value")) if evr.result.get("observed_value") else evr.result.get("observed_value")) observed_value_content_block = RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "KL Divergence: $observed_value", "params": { "observed_value": str(observed_value) if observed_value else "None (-infinity, infinity, or NaN)", }, "styling": { "classes": ["mb-2"] }, }, }) return RenderedContentBlockContainer( **{ "content_block_type": "content_block_container", "content_blocks": [observed_value_content_block, observed_distribution], })
def _prescriptive_renderer(cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs): runtime_configuration = runtime_configuration or {} include_column_name = runtime_configuration.get( "include_column_name", True) include_column_name = (include_column_name if include_column_name is not None else True) styling = runtime_configuration.get("styling") params = substitute_none_for_missing(configuration.kwargs, ["other_table_name"]) template_str = "Row count must equal the row count of table $other_table_name." return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": params, "styling": styling, }, }) ]
def _prescriptive_renderer( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs, ): runtime_configuration = runtime_configuration or {} styling = runtime_configuration.get("styling") params = substitute_none_for_missing( configuration.kwargs, [ "column_list", "ignore_row_if", "row_condition", "condition_parser", "mostly", ], ) if params["mostly"] is not None and params["mostly"] < 1.0: params_with_json_schema["mostly_pct"]["value"] = num_to_str( params["mostly"] * 100, precision=15, no_scientific=True) template_str = f"Values for given compound columns must be unique together, at least $mostly_pct % of the time: " else: template_str = ( f"Values for given compound columns must be unique together: ") for idx in range(len(params["column_list"]) - 1): template_str += f"$column_list_{str(idx)}, " params[f"column_list_{str(idx)}"] = params["column_list"][idx] last_idx = len(params["column_list"]) - 1 template_str += f"$column_list_{str(last_idx)}" params[f"column_list_{str(last_idx)}"] = params["column_list"][ last_idx] if params["row_condition"] is not None: ( conditional_template_str, conditional_params, ) = parse_row_condition_string_pandas_engine( params["row_condition"]) template_str = (conditional_template_str + ", then " + template_str[0].lower() + template_str[1:]) params.update(conditional_params) return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": params, "styling": styling, }, }) ]
def _prescriptive_renderer( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs, ): runtime_configuration = runtime_configuration or {} include_column_name = runtime_configuration.get( "include_column_name", True) include_column_name = (include_column_name if include_column_name is not None else True) styling = runtime_configuration.get("styling") params = substitute_none_for_missing( configuration.kwargs, ["column", "mostly", "row_condition", "condition_parser"], ) return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": params, "styling": styling, }, }) ]
def _get_header_content_block(cls, header="", subheader="", highlight=True): return RenderedHeaderContent( **{ "content_block_type": "header", "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": header, }, }), "subheader": subheader, "styling": { "classes": ["col-12"], "header": { "classes": ["alert", "alert-secondary"] if highlight else [] }, }, })
def _missing_content_block_fn( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs, ): return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "styling": { "parent": { "classes": ["alert", "alert-warning"] } }, "string_template": { "template": "$expectation_type(**$kwargs)", "params": { "expectation_type": configuration.expectation_type, "kwargs": configuration.kwargs, }, "styling": { "params": { "expectation_type": { "classes": ["badge", "badge-warning"], } } }, }, }) ]
def _prescriptive_renderer( cls, configuration: ExpectationConfiguration = None, result: ExpectationValidationResult = None, language: str = None, runtime_configuration: dict = None, **kwargs, ) -> List[ Union[ dict, str, RenderedStringTemplateContent, RenderedTableContent, RenderedBulletListContent, RenderedGraphContent, Any, ] ]: runtime_configuration = runtime_configuration or {} include_column_name = runtime_configuration.get("include_column_name", True) include_column_name = ( include_column_name if include_column_name is not None else True ) styling = runtime_configuration.get("styling") params = substitute_none_for_missing( configuration.kwargs, [ "column", "word", "provider", "mostly", ], ) if params["mostly"] is None: template_str = "values must be lat lon and contain $word when reverse geocoded by $provider" else: if params["mostly"] is not None: params["mostly_pct"] = num_to_str( params["mostly"] * 100, precision=15, no_scientific=True ) template_str += ", at least $mostly_pct % of the time." else: template_str += "." if include_column_name: template_str = f"$column {template_str}" return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": params, "styling": styling, }, } ) ]
def _render_header(cls, evrs, content_blocks) -> None: content_blocks.append( RenderedHeaderContent( **{ "content_block_type": "header", "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Overview", "tag": "h5", "styling": { "classes": ["m-0"] }, }, }), "styling": { "classes": ["col-12", "p-0"], "header": { "classes": ["alert", "alert-secondary"] }, }, }))
def _get_string_template_content_block(cls): return RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "$icon This is a Font Awesome Icon, using a param-level custom tag\n$red_text\n$bold_serif", "params": { "icon": "", "red_text": "And this is red text!", "bold_serif": "And this is big, bold serif text using style attribute...", }, "styling": { "params": { "icon": { "classes": ["fas", "fa-check-circle", "text-success"], "tag": "i", }, "red_text": {"classes": ["text-danger"]}, "bold_serif": { "styles": { "font-size": "22px", "font-weight": "bold", "font-family": "serif", } }, } }, }, "styling": {"classes": ["col-12"], "styles": {"margin-top": "20px"},}, } )
def _render_expectation_types(cls, evrs, content_blocks): # NOTE: The evr-fetching function is an kinda similar to the code other_section_ # renderer.ProfilingResultsOverviewSectionRenderer._render_expectation_types # type_counts = defaultdict(int) # for evr in evrs: # type_counts[evr.expectation_config.expectation_type] += 1 # bullet_list = sorted(type_counts.items(), key=lambda kv: -1*kv[1]) bullet_list = [{ "content_block_type": "string_template", "string_template": { "template": "$expectation_type $is_passing", "params": { "expectation_type": evr.expectation_config.expectation_type, "is_passing": str(evr.success), }, "styling": { "classes": ["list-group-item", "d-flex", "justify-content-between", "align-items-center"], "params": { "is_passing": { "classes": ["badge", "badge-secondary", "badge-pill"], } }, } } } for evr in evrs] content_blocks.append(RenderedBulletListContent(**{ "content_block_type": "bullet_list", "header": RenderedStringTemplateContent(**{ "content_block_type": "string_template", "string_template": { "template": 'Expectation types <span class="mr-3 triangle"></span>', "tag": "h6" } }), "bullet_list": bullet_list, "styling": { "classes": ["col-12", "mt-1"], "header": { "classes": ["collapsed"], "attributes": { "data-toggle": "collapse", "href": "#{{content_block_id}}-body", "role": "button", "aria-expanded": "true", "aria-controls": "collapseExample", }, "styles": { "cursor": "pointer", } }, "body": { "classes": ["list-group", "collapse"], }, }, }))
def _diagnostic_observed_value_renderer(cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs): if not result.result.get("observed_value"): return "--" self_table_row_count = num_to_str( result.result["observed_value"]["self"]) other_table_row_count = num_to_str( result.result["observed_value"]["other"]) return RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Row Count: $self_table_row_count<br>Other Table Row Count: $other_table_row_count", "params": { "self_table_row_count": self_table_row_count, "other_table_row_count": other_table_row_count, }, "styling": { "classes": ["mb-2"] }, }, })
def _render_variable_types(cls, evrs, content_blocks) -> None: column_types = cls._get_column_types(evrs) # TODO: check if we have the information to make this statement. Do all columns have type expectations? column_type_counter = Counter(column_types.values()) table_rows = [ [type, str(column_type_counter[type])] for type in ["int", "float", "string", "datetime", "bool", "unknown"] ] content_blocks.append( RenderedTableContent( **{ "content_block_type": "table", "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Variable types", "tag": "h6", }, }), "table": table_rows, "styling": { "classes": ["col-6", "table-responsive", "mt-1", "p-1"], "body": { "classes": ["table", "table-sm"] }, }, }))
def _prescriptive_renderer( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs, ): runtime_configuration = runtime_configuration or {} include_column_name = runtime_configuration.get( "include_column_name", True) include_column_name = (include_column_name if include_column_name is not None else True) styling = runtime_configuration.get("styling") params = substitute_none_for_missing( configuration.kwargs, [ "column", "value_set", "ties_okay", "row_condition", "condition_parser" ], ) if params["value_set"] is None or len(params["value_set"]) == 0: values_string = "[ ]" else: for i, v in enumerate(params["value_set"]): params["v__" + str(i)] = v values_string = " ".join( ["$v__" + str(i) for i, v in enumerate(params["value_set"])]) template_str = ("most common value must belong to this set: " + values_string + ".") if params.get("ties_okay"): template_str += " Values outside this set that are as common (but not more common) are allowed." if include_column_name: template_str = "$column " + template_str if params["row_condition"] is not None: ( conditional_template_str, conditional_params, ) = parse_row_condition_string_pandas_engine( params["row_condition"]) template_str = conditional_template_str + ", then " + template_str params.update(conditional_params) return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": params, "styling": styling, }, }) ]
def _prescriptive_renderer( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs, ): runtime_configuration = runtime_configuration or {} include_column_name = runtime_configuration.get( "include_column_name", True) include_column_name = (include_column_name if include_column_name is not None else True) styling = runtime_configuration.get("styling") params = substitute_none_for_missing(configuration.kwargs, ["column_A", "column_B"]) if (params["column_A"] is None) or (params["column_B"] is None): template_str = " unrecognized kwargs for expect_column_pair_cramers_phi_value_to_be_less_than: missing column." else: template_str = "Values in $column_A and $column_B must be independent." rendered_string_template_content = RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": params, "styling": styling, }, }) return [rendered_string_template_content]
def _render_histogram(self, evrs): # NOTE: This code is very brittle kl_divergence_evr = self._find_evr_by_type( evrs, "expect_column_kl_divergence_to_be_less_than") # print(json.dumps(kl_divergence_evr, indent=2)) if kl_divergence_evr is None or kl_divergence_evr.result is None or "details" not in kl_divergence_evr.result: return observed_partition_object = kl_divergence_evr.result["details"][ "observed_partition"] weights = observed_partition_object["weights"] if len(weights) > 60: return None header = RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Histogram", "tooltip": { "content": "expect_column_kl_divergence_to_be_less_than" }, "tag": "h6" } }) return self._expectation_string_renderer._get_kl_divergence_chart( observed_partition_object, header)
def _render_header(cls, expectations): column = cls._get_column_name(expectations) new_block = RenderedHeaderContent( **{ "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": convert_to_string_and_escape(column), "tag": "h5", "styling": { "classes": ["m-0"] } } }), "styling": { "classes": ["col-12"], "header": { "classes": ["alert", "alert-secondary"] } } }) return expectations, new_block
def _render_overview_table(self, evrs): unique_n = self._find_evr_by_type( evrs, "expect_column_unique_value_count_to_be_between") unique_proportion = self._find_evr_by_type( evrs, "expect_column_proportion_of_unique_values_to_be_between") null_evr = self._find_evr_by_type( evrs, "expect_column_values_to_not_be_null") evrs = [ evr for evr in [unique_n, unique_proportion, null_evr] if (evr is not None) ] if len(evrs) > 0: new_content_block = self._overview_table_renderer.render(evrs) new_content_block.header = RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": 'Properties', "tag": "h6" } }) new_content_block.styling = { "classes": ["col-3", "mt-1", "pl-1", "pr-1"], "body": { "classes": ["table", "table-sm", "table-unbordered"], "styles": { "width": "100%" }, } } return new_content_block
def _descriptive_column_properties_table_distinct_count_row_renderer( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs, ): assert result, "Must pass in result." observed_value = result.result["observed_value"] template_string_object = RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Distinct (n)", "tooltip": { "content": "expect_column_unique_value_count_to_be_between" }, }, } ) if not observed_value: return [template_string_object, "--"] else: return [template_string_object, observed_value]
def _render_values_set(cls, evrs): set_evr = cls._find_evr_by_type(evrs, "expect_column_values_to_be_in_set") if not set_evr or set_evr.exception_info["raised_exception"]: return if set_evr and "partial_unexpected_counts" in set_evr.result: partial_unexpected_counts = set_evr.result["partial_unexpected_counts"] values = [str(v["value"]) for v in partial_unexpected_counts] elif set_evr and "partial_unexpected_list" in set_evr.result: values = [str(item) for item in set_evr.result["partial_unexpected_list"]] else: return classes = ["col-3", "mt-1", "pl-1", "pr-1"] if any(len(value) > 80 for value in values): content_block_type = "bullet_list" content_block_class = RenderedBulletListContent else: content_block_type = "value_list" content_block_class = ValueListContent new_block = content_block_class( **{ "content_block_type": content_block_type, "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Example Values", "tooltip": {"content": "expect_column_values_to_be_in_set"}, "tag": "h6", }, } ), content_block_type: [ { "content_block_type": "string_template", "string_template": { "template": "$value", "params": {"value": value}, "styling": { "default": { "classes": ["badge", "badge-info"] if content_block_type == "value_list" else [], "styles": {"word-break": "break-all"}, }, }, }, } for value in values ], "styling": {"classes": classes,}, } ) return new_block
def _render_validation_info(cls, validation_results): run_id = validation_results.meta["run_id"] if isinstance(run_id, str): try: run_time = parse(run_id).strftime("%Y-%m-%dT%H:%M:%SZ") except (ValueError, TypeError): run_time = "__none__" run_name = run_id elif isinstance(run_id, dict): run_name = run_id.get("run_name") or "__none__" try: run_time = str( parse( run_id.get("run_time")).strftime("%Y-%m-%dT%H:%M:%SZ")) except (ValueError, TypeError): run_time = "__none__" elif isinstance(run_id, RunIdentifier): run_name = run_id.run_name or "__none__" run_time = run_id.run_time.strftime("%Y-%m-%dT%H:%M:%SZ") # TODO: Deprecate "great_expectations.__version__" ge_version = validation_results.meta.get( "great_expectations_version") or validation_results.meta.get( "great_expectations.__version__") return RenderedTableContent( **{ "content_block_type": "table", "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": "Info", "tag": "h6", "styling": { "classes": ["m-0"] }, }, }), "table": [ ["Great Expectations Version", ge_version], ["Run Name", run_name], ["Run Time", run_time], ], "styling": { "classes": ["col-12", "table-responsive", "mt-1"], "body": { "classes": ["table", "table-sm"], "styles": { "margin-bottom": "0.5rem !important", "margin-top": "0.5rem !important", }, }, }, })
def _render_quantile_table(cls, evrs): table_rows = [] quantile_evr = cls._find_evr_by_type( evrs, "expect_column_quantile_values_to_be_between") if not quantile_evr or quantile_evr.exception_info["raised_exception"]: return quantiles = quantile_evr.result["observed_value"]["quantiles"] quantile_ranges = quantile_evr.result["observed_value"]["values"] quantile_strings = {.25: "Q1", .75: "Q3", .50: "Median"} for idx, quantile in enumerate(quantiles): quantile_string = quantile_strings.get(quantile) table_rows.append([ { "content_block_type": "string_template", "string_template": { "template": quantile_string if quantile_string else "{:3.2f}".format(quantile), "tooltip": { "content": "expect_column_quantile_values_to_be_between \n expect_column_median_to_be_between" if quantile == 0.50 else "expect_column_quantile_values_to_be_between" } } }, quantile_ranges[idx], ]) return RenderedTableContent( **{ "content_block_type": "table", "header": RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": 'Quantiles', "tag": "h6" } }), "table": table_rows, "styling": { "classes": ["col-3", "mt-1", "pl-1", "pr-1"], "body": { "classes": ["table", "table-sm", "table-unbordered"], } }, })
def _prescriptive_renderer( cls, configuration=None, result=None, language=None, runtime_configuration=None, **kwargs, ): runtime_configuration = runtime_configuration or {} include_column_name = runtime_configuration.get("include_column_name", True) include_column_name = ( include_column_name if include_column_name is not None else True ) styling = runtime_configuration.get("styling") params = substitute_none_for_missing( configuration.kwargs, ["column", "mostly", "row_condition", "condition_parser"], ) if params["mostly"] is not None and params["mostly"] < 1.0: params["mostly_pct"] = num_to_str( params["mostly"] * 100, precision=15, no_scientific=True ) # params["mostly_pct"] = "{:.14f}".format(params["mostly"]*100).rstrip("0").rstrip(".") if include_column_name: template_str = "$column values must not be null, at least $mostly_pct % of the time." else: template_str = ( "values must not be null, at least $mostly_pct % of the time." ) else: if include_column_name: template_str = "$column values must never be null." else: template_str = "values must never be null." if params["row_condition"] is not None: ( conditional_template_str, conditional_params, ) = parse_row_condition_string_pandas_engine(params["row_condition"]) template_str = f"{conditional_template_str}, then {template_str}" params.update(conditional_params) return [ RenderedStringTemplateContent( **{ "content_block_type": "string_template", "string_template": { "template": template_str, "params": params, "styling": styling, }, } ) ]