Skip to content
Merged
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
8 changes: 8 additions & 0 deletions docs/options/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ indicators = false
handler = false
```

The configuration file is loaded when `itables` is imported - you will need to restart Python and re-import ITables to get the latest configuration.

You can confirm which configuration file is being used (in a given directory) by running
```
python -m itables.show_config
```


## Option Names and Type Checks

Option names and types are checked by default at runtime when `typeguard>=4.4.1` is installed. You can disable this by setting `warn_on_undocumented_option=False`.
Expand Down
8 changes: 8 additions & 0 deletions docs/py/options/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@
# handler = false
# ```
#
# The configuration file is loaded when `itables` is imported - you will need to restart Python and re-import ITables to get the latest configuration.
#
# You can confirm which configuration file is being used (in a given directory) by running
# ```
# python -m itables.show_config
# ```
#
#
# ## Option Names and Type Checks
#
# Option names and types are checked by default at runtime when `typeguard>=4.4.1` is installed. You can disable this by setting `warn_on_undocumented_option=False`.
Expand Down
3 changes: 2 additions & 1 deletion src/itables/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from itables import downsample, options, sample_dfs
from itables import config, downsample, options, sample_dfs

from .javascript import init_notebook_mode, show, to_html_datatable
from .typing import (
Expand All @@ -20,6 +20,7 @@
"DataFrameOrSeries",
"ITableOptions",
"DTForITablesOptions",
"config",
"options",
"downsample",
"sample_dfs",
Expand Down
10 changes: 8 additions & 2 deletions src/itables/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ def get_config_file(path: Path = Path.cwd()) -> Optional[Path]:

def load_config_file(config_file: Path) -> ITableOptions:
with open(config_file, "rb") as fp:
config = tomllib.load(fp)
try:
config = tomllib.load(fp)
except tomllib.TOMLDecodeError as e:
raise ValueError(f"Failed to load ITables config from {config_file}: {e}")

if config_file.name == "pyproject.toml":
if "tool" not in config or "itables" not in config["tool"]:
Expand All @@ -75,7 +78,10 @@ def load_config_file(config_file: Path) -> ITableOptions:
)
config = config["tool"]["itables"]

check_itable_arguments(config, ITableOptions)
try:
check_itable_arguments(config, ITableOptions)
except ValueError as e:
raise ValueError(f"Invalid ITables config in {config_file}: {e}")
return cast(ITableOptions, config)


Expand Down
28 changes: 28 additions & 0 deletions src/itables/show_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
Show the location and content of the ITables config file.
python -m itables.show_config
"""

from pathlib import Path

from itables.config import get_config_file, load_config_file


def show_config(path: Path):
"""
Show the ITables config file location and content.
"""
if (config_file := get_config_file(path)) is None:
print("No ITables config file found")
return

print(f"ITables config file: {config_file}")
config = load_config_file(config_file)
print("ITables options:")
for key, value in config.items():
print(f" {key}: {value}")


if __name__ == "__main__":
show_config(Path.cwd())
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ def connected(request):
@pytest.fixture(params=[False, True] if PANDAS_VERSION_MAJOR >= 1 else [False])
def use_to_html(request):
return request.param


@pytest.fixture(autouse=True)
def no_itables_config_env_variable(monkeypatch):
monkeypatch.delenv("ITABLES_CONFIG", raising=False)
yield
monkeypatch.undo()
25 changes: 15 additions & 10 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,7 @@
from itables.config import get_config_file, load_config_file


@pytest.fixture()
def no_itables_config(monkeypatch):
monkeypatch.delenv("ITABLES_CONFIG", raising=False)
yield
monkeypatch.undo()


def test_get_config_current_directory(tmp_path, no_itables_config):
def test_get_config_current_directory(tmp_path):
(tmp_path / "itables.toml").write_text('classes = ["compact", "display", "nowrap"]')

config_file = get_config_file(tmp_path)
Expand All @@ -19,7 +12,7 @@ def test_get_config_current_directory(tmp_path, no_itables_config):
assert config == {"classes": ["compact", "display", "nowrap"]}


def test_get_config_parent_directory(tmp_path, no_itables_config):
def test_get_config_parent_directory(tmp_path):
(tmp_path / "itables.toml").write_text('classes = ["compact", "display", "nowrap"]')
tmp_path_child = tmp_path / "child"
tmp_path_child.mkdir()
Expand All @@ -30,7 +23,7 @@ def test_get_config_parent_directory(tmp_path, no_itables_config):
assert config == {"classes": ["compact", "display", "nowrap"]}


def test_get_config_file_from_pyproject(tmp_path, no_itables_config):
def test_get_config_file_from_pyproject(tmp_path):
(tmp_path / "pyproject.toml").write_text(
'[tool.itables]\nclasses = ["compact", "display", "nowrap"]'
)
Expand All @@ -39,3 +32,15 @@ def test_get_config_file_from_pyproject(tmp_path, no_itables_config):
assert config_file is not None
config = load_config_file(config_file)
assert config == {"classes": ["compact", "display", "nowrap"]}


def test_helpful_message_when_config_is_incorrect(tmp_path):
(tmp_path / "itables.toml").write_text("classes = ")

config_file = get_config_file(tmp_path)
assert config_file is not None
with pytest.raises(
ValueError,
match=f"Failed to load ITables config from {tmp_path / 'itables.toml'}",
):
load_config_file(config_file)
17 changes: 17 additions & 0 deletions tests/test_show_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from itables.show_config import show_config


def test_show_config_default(capsys, tmp_path):
show_config(tmp_path)
captured = capsys.readouterr()
assert "No ITables config file found" in captured.out


def test_show_config_with_options(monkeypatch, capsys, tmp_path):
(tmp_path / "itables.toml").write_text('maxBytes = "8K"')

show_config(tmp_path)

captured = capsys.readouterr()
assert "ITables config file:" in captured.out
assert "maxBytes: 8K" in captured.out
Loading