Skip to content

Commit

Permalink
Merge pull request #178 from 15r10nk/pydantic_ai_fixes
Browse files Browse the repository at this point in the history
Pydantic ai fixes
  • Loading branch information
15r10nk authored Jan 12, 2025
2 parents 72c3323 + 5eec756 commit fae5a35
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 19 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}} --extra black -m ${{ matrix.os == 'ubuntu-latest' && 'coverage run -m' || '' }} pytest -n=auto -vv
uv run ${{matrix.extra_deps}} --extra black --extra dirty-equals -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
13 changes: 13 additions & 0 deletions changelog.d/20250112_121000_15r10nk-git_pydantic_ai_fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
### Fixed

- snapshots with pydantic models can now be compared multiple times

``` python
class A(BaseModel):
a: int


def test_something():
for _ in [1, 2]:
assert A(a=1) == snapshot(A(a=1))
```
3 changes: 3 additions & 0 deletions changelog.d/20250112_213028_15r10nk-git_pydantic_ai_fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Added

- added the optional `inline-snapshot[dirty-equals]` dependency to depend on the dirty-equals version which works in combination with inline-snapshot.
7 changes: 7 additions & 0 deletions docs/eq_snapshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ Example:

The date can be replaced with the [dirty-equals](https://dirty-equals.helpmanual.io/latest/) expression `IsDatetime()`.


Example:

=== "using IsDatetime()"
Expand Down Expand Up @@ -195,6 +196,12 @@ Example:
)
```

!!! note
Use the optional *dirty-equals* dependency to install the version that works best in combination with inline-snapshot.
``` sh
pip install inline-snapshot[dirty-equals]
```

### Is(...)

`Is()` can be used to put runtime values inside snapshots.
Expand Down
4 changes: 2 additions & 2 deletions docs/outsource.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Example:

=== "--inline-snapshot=create"
<!-- inline-snapshot: create outcome-passed=1 -->
``` python hl_lines="2 3 7 8 9"
``` python hl_lines="3 4 7 8 9"
from inline_snapshot import snapshot, outsource

from inline_snapshot import external
Expand Down Expand Up @@ -55,7 +55,7 @@ The `external` object can be used inside other data structures.

=== "--inline-snapshot=create"
<!-- inline-snapshot: create outcome-passed=1 -->
``` python hl_lines="2 3 9 10 11 12 13 14 15"
``` python hl_lines="3 4 9 10 11 12 13 14 15"
from inline_snapshot import snapshot, outsource

from inline_snapshot import external
Expand Down
10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ black = [
"black>=23.3.0",
"click>=8.1.4"
]
dirty-equals =[
"dirty-equals>=0.9.0",
]

[dependency-groups]
dev = [
Expand All @@ -54,7 +57,6 @@ dev = [
"coverage[toml]>=7.6.1",
"coverage-enable-subprocess>=1.0",
"pytest>=8",
"dirty-equals>=0.7.0",
"attrs>=24.3.0",
"pydantic>=1",
]
Expand Down Expand Up @@ -134,8 +136,8 @@ matrix.extra-deps.dependencies = [

[tool.hatch.envs.hatch-test]
extra-dependencies = [
"inline-snapshot[black]",
"dirty-equals>=0.7.0",
"inline-snapshot[black,dirty-equals]",
"dirty-equals>=0.9.0",
"hypothesis>=6.75.5",
"mypy>=1.2.0",
"pyright>=1.1.359",
Expand All @@ -153,7 +155,7 @@ cov-report=["coverage report","coverage html"]

[tool.hatch.envs.types]
extra-dependencies = [
"inline-snapshot[black]",
"inline-snapshot[black,dirty-equals]",
"mypy>=1.0.0",
"pytest",
"hypothesis>=6.75.5",
Expand Down
22 changes: 16 additions & 6 deletions src/inline_snapshot/_adapter/generic_call_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,24 @@ def map(cls, value, map_function):
)

def items(self, value, node):
assert isinstance(node, ast.Call)
assert not node.args
assert all(kw.arg for kw in node.keywords)
new_args, new_kwargs = self.arguments(value)

if node is not None:
assert isinstance(node, ast.Call)
assert not node.args
assert all(kw.arg for kw in node.keywords)
kw_arg_node = {kw.arg: kw.value for kw in node.keywords if kw.arg}.get
pos_arg_node = lambda pos: node.args[pos]
else:
kw_arg_node = lambda _: None
pos_arg_node = lambda _: None

return [
Item(value=self.argument(value, kw.arg), node=kw.value)
for kw in node.keywords
if kw.arg
Item(value=arg.value, node=pos_arg_node(i))
for i, arg in enumerate(new_args)
] + [
Item(value=kw.value, node=kw_arg_node(name))
for name, kw in new_kwargs.items()
]

def assign(self, old_value, old_node, new_value):
Expand Down
26 changes: 26 additions & 0 deletions src/inline_snapshot/_align.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@

def align(seq_a, seq_b) -> str:

start = 0

for a, b in zip(seq_a, seq_b):
if a == b:
start += 1
else:
break

if start == len(seq_a) == len(seq_b):
return "m" * start

end = 0

for a, b in zip(reversed(seq_a[start:]), reversed(seq_b[start:])):
if a == b:
end += 1
else:
break

diff = nw_align(seq_a[start : len(seq_a) - end], seq_b[start : len(seq_b) - end])

return "m" * start + diff + "m" * end


def nw_align(seq_a, seq_b) -> str:

matrix: list = [[(0, "e")] + [(0, "i")] * len(seq_b)]

for a in seq_a:
Expand Down
3 changes: 2 additions & 1 deletion src/inline_snapshot/_code_repr.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ def mocked_code_repr(obj):


def value_code_repr(obj):
if not type(obj) == type(obj):
if not type(obj) == type(obj): # pragma: no cover
# this was caused by https://github.com/samuelcolvin/dirty-equals/issues/104
# dispatch will not work in cases like this
return (
f"HasRepr({repr(type(obj))}, '< type(obj) can not be compared with == >')"
Expand Down
22 changes: 17 additions & 5 deletions src/inline_snapshot/_is.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
class Is:
def __init__(self, value):
self.value = value
import typing
from typing import TYPE_CHECKING

def __eq__(self, other):
return self.value == other
if TYPE_CHECKING:

T = typing.TypeVar("T")

def Is(v: T) -> T:
return v

else:

class Is:
def __init__(self, value):
self.value = value

def __eq__(self, other):
return self.value == other
3 changes: 3 additions & 0 deletions src/inline_snapshot/_unmanaged.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def __eq__(self, other):

return self.value == other

def __repr__(self):
return repr(self.value)


def map_unmanaged(value):
if is_unmanaged(value):
Expand Down
2 changes: 2 additions & 0 deletions tests/test_dirty_equals.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import pytest
from inline_snapshot._inline_snapshot import snapshot
from inline_snapshot.testing._example import Example


@pytest.mark.xfail
def test_dirty_equals_repr():
Example(
"""\
Expand Down
18 changes: 18 additions & 0 deletions tests/test_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,21 @@ def test_something():
}
),
)


def test_pydantic_evaluate_twice():
Example(
"""\
from inline_snapshot import snapshot
from pydantic import BaseModel
class A(BaseModel):
a:int
def test_something():
for _ in [1,2]:
assert A(a=1) == snapshot(A(a=1))
"""
).run_pytest(
changed_files=snapshot({}),
)

0 comments on commit fae5a35

Please sign in to comment.