Skip to content

Commit

Permalink
Merge pull request #171 from 15r10nk/format-cmd
Browse files Browse the repository at this point in the history
feat: added format-command config option
  • Loading branch information
15r10nk authored Jan 10, 2025
2 parents 3f02895 + 8920759 commit 93860be
Show file tree
Hide file tree
Showing 25 changed files with 441 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
python-version: ${{matrix.python-version}}

- run: |
uv run ${{matrix.extra_deps}} -m ${{ matrix.os == 'ubuntu-latest' && 'coverage run -m' || '' }} pytest -n=auto
uv run ${{matrix.extra_deps}} --extra black -m ${{ matrix.os == 'ubuntu-latest' && 'coverage run -m' || '' }} pytest -n=auto -vv
- run: |
uv run -m coverage combine
mv .coverage .coverage.${{ matrix.python-version }}-${{matrix.os}}-${{strategy.job-index}}
Expand Down
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ repos:
repo: https://github.com/myint/autoflake
rev: v2.3.1

- repo: local
hooks:
- id: replace-words
name: Replace Words
entry: python3 scripts/replace_words.py
language: system
files: \.(md|py)$

- repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.5.0
hooks:
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

## Fixed

- use '.model_fields' on pydantic model class and not instance. This fixes a deprecation warning in the upcomming pydantic v2.11 (#169)
- use '.model_fields' on pydantic model class and not instance. This fixes a deprecation warning in the upcoming pydantic v2.11 (#169)

<a id='changelog-0.18.1'></a>
# 0.18.1 — 2024-12-22
Expand Down Expand Up @@ -346,7 +346,7 @@

### Fix

- remove upper bound from dependencies in pyproject.toml
- remove upper bound from dependency in pyproject.toml

## v0.5.1 (2023-10-20)

Expand Down
7 changes: 7 additions & 0 deletions changelog.d/20250106_220025_15r10nk-git_format_cmd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Added

- You can now specify which tool you want to use to format your code by setting a `format-command` in your [configuration](https://15r10nk.github.io/inline-snapshot/latest/configuration/#format-command).

### Changed

- **BREAKING-CHANGE** you have to install `inline-snapshot[black]` now if you want to format your code like in the previous versions. This option is not required if you use a `format-command`.
4 changes: 4 additions & 0 deletions changelog.d/20250109_071706_15r10nk-git_format_cmd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- Load default config values even if `[tool.inline-snapshot]` is missing.
This makes the documented default shortcuts `--review` and `--fix` work.
15 changes: 15 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@


``` python exec="1"
from pathlib import Path

new_changes = list(Path.cwd().glob("changelog.d/*.md"))

if new_changes:
print("# upcomming changes")

for file in new_changes:
print(file.read_text().replace("###", "##"))
```


--8<-- "CHANGELOG.md"
26 changes: 18 additions & 8 deletions docs/code_generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,25 @@ The code is generated in the following way:
```


4. The code is formatted with black.
4. The new code fragments are formatted with black if it is installed.

!!! note
Black is an optional dependency since inline-snapshot v0.19.0.
You can install it with:
``` sh
pip install inline-snapshot[black]
```

5. The whole file is formatted with black if it was formatted before.
5. The whole file is formatted
* with black if it was formatted with black before.

!!! note
The black formatting of the whole file could not work for the following reasons:
!!! note
The black formatting of the whole file could not work for the following reasons:

1. black is configured with cli arguments and not in a configuration file.<br>
**Solution:** configure black in a [configuration file](https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file)
2. inline-snapshot uses a different black version.<br>
**Solution:** specify which black version inline-snapshot should use by adding black with a specific version to your dependencies.
3. black is not installed. Black is an optional dependency since inline-snapshot v0.19.0

1. black is configured with cli arguments and not in a configuration file.<br>
**Solution:** configure black in a [configuration file](https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file)
2. inline-snapshot uses a different black version.<br>
**Solution:** specify which black version inline-snapshot should use by adding black with a specific version to your dependencies.
* or with the [format-command][format-command] if you defined one.
10 changes: 10 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Default configuration:
[tool.inline-snapshot]
hash-length=15
default-flags=["short-report"]
format-command=""

[tool.inline-snapshot.shortcuts]
review=["review"]
Expand All @@ -23,3 +24,12 @@ fix=["create","fix"]
By default, it will be `<pytest_config_dir>/.inline-snapshot`,
where `<pytest_config_dir>` is replaced by the directory containing the Pytest configuration file, if any.
External snapshots will be stored in the `external` subfolder of the storage directory.
* **format-command:[](){#format-command}** allows you to specify a custom command which is used to format the python code after code is changed.
``` toml
[tool.inline-snapshot]
format-command="ruff format --stdin-filename {filename}"
```
The placeholder `{filename}` can be used to specify the filename if it is needed to find the correct formatting options for this file.

!!! important
The command should **not** format the file on disk. The current file content (with the new code changes) is passed to *stdin* and the formatted content should be written to *stdout*.
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ markdown_extensions:
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
- attr_list

plugins:
- mkdocstrings:
Expand All @@ -85,6 +86,7 @@ plugins:
- markdown-exec:
ansi: required
- replace-url
- autorefs


extra:
Expand Down
21 changes: 14 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,9 @@ classifiers = [
]
dependencies = [
"asttokens>=2.0.5",
"black>=23.3.0",
"click>=8.1.4",
"executing>=2.1.0",
"rich>=13.7.1",
"tomli>=2.0.0; python_version < '3.11'",
"typing-extensions"
"tomli>=2.0.0; python_version < '3.11'"
]
description = "golden master/snapshot/approval testing library which puts the values right into your source code"
keywords = []
Expand All @@ -39,6 +36,12 @@ readme = "README.md"
requires-python = ">=3.8"
version = "0.18.2"

[project.optional-dependencies]
black = [
"black>=23.3.0",
"click>=8.1.4"
]

[dependency-groups]
dev = [
"hypothesis>=6.75.5",
Expand Down Expand Up @@ -99,6 +102,7 @@ dependencies = [
"mkdocs-material[imaging]>=9.5.17",
"mike",
"mkdocstrings[python]>=0.19.0",
"mkdocs-autorefs",
"replace-url @ {root:uri}/docs/plugins",
"pytest",
"black"
Expand Down Expand Up @@ -130,6 +134,7 @@ matrix.extra-deps.dependencies = [

[tool.hatch.envs.hatch-test]
extra-dependencies = [
"inline-snapshot[black]",
"dirty-equals>=0.7.0",
"hypothesis>=6.75.5",
"mypy>=1.2.0",
Expand All @@ -141,18 +146,20 @@ extra-dependencies = [
env-vars.TOP = "{root}"

[tool.hatch.envs.hatch-test.scripts]
run = "pytest{env:HATCH_TEST_ARGS:} --use-uv {args}"
run-cov = "coverage run -m pytest{env:HATCH_TEST_ARGS:} --use-uv {args}"
run = "pytest{env:HATCH_TEST_ARGS:} {args}"
run-cov = "coverage run -m pytest{env:HATCH_TEST_ARGS:} {args}"
cov-combine = "coverage combine"
cov-report=["coverage report","coverage html"]

[tool.hatch.envs.types]
extra-dependencies = [
"inline-snapshot[black]",
"mypy>=1.0.0",
"pytest",
"hypothesis>=6.75.5",
"pydantic",
"attrs"
"attrs",
"typing-extensions"
]

[[tool.hatch.envs.types.matrix]]
Expand Down
24 changes: 24 additions & 0 deletions scripts/replace_words.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import re
import sys


def replace_words(file_path, replacements):
with open(file_path) as file:
content = file.read()

for old_word, new_word in replacements.items():
content = re.sub(rf"\b{re.escape(old_word)}\b", new_word, content)

with open(file_path, "w") as file:
file.write(content)


if __name__ == "__main__":

replacements = {
"http://localhost:8000/inline-snapshot/": "https://15r10nk.github.io/inline-snapshot/latest/",
}

for file_path in sys.argv[1:]:
print(file_path)
replace_words(file_path, replacements)
47 changes: 25 additions & 22 deletions src/inline_snapshot/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Config:
hash_length: int = 12
default_flags: List[str] = field(default_factory=lambda: ["short-report"])
shortcuts: Dict[str, List[str]] = field(default_factory=dict)
format_command: Optional[str] = None
storage_dir: Optional[Path] = None


Expand All @@ -27,35 +28,37 @@ class Config:

def read_config(path: Path) -> Config:
result = Config()
config = {}
if path.exists():

data = loads(path.read_text("utf-8"))

try:
config = data["tool"]["inline-snapshot"]
except KeyError:
pass
else:
try:
result.hash_length = config["hash-length"]
except KeyError:
pass

try:
result.default_flags = config["default-flags"]
except KeyError:
pass

result.shortcuts = config.get(
"shortcuts", {"fix": ["create", "fix"], "review": ["review"]}
)

if storage_dir := config.get("storage-dir"):
storage_dir = Path(storage_dir)
if not storage_dir.is_absolute():
# Make it relative to pyproject.toml, and absolute.
storage_dir = path.parent.joinpath(storage_dir).absolute()
result.storage_dir = storage_dir

try:
result.hash_length = config["hash-length"]
except KeyError:
pass

try:
result.default_flags = config["default-flags"]
except KeyError:
pass

result.shortcuts = config.get(
"shortcuts", {"fix": ["create", "fix"], "review": ["review"]}
)

if storage_dir := config.get("storage-dir"):
storage_dir = Path(storage_dir)
if not storage_dir.is_absolute():
# Make it relative to pyproject.toml, and absolute.
storage_dir = path.parent.joinpath(storage_dir).absolute()
result.storage_dir = storage_dir

result.format_command = config.get("format-command", None)

env_var = "INLINE_SNAPSHOT_DEFAULT_FLAGS"
if env_var in os.environ:
Expand Down
44 changes: 40 additions & 4 deletions src/inline_snapshot/_format.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,47 @@
import subprocess as sp
import warnings

from black import main
from click.testing import CliRunner
from inline_snapshot._problems import raise_problem
from rich.markup import escape

from . import _config
from ._problems import raise_problem


def enforce_formatting():
return _config.config.format_command is not None


def format_code(text, filename):
if _config.config.format_command is not None:
format_command = _config.config.format_command.format(filename=filename)
result = sp.run(
format_command, shell=True, input=text.encode("utf-8"), capture_output=True
)
if result.returncode != 0:
raise_problem(
f"""\
[b]The format_command '{escape(format_command)}' caused the following error:[/b]
"""
+ result.stdout.decode("utf-8")
+ result.stderr.decode("utf-8")
)
return text
return result.stdout.decode("utf-8")

try:
from black import main
from click.testing import CliRunner
except ImportError:
raise_problem(
f"""\
[b]inline-snapshot is not able to format your code.[/b]
This issue can be solved by:
* installing {escape('inline-snapshot[black]')} which gives you the same formatting like in older versions
* adding a `format-command` to your pyproject.toml (see [link=https://15r10nk.github.io/inline-snapshot/latest/configuration/#format-command]https://15r10nk.github.io/inline-snapshot/latest/configuration/#format-command[/link] for more information).
"""
)
return text

with warnings.catch_warnings():
warnings.simplefilter("ignore")

Expand All @@ -17,7 +53,7 @@ def format_code(text, filename):
if result.exit_code != 0:
raise_problem(
"""\
black could not format your code, which might be caused by this issue:
[b]black could not format your code, which might be caused by this issue:[/b]
[link=https://github.com/15r10nk/inline-snapshot/issues/138]https://github.com/15r10nk/inline-snapshot/issues/138[/link]\
"""
)
Expand Down
3 changes: 2 additions & 1 deletion src/inline_snapshot/_problems.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def report_problems(console: Console):
return
console.rule("[red]Problems")
for problem in all_problems:
console.print(f"[b]{problem}")
console.print(f"{problem}")
console.print()

all_problems = set()
Loading

0 comments on commit 93860be

Please sign in to comment.