@register_format()
General¶
register_format()
allows you to add support for your custom file formats, such as the following Array
type.
from dataclasses import dataclass
from typing import List
@dataclass
class Array:
numbers: List[int]
from pathlib import Path
from inline_snapshot import register_format, TextDiff, Format
from my_array import Array
@register_format
class ArrayFormat(TextDiff, Format[Array]):
suffix = ".arr"
@staticmethod
def is_format_for(data: object):
return isinstance(data, Array)
@staticmethod
def encode(value: Array, path: Path):
with path.open("w", encoding="utf-8", newline="\n") as f:
f.write("\n".join(map(str, value.numbers)))
@staticmethod
def decode(path: Path) -> Array:
with path.open("r", encoding="utf-8", newline="\n") as f:
return Array(list(map(int, f.read().splitlines())))
You can then use external()
to save this type into an external file.
from my_array import Array
from inline_snapshot import external
def test_array():
assert Array([1, 2, 3]) == external()
inline-snapshot will check if the type matches by using is_format_for()
and create a file with the given suffix.
from my_array import Array
from inline_snapshot import external
def test_array():
assert Array([1, 2, 3]) == external(
"uuid:e3e70682-c209-4cac-a29f-6fbed82c07cd.arr"
)
Report¶
inline-snapshot needs to know how changes in your external files should be displayed. TextDiff
and BinaryDiff
can be used as mixin classes (see the Array
example (above)[#array-example]) to provide generic representations for text or binary formats, but you can also define custom functions for your files.
rich_diff()
is used every time the external snapshot value is changed and should show the difference between the original and new versions in a human-readable form.rich_show()
is used every time an external snapshot is created and should show a human-readable form of the initial value.
from pathlib import Path
from inline_snapshot import register_format, Format, external
from number_set import NumberSet
@register_format
class NumberSetFormat(Format[NumberSet]):
suffix = ".numberset"
def rich_diff(self, original: Path, new: Path):
original_numbers = set(self.decode(original).numbers)
new_numbers = set(self.decode(new).numbers)
return (
f"new numbers: [green]{new_numbers-original_numbers}[/]\n"
f"removed numbers: [red]{original_numbers-new_numbers}[/]"
)
def rich_show(self, path: Path):
return " ".join(f"[blue]{n}[/]" for n in self.decode(path).numbers)
def is_format_for(self, data: object):
return isinstance(data, NumberSet)
def encode(self, value: NumberSet, path: Path):
with path.open("w", encoding="utf-8", newline="\n") as f:
f.write("\n".join(sorted(map(str, value.numbers))))
def decode(self, path: Path) -> NumberSet:
with path.open("r", encoding="utf-8", newline="\n") as f:
return NumberSet(set(map(int, f.read().splitlines())))
from dataclasses import dataclass
from typing import Set
@dataclass
class NumberSet:
numbers: Set[int]
The custom format is then used every time a NumberSet
is compared with an empty external.
Reference¶
Format
¶
Base class for the Format Protocol.
priority = 0
class-attribute
instance-attribute
¶
Determines the correct format when multiple format handlers can handle
a given value (is_format_for
).
priority is 0
by default and can be set to a smaller number for
generic formats that work with many data types (e.g., .json), where
is_format_for()
also returns True
for str
and bytes
. This allows
you to use assert "text" == external()
without explicitly providing
a ".txt"
suffix to distinguish it from ".json"
.
A higher priority can be used for more specific formats, such as bytes
with a b"\x89PNG"
prefix that should be stored as .png files.
suffix
instance-attribute
¶
The suffix associated with this format handler.
Every format implementation must define a suffix. This suffix is used when the external file is written and is required to find the correct format handler when the file is read again.
decode(path)
¶
Reads the value from the specified path.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
path
|
Path
|
The path to a temporary file where the value is stored. |
required |
Returns:
Type | Description |
---|---|
T
|
The value of the external object. |
encode(value, path)
¶
Converts the value and stores it in the specified path.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value
|
T
|
The value to be stored. |
required |
path
|
Path
|
The path to a temporary file where the value should be stored. |
required |
is_format_for(value)
¶
Determines if this format handler can handle the given value.
This function is used to find the correct format handler when no suffix is provided.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value
|
object
|
The value to be formatted. |
required |
Returns:
Type | Description |
---|---|
bool
|
|
rich_diff(original, new)
¶
Displays a diff between the original and new files.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
original
|
Path
|
The path to the original external file. |
required |
new
|
Path
|
The path to the new external file. |
required |
Returns:
Type | Description |
---|---|
RenderableType
|
A rich renderable object representing the diff. This can be a |
RenderableType
|
textual diff or another type of representation. |
rich_show(path)
¶
Displays a representation of a newly created external object.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
path
|
Path
|
The path to the external file. |
required |
Returns:
Type | Description |
---|---|
RenderableType
|
A rich renderable object representing the new object. The |
RenderableType
|
representation should be concise. |
register_format(format=None, *, replace_handler=False)
¶
Registers a new format handler for the suffix format.suffix
.
This function can also be used as a decorator:
which is equivalent to:
Parameters:
Name | Type | Description | Default |
---|---|---|---|
format
|
type[Format[FormatT]] | Format[FormatT] | None
|
The format handler class or instance. |
None
|
replace_handler
|
bool
|
If |
False
|
Raises:
Type | Description |
---|---|
UsageError
|
If a handler for the same suffix already exists and |
register_format_alias(suffix, format)
¶
Registers an alias for a given format suffix.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
suffix
|
str
|
The suffix to register the alias for. |
required |
format
|
str
|
The suffix of the format that should be used instead. |
required |
Notes
The alias suffix is used to find the correct format handler.