Skip to content

Commit 5a1bb1a

Browse files
authored
Split test_baseconverter.py::test_310_union_field_roundtrip into two to make it less flaky (#687)
* Split `test_baseconverter.py::test_310_union_field_roundtrip` into two to make it less flaky * Fix Justfile to correctly use Pypy 3.10
1 parent f0c0a53 commit 5a1bb1a

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

Justfile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
python := ""
22
covcleanup := "true"
33

4-
sync:
5-
uv sync {{ if python != '' { '-p ' + python } else { '' } }} --all-groups --all-extras
4+
# Sync the environment, to a particular version if provided. The `python` variable takes precedence over the argument.
5+
sync version="":
6+
uv sync {{ if python != '' { '-p ' + python } else if version != '' { '-p ' + version } else { '' } }} --all-groups --all-extras
67

78
lint:
89
uv run -p python3.13 --group lint ruff check src/ tests bench
@@ -13,8 +14,8 @@ test *args="-x --ff -n auto tests":
1314

1415
testall:
1516
just python=python3.9 test
16-
just python=pypy3.9 test
1717
just python=python3.10 test
18+
just python=pypy3.10 test
1819
just python=python3.11 test
1920
just python=python3.12 test
2021
just python=python3.13 test
@@ -28,10 +29,10 @@ cov *args="-x --ff -n auto tests":
2829
covall:
2930
just python=python3.9 covcleanup=false cov
3031
just python=python3.10 covcleanup=false cov
32+
just python=pypy3.10 covcleanup=false cov
3133
just python=python3.11 covcleanup=false cov
3234
just python=python3.12 covcleanup=false cov
3335
just python=python3.13 covcleanup=false cov
34-
just python=pypy3.10 covcleanup=false cov
3536
uv run coverage combine
3637
uv run coverage report
3738
@rm .coverage*

tests/test_baseconverter.py

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,24 +141,53 @@ def handler(obj, _):
141141

142142

143143
@pytest.mark.skipif(not is_py310_plus, reason="3.10+ union syntax")
144-
@settings(suppress_health_check=[HealthCheck.too_slow])
145144
@given(
146145
simple_typed_classes(
147146
defaults="never", newtypes=False, allow_nan=False, min_attrs=1
148147
),
149148
simple_typed_classes(
150149
defaults="never", newtypes=False, allow_nan=False, min_attrs=1
151150
),
152-
unstructure_strats,
153151
)
154-
def test_310_union_field_roundtrip(cl_and_vals_a, cl_and_vals_b, strat):
152+
def test_310_union_field_roundtrip_dict(cl_and_vals_a, cl_and_vals_b):
155153
"""
156154
Classes with union fields can be unstructured and structured.
157155
"""
158-
converter = BaseConverter(unstruct_strat=strat)
156+
converter = BaseConverter()
157+
cl_a, vals_a, kwargs_a = cl_and_vals_a
158+
cl_b, _, _ = cl_and_vals_b
159+
a_field_names = {a.name for a in fields(cl_a)}
160+
b_field_names = {a.name for a in fields(cl_b)}
161+
162+
common_names = a_field_names & b_field_names
163+
assume(len(a_field_names) > len(common_names))
164+
165+
@define
166+
class C:
167+
a: cl_a | cl_b
168+
169+
inst = C(a=cl_a(*vals_a, **kwargs_a))
170+
171+
assert inst == converter.structure(converter.unstructure(inst), C)
172+
173+
174+
@pytest.mark.skipif(not is_py310_plus, reason="3.10+ union syntax")
175+
@given(
176+
simple_typed_classes(
177+
defaults="never", newtypes=False, allow_nan=False, min_attrs=2, kw_only="never"
178+
),
179+
simple_typed_classes(
180+
defaults="never", newtypes=False, allow_nan=False, min_attrs=1
181+
),
182+
)
183+
def test_310_union_field_roundtrip_tuple(cl_and_vals_a, cl_and_vals_b):
184+
"""
185+
Classes with union fields can be unstructured and structured.
186+
"""
187+
converter = BaseConverter(unstruct_strat=UnstructureStrategy.AS_TUPLE)
159188
cl_a, vals_a, kwargs_a = cl_and_vals_a
160189
cl_b, _, _ = cl_and_vals_b
161-
assume(strat is UnstructureStrategy.AS_DICT or not kwargs_a)
190+
assert not kwargs_a
162191
a_field_names = {a.name for a in fields(cl_a)}
163192
b_field_names = {a.name for a in fields(cl_b)}
164193

@@ -171,18 +200,15 @@ class C:
171200

172201
inst = C(a=cl_a(*vals_a, **kwargs_a))
173202

174-
if strat is UnstructureStrategy.AS_DICT:
175-
assert inst == converter.structure(converter.unstructure(inst), C)
176-
else:
177-
# Our disambiguation functions only support dictionaries for now.
178-
with pytest.raises(StructureHandlerNotFoundError):
179-
converter.structure(converter.unstructure(inst), C)
203+
# Our disambiguation functions only support dictionaries for now.
204+
with pytest.raises(StructureHandlerNotFoundError):
205+
converter.structure(converter.unstructure(inst), C)
180206

181-
def handler(obj, _):
182-
return converter.structure(obj, cl_a)
207+
def handler(obj, _):
208+
return converter.structure(obj, cl_a)
183209

184-
converter.register_structure_hook(cl_a | cl_b, handler)
185-
assert inst == converter.structure(converter.unstructure(inst), C)
210+
converter.register_structure_hook(cl_a | cl_b, handler)
211+
assert inst == converter.structure(converter.unstructure(inst), C)
186212

187213

188214
@given(simple_typed_classes(defaults="never", newtypes=False, allow_nan=False))

0 commit comments

Comments
 (0)