From 3d39af0db0dd25520bf11f7fc1d340a7d24a3971 Mon Sep 17 00:00:00 2001 From: Noah Negin-Ulster Date: Thu, 29 Dec 2022 15:02:19 -0500 Subject: [PATCH] fix: ensure all pytest options are serializable --- poetry.lock | 38 +++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + src/syrupy/__init__.py | 19 ++++++++++++++++--- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index d2cdaec3..eb3247f8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -432,6 +432,21 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "execnet" +version = "1.9.0" +description = "execnet: rapid multi-Python deployment" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, + {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, +] + +[package.extras] +testing = ["pre-commit"] + [[package]] name = "flake8" version = "6.0.0" @@ -935,6 +950,27 @@ aspect = ["aspectlib"] elasticsearch = ["elasticsearch"] histogram = ["pygal", "pygaljs"] +[[package]] +name = "pytest-xdist" +version = "3.1.0" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-xdist-3.1.0.tar.gz", hash = "sha256:40fdb8f3544921c5dfcd486ac080ce22870e71d82ced6d2e78fa97c2addd480c"}, + {file = "pytest_xdist-3.1.0-py3-none-any.whl", hash = "sha256:70a76f191d8a1d2d6be69fc440cdf85f3e4c03c08b520fd5dc5d338d6cf07d89"}, +] + +[package.dependencies] +execnet = ">=1.1" +pytest = ">=6.2.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + [[package]] name = "pywin32-ctypes" version = "0.2.0" @@ -1213,4 +1249,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "2.0" python-versions = '>=3.8.1,<4' -content-hash = "e88747c14dd2913f472de3559d5fbd7577cc49b4e50ea5e13d5c077b3bd3ee05" +content-hash = "145cf99a770f02939511a83b6744fb923c602848c52d6d364d7283e6219ee3bb" diff --git a/pyproject.toml b/pyproject.toml index d425fc13..ad26792b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ codecov = '^2.1.12' invoke = '^1.7.3' coverage = { version = '^6.5.0', extras = ['toml'] } pytest-benchmark = '^4.0.0' +pytest-xdist = '^3.1.0' [tool.poetry.group.dev.dependencies] isort = '^5.10.1' diff --git a/src/syrupy/__init__.py b/src/syrupy/__init__.py index 744bb1cd..3e4ef5d9 100644 --- a/src/syrupy/__init__.py +++ b/src/syrupy/__init__.py @@ -1,5 +1,6 @@ import argparse import sys +from functools import lru_cache from gettext import gettext from typing import ( Any, @@ -30,13 +31,21 @@ _syrupy: Optional["SnapshotSession"] = None -def __default_extension_option(value: str) -> Any: +@lru_cache +def __import_extension(value: Optional[str]) -> Any: + if not value: + return DEFAULT_EXTENSION try: return import_module_member(value) except FailedToLoadModuleMember as e: raise argparse.ArgumentTypeError(e) +def __default_extension_option(value: Optional[str]) -> Any: + __import_extension(value) + return value + + def pytest_addoption(parser: Any) -> None: """ Exposes snapshot plugin configuration to pytest. @@ -64,13 +73,17 @@ def pytest_addoption(parser: Any) -> None: dest="include_snapshot_details", help="Include details of unused snapshots in the final report", ) + + # We lazy evaluate the default extension since pytest-xdist requires + # all pytest options to be serializable. group.addoption( "--snapshot-default-extension", type=__default_extension_option, - default=DEFAULT_EXTENSION, + default=None, dest="default_extension", help="Specify the default snapshot extension", ) + group.addoption( "--snapshot-no-colors", action="store_true", @@ -175,7 +188,7 @@ def pytest_terminal_summary( def snapshot(request: Any) -> "SnapshotAssertion": return SnapshotAssertion( update_snapshots=request.config.option.update_snapshots, - extension_class=request.config.option.default_extension, + extension_class=__import_extension(request.config.option.default_extension), test_location=PyTestLocation(request.node), session=request.session.config._syrupy, )