Skip to content

Commit

Permalink
autoloading_settings
Browse files Browse the repository at this point in the history
noqa added

update test to check configurations
  • Loading branch information
bbeat2782 committed Jul 13, 2023
1 parent be566e3 commit d234872
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* [Feature] Added a line under `ResultSet` to distinguish it from data frame and error message when invalid operations are performed (#468)
* [Feature] Moved `%sqlrender` feature to `%sqlcmd snippets` (#647)
* [Feature] Added tables listing stored snippets when `%sqlcmd snippets` is called (#648)
* [Feature] Modified `%load_ext sql` to load saved configurations from `pyproject.toml` file (#689)
* [Doc] Modified integrations content to ensure they're all consistent (#523)
* [Doc] Document --persist-replace in API section (#539)
* [Fix] Fixed CI issue by updating `invalid_connection_string_duckdb` in `test_magic.py` (#631)
Expand Down
16 changes: 13 additions & 3 deletions doc/api/configuration.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
jupytext:
notebook_metadata_filter: myst
cell_metadata_filter: -all
formats: md:myst
notebook_metadata_filter: myst
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.14.4
jupytext_version: 1.14.7
kernelspec:
display_name: Python 3 (ipykernel)
language: python
Expand Down Expand Up @@ -240,4 +240,14 @@ print(res)
%config SqlMagic.style = "SINGLE_BORDER"
res = %sql SELECT * FROM languages LIMIT 2
print(res)
```
```

## Loading configuration settings

You can define configurations in a `pyproject.toml` file and automatically load the configurations when you run `%load_ext sql`. It will try to find the file recursively from the current to root directory. If the file is not found, default values will be used. A sample `pyproject.toml` could look like this:

```
[tool.jupysql.SqlMagic]
feedback = true
autopandas = true
```
72 changes: 72 additions & 0 deletions src/sql/magic.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import json
import re
from pathlib import Path
import toml
import difflib

try:
from ipywidgets import interact
Expand Down Expand Up @@ -619,6 +622,73 @@ def _persist_dataframe(
display.message_success(f"Success! Persisted {table_name} to the database.")


def find_toml_path():
"""
Recursively finds an absolute path to pyproject.toml starting
from current directory
"""
current = Path().resolve()
while not (current / "pyproject.toml").exists():
if current == current.parent:
return None

current = current.parent
display.message(f"Found pyproject.toml from '{current}'")

return str(current) + "/pyproject.toml"


def get_configs(file_path):
"""Returns saved configs from given file_path"""
with open(file_path, "r") as file:
content = file.read()
data = toml.loads(content)
try:
return data["tool"]["jupysql"]["SqlMagic"]
except KeyError:
return {}


def get_config_variables(obj):
"""Returns a list of configs users can set"""
config_vars = list(vars(obj)["_all_trait_default_generators"].keys())
config_vars.remove("config")
config_vars.remove("parent")
return config_vars


def load_configs(ip):
"""Loads saved configs in pyproject.toml"""
file_path = find_toml_path()
if file_path:
configs = get_configs(file_path)
config_vars = get_config_variables(SqlMagic)
for config, value in configs.items():
if config in config_vars:
default_value = getattr(SqlMagic, config).default_value
if isinstance(value, type(default_value)):
ip.run_cell(f"%config SqlMagic.{config} = {value}")
display.message(f"Setting '{config}' into '{value}'")
else:
display.message(
f"'{value}' is an invalid value for '{config}'. "
f"Please use {type(default_value)} value instead."
)
else:
closest_match = difflib.get_close_matches(config, config_vars, n=1)
if not closest_match:
display.message(
f"'{config}' is an invalid configuration. Please review our "
"configuration guideline: "
"https://jupysql.ploomber.io/en/latest/api/configuration.html#options" # noqa breaks the check-for-broken-links
)
else:
display.message(
f"'{config}' is an invalid configuration. "
f"Did you mean '{closest_match[0]}'?"
)


def load_ipython_extension(ip):
"""Load the extension in IPython."""

Expand All @@ -632,4 +702,6 @@ def load_ipython_extension(ip):
ip.register_magics(SqlPlotMagic)
ip.register_magics(SqlCmdMagic)

load_configs(ip)

patch_ipython_usage_error(ip)
5 changes: 5 additions & 0 deletions src/tests/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[tool.jupysql.SqlMagic]
autocom = true
autolimit = "text"
invalid = false
displaycon = false
27 changes: 27 additions & 0 deletions src/tests/test_magic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1296,3 +1296,30 @@ def test_interact_and_missing_ipywidgets_installed(ip):
"%sql --interact my_variable SELECT * FROM author LIMIT {{my_variable}}"
)
assert isinstance(out.error_in_exec, ModuleNotFoundError)


def test_loading_config(request, monkeypatch, ip, capsys):
monkeypatch.chdir(request.fspath.dirname)
ip.run_cell("%load_ext sql").result
out, _ = capsys.readouterr()

# checking displayed messages
assert "Found pyproject.toml from " in out
assert "'autocom' is an invalid configuration. Did you mean 'autocommit'?" in out
assert (
"'text' is an invalid value for 'autolimit'. Please use "
"<class 'int'> value instead." in out
)
assert (
"'invalid' is an invalid configuration. Please review our configuration "
"guideline: https://jupysql.ploomber.io/en/latest/"
"api/configuration.html#options" in out
)
assert "Setting 'displaycon' into 'False'" in out

# checking configurations
assert ip.run_line_magic("config", "SqlMagic.autocommit") is True
assert ip.run_line_magic("config", "SqlMagic.autolimit") == 0
assert ip.run_line_magic("config", "SqlMagic.displaycon") is False

ip.run_line_magic("config", "SqlMagic.displaycon=True")

0 comments on commit d234872

Please sign in to comment.