{"id":14259646,"url":"https://github.com/syrupy-project/syrupy","last_synced_at":"2025-12-15T00:05:06.737Z","repository":{"id":36466235,"uuid":"216412299","full_name":"syrupy-project/syrupy","owner":"syrupy-project","description":":pancakes: The sweeter pytest snapshot plugin","archived":false,"fork":false,"pushed_at":"2025-10-03T18:43:59.000Z","size":12890,"stargazers_count":708,"open_issues_count":20,"forks_count":43,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-10-16T03:47:14.946Z","etag":null,"topics":["pytest","pytest-plugin","python","snapshot","snapshot-plugin","snapshot-testing","snapshot-tests","snapshottest","testing"],"latest_commit_sha":null,"homepage":"https://syrupy-project.github.io/syrupy/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/syrupy-project.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-10-20T19:01:50.000Z","updated_at":"2025-10-14T21:08:27.000Z","dependencies_parsed_at":"2023-10-20T23:31:52.329Z","dependency_job_id":"56e39f3d-6305-46bb-b1a9-7fc751716a17","html_url":"https://github.com/syrupy-project/syrupy","commit_stats":{"total_commits":752,"total_committers":34,"mean_commits":22.11764705882353,"dds":0.738031914893617,"last_synced_commit":"078c928db1e26a0d3679e61b728bcca8242b7666"},"previous_names":["syrupy-project/syrupy"],"tags_count":118,"template":false,"template_full_name":"tophat/new-project-kit","purl":"pkg:github/syrupy-project/syrupy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syrupy-project%2Fsyrupy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syrupy-project%2Fsyrupy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syrupy-project%2Fsyrupy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syrupy-project%2Fsyrupy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/syrupy-project","download_url":"https://codeload.github.com/syrupy-project/syrupy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syrupy-project%2Fsyrupy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280360459,"owners_count":26317488,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-21T02:00:06.614Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pytest","pytest-plugin","python","snapshot","snapshot-plugin","snapshot-testing","snapshot-tests","snapshottest","testing"],"created_at":"2024-08-22T10:01:47.180Z","updated_at":"2025-10-22T02:51:26.334Z","avatar_url":"https://github.com/syrupy-project.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# syrupy\n\n\u003cimg align=\"right\" width=\"100px\" height=\"100px\" src=\"https://user-images.githubusercontent.com/2528959/69500147-85d71400-0ec6-11ea-867a-277881278e57.png\" alt=\"Logo\"\u003e\n\n[![All Contributors](https://img.shields.io/github/all-contributors/syrupy-project/syrupy?color=ee8449\u0026style=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)\n\n![Pytest\u003e=8,\u003c9.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)\n\n## Overview\n\nSyrupy 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.\n\n## Motivation\n\nSyrupy upholds three principles:\n\n- Extensible: If a particular data type is not supported, users should be able to easily and quickly add support.\n- Idiomatic: Snapshot testing should fit naturally among other test cases in pytest, e.g. `assert x == snapshot` vs. `snapshot.assert_match(x)`.\n- Soundness: Snapshot tests should uncover even the most minute issues. Unlike other snapshot libraries, Syrupy will fail a test suite if a snapshot does not exist, not just on snapshot differences.\n\n## Installation\n\n```shell\npython -m pip install syrupy\n```\n\n### Pytest and Python Compatibility\n\nSyrupy 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:\n\n| Syrupy Version | Python Support | Pytest Support |\n| -------------- | -------------- | -------------- |\n| 5.x.x          | \u003e=3.10         | \u003e=8            |\n| 4.x.x          | \u003e=3.8.1,       | \u003e=7,   \u003c9      |\n| 3.x.x          | \u003e=3.7, \u003c4      | \u003e=5.1, \u003c8      |\n| 2.x.x          | \u003e=3.6, \u003c4      | \u003e=5.1, \u003c8      |\n\n## Usage\n\n### Basic Usage\n\nIn a pytest test file `test_file.py`:\n\n```python\ndef test_foo(snapshot):\n    actual = \"Some computed value!\"\n    assert actual == snapshot\n```\n\nwhen you run `pytest`, the above test should fail due to a missing snapshot. Re-run pytest with the update snapshots flag like so:\n\n```shell\npytest --snapshot-update\n```\n\nA snapshot file should be generated under a `__snapshots__` directory in the same directory as `test_file.py`. The `__snapshots__` directory and all its children should be committed along with your test code.\n\n#### Custom Objects\n\nThe default serializer supports all python built-in types and provides a sensible default for custom objects.\n\n#### Representation\n\nIf you need to customise your object snapshot, it is as easy as overriding the default `__repr__` implementation.\n\n```python\ndef __repr__(self) -\u003e str:\n    return \"MyCustomClass(...)\"\n```\n\nIf you need bypass a custom object representation to use the amber standard, it is easy using the following helpers.\n\n```python\ndef test_object_as_named_tuple(snapshot):\n    assert snapshot == AmberDataSerializer.object_as_named_tuple(obj_with_custom_repr)\n```\n\n\u003e See `test_snapshot_object_as_named_tuple_class` for an example on automatically doing this for all nested properties\n\n#### Attributes\n\nIf you want to limit what properties are serialized at a class type level you could either:\n\n**A**. Provide a filter function to the snapshot [exclude](#exclude) configuration option.\n\n```py\ndef limit_foo_attrs(prop, path):\n    allowed_foo_attrs = {\"do\", \"not\", \"serialize\", \"these\", \"attrs\"}\n    return isinstance(path[-1][1], Foo) and prop in allowed_foo_attrs\n\ndef test_bar(snapshot):\n    actual = Foo(...)\n    assert actual == snapshot(exclude=limit_foo_attrs)\n```\n\n**B**. Provide a filter function to the snapshot [include](#include) configuration option.\n\n```py\ndef limit_foo_attrs(prop, path):\n    allowed_foo_attrs = {\"only\", \"serialize\", \"these\", \"attrs\"}\n    return isinstance(path[-1][1], Foo) and prop in allowed_foo_attrs\n\ndef test_bar(snapshot):\n    actual = Foo(...)\n    assert actual == snapshot(include=limit_foo_attrs)\n```\n\n**C**. Or override the `__dir__` implementation to control the attribute list.\n\n```py\nclass Foo:\n    def __dir__(self):\n        return [\"only\", \"serialize\", \"these\", \"attrs\"]\n\ndef test_bar(snapshot):\n    actual = Foo(...)\n    assert actual == snapshot\n```\n\nBoth options will generate equivalent snapshots but the latter is only viable when you have control over the class implementation and do not need to share the exclusion logic with other objects.\n\n### CLI Options\n\nThese are the cli options exposed to `pytest` by the plugin.\n\n| Option                         | Description                                                                                                                    | Default                                                                                                      |\n| ------------------------------ |--------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|\n| `--snapshot-update`            | Snapshots will be updated to match assertions and unused snapshots will be deleted.                                            | `False`                                                                                                      |\n| `--snapshot-details`           | Includes details of unused, generated, and updated snapshots (test name and snapshot location) in the final report.                                    | `False`                                                                                                      |\n| `--snapshot-warn-unused`       | Prints a warning on unused snapshots rather than fail the test suite.                                                          | `False`                                                                                                      |\n| `--snapshot-default-extension` | Use to change the default snapshot extension class.                                                                            | [AmberSnapshotExtension](https://github.com/syrupy-project/syrupy/blob/main/src/syrupy/extensions/amber/__init__.py) |\n| `--snapshot-no-colors`         | Disable test results output highlighting. Equivalent to setting the environment variables `ANSI_COLORS_DISABLED` or `NO_COLOR` | Disabled by default if not in terminal.                                                                      |\n| `--snapshot-patch-pycharm-diff`| Override PyCharm's default diffs viewer when looking at snapshot diffs. See [IDE Integrations](#ide-integrations)        | `False`                                                                                                      |\n| `--snapshot-diff-mode` | Configures how diffs are displayed on assertion failure. If working with very large snapshots, disabling the diff can improve performance. | `detailed` |\n| `--snapshot-ignore-file-extensions` | Comma separated list of file extensions to ignore when walking the file tree and discovering used/unused snapshots. | No extensions are ignored by default. |\n| `--snapshot-dirname` | Directory name to store snapshots in. | `__snapshots__` |\n\n### Assertion Options\n\nThese are the options available on the `snapshot` assertion fixture.\nUse of these options are one shot and do not persist across assertions.\nFor more persistent options see [advanced usage](#advanced-usage).\n\n#### `matcher`\n\nThis allows you to match on a property path and value to control how specific object shapes are serialized.\n\nThe matcher is a function that takes two keyword arguments.\nIt should return the replacement value to be serialized or the original unmutated value.\n\n| Argument | Description                                                                                                        |\n| -------- | ------------------------------------------------------------------------------------------------------------------ |\n| `data`   | Current serializable value being matched on                                                                        |\n| `path`   | Ordered path traversed to the current value e.g. `((\"a\", dict), (\"b\", dict))` from `{ \"a\": { \"b\": { \"c\": 1 } } }`} |\n\n**NOTE:** Do not mutate the value received as it could cause unintended side effects.\n\n##### Composing Matchers\n\nMultiple matchers can be composed together using `matchers`, e.g.:\n\n```py\nfrom syrupy.matchers import compose_matchers\n\ndef test_multiple_matchers(snapshot):\n    data = {\n        \"number\": 1,\n        \"datetime\": datetime.datetime.now(),\n        \"float\": 1.3\n    }\n\n    assert data == snapshot(\n        matcher=compose_matchers(\n            path_type(types=(int, float), replacer=lambda *_: \"MATCHER_1\"),\n            path_type(types=(datetime.datetime,), replacer=lambda *_: \"MATCHER_2\"),\n        ),\n    )\n```\n\n##### Built-In Matchers\n\nSyrupy comes with built-in helpers that can be used to make easy work of using property matchers.\n\n###### `path_type(mapping=None, *, types=(), strict=True, regex=False)`\n\nEasy way to build a matcher that uses the path and value type to replace serialized data.\nWhen strict, this will raise a `ValueError` if the types specified are not matched.\n\n| Argument   | Description                                                                                                                        |\n| ---------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| `mapping`  | Dict of path string to tuples of class types, including primitives e.g. (MyClass, UUID, datetime, int, str)                        |\n| `types`    | Tuple of class types used if none of the path strings from the mapping are matched                                                 |\n| `strict`   | If a path is matched but the value at the path does not match one of the class types in the tuple then a `PathTypeError` is raised |\n| `regex`    | If true, the `mapping` key is treated as a regular expression when matching paths                                                  |\n| `replacer` | Called with any matched value and result is used as the replacement that is serialized. Defaults to the object type when not given |\n\n```py\nfrom syrupy.matchers import path_type\n\ndef test_bar(snapshot):\n    actual = {\n      \"date_created\": datetime.now(),\n      \"value\": \"Some computed value!!\",\n    }\n    assert actual == snapshot(matcher=path_type({\n      \"date_created\": (datetime,),\n      \"nested.path.id\": (int,),\n    }))\n```\n\n```py\n# name: test_bar\n  dict({\n    'date_created': datetime,\n    'value': 'Some computed value!!',\n  })\n# ---\n```\n\n\u003e NOTE: When `regex` is `True` all matcher mappings are treated as regex patterns\n\n###### `path_value(mapping=None, *, **kwargs)`\n\nShares the same `kwargs` as `path_type` matcher, with the exception of the `mapping` argument type.\nOnly runs replacement for objects at a matching path where the value of the mapping also matches the object data string repr.\n\n| Argument  | Description                                                |\n| --------- | ---------------------------------------------------------- |\n| `mapping` | Dict of path string to object value string representations |\n\n\u003e See `test_regex_matcher_str_value` for example usage.\n\n#### `exclude`\n\nThis allows you to filter out object properties from the serialized snapshot.\n\nThe exclude parameter takes a filter function that accepts two keyword arguments.\nIt should return `true` if the property should be excluded, or `false` if the property should be included.\n\n| Argument | Description                                                                                                                                   |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |\n| `prop`   | Current property on the object, could be any hashable value that can be used to retrieve a value e.g. `1`, `\"prop_str\"`, `SomeHashableObject` |\n| `path`   | Ordered path traversed to the current value e.g. `((\"a\", dict), (\"b\", dict))` from `{ \"a\": { \"b\": { \"c\": 1 } } }`}                            |\n\n##### Built-In Filters\n\nSyrupy comes with built-in helpers that can be used to make easy work of using the filter options.\n\n###### `props(prop_name, *prop_name)`\n\nEasy way to build a filter that excludes based on string based property names.\n\nTakes an argument list of property names, with support for indexed iterables.\n\n```py\nfrom syrupy.filters import props\n\ndef test_bar(snapshot):\n    actual = {\n      \"id\": uuid.uuid4(),\n      \"list\": [1,2,3],\n    }\n    assert actual == snapshot(exclude=props(\"id\", \"1\"))\n```\n\n```py\n# name: test_bar\n  dict({\n    'list': list([\n      1,\n      3,\n    ]),\n  })\n# ---\n```\n\n###### `paths(path_string, *path_strings)`\n\nEasy way to build a filter that uses full path strings delimited with `.`.\n\nTakes an argument list of path strings.\n\n```py\nfrom syrupy.filters import paths\n\ndef test_bar(snapshot):\n    actual = {\n      \"date\": datetime.now(),\n      \"list\": [1,2,3],\n    }\n    assert actual == snapshot(exclude=paths(\"date\", \"list.1\"))\n```\n\n```py\n# name: test_bar\n  dict({\n    'list': list([\n      1,\n      3,\n    ]),\n  })\n# ---\n```\n\n#### `include`\n\nThis allows you filter an object's properties to a subset using a predicate. This is the opposite of [exclude](#exclude). All the same property filters supporterd by [exclude](#exclude) are supported for `include`.\n\nThe include parameter takes a filter function that accepts two keyword arguments.\nIt should return `true` if the property should be include, or `false` if the property should not be included.\n\n| Argument | Description                                                                                                                                   |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |\n| `prop`   | Current property on the object, could be any hashable value that can be used to retrieve a value e.g. `1`, `\"prop_str\"`, `SomeHashableObject` |\n| `path`   | Ordered path traversed to the current value e.g. `((\"a\", dict), (\"b\", dict))` from `{ \"a\": { \"b\": { \"c\": 1 } } }`}\n\nNote that `include` has some caveats which make it a bit more difficult to use than `exclude`. Both `include` and `exclude` are evaluated for each key of an object before traversing down nested paths. This means if you want to include a nested path, you must include all parents of the nested path, otherwise the nested child will never be reached to be evaluated against the include predicate. For example:\n\n```py\nobj = {\n    \"nested\": { \"key\": True }\n}\nassert obj == snapshot(include=paths(\"nested\", \"nested.key\"))\n```\n\nThe extra \"nested\" is required, otherwise the nested dictionary will never be searched -- it'd get pruned too early.\n\nTo avoid adding duplicate path parts, we provide a convenient `paths_include` which supports a list/tuple instead of a string for each path to match:\n\n```py\nobj = {\n    \"other\": False,\n    \"nested\": { \"key\": True }\n}\nassert obj == snapshot(include=paths_include([\"other\"], [\"nested\", \"key\"]))\n```\n\n#### `extension_class`\n\nThis is a way to modify how the snapshot matches and serializes your data in a single assertion.\n\n```py\ndef test_foo(snapshot):\n    actual_svg = \"\u003csvg\u003e\u003c/svg\u003e\"\n    assert actual_svg == snapshot(extension_class=SVGImageSnapshotExtension)\n```\n\n#### `diff`\n\nThis is an option to snapshot only the diff between the actual object and a previous snapshot, with the `diff` argument being the previous snapshot `index`/`name`.\n\n```py\ndef test_diff(snapshot):\n    actual0 = [1,2,3,4]\n    actual1 = [0,1,3,4]\n\n    assert actual0 == snapshot\n    assert actual1 == snapshot(diff=0)\n    # This is equivalent to the lines above\n    # Must use the index name to diff when given\n    assert actual0 == snapshot(name='snap_name')\n    assert actual1 == snapshot(diff='snap_name')\n```\n\n##### Built-In Extensions\n\nSyrupy comes with a few built-in preset configurations for you to choose from. You should also feel free to extend the `AbstractSyrupyExtension` if your project has a need not captured by one our built-ins.\n\n**Amber Extensions**\n\n- **`AmberSnapshotExtension`**: This is the default extension which generates `.ambr` files. Serialization of most data types are supported.\n  - Line control characters are normalised when snapshots are generated i.e. `\\r` and `\\n` characters are all written as `\\n`. This is to allow interoperability of snapshots between operating systems that use disparate line control characters.\n- **`SingleFileAmberSnapshotExtension`**: A variant of the `AmberSnapshotExtension` which writes 1 snapshot per file.\n\n**Other Formats**\n\n- **`SingleFileSnapshotExtension`**: This extension creates one `.raw` file per test case. Note that the default behaviour of the SingleFileSnapshotExtension is to write raw bytes to disk. There is no further \"serialization\" that happens. The `SingleFileSnapshotExtension` is mostly used as a building block for other extensions such as the image extensions, the JSON extension, as well as the `SingleFileAmberSnapshotExtension` extension. In the default \"binary\" mode, attempting to serialize a non-byte-like object will throw a TypeError.\n- **`PNGImageSnapshotExtension`**: An extension of single file, this should be used to produce `.png` files from a byte string.\n- **`SVGImageSnapshotExtension`**: Another extension of single file. This produces `.svg` files from an svg string.\n- **`JSONSnapshotExtension`**: Another extension of single file. This produces `.json` files from dictionaries and lists.\n\n#### `name`\n\nBy default, if you make multiple snapshot assertions within a single test case, an auto-increment identifier will be used to index the snapshots. You can override this behaviour by specifying a custom snapshot name to use in place of the auto-increment number.\n\n```py\ndef test_case(snapshot):\n    assert \"actual\" == snapshot(name=\"case_a\")\n    assert \"other\" == snapshot(name=\"case_b\")\n```\n\n\u003e _Warning_: If you use a custom name, you must make sure the name is not re-used within a test case.\n\n### Advanced Usage\n\nBy overriding the provided [`AbstractSyrupyExtension`](https://github.com/syrupy-project/syrupy/tree/main/src/syrupy/extensions/base.py) you can implement varied custom behaviours.\n\nSee examples of how syrupy can be used and extended in the [test examples](https://github.com/syrupy-project/syrupy/tree/main/tests/examples).\n\n#### Overriding defaults\n\nIt is possible to override `include`, `exclude`, `matchers` and `extension_class` on a more global level just once,\ninstead of every time per test. By default, after every assertion the modified values per snapshot assert are reverted\nto their default values. However, it is possible to override those default values with ones you would like persisted,\nwhich will be treated as the new defaults.\n\nTo achieve that you can use `snapshot.with_defaults`, which will create new instance of `SnapshotAssertion` with the provided values.\n\n`snapshot.use_extension` is retained for compatibility. However, it is limited to only overriding the default extension class.\n\n#### JSONSnapshotExtension\n\nThis extension can be useful when testing API responses, or when you have to deal with long dictionaries that are cumbersome to validate inside a test. For example:\n\n```python\nimport pytest\n\nfrom syrupy.extensions.json import JSONSnapshotExtension\n\n@pytest.fixture\ndef snapshot_json(snapshot):\n    return snapshot.with_defaults(extension_class=JSONSnapshotExtension)\n    # or return snapshot.use_extension(JSONSnapshotExtension)\n\n\ndef test_api_call(client, snapshot_json):\n    resp = client.post(\"/endpoint\")\n    assert resp.status_code == 200\n    assert snapshot_json == resp.json()\n```\n\nAPI responses often contain dynamic data, like IDs or dates. You can still validate and store other data of a response by leveraging syrupy matchers. For example:\n\n```py\nfrom datetime import datetime\n\nfrom syrupy.matchers import path_type\n\ndef test_api_call(client, snapshot_json):\n    resp = client.post(\"/user\", json={\"name\": \"Jane\"})\n    assert resp.status_code == 201\n\n    matcher = path_type({\n      \"id\": (int,),\n      \"registeredAt\": (datetime,)\n    })\n    assert snapshot_json(matcher=matcher) == resp.json()\n```\n\nThe generated snapshot:\n\n```json\n{\n  \"id\": \"\u003cclass 'int'\u003e\",\n  \"registeredAt\": \"\u003cclass 'datetime'\u003e\",\n  \"name\": \"Jane\"\n}\n```\n\nOr a case where the value needs to be replaced using a condition e.g. file path string\n\n```py\nimport re\n\nfrom syrupy.matchers import path_type\n\ndef test_matches_generated_string_value(snapshot, tmp_file):\n    matcher = path_value(\n        mapping={\"file_path\": r\"\\w+://(.*/)+dir/filename.txt\"},\n        replacer=lambda _, match: match[0].replace(match[1], \"\u003ctmp-file-path\u003e/\"),\n        types=(str,),\n    )\n\n    assert snapshot(matcher=matcher) == tmp_file\n```\n\nThe generated snapshot:\n\n```json\n{\n  \"name\": \"Temp Files\",\n  \"file_path\": \"scheme://\u003ctmp-file-path\u003e/dir/filename.txt\"\n}\n```\n\n#### Ignoring File Extensions (e.g. DVC Integration)\n\nIf using a tool such as [DVC](https://dvc.org/) or other tool where you need to ignore files by file extension, you can update your `pytest.ini` like so:\n\n```ini\n[pytest]\naddopts = --snapshot-ignore-file-extensions dvc\n```\n\nA comma separated list is supported, like so:\n\n```ini\n[pytest]\naddopts = --snapshot-ignore-file-extensions dvc,tmp,zip\n```\n\n### Extending Syrupy\n\n- [Custom defaults](https://github.com/syrupy-project/syrupy/tree/main/tests/examples/test_custom_defaults.py)\n- [Custom snapshot directory 1](https://github.com/syrupy-project/syrupy/tree/main/tests/examples/test_custom_snapshot_directory.py)\n- [Custom snapshot directory 2](https://github.com/syrupy-project/syrupy/tree/main/tests/examples/test_custom_snapshot_directory_2.py)\n- [Custom snapshot name](https://github.com/syrupy-project/syrupy/tree/main/tests/examples/test_custom_snapshot_name.py)\n- [Custom object snapshots](https://github.com/syrupy-project/syrupy/tree/main/tests/examples/test_custom_object_repr.py)\n- [Custom comparator](https://github.com/syrupy-project/syrupy/tree/main/tests/integration/test_custom_comparator.py)\n- [JPEG image extension](https://github.com/syrupy-project/syrupy/tree/main/tests/examples/test_custom_image_extension.py)\n- [Built-in image extensions](https://github.com/syrupy-project/syrupy/blob/main/tests/syrupy/extensions/image/test_image_svg.py)\n\n### Inline Snapshots\n\nSyrupy does not support inline snapshots. For inline snapshots, we recommend checking out the [inline-snapshot](https://github.com/15r10nk/inline-snapshot) library.\n\n## IDE Integrations\n\n### PyCharm\n\nThe [PyCharm](https://www.jetbrains.com/pycharm/) IDE comes with a built-in tool for visualizing differences between expected and actual results in a test. To properly render Syrupy snapshots in the PyCharm diff viewer, we need to apply a patch to the diff viewer library. To do this, use the `--snapshot-patch-pycharm-diff` flag, e.g.:\n\nIn your `pytest.ini`:\n\n```ini\n[pytest]\naddopts = --snapshot-patch-pycharm-diff\n```\n\nSee [#675](https://github.com/syrupy-project/syrupy/issues/675) for the original issue.\n\n## Known Limitations\n\n- `pytest-xdist` support only partially exists. There is no issue when it comes to reads however when you attempt to run `pytest --snapshot-update`, if running with more than 1 process, the ability to detect unused snapshots is disabled. See [#535](https://github.com/syrupy-project/syrupy/issues/535) for more information.\n\n_We welcome contributions to patch these known limitations._\n\n## Migrating from another tool\n\n### From snapshottest\n\nYou 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:\n\n```shell\npip uninstall snapshottest -y;\nfind . -type d ! -path '*/\\.*' -name 'snapshots' | xargs rm -r\n```\n\n## Uninstalling\n\n```python\npip uninstall syrupy\n```\n\nIf you have decided not to use Syrupy for your project after giving us a try, we'd love to get your feedback. Please create a GitHub issue if applicable.\n\n## Contributing\n\nFeel free to open a PR or GitHub issue. Contributions welcome!\n\nTo develop locally, clone this repository and run `. script/bootstrap` to install test dependencies. You can then use `invoke --list` to see available commands.\n\n### See contributing [guide](https://github.com/syrupy-project/syrupy/tree/main/CONTRIBUTING.md)\n\n## Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://noahnu.com\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/1297096?v=4?s=100\" width=\"100px;\" alt=\"Noah\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eNoah\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#infra-noahnu\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"#ideas-noahnu\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=noahnu\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=noahnu\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=noahnu\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://emmanuel.ogbizi.com\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/2528959?v=4?s=100\" width=\"100px;\" alt=\"Emmanuel Ogbizi\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEmmanuel Ogbizi\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=iamogbz\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#design-iamogbz\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"#infra-iamogbz\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=iamogbz\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=iamogbz\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/adamlazz\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/453811?v=4?s=100\" width=\"100px;\" alt=\"Adam Lazzarato\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAdam Lazzarato\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=adamlazz\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://mcataford.github.io\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/6210361?v=4?s=100\" width=\"100px;\" alt=\"Marc Cataford\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMarc Cataford\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=mcataford\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=mcataford\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://msrose.github.io\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/3495264?v=4?s=100\" width=\"100px;\" alt=\"Michael Rose\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMichael Rose\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=msrose\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=msrose\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://fashionablenonsense.com/\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/3112159?v=4?s=100\" width=\"100px;\" alt=\"Jimmy Jia\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJimmy Jia\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=taion\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=taion\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://stevenloria.com\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/2379650?v=4?s=100\" width=\"100px;\" alt=\"Steven Loria\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSteven Loria\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#infra-sloria\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/arturbalabanov\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/3062003?v=4?s=100\" width=\"100px;\" alt=\"Artur Balabanov\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eArtur Balabanov\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=arturbalabanov\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://huonw.github.io/\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/1203825?v=4?s=100\" width=\"100px;\" alt=\"Huon Wilson\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eHuon Wilson\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=huonw\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Ahuonw\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/eaculb\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/31480498?v=4?s=100\" width=\"100px;\" alt=\"Elizabeth Culbertson\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eElizabeth Culbertson\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=eaculb\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=eaculb\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/joakimnordling\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6637576?v=4?s=100\" width=\"100px;\" alt=\"Joakim Nordling\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJoakim Nordling\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Ajoakimnordling\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/bendidi\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/22003440?v=4?s=100\" width=\"100px;\" alt=\"Ouail\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eOuail\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=bendidi\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/fbjorn\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/9670990?v=4?s=100\" width=\"100px;\" alt=\"Denis\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDenis\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=fbjorn\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/N0124\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/29734397?v=4?s=100\" width=\"100px;\" alt=\"N0124\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eN0124\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=N0124\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/dtczest\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/97055299?v=4?s=100\" width=\"100px;\" alt=\"dtczest\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003edtczest\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Adtczest\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/spagh-eddie\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/58013020?v=4?s=100\" width=\"100px;\" alt=\"Eddie Darling\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEddie Darling\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=spagh-eddie\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/darrenburns\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/5740731?v=4?s=100\" width=\"100px;\" alt=\"darrenburns\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003edarrenburns\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=darrenburns\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/mhwaage\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/57612883?v=4?s=100\" width=\"100px;\" alt=\"Magnus Heskestad Waage\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMagnus Heskestad Waage\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Amhwaage\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/herb\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/139780?v=4?s=100\" width=\"100px;\" alt=\"Herbert Ho\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eHerbert Ho\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Aherb\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/tolgaeren\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/794719?v=4?s=100\" width=\"100px;\" alt=\"Tolga Eren\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTolga Eren\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Atolgaeren\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://johnkurkowski.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/299487?v=4?s=100\" width=\"100px;\" alt=\"John Kurkowski\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJohn Kurkowski\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Ajohn-kurkowski\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://www.atharvaarya.tech/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/55894364?v=4?s=100\" width=\"100px;\" alt=\"Atharva Arya\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAtharva Arya\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=atharva-2001\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/michaljelonek\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/7791528?v=4?s=100\" width=\"100px;\" alt=\"Michał Jelonek\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMichał Jelonek\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=michaljelonek\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ManiacDC\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1823305?v=4?s=100\" width=\"100px;\" alt=\"ManiacDC\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eManiacDC\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=ManiacDC\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://schemathesis.io/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1236561?v=4?s=100\" width=\"100px;\" alt=\"Dmitry Dygalo\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDmitry Dygalo\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=Stranger6667\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://allanchain.github.io/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/36528777?v=4?s=100\" width=\"100px;\" alt=\"Allan Chain\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAllan Chain\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3AAllanChain\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/UltimateLobster\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/21122724?v=4?s=100\" width=\"100px;\" alt=\"Nir Schulman\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eNir Schulman\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=UltimateLobster\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://joostlek.dev\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/7083755?v=4?s=100\" width=\"100px;\" alt=\"Joost Lekkerkerker\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJoost Lekkerkerker\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=joostlek\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/epenet\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6771947?v=4?s=100\" width=\"100px;\" alt=\"epenet\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eepenet\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/commits?author=epenet\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://about.me/tomsparrow\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/793763?v=4?s=100\" width=\"100px;\" alt=\"Tom Sparrow\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTom Sparrow\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Asparrowt\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/samylaumonier\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/2417752?v=4?s=100\" width=\"100px;\" alt=\"Samy Laumonier\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSamy Laumonier\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Asamylaumonier\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/paul-ollis\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6062510?v=4?s=100\" width=\"100px;\" alt=\"Paul Ollis\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePaul Ollis\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Apaul-ollis\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://rahuliyer.me\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/4255590?v=4?s=100\" width=\"100px;\" alt=\"Rahul Iyer\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRahul Iyer\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/syrupy-project/syrupy/issues?q=author%3Arahuliyer95\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis section is automatically generated via tagging the all-contributors bot in a PR:\n\n```text\n@all-contributors please add \u003cusername\u003e for \u003ccontribution type\u003e\n```\n\n## License\n\nSyrupy is licensed under [MIT](https://github.com/syrupy-project/syrupy/tree/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyrupy-project%2Fsyrupy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsyrupy-project%2Fsyrupy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyrupy-project%2Fsyrupy/lists"}