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
1 change: 1 addition & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'
cache: 'pip'
- run: |
python -m venv .venv
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ITables ChangeLog

**Added**
- We have added the `columnControl` extension that was recently added to DataTables ([blog post](https://datatables.net/blog/2025/columncontrol)) ([#403](https://github.com/mwouts/itables/issues/403))
- The default options can be set through an `itables.toml` configuration file, either in the current or in a parent folder ([#429](https://github.com/mwouts/itables/issues/429))

**Changed**
- We have changed the default value of the `html` argument in `itables.sample_dfs.get_countries`. It now defaults to `False`, in which case the example dataframes contains no HTML code.
Expand Down
8 changes: 7 additions & 1 deletion docs/options/buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,16 @@ the location of the buttons (the default is `layout={"topStart": "buttons"}`). A

As always, it is possible to set default values for these parameters by setting these on `itables.options`. For instance, set
```python
itables.options.buttons = ["copyHtml5", "csvHtml5", "excelHtml5"]
itables.options.buttons = ["pageLength", "copyHtml5", "csvHtml5", "excelHtml5"]
```
to get the buttons for all your tables.

You can also add
```
buttons = ["pageLength", "copyHtml5", "csvHtml5", "excelHtml5"]
```
to your `itables.toml` configuration file.


By default, the exported file name is the name of the HTML page. To change it, set a
[`title` option](https://datatables.net/extensions/buttons/examples/html5/filename.html) on the buttons, like
Expand Down
7 changes: 7 additions & 0 deletions docs/options/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,10 @@ itables.show(df, classes="display")

itables.show(df, classes="display nowrap cell-border")
```

```tip
You can change the default for all your notebooks and apps by creating an `itables.toml` file in the current or a parent directory, with e.g. this content:
~~~
classes = ["display", "nowrap", "compact"]
~~~
```
14 changes: 14 additions & 0 deletions docs/options/column_control.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,17 @@ itables.show(
ordering={"indicators": False, "handler": False},
)
```

As usual, you can make this the default by either setting `itables.options.columnControl` in your notebook or application, or by adding this to your `itables.toml` configuration file:
```
[[columnControl]]
target = 0
content = ["order"]
[[columnControl]]
target = "tfoot"
content = ["search"]
[ordering]
indicators = false
handler = false
```
67 changes: 39 additions & 28 deletions docs/options/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,61 @@ kernelspec:

## DataTable Options

ITables is a wrapper for the Javascript DataTables library, which means that you can use more or less directly the DataTables [options](https://datatables.net/options) from within Python.
ITables is a wrapper for the JavaScript DataTables library, which means you can often use DataTables [options](https://datatables.net/options) directly within ITables.

Since ITables just maps these options to DataTables, you are invited to have a look at DataTable's great [documentation](https://datatables.net/), and to its huge collection of [examples](https://datatables.net/examples/index). The DataTable [forum](https://datatables.net/forums/) can be quite useful as well.
Since ITables simply maps these options to DataTables, we encourage you to consult DataTables’ excellent [documentation](https://datatables.net/) and its extensive collection of [examples](https://datatables.net/examples/index). The DataTables [forum](https://datatables.net/forums/) can also be quite helpful.

A non-exhaustive list of the DataTable options, together with their expected types, is available at [`itables.typing.DataTableOptions`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py).
A non-exhaustive list of DataTables options, along with their expected types, is provided by `DataTableOptions` in [`itables.typing`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py).

Option names and types are checked by default at run time when `typeguard>=4.4.1` is installed - you can deactivate this by setting `warn_on_undocumented_option=False`.
## ITable Options

ITables adds a few options of its own, such as `connected`, `maxBytes`, `allow_html`, and others. An exhaustive list of these additional options is provided by `ITableOptions` in [`itables.typing`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py).

## Default Values

If you see an option that you find useful and is not documented, or a type hint that is incorrect, please make a PR (and add an example to the documentation, too).
The default values for these options are set in [`itables.options`](https://github.com/mwouts/itables/blob/main/src/itables/options.py). These defaults are used in each call to `to_html_datatable`, `show`, or `ITable`, unless a corresponding option is set locally—in which case, the local value takes precedence.

```{code-cell} ipython3
:tags: [scroll-output]
## Changing the Defaults

import inspect
You can change the default options in your notebook or application with:

```python
import itables

print(inspect.getsource(itables.typing.DataTableOptions))
itables.options.maxBytes = "128KB"
```

## ITable Options

ITables itself adds a few options like `connected`, `maxBytes`, `allow_html` etc.
## Configuration File

The ITable options are documented at [`itables.typing.ITableOptions`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py):
Since v2.5.0, ITable can load its default options from a configuration file. The configuration file is identified using `get_config_file` from [`itables.config`](https://github.com/mwouts/itables/blob/main/src/itables/config.py). It can be:

```{code-cell} ipython3
:tags: [scroll-output]
- The file pointed to by the environment variable `ITABLES_CONFIG`, if set and non-empty (if the variable is an empty string, no configuration file is used)
- An `itables.toml` file in the current or a parent directory
- A `tool.itables` section in a `pyproject.toml` file in the current or a parent directory

print(inspect.getsource(itables.typing.ITableOptions))
A sample configuration file could look like this:
```
# itables.toml
classes = ["display", "nowrap", "compact"]
buttons = ["pageLength", "copyHtml5", "csvHtml5", "excelHtml5"]
```

## Default values

Some of the options have a default value set in [`itables.options`](https://github.com/mwouts/itables/blob/main/src/itables/options.py). You can change these defaults easily, and even set defauts for the options that don't have one yet with e.g.

```python
import itables

itables.options.maxBytes = "128KB"
Add this to use the [column control](column_control.md) extension:
```
[[columnControl]]
target = 0
content = ["order"]
[[columnControl]]
target = "tfoot"
content = ["search"]

[ordering]
indicators = false
handler = false
```

```{code-cell} ipython3
:tags: [scroll-output]
## Option Names and Type Checks

print(inspect.getsource(itables.options))
```
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`.

If you find an option that is useful but undocumented, or if you notice an incorrect type hint, please submit a PR (and consider adding an example to the documentation, too).
8 changes: 7 additions & 1 deletion docs/py/options/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@
#
# As always, it is possible to set default values for these parameters by setting these on `itables.options`. For instance, set
# ```python
# itables.options.buttons = ["copyHtml5", "csvHtml5", "excelHtml5"]
# itables.options.buttons = ["pageLength", "copyHtml5", "csvHtml5", "excelHtml5"]
# ```
# to get the buttons for all your tables.
#
# You can also add
# ```
# buttons = ["pageLength", "copyHtml5", "csvHtml5", "excelHtml5"]
# ```
# to your `itables.toml` configuration file.
#
#
# By default, the exported file name is the name of the HTML page. To change it, set a
# [`title` option](https://datatables.net/extensions/buttons/examples/html5/filename.html) on the buttons, like
Expand Down
8 changes: 8 additions & 0 deletions docs/py/options/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@

# %% tags=["full-width"]
itables.show(df, classes="display nowrap cell-border")

# %% [markdown]
# ```tip
# You can change the default for all your notebooks and apps by creating an `itables.toml` file in the current or a parent directory, with e.g. this content:
# ~~~
# classes = ["display", "nowrap", "compact"]
# ~~~
# ```
15 changes: 15 additions & 0 deletions docs/py/options/column_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,18 @@
],
ordering={"indicators": False, "handler": False},
)

# %% [markdown]
# As usual, you can make this the default by either setting `itables.options.columnControl` in your notebook or application, or by adding this to your `itables.toml` configuration file:
# ```
# [[columnControl]]
# target = 0
# content = ["order"]
# [[columnControl]]
# target = "tfoot"
# content = ["search"]
#
# [ordering]
# indicators = false
# handler = false
# ```
73 changes: 45 additions & 28 deletions docs/py/options/options.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# ---
# jupyter:
# jupytext:
# default_lexer: ipython3
# formats: docs///md:myst,docs/py///py:percent
# notebook_metadata_filter: -jupytext.text_representation.jupytext_version
# text_representation:
Expand All @@ -19,43 +18,61 @@
#
# ## DataTable Options
#
# ITables is a wrapper for the Javascript DataTables library, which means that you can use more or less directly the DataTables [options](https://datatables.net/options) from within Python.
# ITables is a wrapper for the JavaScript DataTables library, which means you can often use DataTables [options](https://datatables.net/options) directly within ITables.
#
# Since ITables just maps these options to DataTables, you are invited to have a look at DataTable's great [documentation](https://datatables.net/), and to its huge collection of [examples](https://datatables.net/examples/index). The DataTable [forum](https://datatables.net/forums/) can be quite useful as well.
# Since ITables simply maps these options to DataTables, we encourage you to consult DataTables’ excellent [documentation](https://datatables.net/) and its extensive collection of [examples](https://datatables.net/examples/index). The DataTables [forum](https://datatables.net/forums/) can also be quite helpful.
#
# A non-exhaustive list of the DataTable options, together with their expected types, is available at [`itables.typing.DataTableOptions`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py).
# A non-exhaustive list of DataTables options, along with their expected types, is provided by `DataTableOptions` in [`itables.typing`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py).
#
# Option names and types are checked by default at run time when `typeguard>=4.4.1` is installed - you can deactivate this by setting `warn_on_undocumented_option=False`.
#
# If you see an option that you find useful and is not documented, or a type hint that is incorrect, please make a PR (and add an example to the documentation, too).

# %% tags=["scroll-output"]
import inspect

import itables

print(inspect.getsource(itables.typing.DataTableOptions))

# %% [markdown]
# ## ITable Options
#
# ITables itself adds a few options like `connected`, `maxBytes`, `allow_html` etc.
# ITables adds a few options of its own, such as `connected`, `maxBytes`, `allow_html`, and others. An exhaustive list of these additional options is provided by `ITableOptions` in [`itables.typing`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py).
#
# The ITable options are documented at [`itables.typing.ITableOptions`](https://github.com/mwouts/itables/blob/main/src/itables/typing.py):

# %% tags=["scroll-output"]
print(inspect.getsource(itables.typing.ITableOptions))

# %% [markdown]
# ## Default values
# ## Default Values
#
# The default values for these options are set in [`itables.options`](https://github.com/mwouts/itables/blob/main/src/itables/options.py). These defaults are used in each call to `to_html_datatable`, `show`, or `ITable`, unless a corresponding option is set locally—in which case, the local value takes precedence.
#
# Some of the options have a default value set in [`itables.options`](https://github.com/mwouts/itables/blob/main/src/itables/options.py). You can change these defaults easily, and even set defauts for the options that don't have one yet with e.g.
# ## Changing the Defaults
#
# You can change the default options in your notebook or application with:
#
# ```python
# import itables
#
# itables.options.maxBytes = "128KB"
# ```

# %% tags=["scroll-output"]
print(inspect.getsource(itables.options))
#
# ## Configuration File
#
# Since v2.5.0, ITable can load its default options from a configuration file. The configuration file is identified using `get_config_file` from [`itables.config`](https://github.com/mwouts/itables/blob/main/src/itables/config.py). It can be:
#
# - The file pointed to by the environment variable `ITABLES_CONFIG`, if set and non-empty (if the variable is an empty string, no configuration file is used)
# - An `itables.toml` file in the current or a parent directory
# - A `tool.itables` section in a `pyproject.toml` file in the current or a parent directory
#
# A sample configuration file could look like this:
# ```
# # itables.toml
# classes = ["display", "nowrap", "compact"]
# buttons = ["pageLength", "copyHtml5", "csvHtml5", "excelHtml5"]
# ```
#
# Add this to use the [column control](column_control.md) extension:
# ```
# [[columnControl]]
# target = 0
# content = ["order"]
# [[columnControl]]
# target = "tfoot"
# content = ["search"]
#
# [ordering]
# indicators = false
# handler = false
# ```
#
# ## 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`.
#
# If you find an option that is useful but undocumented, or if you notice an incorrect type hint, please submit a PR (and consider adding an example to the documentation, too).
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ classifiers = [
"Typing :: Typed",
]
requires-python = ">= 3.9"
dependencies = ["IPython", "pandas", "numpy"]
dependencies = ["IPython", "pandas", "numpy", "tomli;python_version<\"3.11\""]
dynamic = ["version"]

[project.optional-dependencies]
Expand Down
86 changes: 86 additions & 0 deletions src/itables/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""
The ITables options can be modified through an itables.toml configuration file.

The location of that file can be specified through the ITABLES_CONFIG
environment variable (use an empty string for no config). Otherwise ITables will
look for an itables.toml file in the current directory and its parent
directories, for a tool.itables section in a pyproject.toml file in the
current or parent directories, and then for itables.toml in the user config directory.
"""

import os
from itertools import chain
from pathlib import Path
from typing import Any, Optional, cast

try:
import tomllib
except ImportError:
import tomli as tomllib # pyright: ignore[reportMissingImports]

from platformdirs import user_config_path
Copy link

@daureg daureg Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

platformdirs should be added as a dependency:

git clone https://github.com/mwouts/itables.git
cd itables
uvx hatch test
ImportError while loading conftest '/home/glefalher/nwork/itables/tests/conftest.py'.
tests/conftest.py:4: in <module>
    from itables.sample_dfs import PANDAS_VERSION_MAJOR, get_dict_of_test_dfs
src/itables/__init__.py:1: in <module>
    from itables import config, downsample, options, sample_dfs
src/itables/config.py:24: in <module>
    from platformdirs import user_config_path
E   ModuleNotFoundError: No module named 'platformdirs'


from itables.typing import ITableOptions, check_itable_arguments


def get_config_file(path: Path = Path.cwd()) -> Optional[Path]:
"""Return the itables config file if found"""
if (config_file := os.getenv("ITABLES_CONFIG")) is not None:
if not config_file:
# Setting ITABLES_CONFIG to an empty string
# disables config file loading
return None

config_file = Path(config_file)
if not config_file.exists():
raise FileNotFoundError(
f"ITables config file was not found: ITABLES_CONFIG={config_file}"
)
return config_file

ceiling_directories = {
Path(path)
for path in os.getenv("ITABLES_CEILING_DIRECTORIES", "").split(":")
if path
}
for parent in chain([path], path.parents):
config_file = parent / "itables.toml"
if config_file.exists():
return config_file
config_file = parent / "pyproject.toml"
if config_file.exists():
with open(config_file, "rb") as fp:
config = tomllib.load(fp)
if "tool" not in config or "itables" not in config["tool"]:
continue
return config_file
if parent in ceiling_directories:
break

config_file = user_config_path("itables") / "itables.toml"
if config_file.exists():
return config_file

return None


def load_config_file(config_file: Path) -> ITableOptions:
with open(config_file, "rb") as fp:
config = tomllib.load(fp)

if config_file.name == "pyproject.toml":
if "tool" not in config or "itables" not in config["tool"]:
raise ValueError(
f"This pyproject.toml file has no tool.itables section: {config_file}"
)
config = config["tool"]["itables"]

check_itable_arguments(config, ITableOptions)
return cast(ITableOptions, config)


def set_options_from_config_file(options: dict[str, Any]) -> None:
if (config_file := get_config_file()) is not None:
config = load_config_file(config_file)
for key, value in config.items():
options[key] = value
Loading
Loading