17
17
import commonmark
18
18
import narwhals as nw
19
19
from great_tables import GT, from_column, google_font, html, loc, md, style, vals
20
+ from great_tables.gt import _get_column_of_values
20
21
from great_tables.vals import fmt_integer, fmt_number
21
22
from importlib_resources import files
22
23
from narwhals.typing import FrameT
@@ -11483,7 +11484,9 @@ def get_tabular_report(
11483
11484
# Create the label, table type, and thresholds HTML fragments
11484
11485
label_html = _create_label_html(label=self.label, start_time="")
11485
11486
table_type_html = _create_table_type_html(tbl_type=tbl_info, tbl_name=self.tbl_name)
11486
- thresholds_html = _create_thresholds_html(thresholds=thresholds, locale=locale)
11487
+ thresholds_html = _create_thresholds_html(
11488
+ thresholds=thresholds, locale=locale, df_lib=df_lib
11489
+ )
11487
11490
11488
11491
# Compose the subtitle HTML fragment
11489
11492
combined_subtitle = (
@@ -11796,6 +11799,7 @@ def get_tabular_report(
11796
11799
interrogation_performed=interrogation_performed,
11797
11800
active=active,
11798
11801
locale=locale,
11802
+ df_lib=df_lib,
11799
11803
)
11800
11804
11801
11805
# ------------------------------------------------
@@ -11812,6 +11816,7 @@ def get_tabular_report(
11812
11816
interrogation_performed=interrogation_performed,
11813
11817
active=active,
11814
11818
locale=locale,
11819
+ df_lib=df_lib,
11815
11820
)
11816
11821
11817
11822
validation_info_dict["fail"] = _transform_passed_failed(
@@ -11820,6 +11825,7 @@ def get_tabular_report(
11820
11825
interrogation_performed=interrogation_performed,
11821
11826
active=active,
11822
11827
locale=locale,
11828
+ df_lib=df_lib,
11823
11829
)
11824
11830
11825
11831
# ------------------------------------------------
@@ -11999,7 +12005,9 @@ def get_tabular_report(
11999
12005
# Create the label, table type, and thresholds HTML fragments
12000
12006
label_html = _create_label_html(label=self.label, start_time=self.time_start)
12001
12007
table_type_html = _create_table_type_html(tbl_type=tbl_info, tbl_name=self.tbl_name)
12002
- thresholds_html = _create_thresholds_html(thresholds=thresholds, locale=locale)
12008
+ thresholds_html = _create_thresholds_html(
12009
+ thresholds=thresholds, locale=locale, df_lib=df_lib
12010
+ )
12003
12011
12004
12012
# Compose the subtitle HTML fragment
12005
12013
combined_subtitle = (
@@ -14154,41 +14162,122 @@ def _create_label_html(label: str | None, start_time: str) -> str:
14154
14162
)
14155
14163
14156
14164
14157
- def _create_thresholds_html(thresholds: Thresholds, locale: str) -> str:
14165
+ def _format_single_integer_with_gt(value: int, locale: str = "en", df_lib=None) -> str:
14166
+ """Format a single integer using Great Tables GT object to avoid pandas dependency."""
14167
+ if df_lib is None:
14168
+ # Use library detection to select appropriate DataFrame library
14169
+ if _is_lib_present("polars"):
14170
+ import polars as pl
14171
+
14172
+ df_lib = pl
14173
+ elif _is_lib_present("pandas"):
14174
+ import pandas as pd
14175
+
14176
+ df_lib = pd
14177
+ else:
14178
+ raise ImportError("Neither Polars nor Pandas is available for formatting")
14179
+
14180
+ # Create a single-row, single-column DataFrame using the specified library
14181
+ df = df_lib.DataFrame({"value": [value]})
14182
+
14183
+ # Create GT object and format the column
14184
+ gt_obj = GT(df).fmt_integer(columns="value", locale=locale)
14185
+
14186
+ # Extract the formatted value using _get_column_of_values
14187
+ formatted_values = _get_column_of_values(gt_obj, column_name="value", context="html")
14188
+
14189
+ return formatted_values[0] # Return the single formatted value
14190
+
14191
+
14192
+ def _format_single_float_with_gt_custom(
14193
+ value: float,
14194
+ decimals: int = 2,
14195
+ drop_trailing_zeros: bool = False,
14196
+ locale: str = "en",
14197
+ df_lib=None,
14198
+ ) -> str:
14199
+ """Format a single float with custom options using Great Tables GT object to avoid pandas dependency."""
14200
+ if df_lib is None:
14201
+ # Use library detection to select appropriate DataFrame library
14202
+ if _is_lib_present("polars"):
14203
+ import polars as pl
14204
+
14205
+ df_lib = pl
14206
+ elif _is_lib_present("pandas"):
14207
+ import pandas as pd
14208
+
14209
+ df_lib = pd
14210
+ else:
14211
+ raise ImportError("Neither Polars nor Pandas is available for formatting")
14212
+
14213
+ # Create a single-row, single-column DataFrame using the specified library
14214
+ df = df_lib.DataFrame({"value": [value]})
14215
+
14216
+ # Create GT object and format the column
14217
+ gt_obj = GT(df).fmt_number(
14218
+ columns="value", decimals=decimals, drop_trailing_zeros=drop_trailing_zeros, locale=locale
14219
+ )
14220
+
14221
+ # Extract the formatted value using _get_column_of_values
14222
+ formatted_values = _get_column_of_values(gt_obj, column_name="value", context="html")
14223
+
14224
+ return formatted_values[0] # Return the single formatted value
14225
+
14226
+
14227
+ def _create_thresholds_html(thresholds: Thresholds, locale: str, df_lib=None) -> str:
14158
14228
if thresholds == Thresholds():
14159
14229
return ""
14160
14230
14231
+ # Helper functions to format numbers safely
14232
+ def _format_number_safe(value: float, decimals: int, drop_trailing_zeros: bool = False) -> str:
14233
+ if df_lib is not None and value is not None:
14234
+ # Use GT-based formatting to avoid Pandas dependency completely
14235
+ return _format_single_float_with_gt_custom(
14236
+ value,
14237
+ decimals=decimals,
14238
+ drop_trailing_zeros=drop_trailing_zeros,
14239
+ locale=locale,
14240
+ df_lib=df_lib,
14241
+ )
14242
+ else:
14243
+ # Fallback to the original behavior
14244
+ return fmt_number(
14245
+ value, decimals=decimals, drop_trailing_zeros=drop_trailing_zeros, locale=locale
14246
+ )[0]
14247
+
14248
+ def _format_integer_safe(value: int) -> str:
14249
+ if df_lib is not None and value is not None:
14250
+ # Use GT-based formatting to avoid Pandas dependency completely
14251
+ return _format_single_integer_with_gt(value, locale=locale, df_lib=df_lib)
14252
+ else:
14253
+ # Fallback to the original behavior
14254
+ return fmt_integer(value, locale=locale)[0]
14255
+
14161
14256
warning = (
14162
- fmt_number(
14163
- thresholds.warning_fraction, decimals=3, drop_trailing_zeros=True, locale=locale
14164
- )[0]
14257
+ _format_number_safe(thresholds.warning_fraction, decimals=3, drop_trailing_zeros=True)
14165
14258
if thresholds.warning_fraction is not None
14166
14259
else (
14167
- fmt_integer (thresholds.warning_count, locale=locale)[0]
14260
+ _format_integer_safe (thresholds.warning_count)
14168
14261
if thresholds.warning_count is not None
14169
14262
else "—"
14170
14263
)
14171
14264
)
14172
14265
14173
14266
error = (
14174
- fmt_number(thresholds.error_fraction, decimals=3, drop_trailing_zeros=True, locale=locale)[
14175
- 0
14176
- ]
14267
+ _format_number_safe(thresholds.error_fraction, decimals=3, drop_trailing_zeros=True)
14177
14268
if thresholds.error_fraction is not None
14178
14269
else (
14179
- fmt_integer (thresholds.error_count, locale=locale)[0]
14270
+ _format_integer_safe (thresholds.error_count)
14180
14271
if thresholds.error_count is not None
14181
14272
else "—"
14182
14273
)
14183
14274
)
14184
14275
14185
14276
critical = (
14186
- fmt_number(
14187
- thresholds.critical_fraction, decimals=3, drop_trailing_zeros=True, locale=locale
14188
- )[0]
14277
+ _format_number_safe(thresholds.critical_fraction, decimals=3, drop_trailing_zeros=True)
14189
14278
if thresholds.critical_fraction is not None
14190
14279
else (
14191
- fmt_integer (thresholds.critical_count, locale=locale)[0]
14280
+ _format_integer_safe (thresholds.critical_count)
14192
14281
if thresholds.critical_count is not None
14193
14282
else "—"
14194
14283
)
0 commit comments