diff --git a/README.md b/README.md index 2ed7d049..30e98c4f 100644 --- a/README.md +++ b/README.md @@ -164,13 +164,13 @@ def test_bar(snapshot): })) ``` -```ambr +```py # name: test_bar - { - 'date_created': , + dict({ + 'date_created': datetime, 'value': 'Some computed value!!', - } ---- + }) +# --- ``` #### `exclude` @@ -206,15 +206,15 @@ def test_bar(snapshot): assert actual == snapshot(exclude=props("id", "1")) ``` -```ambr +```py # name: test_bar - { - 'list': [ + dict({ + 'list': list([ 1, 3, - ], - } ---- + ]), + }) +# --- ``` ###### `paths(path_string, *path_strings)` @@ -234,15 +234,15 @@ def test_bar(snapshot): assert actual == snapshot(exclude=paths("date", "list.1")) ``` -```ambr +```py # name: test_bar - { - 'list': [ + dict({ + 'list': list([ 1, 3, - ], - } ---- + ]), + }) +# --- ``` #### `extension_class` diff --git a/src/syrupy/extensions/amber/serializer.py b/src/syrupy/extensions/amber/serializer.py index c276b69d..b9ef4879 100644 --- a/src/syrupy/extensions/amber/serializer.py +++ b/src/syrupy/extensions/amber/serializer.py @@ -60,7 +60,7 @@ class DataSerializer: _indent: str = " " _max_depth: int = 99 _marker_comment: str = "# " - _marker_divider: str = "---" + _marker_divider: str = f"{_marker_comment}---" _marker_name: str = f"{_marker_comment}name:" _marker_crn: str = "\r\n" @@ -189,8 +189,8 @@ def serialize_string(cls, data: str, *, depth: int = 0, **kwargs: Any) -> str: for line in str(data).splitlines(keepends=True) ), depth=depth, - open_tag="'", - close_tag="'", + open_tag="'''", + close_tag="'''", include_type=False, ends="", ) @@ -199,21 +199,16 @@ def serialize_string(cls, data: str, *, depth: int = 0, **kwargs: Any) -> str: def serialize_iterable( cls, data: Iterable["SerializableData"], **kwargs: Any ) -> str: - open_paren, close_paren = next( - parens - for iter_type, parens in { - GeneratorType: ("(", ")"), - list: ("[", "]"), - tuple: ("(", ")"), - }.items() - if isinstance(data, iter_type) - ) + open_paren, close_paren = (None, None) + if isinstance(data, list): + open_paren, close_paren = ("[", "]") + values = list(data) return cls.__serialize_iterable( data=data, resolve_entries=(range(len(values)), item_getter, None), - open_tag=open_paren, - close_tag=close_paren, + open_paren=open_paren, + close_paren=close_paren, **kwargs, ) @@ -222,8 +217,8 @@ def serialize_set(cls, data: Set["SerializableData"], **kwargs: Any) -> str: return cls.__serialize_iterable( data=data, resolve_entries=(cls.sort(data), lambda _, p: p, None), - open_tag="{", - close_tag="}", + open_paren="{", + close_paren="}", **kwargs, ) @@ -232,8 +227,6 @@ def serialize_namedtuple(cls, data: NamedTuple, **kwargs: Any) -> str: return cls.__serialize_iterable( data=data, resolve_entries=(cls.sort(data._fields), attr_getter, None), - open_tag="(", - close_tag=")", separator="=", **kwargs, ) @@ -245,8 +238,8 @@ def serialize_dict( return cls.__serialize_iterable( data=data, resolve_entries=(cls.sort(data.keys()), item_getter, None), - open_tag="{", - close_tag="}", + open_paren="{", + close_paren="}", separator=": ", serialize_key=True, **kwargs, @@ -265,8 +258,6 @@ def serialize_unknown(cls, data: Any, *, depth: int = 0, **kwargs: Any) -> str: lambda v: not callable(v), ), depth=depth, - open_tag="{", - close_tag="}", separator="=", **kwargs, ) @@ -284,7 +275,7 @@ def sort(cls, iterable: Iterable[Any]) -> Iterable[Any]: @classmethod def object_type(cls, data: "SerializableData") -> str: - return f"" + return f"{data.__class__.__name__}" @classmethod def __is_namedtuple(cls, obj: Any) -> bool: @@ -307,8 +298,8 @@ def __serialize_iterable( *, data: "SerializableData", resolve_entries: "IterableEntries", - open_tag: str, - close_tag: str, + open_paren: Optional[str] = None, + close_paren: Optional[str] = None, depth: int = 0, exclude: Optional["PropertyFilter"] = None, path: "PropertyPath" = (), @@ -349,8 +340,8 @@ def value_str(key: "PropertyName", value: "SerializableData") -> str: data=data, lines=(f"{key_str(key)}{value_str(key, value)}," for key, value in entries), depth=depth, - open_tag=open_tag, - close_tag=close_tag, + open_tag=f"({open_paren or ''}", + close_tag=f"{close_paren or ''})", ) @classmethod @@ -367,7 +358,7 @@ def __serialize_lines( ) -> str: lines = ends.join(lines) lines_end = "\n" if lines else "" - maybe_obj_type = f"{cls.object_type(data)} " if include_type else "" + maybe_obj_type = f"{cls.object_type(data)}" if include_type else "" formatted_open_tag = cls.with_indent(f"{maybe_obj_type}{open_tag}", depth) formatted_close_tag = cls.with_indent(close_tag, depth) return f"{formatted_open_tag}\n{lines}{lines_end}{formatted_close_tag}" diff --git a/tests/examples/__snaps_example__/test_custom_snapshot_directory.ambr b/tests/examples/__snaps_example__/test_custom_snapshot_directory.ambr index 9c3dc6da..03976d12 100644 --- a/tests/examples/__snaps_example__/test_custom_snapshot_directory.ambr +++ b/tests/examples/__snaps_example__/test_custom_snapshot_directory.ambr @@ -1,3 +1,3 @@ # name: test_case_1 'Syrupy is amazing!' ---- +# --- diff --git a/tests/examples/__snapshots__/test_custom_object_repr.ambr b/tests/examples/__snapshots__/test_custom_object_repr.ambr index 573f98cf..2cb487e7 100644 --- a/tests/examples/__snapshots__/test_custom_object_repr.ambr +++ b/tests/examples/__snapshots__/test_custom_object_repr.ambr @@ -1,18 +1,18 @@ # name: test_snapshot_custom_class - { + MyCustomClass( prop1=1, prop2='a', - prop3= { + prop3=set({ 1, 2, 3, - }, - } ---- + }), + ) +# --- # name: test_snapshot_custom_repr_class MyCustomReprClass( prop1=1, prop2='a', prop3={1, 2, 3}, ) ---- +# --- diff --git a/tests/examples/__snapshots__/test_custom_snapshot_name.ambr b/tests/examples/__snapshots__/test_custom_snapshot_name.ambr index a6b95093..24dd5540 100644 --- a/tests/examples/__snapshots__/test_custom_snapshot_name.ambr +++ b/tests/examples/__snapshots__/test_custom_snapshot_name.ambr @@ -1,3 +1,3 @@ # name: test_canadian_nameπŸ‡¨πŸ‡¦ 'Name should be test_canadian_nameπŸ‡¨πŸ‡¦.' ---- +# --- diff --git a/tests/integration/test_snapshot_option_update.py b/tests/integration/test_snapshot_option_update.py index 2ce6fe71..12f4533d 100644 --- a/tests/integration/test_snapshot_option_update.py +++ b/tests/integration/test_snapshot_option_update.py @@ -128,7 +128,7 @@ def test_update_failure_shows_snapshot_diff(run_testcases, testcases_updated): ( r".*assert snapshot == \['this', 'will', 'not', 'match'\]", r".*AssertionError: assert \[- snapshot\] == \[\+ received\]", - r".* \[", + r".* list\(\[", r".* ...", r".* 'will',", r".* - 'be',", @@ -138,7 +138,7 @@ def test_update_failure_shows_snapshot_diff(run_testcases, testcases_updated): r".* \]", r".*assert \['this', 'will', 'fail'\] == snapshot", r".*AssertionError: assert \[\+ received\] == \[- snapshot\]", - r".* \[", + r".* list\(\[", r".* ...", r".* 'will',", r".* - 'be',", @@ -147,7 +147,7 @@ def test_update_failure_shows_snapshot_diff(run_testcases, testcases_updated): r".* \]", r".*assert snapshot == \['this', 'will', 'be', 'too', 'much'\]", r".*AssertionError: assert \[- snapshot\] == \[\+ received\]", - r".* \[", + r".* list\(\[", r".* ...", r".* 'be',", r".* - 'updated',", diff --git a/tests/syrupy/extensions/__snapshots__/test_base.ambr b/tests/syrupy/extensions/__snapshots__/test_base.ambr index a2db256d..ae4f37b3 100644 --- a/tests/syrupy/extensions/__snapshots__/test_base.ambr +++ b/tests/syrupy/extensions/__snapshots__/test_base.ambr @@ -1,5 +1,5 @@ # name: TestSnapshotReporter.test_diff_lines[-0-SnapshotReporterNoContext] - ' + ''' ... - line 2 + line 02 @@ -7,10 +7,10 @@ - line 04 + line 4 ... - ' ---- + ''' +# --- # name: TestSnapshotReporter.test_diff_lines[-0-SnapshotReporter] - ' + ''' line 0 line 1 - line 2 @@ -21,18 +21,18 @@ line 5 ... line 7 - ' ---- + ''' +# --- # name: TestSnapshotReporter.test_diff_lines[-1-SnapshotReporterNoContext] - ' + ''' ... - line 3 + line 3 ... - ' ---- + ''' +# --- # name: TestSnapshotReporter.test_diff_lines[-1-SnapshotReporter] - ' + ''' line 0 ... line 2 @@ -41,10 +41,10 @@ line 4 ... line 7 - ' ---- + ''' +# --- # name: TestSnapshotReporter.test_diff_lines[-2-SnapshotReporterNoContext] - ' + ''' - line 0␍ + line 0␀ ... @@ -53,10 +53,10 @@ - line 3␀ + line 3␍␀ ... - ' ---- + ''' +# --- # name: TestSnapshotReporter.test_diff_lines[-2-SnapshotReporter] - ' + ''' - line 0␍ + line 0␀ line 1 @@ -67,5 +67,5 @@ line 4 ... line 7 - ' ---- + ''' +# --- diff --git a/tests/syrupy/extensions/amber/__snapshots__/test_amber_filters.ambr b/tests/syrupy/extensions/amber/__snapshots__/test_amber_filters.ambr index d5a34f73..6c53156e 100644 --- a/tests/syrupy/extensions/amber/__snapshots__/test_amber_filters.ambr +++ b/tests/syrupy/extensions/amber/__snapshots__/test_amber_filters.ambr @@ -1,36 +1,36 @@ # name: test_filters_error_prop[path_filter] - { + WithNested( include_me='prop value', - nested= { + nested=CustomClass( include_me='prop value', - }, - } ---- + ), + ) +# --- # name: test_filters_error_prop[prop_filter] - { + WithNested( include_me='prop value', - nested= { + nested=CustomClass( include_me='prop value', - }, - } ---- + ), + ) +# --- # name: test_filters_expected_paths - { - 'list': [ + dict({ + 'list': list([ 2, - ], - 'nested': { + ]), + 'nested': dict({ 'other': 'value', - }, - } ---- + }), + }) +# --- # name: test_filters_expected_props - { - 'list': [ + dict({ + 'list': list([ 2, - ], - 'nested': { + ]), + 'nested': dict({ 'other': 'value', - }, - } ---- + }), + }) +# --- diff --git a/tests/syrupy/extensions/amber/__snapshots__/test_amber_matchers.ambr b/tests/syrupy/extensions/amber/__snapshots__/test_amber_matchers.ambr index 912071bb..d4558392 100644 --- a/tests/syrupy/extensions/amber/__snapshots__/test_amber_matchers.ambr +++ b/tests/syrupy/extensions/amber/__snapshots__/test_amber_matchers.ambr @@ -1,64 +1,64 @@ # name: test_matches_expected_type - { - 'date_created': , - 'nested': { - 'id': , - }, - 'some_uuid': , - } ---- + dict({ + 'date_created': datetime, + 'nested': dict({ + 'id': int, + }), + 'some_uuid': UUID, + }) +# --- # name: test_matches_non_deterministic_snapshots - { + dict({ 'a': UUID(...), - 'b': { + 'b': dict({ 'b_1': 'This is deterministic', 'b_2': datetime.datetime(...), - }, - 'c': [ + }), + 'c': list([ 'Your wish is my command', 'Do not replace this one', - ], - } ---- + ]), + }) +# --- # name: test_matches_non_deterministic_snapshots.1 - { + dict({ 'a': UUID('06335e84-2872-4914-8c5d-3ed07d2a2f16'), - 'b': { + 'b': dict({ 'b_1': 'This is deterministic', 'b_2': datetime.datetime(2020, 5, 31, 0, 0), - }, - 'c': [ + }), + 'c': list([ 'Replace this one', 'Do not replace this one', - ], - } ---- + ]), + }) +# --- # name: test_matches_regex_in_regex_mode - { - 'any_number': , + dict({ + 'any_number': int, 'any_number_adjacent': 'hi', - 'data': { - 'list': [ - { - 'date_created': , + 'data': dict({ + 'list': list([ + dict({ + 'date_created': datetime, 'k': '1', - }, - { - 'date_created': , + }), + dict({ + 'date_created': datetime, 'k': '2', - }, - ], - }, + }), + ]), + }), 'specific_number': 5, - } ---- + }) +# --- # name: test_raises_unexpected_type - { - 'date_created': , + dict({ + 'date_created': datetime, 'date_updated': datetime.date(2020, 6, 1), - 'nested': { - 'id': , - }, - 'some_uuid': , - } ---- + 'nested': dict({ + 'id': int, + }), + 'some_uuid': UUID, + }) +# --- diff --git a/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr b/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr index 392d7e53..22cb2fe1 100644 --- a/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr +++ b/tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr @@ -1,439 +1,439 @@ # name: TestClass.TestNestedClass.test_nested_class_method[x] 'parameterized nested class method x' ---- +# --- # name: TestClass.TestNestedClass.test_nested_class_method[y] 'parameterized nested class method y' ---- +# --- # name: TestClass.TestNestedClass.test_nested_class_method[z] 'parameterized nested class method z' ---- +# --- # name: TestClass.test_class_method_name 'this is in a test class' ---- +# --- # name: TestClass.test_class_method_parametrized[a] 'a' ---- +# --- # name: TestClass.test_class_method_parametrized[b] 'b' ---- +# --- # name: TestClass.test_class_method_parametrized[c] 'c' ---- +# --- # name: TestSubClass.TestNestedClass.test_nested_class_method[x] 'parameterized nested class method x' ---- +# --- # name: TestSubClass.TestNestedClass.test_nested_class_method[y] 'parameterized nested class method y' ---- +# --- # name: TestSubClass.TestNestedClass.test_nested_class_method[z] 'parameterized nested class method z' ---- +# --- # name: TestSubClass.test_class_method_name 'this is in a test class' ---- +# --- # name: TestSubClass.test_class_method_parametrized[a] 'a' ---- +# --- # name: TestSubClass.test_class_method_parametrized[b] 'b' ---- +# --- # name: TestSubClass.test_class_method_parametrized[c] 'c' ---- +# --- # name: test_bool[False] False ---- +# --- # name: test_bool[True] True ---- +# --- # name: test_custom_object_repr - { + CustomClass( a=1, b='2', - c= [ + c=list([ 1, 2, 3, ..., - ], - d= { + ]), + d=dict({ 'a': 1, 'b': 2, 'c': 3, 'd': ..., - }, - x= { + }), + x=CustomClass( a=1, b='2', - c= [ + c=list([ 1, 2, 3, ..., - ], - d= { + ]), + d=dict({ 'a': 1, 'b': 2, 'c': 3, 'd': ..., - }, + }), x=None, - }, - } ---- + ), + ) +# --- # name: test_cycle[cyclic0] - [ + list([ 1, 2, 3, ..., - ] ---- + ]) +# --- # name: test_cycle[cyclic1] - { + dict({ 'a': 1, 'b': 2, 'c': 3, 'd': ..., - } ---- + }) +# --- # name: test_deeply_nested_multiline_string_in_dict - { - 'value_a': { - 'value_b': ' + dict({ + 'value_a': dict({ + 'value_b': ''' line 1 line 2 line 3 - ', - }, - } ---- + ''', + }), + }) +# --- # name: test_dict[actual0] - { - 'a': { + dict({ + 'a': dict({ 'e': False, - }, + }), 'b': True, 'c': 'Some text.', - 'd': [ + 'd': list([ '1', 2, - ], - } ---- + ]), + }) +# --- # name: test_dict[actual1] - { - 'a': { + dict({ + 'a': dict({ 'e': False, - }, + }), 'b': True, 'c': 'Some ttext.', - 'd': [ + 'd': list([ '1', 2, - ], - } ---- + ]), + }) +# --- # name: test_dict[actual2] - { - ' + dict({ + ''' multi line key - ': 'Some morre text.', + ''': 'Some morre text.', 'a': 'Some ttext.', 1: True, - ( + ExampleTuple( a=1, b=2, c=3, d=4, - ): { + ): dict({ 'e': False, - }, - { + }), + frozenset({ '1', '2', - }: [ + }): list([ '1', 2, - ], - } ---- + ]), + }) +# --- # name: test_dict[actual3] - { - } ---- + dict({ + }) +# --- # name: test_dict[actual4] - { - 'key': [ - ' + dict({ + 'key': list([ + ''' line1 line2 - ', - ], - } ---- + ''', + ]), + }) +# --- # name: test_dict[actual5] - { - 'key': [ + dict({ + 'key': list([ 1, - ' + ''' line1 line2 - ', + ''', 2, - ' + ''' line3 line4 - ', - ], - } ---- + ''', + ]), + }) +# --- # name: test_dict[actual6] - { - 'key': [ + dict({ + 'key': list([ 1, - [ - ' + list([ + ''' line1 line2 - ', - ], + ''', + ]), 2, - ], - } ---- + ]), + }) +# --- # name: test_doubly_parametrized[bar-foo] 'foo' ---- +# --- # name: test_doubly_parametrized[bar-foo].1 'bar' ---- +# --- # name: test_empty_snapshot None ---- +# --- # name: test_empty_snapshot.1 '' ---- +# --- # name: test_list[actual0] - [ - ] ---- + list([ + ]) +# --- # name: test_list[actual1] - [ + list([ 'this', 'is', 'a', 'list', - ] ---- + ]) +# --- # name: test_list[actual2] - [ + list([ 'contains', 'empty', - [ - ], - ] ---- + list([ + ]), + ]) +# --- # name: test_list[actual3] - [ + list([ 1, 2, 'string', - { + dict({ 'key': 'value', - }, - ] ---- + }), + ]) +# --- # name: test_multiline_string_in_dict - { - 'value': ' + dict({ + 'value': ''' line 1 line 2 - ', - } ---- + ''', + }) +# --- # name: test_multiple_snapshots 'First.' ---- +# --- # name: test_multiple_snapshots.1 'Second.' ---- +# --- # name: test_multiple_snapshots.2 'Third.' ---- +# --- # name: test_newline_control_characters - ' + ''' line 1 line 2 - ' ---- + ''' +# --- # name: test_newline_control_characters.1 - ' + ''' line 1 line 2 - ' ---- + ''' +# --- # name: test_newline_control_characters.2 - ' + ''' line 1 line 2 - ' ---- + ''' +# --- # name: test_newline_control_characters.3 - ' + ''' line 1 line 2 - ' ---- + ''' +# --- # name: test_newline_control_characters.4 - ' + ''' line 1 line 2 - ' ---- + ''' +# --- # name: test_newline_control_characters.5 - ' + ''' line 1 line 2 - ' ---- + ''' +# --- # name: test_numbers 3.5 ---- +# --- # name: test_numbers.1 7 ---- +# --- # name: test_numbers.2 0.3333333333333333 ---- +# --- # name: test_parameter_with_dot[value.with.dot] 'value.with.dot' ---- +# --- # name: test_reflection - { + SnapshotAssertion( name='snapshot', num_executions=0, - } ---- + ) +# --- # name: test_set[actual0] - { + set({ 'a', 'is', 'set', 'this', - } ---- + }) +# --- # name: test_set[actual1] - { + set({ 'contains', 'frozen', - { + frozenset({ '1', '2', - }, - } ---- + }), + }) +# --- # name: test_set[actual2] - { + set({ 'contains', 'tuple', - ( + tuple( 1, 2, ), - } ---- + }) +# --- # name: test_set[actual3] - { + set({ 'contains', 'namedtuple', - ( + ExampleTuple( a=1, b=2, c=3, d=4, ), - } ---- + }) +# --- # name: test_set[actual4] - { - } ---- + set({ + }) +# --- # name: test_snapshot_markers - ' + ''' # # - --- + # --- # name: - ' ---- + ''' +# --- # name: test_string[0] '' ---- +# --- # name: test_string[10] b'Byte string' ---- +# --- # name: test_string[1] 'Raw string' ---- +# --- # name: test_string[2] 'Escaped \\n' ---- +# --- # name: test_string[3] 'Backslash \\u U' ---- +# --- # name: test_string[4] 'πŸ₯žπŸπŸ―' ---- +# --- # name: test_string[5] 'singleline:' ---- +# --- # name: test_string[6] '- singleline' ---- +# --- # name: test_string[7] - ' + ''' multi-line line 2 line 3 - ' ---- + ''' +# --- # name: test_string[8] - ' + ''' multi-line line 2 line 3 - ' ---- + ''' +# --- # name: test_string[9] "string with 'quotes'" ---- +# --- # name: test_tuple - ( + tuple( 'this', 'is', - ( + tuple( 'a', 'tuple', ), ) ---- +# --- # name: test_tuple.1 - ( + ExampleTuple( a='this', b='is', c='a', - d= { + d=set({ 'named', 'tuple', - }, + }), ) ---- +# --- # name: test_tuple.2 - ( + tuple( ) ---- +# --- diff --git a/tests/syrupy/extensions/image/__snapshots__/test_image_png.ambr b/tests/syrupy/extensions/image/__snapshots__/test_image_png.ambr index 850ded2d..03ca82c6 100644 --- a/tests/syrupy/extensions/image/__snapshots__/test_image_png.ambr +++ b/tests/syrupy/extensions/image/__snapshots__/test_image_png.ambr @@ -1,3 +1,3 @@ # name: test_multiple_snapshot_extensions.1 b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x002\x00\x00\x002\x04\x03\x00\x00\x00\xec\x11\x95\x82\x00\x00\x00\x1bPLTE\xcc\xcc\xcc\x96\x96\x96\xaa\xaa\xaa\xb7\xb7\xb7\xb1\xb1\xb1\x9c\x9c\x9c\xbe\xbe\xbe\xa3\xa3\xa3\xc5\xc5\xc5\x05\xa4\xf2?\x00\x00\x00\tpHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\x01\x95+\x0e\x1b\x00\x00\x00AIDAT8\x8dc`\x18\x05\xa3\x80\xfe\x80I\xd9\xdc\x00F\xa2\x02\x16\x86\x88\x00\xa6\x16\x10\x89.\xc3\x1a" \xc0\x11\x01"\xd1e\xd8\x12#\x028"@$\x86=*\xe6\x06L- \x92zn\x1f\x05\xc3\x1b\x00\x00\xe5\xfb\x08g\r"af\x00\x00\x00\x00IEND\xaeB`\x82' ---- +# --- diff --git a/tests/syrupy/extensions/image/__snapshots__/test_image_svg.ambr b/tests/syrupy/extensions/image/__snapshots__/test_image_svg.ambr index 6a118b13..84618e01 100644 --- a/tests/syrupy/extensions/image/__snapshots__/test_image_svg.ambr +++ b/tests/syrupy/extensions/image/__snapshots__/test_image_svg.ambr @@ -1,3 +1,3 @@ # name: test_multiple_snapshot_extensions.1 '50 x 50' ---- +# ---