Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ jobs:
- name: Install dependencies
run: |
pip install -e '.[extra]'
pip install -e '.[css]'
pip install pandas
- name: save browser tables
run: |
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,5 @@ latex_testing.qmd
latex_testing.pdf
latex_examples.qmd
latex_examples.pdf

uv.lock
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ test-no-pandas:
test-update:
pytest --snapshot-update

install-pre-commit: # Install pre-commit hooks
@uvx pre-commit install

run-pre-commit: # Run pre-commit hooks
@uvx pre-commit run --all-files

check:
pyright --pythonversion 3.8 gt
pyright --pythonversion 3.9 gt
Expand Down
6 changes: 3 additions & 3 deletions great_tables/_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ def as_raw_html(
)

if inline_css:
_try_import(name="css_inline", pip_install_line="pip install css-inline")
_try_import(pkg="css_inline", group="css")
from css_inline import inline, inline_fragment

if make_page:
Expand Down Expand Up @@ -437,7 +437,7 @@ def save(

"""
# Import the required packages
_try_import(name="selenium", pip_install_line="pip install selenium")
_try_import(pkg="selenium", group="extra")

from ._utils_selenium import _get_web_driver

Expand Down Expand Up @@ -555,7 +555,7 @@ def _save_screenshot(

el = WebDriverWait(driver, 1).until(EC.visibility_of_element_located((By.TAG_NAME, "body")))

_try_import(name="PIL", pip_install_line="pip install pillow")
_try_import(pkg="PIL", group="extra")

from PIL import Image

Expand Down
19 changes: 8 additions & 11 deletions great_tables/_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import contextlib
import importlib
import itertools
import re
Expand All @@ -15,17 +16,13 @@
from ._tbl_data import TblData


def _try_import(name: str, pip_install_line: str | None = None) -> ModuleType:
try:
return importlib.import_module(name)
except ImportError:
if pip_install_line is not None:
raise ImportError(
f"Module {name} not found. Run the following to install."
f"\n\n`{pip_install_line}`"
) from None
else:
raise ImportError(f"Module {name} not found.")
def _try_import(pkg: str, group: str) -> ModuleType:
"""Try importing a optionally dependent package."""
with contextlib.suppress(ImportError):
return importlib.import_module(pkg)

msg = f"Module `{pkg!s}` not found. Install with `<pkg manager> install great-tables[{group}]`."
raise ImportError(msg)


def heading_has_title(title: str | BaseText | None) -> bool:
Expand Down
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,15 @@ requires-python = ">=3.9"
[project.optional-dependencies]
all = [
"great_tables[extra]",
"great_tables[css]",
"great_tables[dev]",
]

extra = [
css = [
"css-inline>=0.14.1",
]

extra = [
"selenium>=4.18.1",
"Pillow>=10.2.0",
]
Expand Down Expand Up @@ -98,6 +102,7 @@ testpaths = [

markers = [
"extra: marks tests that require extra dependencies to run",
"css: marks tests that require CSS support",
"no_pandas: test meant to run without pandas installed",
]

Expand Down
19 changes: 19 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,28 @@
heading_has_subtitle,
heading_has_title,
seq_groups,
_try_import,
)


@pytest.mark.parametrize(
"args",
[
("selenium", "extras"),
("PIL", "extras"),
("css_inline", "css"),
],
)
def test_try_import_success(args: tuple[str, str]) -> None:
module = _try_import(*args)
assert module is not None


def test_try_import_failure() -> None:
with pytest.raises(ImportError, match="not found. Install with"):
_try_import("non_existent_lib", "extras")


def test_heading_has_title():
assert heading_has_title("title")
assert not heading_has_title(None)
Expand Down
Loading