Skip to content

Commit 5c020db

Browse files
committed
feat: update min. python version to 3.10
BREAKING CHANGE: Min. python version is now 3.10.
1 parent 434c63f commit 5c020db

File tree

19 files changed

+619
-580
lines changed

19 files changed

+619
-580
lines changed

.poetry-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.1.2
1+
2.2.1

README.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
[![All Contributors](https://img.shields.io/github/all-contributors/syrupy-project/syrupy?color=ee8449&style=flat-square)](#contributors) [![Stage](https://img.shields.io/pypi/status/syrupy)](https://pypi.org/project/syrupy/) [![codecov](https://codecov.io/gh/syrupy-project/syrupy/graph/badge.svg?token=GB9EmYKPAl)](https://codecov.io/gh/syrupy-project/syrupy)
88

9-
![Pytest>=5.1.0,<9.0.0](https://img.shields.io/badge/pytest-%3E%3D5.1.0,%20%3C9.0.0-green) [![Pypi](https://img.shields.io/pypi/v/syrupy)](https://pypi.org/project/syrupy/) [![Wheel](https://img.shields.io/pypi/wheel/syrupy)](https://pypi.org/project/syrupy/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/syrupy) [![PyPI - Downloads](https://img.shields.io/pypi/dm/syrupy)](https://pypi.org/project/syrupy/) [![PyPI - License](https://img.shields.io/pypi/l/syrupy)](./LICENSE)
9+
![Pytest>=8,<9.0.0](https://img.shields.io/badge/pytest-%3E=8,%20%3C9.0.0-green) [![Pypi](https://img.shields.io/pypi/v/syrupy)](https://pypi.org/project/syrupy/) [![Wheel](https://img.shields.io/pypi/wheel/syrupy)](https://pypi.org/project/syrupy/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/syrupy) [![PyPI - Downloads](https://img.shields.io/pypi/dm/syrupy)](https://pypi.org/project/syrupy/) [![PyPI - License](https://img.shields.io/pypi/l/syrupy)](./LICENSE)
1010

1111
## Overview
1212

1313
Syrupy is a zero-dependency [pytest](https://docs.pytest.org/en/latest/) snapshot plugin. It enables developers to write tests which assert immutability of computed results.
1414

1515
## Motivation
1616

17-
The most popular snapshot test plugin compatible with pytest has some core limitations which this package attempts to address by upholding some key values:
17+
Syrupy upholds three principles:
1818

1919
- Extensible: If a particular data type is not supported, users should be able to easily and quickly add support.
2020
- Idiomatic: Snapshot testing should fit naturally among other test cases in pytest, e.g. `assert x == snapshot` vs. `snapshot.assert_match(x)`.
@@ -26,23 +26,14 @@ The most popular snapshot test plugin compatible with pytest has some core limit
2626
python -m pip install syrupy
2727
```
2828

29-
### Migration from snapshottest
30-
31-
You cannot use syrupy alongside snapshottest due to argument conflicts. To ease migration, we've made syrupy aware of snapshottest call syntax. Simply uninstall snapshottest and remove old snapshots:
32-
33-
```shell
34-
pip uninstall snapshottest -y;
35-
find . -type d ! -path '*/\.*' -name 'snapshots' | xargs rm -r
36-
```
37-
3829
### Pytest and Python Compatibility
3930

4031
Syrupy will always be compatible with the latest version of Python and Pytest. If you're running an old version of Python or Pytest, you will need to use an older major version of Syrupy:
4132

4233
| Syrupy Version | Python Support | Pytest Support |
4334
| -------------- | -------------- | -------------- |
44-
| 5.x.x | >3.9 | >=8 |
45-
| 4.x.x | >3.8.1, | >=7, <9 |
35+
| 5.x.x | >=3.10 | >=8 |
36+
| 4.x.x | >=3.8.1, | >=7, <9 |
4637
| 3.x.x | >=3.7, <4 | >=5.1, <8 |
4738
| 2.x.x | >=3.6, <4 | >=5.1, <8 |
4839

@@ -545,6 +536,17 @@ See [#675](https://github.com/syrupy-project/syrupy/issues/675) for the original
545536

546537
_We welcome contributions to patch these known limitations._
547538

539+
## Migrating from another tool
540+
541+
### From snapshottest
542+
543+
You cannot use syrupy alongside snapshottest due to argument conflicts. To ease migration, we've made syrupy aware of snapshottest call syntax. Simply uninstall snapshottest and remove old snapshots:
544+
545+
```shell
546+
pip uninstall snapshottest -y;
547+
find . -type d ! -path '*/\.*' -name 'snapshots' | xargs rm -r
548+
```
549+
548550
## Uninstalling
549551

550552
```python

poetry.lock

Lines changed: 543 additions & 489 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ license = 'MIT'
44
dynamic = [ "version", "classifiers" ]
55
description = 'Pytest Snapshot Test Utility'
66
readme = 'README.md'
7-
requires-python = ">=3.9"
7+
requires-python = ">=3.10"
88
authors = [{name = 'Noah Ulster'}]
99
dependencies = [
1010
"pytest (>= 8.0.0)"
@@ -22,7 +22,6 @@ classifiers = [
2222
'Intended Audience :: Developers',
2323
'Operating System :: OS Independent',
2424
'Programming Language :: Python :: 3',
25-
'Programming Language :: Python :: 3.9',
2625
'Programming Language :: Python :: 3.10',
2726
'Programming Language :: Python :: 3.11',
2827
'Programming Language :: Python :: 3.12',
@@ -64,7 +63,6 @@ exclude_lines = ['pragma: no-cover', 'if TYPE_CHECKING:', '@abstractmethod']
6463

6564
[tool.ruff]
6665
line-length = 88
67-
target-version = "py39"
6866
unsafe-fixes = true
6967

7068
[tool.ruff.lint]
@@ -77,5 +75,5 @@ extend-select = [
7775
]
7876

7977
[build-system]
80-
requires = ['poetry-core>=2.1.2']
78+
requires = ['poetry-core>=2.2.1']
8179
build-backend = 'poetry.core.masonry.api'

src/syrupy/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535

3636
@lru_cache(maxsize=1)
37-
def __import_extension(value: Optional[str]) -> Any:
37+
def __import_extension(value: str | None) -> Any:
3838
if not value:
3939
return DEFAULT_EXTENSION
4040
try:
@@ -126,7 +126,7 @@ def __terminal_color(
126126
@pytest.hookimpl(tryfirst=True)
127127
def pytest_assertrepr_compare(
128128
config: "pytest.Config", op: str, left: Any, right: Any
129-
) -> Optional[list[str]]:
129+
) -> list[str] | None:
130130
"""
131131
Return explanation for comparisons in failing assert expressions.
132132
https://docs.pytest.org/en/latest/reference.html#pytest.hookspec.pytest_assertrepr_compare

src/syrupy/assertion.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import traceback
22
from collections import namedtuple
3+
from collections.abc import Callable
34
from dataclasses import (
45
dataclass,
56
field,
@@ -9,7 +10,6 @@
910
from typing import (
1011
TYPE_CHECKING,
1112
Any,
12-
Callable,
1313
Optional,
1414
)
1515

@@ -49,7 +49,7 @@ class AssertionResult:
4949
created: bool
5050
updated: bool
5151
success: bool
52-
exception: Optional[Exception]
52+
exception: Exception | None
5353
test_location: "PyTestLocation"
5454

5555
@property
@@ -77,7 +77,7 @@ class SnapshotAssertion:
7777
init=False,
7878
default=None,
7979
)
80-
_custom_index: Optional[str] = field(
80+
_custom_index: str | None = field(
8181
init=False,
8282
default=None,
8383
)
@@ -182,7 +182,7 @@ def with_defaults(
182182
exclude: Optional["PropertyFilter"] = None,
183183
include: Optional["PropertyFilter"] = None,
184184
matcher: Optional["PropertyMatcher"] = None,
185-
extension_class: Optional[type["AbstractSyrupyExtension"]] = None,
185+
extension_class: type["AbstractSyrupyExtension"] | None = None,
186186
) -> "SnapshotAssertion":
187187
"""
188188
Create new snapshot assertion fixture with provided values. This preserves
@@ -199,7 +199,7 @@ def with_defaults(
199199
)
200200

201201
def use_extension(
202-
self, extension_class: Optional[type["AbstractSyrupyExtension"]] = None
202+
self, extension_class: type["AbstractSyrupyExtension"] | None = None
203203
) -> "SnapshotAssertion":
204204
"""
205205
Create new snapshot assertion fixture with the same options but using
@@ -269,7 +269,7 @@ def __call__(
269269
diff: Optional["SnapshotIndex"] = None,
270270
exclude: Optional["PropertyFilter"] = None,
271271
include: Optional["PropertyFilter"] = None,
272-
extension_class: Optional[type["AbstractSyrupyExtension"]] = None,
272+
extension_class: type["AbstractSyrupyExtension"] | None = None,
273273
matcher: Optional["PropertyMatcher"] = None,
274274
name: Optional["SnapshotIndex"] = None,
275275
) -> "SnapshotAssertion":
@@ -303,8 +303,8 @@ def _assert(self, data: "SerializableData") -> bool:
303303
snapshot_name = self.extension.get_snapshot_name(
304304
test_location=self.test_location, index=self.index
305305
)
306-
snapshot_data: Optional[SerializedData] = None
307-
serialized_data: Optional[SerializedData] = None
306+
snapshot_data: SerializedData | None = None
307+
serialized_data: SerializedData | None = None
308308
matches = False
309309
assertion_success = False
310310
assertion_exception = None

src/syrupy/data.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Snapshot:
2222
name: str
2323
data: Optional["SerializedData"] = None
2424
# A tainted snapshot needs to be regenerated
25-
tainted: Optional[bool] = field(default=None)
25+
tainted: bool | None = field(default=None)
2626

2727

2828
@dataclass(frozen=True)
@@ -43,7 +43,7 @@ class SnapshotCollection:
4343
_snapshots: dict[str, "Snapshot"] = field(default_factory=dict)
4444

4545
# A tainted collection needs to be regenerated
46-
tainted: Optional[bool] = field(default=None)
46+
tainted: bool | None = field(default=None)
4747

4848
@property
4949
def has_snapshots(self) -> bool:
@@ -125,8 +125,8 @@ def __contains__(self, key: str) -> bool:
125125

126126
@dataclass
127127
class DiffedLine:
128-
a: Optional[str] = None
129-
b: Optional[str] = None
128+
a: str | None = None
129+
b: str | None = None
130130
c: list[str] = field(default_factory=list)
131131
diff_a: str = ""
132132
diff_b: str = ""

src/syrupy/extensions/amber/serializer.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import collections
22
import inspect
33
from collections import OrderedDict
4-
from collections.abc import Generator, Iterable
4+
from collections.abc import Callable, Generator, Iterable
55
from types import (
66
FunctionType,
77
GeneratorType,
@@ -10,10 +10,8 @@
1010
from typing import (
1111
TYPE_CHECKING,
1212
Any,
13-
Callable,
1413
NamedTuple,
1514
Optional,
16-
Union,
1715
)
1816

1917
from syrupy.constants import (
@@ -41,7 +39,7 @@
4139
IterableEntries = tuple[
4240
Iterable["PropertyName"],
4341
"PropertyValueGetter",
44-
Optional["PropertyValueFilter"],
42+
"PropertyValueFilter" | None,
4543
]
4644

4745

@@ -240,7 +238,7 @@ def _serialize(
240238
include: Optional["PropertyFilter"] = None,
241239
matcher: Optional["PropertyMatcher"] = None,
242240
path: "PropertyPath" = (),
243-
visited: Optional[set[Any]] = None,
241+
visited: set[Any] | None = None,
244242
) -> str:
245243
visited = set() if visited is None else visited
246244
data_id = id(data)
@@ -276,7 +274,7 @@ def _serialize(
276274

277275
@classmethod
278276
def serialize_number(
279-
cls, data: Union[int, float], *, depth: int = 0, **kwargs: Any
277+
cls, data: int | float, *, depth: int = 0, **kwargs: Any
280278
) -> str:
281279
return cls.__serialize_plain(data=data, depth=depth)
282280

@@ -424,13 +422,13 @@ def serialize_custom_iterable(
424422
*,
425423
data: "SerializableData",
426424
resolve_entries: "IterableEntries",
427-
open_paren: Optional[str] = None,
428-
close_paren: Optional[str] = None,
425+
open_paren: str | None = None,
426+
close_paren: str | None = None,
429427
depth: int = 0,
430428
exclude: Optional["PropertyFilter"] = None,
431429
include: Optional["PropertyFilter"] = None,
432430
path: "PropertyPath" = (),
433-
separator: Optional[str] = None,
431+
separator: str | None = None,
434432
serialize_key: bool = False,
435433
**kwargs: Any,
436434
) -> str:
@@ -507,7 +505,7 @@ class AmberDataSerializerSorted(AmberDataSerializer):
507505
VERSION = f"{AmberDataSerializer.VERSION}-sorted"
508506

509507
@classmethod
510-
def __maybe_int(cls, part: str) -> tuple[int, Union[str, int]]:
508+
def __maybe_int(cls, part: str) -> tuple[int, str | int]:
511509
try:
512510
# cast to int only if the string is the exact representation of the int
513511
# for example, '012' != str(int('012'))

src/syrupy/extensions/base.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
ABC,
44
abstractmethod,
55
)
6-
from collections.abc import Iterator
6+
from collections.abc import Callable, Iterator
77
from gettext import gettext
88
from itertools import zip_longest
99
from pathlib import Path
1010
from typing import (
1111
TYPE_CHECKING,
12-
Callable,
1312
Optional,
1413
)
1514

@@ -107,7 +106,7 @@ def discover_snapshots(
107106
self,
108107
*,
109108
test_location: "PyTestLocation",
110-
ignore_extensions: Optional[list[str]] = None,
109+
ignore_extensions: list[str] | None = None,
111110
) -> "SnapshotCollections":
112111
"""
113112
Returns all snapshot collections in test site
@@ -317,7 +316,7 @@ def __diff_lines(self, a: str, b: str) -> Iterator[str]:
317316
yield from map(context_style, self.__limit_context(line.c))
318317

319318
def __diffed_lines(self, a: str, b: str) -> Iterator["DiffedLine"]:
320-
staged_diffed_line: Optional[DiffedLine] = None
319+
staged_diffed_line: DiffedLine | None = None
321320
for line in qdiff(a.splitlines(keepends=True), b.splitlines(keepends=True)):
322321
is_context_line = line[0] == " "
323322
is_snapshot_line = line[0] == "-"

src/syrupy/extensions/json/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def _filter(
5959
exclude: Optional["PropertyFilter"] = None,
6060
include: Optional["PropertyFilter"] = None,
6161
matcher: Optional["PropertyMatcher"] = None,
62-
visited: Optional[set[Any]] = None,
62+
visited: set[Any] | None = None,
6363
) -> "SerializableData":
6464
data_id = id(data)
6565
visited = set() if visited is None else visited

0 commit comments

Comments
 (0)