Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: quarto option to disable table processing, warn on render #611

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
9 changes: 6 additions & 3 deletions great_tables/_gt_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from collections.abc import Sequence
from dataclasses import dataclass, field, replace
from enum import Enum, auto
from typing import Any, Callable, TypeVar, overload, TYPE_CHECKING, Literal
from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, overload

from typing_extensions import Self, TypeAlias, Union

Expand All @@ -15,17 +15,17 @@
DataFrameLike,
TblData,
_get_cell,
_get_column_dtype,
_set_cell,
copy_data,
create_empty_frame,
get_column_names,
_get_column_dtype,
n_rows,
to_list,
validate_frame,
)
from ._text import BaseText
from ._utils import _str_detect, OrderedSet
from ._utils import OrderedSet, _str_detect

if TYPE_CHECKING:
from ._helpers import UnitStr
Expand Down Expand Up @@ -1219,6 +1219,9 @@ class Options:
quarto_disable_processing: OptionsInfo = OptionsInfo(False, "quarto", "logical", False)
quarto_use_bootstrap: OptionsInfo = OptionsInfo(False, "quarto", "logical", False)

def __getitem__(self, k: str) -> Any:
return getattr(self, k).value

def _get_all_options_keys(self) -> list[str | None]:
return [x.parameter for x in self._options.values()]

Expand Down
6 changes: 4 additions & 2 deletions great_tables/_options.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from __future__ import annotations

from dataclasses import dataclass, fields, replace
from typing import TYPE_CHECKING, ClassVar, cast, Iterable
from typing import TYPE_CHECKING, ClassVar, Iterable, cast

from . import _utils
from ._helpers import FontStackName, GoogleFont, _intify_scaled_px, px


if TYPE_CHECKING:
from ._types import GTSelf

Expand Down Expand Up @@ -164,6 +163,7 @@ def tab_options(
row_striping_background_color: str | None = None,
row_striping_include_stub: bool | None = None,
row_striping_include_table_body: bool | None = None,
quarto_disable_processing: bool | None = None,
) -> GTSelf:
"""
Modify the table output options.
Expand Down Expand Up @@ -473,6 +473,8 @@ def tab_options(
An option for whether to include the stub when striping rows.
row_striping_include_table_body
An option for whether to include the table body when striping rows.
quarto_disable_processing
Whether to disable Quarto table processing.


Returns
Expand Down
38 changes: 38 additions & 0 deletions great_tables/_render_checks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import warnings

from ._gt_data import GTData
from ._render import infer_render_env


class RenderWarning(Warning):
"""Base warning for render checks."""


def _render_check(data: GTData):
if infer_render_env() == "quarto":
_render_check_quarto(data)


def _render_check_quarto(data: GTData):
"""Check for rendering issues in Quarto.

* Quarto uses Pandoc internally to handle tables, and Pandoc tables do not support pixel widths.
As a result, when cols_width is used in a Quarto environment, widths need to be converted to
percentages.
* Alternatively, users may set the option quarto_disable_processing to True.
* Disabling table processing also helps with pieces like table striping, but means Quarto will
not process cross-references, etc..
"""

# quarto_disable_processing is set, no need to warn ----
if data._options["quarto_disable_processing"]:
return

# cols_widths set ----
if any([col.column_width is not None for col in data._boxhead]):
warnings.warn(
"Rendering table with .col_widths() in Quarto may result in unexpected behavior."
" This is because Quarto performs custom table processing."
" Set .tab_options(quarto_disable_processing=True) to disable Quarto table processing.",
RenderWarning,
)
4 changes: 4 additions & 0 deletions great_tables/gt.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
)
from ._pipe import pipe
from ._render import infer_render_env_defaults
from ._render_checks import _render_check
from ._source_notes import tab_source_note
from ._spanners import (
cols_hide,
Expand Down Expand Up @@ -350,6 +351,9 @@ def _render_as_html(
make_page: bool = False,
all_important: bool = False,
) -> str:
# TODO: better to put these checks in a pre render hook?
_render_check(self)

heading_component = create_heading_component_h(data=self)
column_labels_component = create_columns_component_h(data=self)
body_component = create_body_component_h(data=self)
Expand Down
48 changes: 48 additions & 0 deletions tests/test__render_checks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import warnings

import pytest

from contextlib import contextmanager
from great_tables import GT, exibble
from great_tables._render import infer_render_env
from great_tables._render_checks import RenderWarning, _render_check_quarto


@contextmanager
def set_quarto_env():
import os

orig = os.environ.get("QUARTO_BIN_PATH", None)

try:
os.environ["QUARTO_BIN_PATH"] = "1"
yield
finally:
if orig is not None:
os.environ["QUARTO_BIN_PATH"] = orig
else:
del os.environ["QUARTO_BIN_PATH"]


def test_check_quarto_runs():
gt = GT(exibble).cols_width({"num": "100px"})

with set_quarto_env(), pytest.warns(RenderWarning):
assert infer_render_env() == "quarto"
gt.render("html")


def test_check_quarto_disable_processing():
gt = GT(exibble).cols_width({"num": "100px"}).tab_options(quarto_disable_processing=True)

# assert no warning issued
with warnings.catch_warnings():
warnings.simplefilter("error")
_render_check_quarto(gt)


def test_check_quarto_cols_width():
gt = GT(exibble).cols_width({"num": "100px"})

with pytest.warns(RenderWarning):
_render_check_quarto(gt)
Loading