From f245c511a62e60e5e17e4129c27eaffa48e1e690 Mon Sep 17 00:00:00 2001 From: ManiacDC Date: Thu, 19 Oct 2023 14:40:26 -0400 Subject: [PATCH 1/4] feat(serializer): add support for FunctionType serialization * add FunctionType serialization in amber and json extensions * add tests --- src/syrupy/extensions/amber/serializer.py | 12 ++++++++++++ src/syrupy/extensions/json/__init__.py | 12 +++++++++++- .../__snapshots__/test_amber_serializer.ambr | 6 ++++++ .../extensions/amber/test_amber_serializer.py | 19 +++++++++++++++++++ .../test_function_in_file.json | 1 + .../test_function_local.json | 1 + .../extensions/json/test_json_serializer.py | 19 +++++++++++++++++++ 7 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json create mode 100644 tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json diff --git a/src/syrupy/extensions/amber/serializer.py b/src/syrupy/extensions/amber/serializer.py index 07e25177..742593a4 100644 --- a/src/syrupy/extensions/amber/serializer.py +++ b/src/syrupy/extensions/amber/serializer.py @@ -1,7 +1,9 @@ import collections +import inspect import os from collections import OrderedDict from types import ( + FunctionType, GeneratorType, MappingProxyType, ) @@ -257,6 +259,8 @@ def _serialize( serialize_method = cls.serialize_namedtuple elif isinstance(data, (list, tuple, GeneratorType)): serialize_method = cls.serialize_iterable + elif isinstance(data, FunctionType): + serialize_method = cls.serialize_function return serialize_method(**serialize_kwargs) @classmethod @@ -337,6 +341,14 @@ def serialize_dict( **kwargs, ) + @classmethod + def serialize_function( + cls, data: FunctionType, *, depth: int = 0, **kwargs: Any + ) -> str: + return cls.__serialize_plain( + data=f"{data.__qualname__}{str(inspect.signature(data))}", depth=depth + ) + @classmethod def serialize_unknown(cls, data: Any, *, depth: int = 0, **kwargs: Any) -> str: if data.__class__.__repr__ != object.__repr__: diff --git a/src/syrupy/extensions/json/__init__.py b/src/syrupy/extensions/json/__init__.py index 5b52a8d5..a59186b4 100644 --- a/src/syrupy/extensions/json/__init__.py +++ b/src/syrupy/extensions/json/__init__.py @@ -1,7 +1,11 @@ import datetime +import inspect import json from collections import OrderedDict -from types import GeneratorType +from types import ( + FunctionType, + GeneratorType, +) from typing import ( TYPE_CHECKING, Any, @@ -133,6 +137,12 @@ def _filter( if isinstance(data, (datetime.datetime,)): return data.strftime("%Y-%m-%dT%H:%M:%S.%f%z") + if isinstance(data, FunctionType): + return ( + f"<{FunctionType.__name__} " + f"'{data.__qualname__}{str(inspect.signature(data))}'>" + ) + if data.__class__.__repr__ != object.__repr__: return repr(data) diff --git a/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr b/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr index 72f06006..34a0fabb 100644 --- a/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr +++ b/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr @@ -217,6 +217,12 @@ # name: test_empty_snapshot.1 '' # --- +# name: test_function_in_file + "function_to_test(var1, var2='test_val', var3: str = 'test_val2', *, kwvar1, kwvar2='some_val') -> str" +# --- +# name: test_function_local + "test_function_local..local_function_to_test(var1, var2='test_val', var3: str = 'test_val2', *, kwvar1, kwvar2='some_val') -> int" +# --- # name: test_list[actual0] list([ ]) diff --git a/tests/syrupy/extensions/amber/test_amber_serializer.py b/tests/syrupy/extensions/amber/test_amber_serializer.py index 9edad07c..28db7559 100644 --- a/tests/syrupy/extensions/amber/test_amber_serializer.py +++ b/tests/syrupy/extensions/amber/test_amber_serializer.py @@ -233,3 +233,22 @@ def test_ordered_dict(snapshot): def test_many_sorted(snapshot): for i in range(25): assert i == snapshot + + +def function_to_test( + var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" +) -> str: + return "2" + + +def test_function_in_file(snapshot): + assert snapshot() == function_to_test + + +def test_function_local(snapshot): + def local_function_to_test( + var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" + ) -> int: + return 1 + + assert snapshot() == local_function_to_test diff --git a/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json new file mode 100644 index 00000000..3f8b8ec3 --- /dev/null +++ b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json @@ -0,0 +1 @@ +" str'>" diff --git a/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json new file mode 100644 index 00000000..8bd51b2a --- /dev/null +++ b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json @@ -0,0 +1 @@ +".local_function_to_test(var1, var2='test_val', var3: str = 'test_val2', *, kwvar1, kwvar2='some_val') -> int'>" diff --git a/tests/syrupy/extensions/json/test_json_serializer.py b/tests/syrupy/extensions/json/test_json_serializer.py index e957c09e..bb951ef6 100644 --- a/tests/syrupy/extensions/json/test_json_serializer.py +++ b/tests/syrupy/extensions/json/test_json_serializer.py @@ -232,3 +232,22 @@ def test_ordered_dict(snapshot_json): d["b"] = 0 d["a"] = OrderedDict(b=True, a=False) assert snapshot_json == d + + +def function_to_test( + var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" +) -> str: + return "2" + + +def test_function_in_file(snapshot_json): + assert snapshot_json() == function_to_test + + +def test_function_local(snapshot_json): + def local_function_to_test( + var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" + ) -> int: + return 1 + + assert snapshot_json() == local_function_to_test From 83999e7e20d68040e93b8840d1ad3d1cd97da5af Mon Sep 17 00:00:00 2001 From: ManiacDC Date: Tue, 24 Oct 2023 09:30:18 -0400 Subject: [PATCH 2/4] PR Fixes * remove snapshot invocations * remove single quotes around json serialization due to single quotes in inspect signature. --- src/syrupy/extensions/json/__init__.py | 2 +- tests/syrupy/extensions/amber/test_amber_serializer.py | 8 ++++---- .../test_json_serializer/test_function_in_file.json | 2 +- .../test_json_serializer/test_function_local.json | 2 +- tests/syrupy/extensions/json/test_json_serializer.py | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/syrupy/extensions/json/__init__.py b/src/syrupy/extensions/json/__init__.py index a59186b4..bd26a65c 100644 --- a/src/syrupy/extensions/json/__init__.py +++ b/src/syrupy/extensions/json/__init__.py @@ -140,7 +140,7 @@ def _filter( if isinstance(data, FunctionType): return ( f"<{FunctionType.__name__} " - f"'{data.__qualname__}{str(inspect.signature(data))}'>" + f"{data.__qualname__}{str(inspect.signature(data))}>" ) if data.__class__.__repr__ != object.__repr__: diff --git a/tests/syrupy/extensions/amber/test_amber_serializer.py b/tests/syrupy/extensions/amber/test_amber_serializer.py index 28db7559..5c7c476b 100644 --- a/tests/syrupy/extensions/amber/test_amber_serializer.py +++ b/tests/syrupy/extensions/amber/test_amber_serializer.py @@ -236,19 +236,19 @@ def test_many_sorted(snapshot): def function_to_test( - var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" + var1, var2="test_val", var3: str="test_val2", *, kwvar1, kwvar2: str="some_val" ) -> str: return "2" def test_function_in_file(snapshot): - assert snapshot() == function_to_test + assert snapshot == function_to_test def test_function_local(snapshot): def local_function_to_test( - var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" + var1, var2="test_val", var3: str="test_val2", *, kwvar1, kwvar2="some_val" ) -> int: return 1 - assert snapshot() == local_function_to_test + assert snapshot == local_function_to_test diff --git a/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json index 3f8b8ec3..c02919a3 100644 --- a/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json +++ b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_in_file.json @@ -1 +1 @@ -" str'>" +" str>" diff --git a/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json index 8bd51b2a..bc801efe 100644 --- a/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json +++ b/tests/syrupy/extensions/json/__snapshots__/test_json_serializer/test_function_local.json @@ -1 +1 @@ -".local_function_to_test(var1, var2='test_val', var3: str = 'test_val2', *, kwvar1, kwvar2='some_val') -> int'>" +".local_function_to_test(var1, var2='test_val', var3: str = 'test_val2', *, kwvar1, kwvar2='some_val') -> int>" diff --git a/tests/syrupy/extensions/json/test_json_serializer.py b/tests/syrupy/extensions/json/test_json_serializer.py index bb951ef6..449cfcf3 100644 --- a/tests/syrupy/extensions/json/test_json_serializer.py +++ b/tests/syrupy/extensions/json/test_json_serializer.py @@ -241,7 +241,7 @@ def function_to_test( def test_function_in_file(snapshot_json): - assert snapshot_json() == function_to_test + assert snapshot_json == function_to_test def test_function_local(snapshot_json): @@ -250,4 +250,4 @@ def local_function_to_test( ) -> int: return 1 - assert snapshot_json() == local_function_to_test + assert snapshot_json == local_function_to_test From 9c276a0a60dc5db0376e877ca74bb6c250d3ae0a Mon Sep 17 00:00:00 2001 From: ManiacDC Date: Tue, 24 Oct 2023 09:51:22 -0400 Subject: [PATCH 3/4] * remove accidentally added test code --- tests/syrupy/extensions/amber/test_amber_serializer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/syrupy/extensions/amber/test_amber_serializer.py b/tests/syrupy/extensions/amber/test_amber_serializer.py index 5c7c476b..63141d27 100644 --- a/tests/syrupy/extensions/amber/test_amber_serializer.py +++ b/tests/syrupy/extensions/amber/test_amber_serializer.py @@ -236,7 +236,7 @@ def test_many_sorted(snapshot): def function_to_test( - var1, var2="test_val", var3: str="test_val2", *, kwvar1, kwvar2: str="some_val" + var1, var2="test_val", var3: str="test_val2", *, kwvar1, kwvar2="some_val" ) -> str: return "2" From b2ff647a64ed7fee73f71e1b3a3ecd435ea93459 Mon Sep 17 00:00:00 2001 From: ManiacDC Date: Tue, 24 Oct 2023 09:55:36 -0400 Subject: [PATCH 4/4] * fix formatting --- tests/syrupy/extensions/amber/test_amber_serializer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/syrupy/extensions/amber/test_amber_serializer.py b/tests/syrupy/extensions/amber/test_amber_serializer.py index 63141d27..365bc7fe 100644 --- a/tests/syrupy/extensions/amber/test_amber_serializer.py +++ b/tests/syrupy/extensions/amber/test_amber_serializer.py @@ -236,7 +236,7 @@ def test_many_sorted(snapshot): def function_to_test( - var1, var2="test_val", var3: str="test_val2", *, kwvar1, kwvar2="some_val" + var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" ) -> str: return "2" @@ -247,7 +247,7 @@ def test_function_in_file(snapshot): def test_function_local(snapshot): def local_function_to_test( - var1, var2="test_val", var3: str="test_val2", *, kwvar1, kwvar2="some_val" + var1, var2="test_val", var3: str = "test_val2", *, kwvar1, kwvar2="some_val" ) -> int: return 1