feat(configuration): allow local configuration to override global config

closes #422
This commit is contained in:
Christopher Pickering 2022-10-12 09:29:31 +02:00
parent a86df438b5
commit b4cbcb45cd
No known key found for this signature in database
GPG key ID: E14DB3B0A0FACF84
8 changed files with 88 additions and 15 deletions

View file

@ -7,7 +7,7 @@ date: Last Modified
# Configuration # Configuration
Configuration is done either through your projects `pyproject.toml` file, or a `.djlintrc` file. Command line args will always override any settings in `pyproject.toml`. Configuration is done either through your projects `pyproject.toml` file, or a `.djlintrc` file. Command line args will always override any settings in `pyproject.toml`. Local project settings will always override global configuration files.
The format for `pyproject.toml` is `toml`. The format for `pyproject.toml` is `toml`.

View file

@ -6,7 +6,7 @@ keywords: template linter, template formatter, djLint, HTML, templates, formatte
# {{ "configuration" | i18n }} # {{ "configuration" | i18n }}
La configuration se fait soit à travers le fichier `pyproject.toml` de votre projet, soit à travers un fichier `.djlintrc`. Les arguments de la ligne de commande remplaceront toujours les paramètres du fichier `pyproject.toml`. La configuration se fait soit à travers le fichier `pyproject.toml` de votre projet, soit à travers un fichier `.djlintrc`. Les arguments de la ligne de commande remplaceront toujours les paramètres du fichier `pyproject.toml`. Les paramètres locaux du projet prévaudront toujours sur les fichiers de configuration globaux.
Le format du fichier `pyproject.toml` est `toml`. Le format du fichier `pyproject.toml` est `toml`.

View file

@ -6,7 +6,7 @@ keywords: облицовка шаблонов, форматер шаблонов
# {{ "configuration" | i18n }} # {{ "configuration" | i18n }}
Конфигурация выполняется либо через файл `pyproject.toml` вашего проекта, либо через файл `.djlintrc`. Арги командной строки всегда будут переопределять любые настройки в `pyproject.toml`. Конфигурация выполняется либо через файл `pyproject.toml` вашего проекта, либо через файл `.djlintrc`. Арги командной строки всегда будут переопределять любые настройки в `pyproject.toml`. Локальные настройки проекта всегда будут иметь приоритет над глобальными конфигурационными файлами.
```ini ```ini
[tool.djlint] [tool.djlint]

View file

@ -103,7 +103,10 @@ def load_project_settings(src: Path, config: Optional[str]) -> Dict:
if config: if config:
try: try:
return json.loads(Path(config).resolve().read_text(encoding="utf8")) djlint_content = json.loads(
Path(config).resolve().read_text(encoding="utf8")
)
# pylint: disable=broad-except # pylint: disable=broad-except
except BaseException: except BaseException:
logger.info( logger.info(
@ -115,7 +118,7 @@ def load_project_settings(src: Path, config: Optional[str]) -> Dict:
if pyproject_file: if pyproject_file:
content = tomllib.load(pyproject_file.open("rb")) content = tomllib.load(pyproject_file.open("rb"))
try: try:
return content["tool"]["djlint"] # type: ignore return {**djlint_content, **content["tool"]["djlint"]} # type: ignore
except KeyError: except KeyError:
logger.info("No pyproject.toml found.") logger.info("No pyproject.toml found.")
@ -123,7 +126,10 @@ def load_project_settings(src: Path, config: Optional[str]) -> Dict:
if djlintrc_file: if djlintrc_file:
try: try:
return json.loads(djlintrc_file.read_text(encoding="utf8")) return {
**djlint_content,
**json.loads(djlintrc_file.read_text(encoding="utf8")),
}
# pylint: disable=broad-except # pylint: disable=broad-except
except BaseException: except BaseException:
logger.info("Failed to load .djlintrc file.") logger.info("Failed to load .djlintrc file.")

View file

@ -1,6 +1,7 @@
{ {
"profile": "django", "profile": "django",
"indent": 2, "indent": 2,
"ignore": "",
"files": [ "files": [
"./tests/test_config/test_files/test.html", "./tests/test_config/test_files/test.html",
"./tests/test_config/test_files/test_two.html" "./tests/test_config/test_files/test_two.html"

View file

@ -5,11 +5,14 @@ run::
pytest tests/test_config/test_files/test_config.py --cov=src/djlint --cov-branch \ pytest tests/test_config/test_files/test_config.py --cov=src/djlint --cov-branch \
--cov-report xml:coverage.xml --cov-report term-missing --cov-report xml:coverage.xml --cov-report term-missing
pytest tests/test_config/test_files/test_config.py::test_check_custom_file_src pytest tests/test_config/test_files/test_config.py::test_global_override
""" """
# pylint: disable=C0116 # pylint: disable=C0116
import os
from pathlib import Path
from click.testing import CliRunner from click.testing import CliRunner
from src.djlint import main as djlint from src.djlint import main as djlint
@ -22,7 +25,7 @@ def test_check_custom_file_src(runner: CliRunner) -> None:
"-", "-",
"--check", "--check",
"--configuration", "--configuration",
"tests/test_config/test_files/.djlintrc", "tests/test_config/test_files/.djlintrc_global",
], ],
) )
assert """Checking 2/2 files""" in result.output assert """Checking 2/2 files""" in result.output
@ -35,7 +38,7 @@ def test_lint_custom_file_src(runner: CliRunner) -> None:
"-", "-",
"--lint", "--lint",
"--configuration", "--configuration",
"tests/test_config/test_files/.djlintrc", "tests/test_config/test_files/.djlintrc_global",
], ],
) )
assert """Linting 2/2 files""" in result.output assert """Linting 2/2 files""" in result.output
@ -48,7 +51,74 @@ def test_reformat_custom_file_src(runner: CliRunner) -> None:
"-", "-",
"--reformat", "--reformat",
"--configuration", "--configuration",
"tests/test_config/test_files/.djlintrc", "tests/test_config/test_files/.djlintrc_global",
], ],
) )
assert """Reformatting 2/2 files""" in result.output assert """Reformatting 2/2 files""" in result.output
def test_global_override(runner: CliRunner) -> None:
result = runner.invoke(
djlint,
[
"-",
"--lint",
"--configuration",
"tests/test_config/test_files/.djlintrc_global",
],
)
# fails
assert result.exit_code == 1
# check cli override
result = runner.invoke(
djlint,
[
"-",
"--lint",
"--configuration",
"tests/test_config/test_files/.djlintrc_global",
"--ignore",
"H025,H020",
],
)
# passes
assert result.exit_code == 0
# check project settings override
# create project settings folder
# add a gitignore file
with open(
"tests/test_config/test_files/.djlintrc", "w", encoding="utf8"
) as local_settings:
local_settings.write('{ "ignore":"H025"}')
result = runner.invoke(
djlint,
[
"tests/test_config/test_files/test_two.html",
"--lint",
"--configuration",
"tests/test_config/test_files/.djlintrc_global",
],
)
result_two = runner.invoke(
djlint,
[
"tests/test_config/test_files/test.html",
"--lint",
"--configuration",
"tests/test_config/test_files/.djlintrc_global",
],
)
try:
os.remove("tests/test_config/test_files/.djlintrc")
except BaseException as e:
print("cleanup failed")
print(e)
# H025 should be ignored, but H022 not
assert "H025" not in result.output
assert "H020" in result_two.output

View file

@ -1,5 +1,4 @@
{ {
"profile": "django", "profile": "django",
"indent": 2,
"custom_blocks": "toc,example" "custom_blocks": "toc,example"
} }

View file

@ -18,12 +18,10 @@ from src.djlint import main as djlint
def test_config(runner: CliRunner) -> None: def test_config(runner: CliRunner) -> None:
result = runner.invoke(djlint, ["tests/test_config/test_json/html.html", "--check"]) result = runner.invoke(djlint, ["tests/test_config/test_json/html.html", "--check"])
print(result.output)
assert ( assert (
"""-{% example stuff %}<p>this is a long paragraph</p>{% endexample %} """-{% example stuff %}<p>this is a long paragraph</p>{% endexample %}
+{% example stuff %} +{% example stuff %}
+ <p>this is a long paragraph</p> + <p>this is a long paragraph</p>
+{% endexample %} +{% endexample %}
""" """
in result.output in result.output
@ -41,7 +39,6 @@ def test_custom_config(runner: CliRunner) -> None:
"tests/test_config/test_json/.djlint-cust", "tests/test_config/test_json/.djlint-cust",
], ],
) )
assert ( assert (
"""-{% example stuff %}<p>this is a long paragraph</p>{% endexample %} """-{% example stuff %}<p>this is a long paragraph</p>{% endexample %}
+{% example stuff %} +{% example stuff %}