Skip to content

Commit b5e5685

Browse files
committed
More details on the configuration file
1 parent 3c83bd7 commit b5e5685

File tree

8 files changed

+93
-13
lines changed

8 files changed

+93
-13
lines changed

docs/options/options.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ indicators = false
6969
handler = false
7070
```
7171

72+
The configuration file is loaded when `itables` is imported - you will need to restart Python and re-import ITables to get the latest configuration.
73+
74+
You can confirm which configuration file is being used (in a given directory) by running
75+
```
76+
python -m itables.show_config
77+
```
78+
79+
7280
## Option Names and Type Checks
7381

7482
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`.

docs/py/options/options.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@
7171
# handler = false
7272
# ```
7373
#
74+
# The configuration file is loaded when `itables` is imported - you will need to restart Python and re-import ITables to get the latest configuration.
75+
#
76+
# You can confirm which configuration file is being used (in a given directory) by running
77+
# ```
78+
# python -m itables.show_config
79+
# ```
80+
#
81+
#
7482
# ## Option Names and Type Checks
7583
#
7684
# 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`.

src/itables/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from itables import downsample, options, sample_dfs
1+
from itables import config, downsample, options, sample_dfs
22

33
from .javascript import init_notebook_mode, show, to_html_datatable
44
from .typing import (
@@ -20,6 +20,7 @@
2020
"DataFrameOrSeries",
2121
"ITableOptions",
2222
"DTForITablesOptions",
23+
"config",
2324
"options",
2425
"downsample",
2526
"sample_dfs",

src/itables/config.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ def get_config_file(path: Path = Path.cwd()) -> Optional[Path]:
6666

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

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

78-
check_itable_arguments(config, ITableOptions)
81+
try:
82+
check_itable_arguments(config, ITableOptions)
83+
except ValueError as e:
84+
raise ValueError(f"Invalid ITables config in {config_file}: {e}")
7985
return cast(ITableOptions, config)
8086

8187

src/itables/show_config.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
Show the location and content of the ITables config file.
3+
4+
python -m itables.show_config
5+
"""
6+
7+
from pathlib import Path
8+
9+
from itables.config import get_config_file, load_config_file
10+
11+
12+
def show_config(path: Path):
13+
"""
14+
Show the ITables config file location and content.
15+
"""
16+
if (config_file := get_config_file(path)) is None:
17+
print("No ITables config file found")
18+
return
19+
20+
print(f"ITables config file: {config_file}")
21+
config = load_config_file(config_file)
22+
print("ITables options:")
23+
for key, value in config.items():
24+
print(f" {key}: {value}")
25+
26+
27+
if __name__ == "__main__":
28+
show_config(Path.cwd())

tests/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,10 @@ def connected(request):
2929
@pytest.fixture(params=[False, True] if PANDAS_VERSION_MAJOR >= 1 else [False])
3030
def use_to_html(request):
3131
return request.param
32+
33+
34+
@pytest.fixture(autouse=True)
35+
def no_itables_config_env_variable(monkeypatch):
36+
monkeypatch.delenv("ITABLES_CONFIG", raising=False)
37+
yield
38+
monkeypatch.undo()

tests/test_config.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@
33
from itables.config import get_config_file, load_config_file
44

55

6-
@pytest.fixture()
7-
def no_itables_config(monkeypatch):
8-
monkeypatch.delenv("ITABLES_CONFIG", raising=False)
9-
yield
10-
monkeypatch.undo()
11-
12-
13-
def test_get_config_current_directory(tmp_path, no_itables_config):
6+
def test_get_config_current_directory(tmp_path):
147
(tmp_path / "itables.toml").write_text('classes = ["compact", "display", "nowrap"]')
158

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

2114

22-
def test_get_config_parent_directory(tmp_path, no_itables_config):
15+
def test_get_config_parent_directory(tmp_path):
2316
(tmp_path / "itables.toml").write_text('classes = ["compact", "display", "nowrap"]')
2417
tmp_path_child = tmp_path / "child"
2518
tmp_path_child.mkdir()
@@ -30,7 +23,7 @@ def test_get_config_parent_directory(tmp_path, no_itables_config):
3023
assert config == {"classes": ["compact", "display", "nowrap"]}
3124

3225

33-
def test_get_config_file_from_pyproject(tmp_path, no_itables_config):
26+
def test_get_config_file_from_pyproject(tmp_path):
3427
(tmp_path / "pyproject.toml").write_text(
3528
'[tool.itables]\nclasses = ["compact", "display", "nowrap"]'
3629
)
@@ -39,3 +32,15 @@ def test_get_config_file_from_pyproject(tmp_path, no_itables_config):
3932
assert config_file is not None
4033
config = load_config_file(config_file)
4134
assert config == {"classes": ["compact", "display", "nowrap"]}
35+
36+
37+
def test_helpful_message_when_config_is_incorrect(tmp_path):
38+
(tmp_path / "itables.toml").write_text("classes = ")
39+
40+
config_file = get_config_file(tmp_path)
41+
assert config_file is not None
42+
with pytest.raises(
43+
ValueError,
44+
match=f"Failed to load ITables config from {tmp_path / 'itables.toml'}",
45+
):
46+
load_config_file(config_file)

tests/test_show_config.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from itables.show_config import show_config
2+
3+
4+
def test_show_config_default(capsys, tmp_path):
5+
show_config(tmp_path)
6+
captured = capsys.readouterr()
7+
assert "No ITables config file found" in captured.out
8+
9+
10+
def test_show_config_with_options(monkeypatch, capsys, tmp_path):
11+
(tmp_path / "itables.toml").write_text('maxBytes = "8K"')
12+
13+
show_config(tmp_path)
14+
15+
captured = capsys.readouterr()
16+
assert "ITables config file:" in captured.out
17+
assert "maxBytes: 8K" in captured.out

0 commit comments

Comments
 (0)