Skip to content

Commit

Permalink
Merge pull request #185 from 15r10nk/preparations
Browse files Browse the repository at this point in the history
preparations for something ...
  • Loading branch information
15r10nk authored Feb 1, 2025
2 parents 216e205 + fe8296d commit 341d4fe
Show file tree
Hide file tree
Showing 19 changed files with 173 additions and 95 deletions.
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ ci:

repos:
- hooks:
- id: check-yaml
- id: check-ast
- id: check-merge-conflict
- id: trailing-whitespace
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[![Docs](https://img.shields.io/badge/docs-mkdocs-green)](https://15r10nk.github.io/inline-snapshot/latest/)
[![pypi version](https://img.shields.io/pypi/v/inline-snapshot.svg)](https://pypi.org/project/inline-snapshot/)
![Python Versions](https://img.shields.io/pypi/pyversions/inline-snapshot)
![PyPI - Downloads](https://img.shields.io/pypi/dw/inline-snapshot)
[![PyPI - Downloads](https://img.shields.io/pypi/dw/inline-snapshot)](https://pypacktrends.com/?packages=inline-snapshot&time_range=2years)
[![coverage](https://img.shields.io/badge/coverage-100%25-blue)](https://15r10nk.github.io/inline-snapshot/latest/contributing/#coverage)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/15r10nk)](https://github.com/sponsors/15r10nk)

Expand Down
4 changes: 4 additions & 0 deletions changelog.d/20250131_085021_15r10nk-git_preparations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- fixed an issue where --inline-snapshot=review discarded the user input and never formatted
the code if you used cpython 3.13.
23 changes: 23 additions & 0 deletions changelog.d/20250201_085056_15r10nk-git_preparations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Changed

- pytest assert rewriting works now together with inline-snapshot if you use `cpython>=3.11`

-->
<!--
### Deprecated
- A bullet item for the Deprecated category.
-->
<!--
### Fixed
- A bullet item for the Fixed category.
-->
<!--
### Security
- A bullet item for the Security category.
-->
5 changes: 4 additions & 1 deletion docs/code_generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ It might be necessary to import the right modules to match the `repr()` output.
The code is generated in the following way:

1. The value is copied with `value = copy.deepcopy(value)` and it is checked if the copied value is equal to the original value.
2. The code is generated with `repr(value)` (which can be [customized](customize_repr.md))
2. The code is generated with:
* `repr(value)` (which can be [customized](customize_repr.md))
* or a special internal implementation for container types to support [unmanaged snapshot values](eq_snapshot.md#unmanaged-snapshot-values).
This can currently not be customized.
3. Strings which contain newlines are converted to triple quoted strings.

!!! note
Expand Down
25 changes: 16 additions & 9 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ theme:
features:
- toc.follow
- content.code.annotate
- navigation.tabs

palette:
- media: (prefers-color-scheme)

Expand All @@ -34,7 +36,13 @@ watch:
- src/inline_snapshot

nav:
- Introduction: index.md
- Home:
- Introduction: index.md
- Configuration: configuration.md
- pytest integration: pytest.md
- Categories: categories.md
- Code generation: code_generation.md
- Limitations: limitations.md
- Core:
- x == snapshot(): eq_snapshot.md
- x <= snapshot(): cmp_snapshot.md
Expand All @@ -46,14 +54,10 @@ nav:
- Extensions:
- first-party (extra): extra.md
- third-party: third_party.md
- pytest integration: pytest.md
- Categories: categories.md
- Configuration: configuration.md
- Code generation: code_generation.md
- Testing: testing.md
- Limitations: limitations.md
- Contributing: contributing.md
- Changelog: changelog.md
- Development:
- Testing: testing.md
- Contributing: contributing.md
- Changelog: changelog.md



Expand All @@ -73,6 +77,9 @@ markdown_extensions:
- pymdownx.tabbed:
alternate_style: true
- attr_list
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg

plugins:
- mkdocstrings:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ classifiers = [
]
dependencies = [
"asttokens>=2.0.5",
"executing>=2.1.0",
"executing>=2.2.0",
"rich>=13.7.1",
"tomli>=2.0.0; python_version < '3.11'"
]
Expand Down
17 changes: 10 additions & 7 deletions src/inline_snapshot/_adapter/value_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import ast
import warnings

from inline_snapshot._code_repr import value_code_repr
from inline_snapshot._unmanaged import Unmanaged
from inline_snapshot._unmanaged import update_allowed
from inline_snapshot._utils import value_to_token
from inline_snapshot.syntax_warnings import InlineSnapshotInfo

from .._change import Replace
from .._code_repr import value_code_repr
from .._sentinels import undefined
from .._unmanaged import Unmanaged
from .._unmanaged import update_allowed
from .._utils import value_to_token
from ..syntax_warnings import InlineSnapshotInfo
from .adapter import Adapter


Expand Down Expand Up @@ -46,7 +46,10 @@ def assign(self, old_value, old_node, new_value):
return old_value

if not old_value == new_value:
flag = "fix"
if old_value is undefined:
flag = "create"
else:
flag = "fix"
elif (
old_node is not None
and update_allowed(old_value)
Expand Down
20 changes: 15 additions & 5 deletions src/inline_snapshot/_flags.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from __future__ import annotations

from typing import Set
from typing import cast

from ._types import Category

Expand All @@ -11,14 +14,21 @@ class Flags:
trim: the snapshot contains more values than neccessary. 1 could be trimmed in `5 in snapshot([1,5])`.
"""

def __init__(self, flags: Set[Category] = set()):
self.fix = "fix" in flags
self.update = "update" in flags
def __init__(self, flags: set[Category] = set()):
self.create = "create" in flags
self.fix = "fix" in flags
self.trim = "trim" in flags
self.update = "update" in flags

def to_set(self) -> set[Category]:
return cast(Set[Category], {k for k, v in self.__dict__.items() if v})

def to_set(self):
return {k for k, v in self.__dict__.items() if v}
def __iter__(self):
return (k for k, v in self.__dict__.items() if v)

def __repr__(self):
return f"Flags({self.to_set()})"

@staticmethod
def all() -> Flags:
return Flags({"fix", "create", "update", "trim"})
6 changes: 5 additions & 1 deletion src/inline_snapshot/_inline_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ def __init__(self, value, expr, context: AdapterContext):

def _changes(self):

if self._value._old_value is undefined:
if (
self._value._old_value is undefined
if self._expr is None
else not self._expr.node.args
):

if self._value._new_value is undefined:
return
Expand Down
8 changes: 1 addition & 7 deletions src/inline_snapshot/_sentinels.py
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
# sentinels
class Undefined:
def __repr__(self):
return "undefined"


undefined = Undefined()
undefined = ...
37 changes: 17 additions & 20 deletions src/inline_snapshot/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pathlib import Path

import pytest
from executing import is_pytest_compatible
from rich import box
from rich.console import Console
from rich.panel import Panel
Expand All @@ -28,6 +29,10 @@
pytest.register_assert_rewrite("inline_snapshot.extra")
pytest.register_assert_rewrite("inline_snapshot.testing._example")

if sys.version_info >= (3, 13):
# fixes #186
import readline # noqa


def pytest_addoption(parser, pluginmanager):
group = parser.getgroup("inline-snapshot")
Expand Down Expand Up @@ -61,7 +66,7 @@ def pytest_addoption(parser, pluginmanager):
)


categories = {"create", "update", "trim", "fix"}
categories = Flags.all().to_set()
flags = set()


Expand Down Expand Up @@ -113,7 +118,7 @@ def pytest_configure(config):
elif flags & {"review"}:
state().active = True

state().update_flags = Flags({"fix", "create", "update", "trim"})
state().update_flags = Flags.all()
else:

state().active = "disable" not in flags
Expand All @@ -126,7 +131,7 @@ def pytest_configure(config):

_external.storage = _external.DiscStorage(external_storage)

if flags - {"short-report", "disable"}:
if flags - {"short-report", "disable"} and not is_pytest_compatible():

# hack to disable the assertion rewriting
# I found no other way because the hook gets installed early
Expand Down Expand Up @@ -166,6 +171,7 @@ def snapshot_check():


def pytest_assertrepr_compare(config, op, left, right):

results = []
if isinstance(left, GenericValue):
results = config.hook.pytest_assertrepr_compare(
Expand Down Expand Up @@ -253,19 +259,9 @@ def apply_changes(flag):
return False

# auto mode
changes = {
"update": [],
"fix": [],
"trim": [],
"create": [],
}

snapshot_changes = {
"update": 0,
"fix": 0,
"trim": 0,
"create": 0,
}
changes = {f: [] for f in Flags.all()}

snapshot_changes = {f: 0 for f in Flags.all()}

for snapshot in state().snapshots.values():
all_categories = set()
Expand Down Expand Up @@ -324,12 +320,13 @@ def report(flag, message, message_n):

return

assert not any(
type(e).__name__ == "AssertionRewritingHook" for e in sys.meta_path
)
if not is_pytest_compatible():
assert not any(
type(e).__name__ == "AssertionRewritingHook" for e in sys.meta_path
)

used_changes = []
for flag in ("create", "fix", "trim", "update"):
for flag in Flags.all():
if not changes[flag]:
continue

Expand Down
35 changes: 24 additions & 11 deletions src/inline_snapshot/testing/_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,13 @@ def run_inline(

self._write_files(tmp_path)

raised_exception = None
raised_exception = []
with snapshot_env() as state:
with ChangeRecorder().activate() as recorder:
state.update_flags = Flags({*flags})
inline_snapshot._external.storage = (
inline_snapshot._external.DiscStorage(tmp_path / ".storage")
)

try:
for filename in tmp_path.glob("*.py"):
globals: dict[str, Any] = {}
Expand All @@ -152,11 +151,11 @@ def run_inline(
# run all test_* functions
for k, v in globals.items():
if k.startswith("test_") and callable(v):
v()
except Exception as e:
traceback.print_exc()
raised_exception = e

try:
v()
except Exception as e:
traceback.print_exc()
raised_exception.append(e)
finally:
state.active = False

Expand Down Expand Up @@ -184,9 +183,9 @@ def run_inline(
if reported_categories is not None:
assert sorted(snapshot_flags) == reported_categories

if raised_exception is not None:
assert raises == f"{type(raised_exception).__name__}:\n" + str(
raised_exception
if raised_exception:
assert raises == "\n".join(
f"{type(e).__name__}:\n" + str(e) for e in raised_exception
)
else:
assert raises == None
Expand Down Expand Up @@ -259,7 +258,21 @@ def run_pytest(
assert result.returncode == returncode

if stderr is not None:
assert result.stderr.decode() == stderr

original = result.stderr.decode().splitlines()
lines = [
line
for line in original
if not any(
s in line
for s in [
'No entry for terminal type "unknown"',
"using dumb terminal settings.",
]
)
]

assert "\n".join(lines) == stderr

if report is not None:

Expand Down
16 changes: 16 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,22 @@ def errors(self):
result = re.sub(r"\d+\.\d+s", "<time>", result)
return result

@property
def stderr(self):
original = self._result.stderr.lines
lines = [
line
for line in original
if not any(
s in line
for s in [
'No entry for terminal type "unknown"',
"using dumb terminal settings.",
]
)
]
return pytest.LineMatcher(lines)

def errorLines(self):
result = self._join_lines(
[line for line in self.stdout.lines if line and line[:2] in ("> ", "E ")]
Expand Down
Loading

0 comments on commit 341d4fe

Please sign in to comment.