From b43dd38e15835de7ce4f9e6b6aaa8d8c84e5eff2 Mon Sep 17 00:00:00 2001 From: Frank Hoffmann <15r10nk-git@polarbit.de> Date: Fri, 24 May 2024 17:21:18 +0200 Subject: [PATCH] fix: fixed pydantic integration and HasRepr --- inline_snapshot/_code_repr.py | 7 +++--- noxfile.py | 1 + tests/conftest.py | 12 ++++++++++ tests/example.py | 19 ++++++++-------- tests/test_code_repr.py | 36 +++++++++++++++++++++++++++++- tests/test_example.py | 38 +++++++++++++++++++++++++++---- tests/test_pydantic.py | 42 +++++++++++++++++++++++++++++++++++ 7 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 tests/test_pydantic.py diff --git a/inline_snapshot/_code_repr.py b/inline_snapshot/_code_repr.py index 0cbecfc..806c243 100644 --- a/inline_snapshot/_code_repr.py +++ b/inline_snapshot/_code_repr.py @@ -58,7 +58,7 @@ def _(obj: MyCustomClass): def code_repr(obj): - with mock.patch("builtins.repr", code_repr_dispatch): + with mock.patch("builtins.repr", code_repr): result = code_repr_dispatch(obj) try: @@ -126,7 +126,7 @@ def _(v: IsDataclass): try: from pydantic import BaseModel -except ImportError: +except ImportError: # pragma: no cover pass else: @@ -136,7 +136,8 @@ def _(model: BaseModel): type(model).__qualname__ + "(" + ", ".join( - e + "=" + repr(getattr(model, e)) for e in model.__pydantic_fields_set__ + e + "=" + repr(getattr(model, e)) + for e in sorted(model.__pydantic_fields_set__) ) + ")" ) diff --git a/noxfile.py b/noxfile.py index b3b5a53..ec4faf8 100644 --- a/noxfile.py +++ b/noxfile.py @@ -46,6 +46,7 @@ def test(session): "time-machine", "mypy", "pyright", + "pydantic", ) cmd = [] diff --git a/tests/conftest.py b/tests/conftest.py index 24b762a..2eca13e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import ast import os import platform import re @@ -18,6 +19,7 @@ import inline_snapshot._external from .utils import snapshot_env from inline_snapshot import _inline_snapshot +from inline_snapshot import register_repr from inline_snapshot._format import format_code from inline_snapshot._inline_snapshot import Flags from inline_snapshot._rewrite_code import ChangeRecorder @@ -30,6 +32,16 @@ black.files.find_project_root = black.files.find_project_root.__wrapped__ # type: ignore +@register_repr +def _(v: executing.Source): + return f"" + + +@register_repr +def _(v: ast.AST): + return repr(ast.dump(v)) + + @pytest.fixture() def check_update(source): def w(source_code, *, flags="", reported_flags=None, number=1): diff --git a/tests/example.py b/tests/example.py index 216c8ed..bda858d 100644 --- a/tests/example.py +++ b/tests/example.py @@ -8,8 +8,6 @@ from tempfile import TemporaryDirectory from typing import Any -import black - import inline_snapshot._external from .utils import snapshot_env from inline_snapshot import _inline_snapshot @@ -19,10 +17,6 @@ pytest_plugins = "pytester" -if hasattr(black.files.find_project_root, "__wrapped__"): - black.files.find_project_root = black.files.find_project_root.__wrapped__ # type: ignore - - ansi_escape = re.compile( r""" \x1B # ESC @@ -54,7 +48,7 @@ def read_files(self, dir: Path): return {p.name: p.read_text() for p in dir.iterdir() if p.is_file()} def run_inline( - self, *flags, changes=None, reported_flags=None, files=None + self, *flags, changes=None, reported_flags=None, changed_files=None ) -> Example: with TemporaryDirectory() as dir: @@ -102,12 +96,17 @@ def run_inline( assert sorted(snapshot_flags) == reported_flags if changes is not None: - assert [repr(c) for c in all_changes] == changes + assert [c for c in all_changes] == changes recorder.fix_all() - if files is not None: - assert files == self.read_files(tmp_path) + if changed_files is not None: + current_files = {} + + for name, content in sorted(self.read_files(tmp_path).items()): + if name not in self.files or self.files[name] != content: + current_files[name] = content + assert changed_files == current_files return Example(self.read_files(tmp_path)) diff --git a/tests/test_code_repr.py b/tests/test_code_repr.py index d06099b..1cef7fe 100644 --- a/tests/test_code_repr.py +++ b/tests/test_code_repr.py @@ -120,6 +120,40 @@ class container: ) +def test_dataclass_field_repr(check_update): + + Example( + """\ +from inline_snapshot import snapshot +from dataclasses import dataclass,field + +@dataclass +class container: + a: int + b: int = field(default=5,repr=False) + +assert container(a=1,b=5) == snapshot() +""" + ).run_inline( + "create", + changed_files=snapshot( + { + "test_something.py": """\ +from inline_snapshot import snapshot +from dataclasses import dataclass,field + +@dataclass +class container: + a: int + b: int = field(default=5,repr=False) + +assert container(a=1,b=5) == snapshot(container(a=1)) +""" + } + ), + ).run_inline() + + def test_flag(check_update): assert ( @@ -196,7 +230,7 @@ class Color(Enum): """ ).run_inline( "create", - files=snapshot( + changed_files=snapshot( { "test_something.py": """\ from enum import Enum diff --git a/tests/test_example.py b/tests/test_example.py index 9f24116..9be6b77 100644 --- a/tests/test_example.py +++ b/tests/test_example.py @@ -1,15 +1,45 @@ +from executing import Source + from .example import Example +from inline_snapshot import HasRepr +from inline_snapshot import snapshot +from inline_snapshot._change import Replace -def test_diff_multiple_files(): +def test_example(): - Example( - """ + e = Example( + { + "test_a.py": """ from inline_snapshot import snapshot def test_a(): assert 1==snapshot(2) """, - ).run_pytest( + "test_b.py": "1+1", + }, + ) + + e.run_pytest( "--inline-snapshot=create,fix", ) + + e.run_inline( + "fix", + reported_flags=snapshot(["fix"]), + changes=snapshot( + [ + Replace( + flag="fix", + source=HasRepr(Source, ""), + node="Constant(value=2)", + new_code="1", + old_value=2, + new_value=1, + ) + ] + ), + ).run_inline( + "fix", + changed_files=snapshot({}), + ) diff --git a/tests/test_pydantic.py b/tests/test_pydantic.py new file mode 100644 index 0000000..c6c55a7 --- /dev/null +++ b/tests/test_pydantic.py @@ -0,0 +1,42 @@ +from .example import Example +from inline_snapshot import snapshot + + +def test_pydantic_repr(): + + Example( + """ +from pydantic import BaseModel +from inline_snapshot import snapshot + +class M(BaseModel): + size:int + name:str + age:int=4 + +def test_pydantic(): + assert M(size=5,name="Tom")==snapshot() + + """ + ).run_inline( + "create", + changed_files=snapshot( + { + "test_something.py": """\ + +from pydantic import BaseModel +from inline_snapshot import snapshot + +class M(BaseModel): + size:int + name:str + age:int=4 + +def test_pydantic(): + assert M(size=5,name="Tom")==snapshot(M(name="Tom", size=5)) + + \ +""" + } + ), + ).run_inline()