From 2d37226ff19506e23bbc291125a29ce514575819 Mon Sep 17 00:00:00 2001
From: Tin Tvrtkovic <tinchester@gmail.com>
Date: Thu, 29 Aug 2024 18:34:36 +0200
Subject: [PATCH] Stop generating nan values in tests to work with latest attrs

---
 pyproject.toml              |   8 +-
 tests/test_baseconverter.py |  18 ++--
 tests/test_converter.py     |  38 ++++----
 tests/test_gen_dict.py      |  10 ++-
 tests/typed.py              |  51 ++++++++---
 tests/untyped.py            |   2 +-
 7 files changed, 176 insertions(+), 123 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index d5b1f914..fc1fb49c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,13 +7,13 @@ lint = [
     "ruff>=0.0.277",
 ]
 test = [
-    "hypothesis>=6.79.4",
-    "pytest>=7.4.0",
+    "hypothesis>=6.111.2",
+    "pytest>=8.3.2",
     "pytest-benchmark>=4.0.0",
     "immutables>=0.20",
     "typing-extensions>=4.7.1",
-    "coverage>=7.4.0",
-    "pytest-xdist>=3.4.0",
+    "coverage>=7.6.1",
+    "pytest-xdist>=3.6.1",
 ]
 docs = [
     "sphinx>=5.3.0",
diff --git a/tests/test_baseconverter.py b/tests/test_baseconverter.py
index 558e9013..1b8dc78a 100644
--- a/tests/test_baseconverter.py
+++ b/tests/test_baseconverter.py
@@ -15,7 +15,7 @@
 unstructure_strats = one_of(just(s) for s in UnstructureStrategy)
 
 
-@given(simple_typed_classes(newtypes=False), unstructure_strats)
+@given(simple_typed_classes(newtypes=False, allow_nan=False), unstructure_strats)
 def test_simple_roundtrip(cls_and_vals, strat):
     """
     Simple classes with metadata can be unstructured and restructured.
@@ -43,7 +43,7 @@ def test_simple_roundtrip_defaults(attr_and_strat, strat):
     assert inst == converter.structure(converter.unstructure(inst), cl)
 
 
-@given(nested_typed_classes(newtypes=False))
+@given(nested_typed_classes(newtypes=False, allow_nan=False))
 def test_nested_roundtrip(cls_and_vals):
     """
     Nested classes with metadata can be unstructured and restructured.
@@ -55,7 +55,7 @@ def test_nested_roundtrip(cls_and_vals):
     assert inst == converter.structure(converter.unstructure(inst), cl)
 
 
-@given(nested_typed_classes(kw_only=False, newtypes=False))
+@given(nested_typed_classes(kw_only=False, newtypes=False, allow_nan=False))
 def test_nested_roundtrip_tuple(cls_and_vals):
     """
     Nested classes with metadata can be unstructured and restructured.
@@ -70,8 +70,8 @@ def test_nested_roundtrip_tuple(cls_and_vals):
 
 @settings(suppress_health_check=[HealthCheck.filter_too_much, HealthCheck.too_slow])
 @given(
-    simple_typed_classes(defaults=False, newtypes=False),
-    simple_typed_classes(defaults=False, newtypes=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
     unstructure_strats,
 )
 def test_union_field_roundtrip(cl_and_vals_a, cl_and_vals_b, strat):
@@ -113,8 +113,8 @@ def handler(obj, _):
 @pytest.mark.skipif(not is_py310_plus, reason="3.10+ union syntax")
 @settings(suppress_health_check=[HealthCheck.filter_too_much, HealthCheck.too_slow])
 @given(
-    simple_typed_classes(defaults=False, newtypes=False),
-    simple_typed_classes(defaults=False, newtypes=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
     unstructure_strats,
 )
 def test_310_union_field_roundtrip(cl_and_vals_a, cl_and_vals_b, strat):
@@ -153,7 +153,7 @@ def handler(obj, _):
         assert inst == converter.structure(converter.unstructure(inst), C)
 
 
-@given(simple_typed_classes(defaults=False, newtypes=False))
+@given(simple_typed_classes(defaults=False, newtypes=False, allow_nan=False))
 def test_optional_field_roundtrip(cl_and_vals):
     """
     Classes with optional fields can be unstructured and structured.
@@ -175,7 +175,7 @@ class C:
 
 
 @pytest.mark.skipif(not is_py310_plus, reason="3.10+ union syntax")
-@given(simple_typed_classes(defaults=False, newtypes=False))
+@given(simple_typed_classes(defaults=False, newtypes=False, allow_nan=False))
 def test_310_optional_field_roundtrip(cl_and_vals):
     """
     Classes with optional fields can be unstructured and structured.
diff --git a/tests/test_converter.py b/tests/test_converter.py
index b401860c..47e70edc 100644
--- a/tests/test_converter.py
+++ b/tests/test_converter.py
@@ -40,7 +40,10 @@
 unstructure_strats = one_of(just(s) for s in UnstructureStrategy)
 
 
-@given(simple_typed_classes() | simple_typed_dataclasses(), booleans())
+@given(
+    simple_typed_classes(allow_nan=False) | simple_typed_dataclasses(allow_nan=False),
+    booleans(),
+)
 def test_simple_roundtrip(cls_and_vals, detailed_validation):
     """
     Simple classes with metadata can be unstructured and restructured.
@@ -54,8 +57,8 @@ def test_simple_roundtrip(cls_and_vals, detailed_validation):
 
 
 @given(
-    simple_typed_classes(kw_only=False, newtypes=False)
-    | simple_typed_dataclasses(newtypes=False),
+    simple_typed_classes(kw_only=False, newtypes=False, allow_nan=False)
+    | simple_typed_dataclasses(newtypes=False, allow_nan=False),
     booleans(),
 )
 def test_simple_roundtrip_tuple(cls_and_vals, dv: bool):
@@ -72,7 +75,7 @@ def test_simple_roundtrip_tuple(cls_and_vals, dv: bool):
     assert inst == converter.structure(unstructured, cl)
 
 
-@given(simple_typed_attrs(defaults=True))
+@given(simple_typed_attrs(defaults=True, allow_nan=False))
 def test_simple_roundtrip_defaults(attr_and_vals):
     """
     Simple classes with metadata can be unstructured and restructured.
@@ -87,7 +90,9 @@ def test_simple_roundtrip_defaults(attr_and_vals):
     assert inst == converter.structure(converter.unstructure(inst), cl)
 
 
-@given(simple_typed_attrs(defaults=True, kw_only=False, newtypes=False))
+@given(
+    simple_typed_attrs(defaults=True, kw_only=False, newtypes=False, allow_nan=False)
+)
 def test_simple_roundtrip_defaults_tuple(attr_and_vals):
     """
     Simple classes with metadata can be unstructured and restructured.
@@ -103,7 +108,8 @@ def test_simple_roundtrip_defaults_tuple(attr_and_vals):
 
 
 @given(
-    simple_typed_classes(newtypes=False) | simple_typed_dataclasses(newtypes=False),
+    simple_typed_classes(newtypes=False, allow_nan=False)
+    | simple_typed_dataclasses(newtypes=False, allow_nan=False),
     unstructure_strats,
 )
 def test_simple_roundtrip_with_extra_keys_forbidden(cls_and_vals, strat):
@@ -200,7 +206,7 @@ class A:
     assert cve.value.exceptions[0].extra_fields == {"b"}
 
 
-@given(nested_typed_classes(defaults=True, min_attrs=1), booleans())
+@given(nested_typed_classes(defaults=True, min_attrs=1, allow_nan=False), booleans())
 def test_nested_roundtrip(cls_and_vals, omit_if_default):
     """
     Nested classes with metadata can be unstructured and restructured.
@@ -214,7 +220,9 @@ def test_nested_roundtrip(cls_and_vals, omit_if_default):
 
 
 @given(
-    nested_typed_classes(defaults=True, min_attrs=1, kw_only=False, newtypes=False),
+    nested_typed_classes(
+        defaults=True, min_attrs=1, kw_only=False, newtypes=False, allow_nan=False
+    ),
     booleans(),
 )
 def test_nested_roundtrip_tuple(cls_and_vals, omit_if_default: bool):
@@ -233,8 +241,8 @@ def test_nested_roundtrip_tuple(cls_and_vals, omit_if_default: bool):
 
 @settings(suppress_health_check=[HealthCheck.filter_too_much, HealthCheck.too_slow])
 @given(
-    simple_typed_classes(defaults=False, newtypes=False),
-    simple_typed_classes(defaults=False, newtypes=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
     unstructure_strats,
 )
 def test_union_field_roundtrip(cl_and_vals_a, cl_and_vals_b, strat):
@@ -278,8 +286,8 @@ def handler(obj, _):
 @pytest.mark.skipif(not is_py310_plus, reason="3.10+ union syntax")
 @settings(suppress_health_check=[HealthCheck.filter_too_much, HealthCheck.too_slow])
 @given(
-    simple_typed_classes(defaults=False, newtypes=False),
-    simple_typed_classes(defaults=False, newtypes=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
+    simple_typed_classes(defaults=False, newtypes=False, allow_nan=False),
     unstructure_strats,
 )
 def test_310_union_field_roundtrip(cl_and_vals_a, cl_and_vals_b, strat):
@@ -320,7 +328,7 @@ def handler(obj, _):
         assert inst == converter.structure(unstructured, C)
 
 
-@given(simple_typed_classes(defaults=False))
+@given(simple_typed_classes(defaults=False, allow_nan=False))
 def test_optional_field_roundtrip(cl_and_vals):
     """
     Classes with optional fields can be unstructured and structured.
@@ -342,7 +350,7 @@ class C:
 
 
 @pytest.mark.skipif(not is_py310_plus, reason="3.10+ union syntax")
-@given(simple_typed_classes(defaults=False))
+@given(simple_typed_classes(defaults=False, allow_nan=False))
 def test_310_optional_field_roundtrip(cl_and_vals):
     """
     Classes with optional fields can be unstructured and structured.
@@ -363,7 +371,7 @@ class C:
     assert inst == converter.structure(unstructured, C)
 
 
-@given(simple_typed_classes(defaults=True))
+@given(simple_typed_classes(defaults=True, allow_nan=False))
 def test_omit_default_roundtrip(cl_and_vals):
     """
     Omit default on the converter works.
diff --git a/tests/test_gen_dict.py b/tests/test_gen_dict.py
index 16911d51..1130e766 100644
--- a/tests/test_gen_dict.py
+++ b/tests/test_gen_dict.py
@@ -160,9 +160,9 @@ def test_individual_overrides(converter_cls, cl_and_vals):
 
 
 @given(
-    cl_and_vals=nested_typed_classes()
-    | simple_typed_classes()
-    | simple_typed_dataclasses(),
+    cl_and_vals=nested_typed_classes(allow_nan=False)
+    | simple_typed_classes(allow_nan=False)
+    | simple_typed_dataclasses(allow_nan=False),
     dv=...,
 )
 def test_unmodified_generated_structuring(cl_and_vals, dv: bool):
@@ -185,7 +185,9 @@ def test_unmodified_generated_structuring(cl_and_vals, dv: bool):
 
 
 @given(
-    simple_typed_classes(min_attrs=1) | simple_typed_dataclasses(min_attrs=1), data()
+    simple_typed_classes(min_attrs=1, allow_nan=False)
+    | simple_typed_dataclasses(min_attrs=1, allow_nan=False),
+    data(),
 )
 def test_renaming(cl_and_vals, data):
     converter = Converter()
diff --git a/tests/typed.py b/tests/typed.py
index 7589c9a6..2cd4db21 100644
--- a/tests/typed.py
+++ b/tests/typed.py
@@ -67,7 +67,7 @@ def simple_typed_classes(
     newtypes=True,
     text_codec: str = "utf8",
     allow_infinity=None,
-    allow_nan=None,
+    allow_nan=True,
 ) -> SearchStrategy[Tuple[Type, PosArgs, KwArgs]]:
     """Yield tuples of (class, values)."""
     return lists_of_typed_attrs(
@@ -82,7 +82,9 @@ def simple_typed_classes(
     ).flatmap(partial(_create_hyp_class, frozen=frozen))
 
 
-def simple_typed_dataclasses(defaults=None, min_attrs=0, frozen=False, newtypes=True):
+def simple_typed_dataclasses(
+    defaults=None, min_attrs=0, frozen=False, newtypes=True, allow_nan=True
+):
     """Yield tuples of (class, values)."""
     return lists_of_typed_attrs(
         defaults,
@@ -90,15 +92,20 @@ def simple_typed_dataclasses(defaults=None, min_attrs=0, frozen=False, newtypes=
         for_frozen=frozen,
         allow_mutable_defaults=False,
         newtypes=newtypes,
+        allow_nan=allow_nan,
     ).flatmap(partial(_create_dataclass, frozen=frozen))
 
 
 def simple_typed_classes_and_strats(
-    defaults=None, min_attrs=0, kw_only=None, newtypes=True
+    defaults=None, min_attrs=0, kw_only=None, newtypes=True, allow_nan=True
 ) -> SearchStrategy[Tuple[Type, SearchStrategy[PosArgs], SearchStrategy[KwArgs]]]:
     """Yield tuples of (class, (strategies))."""
     return lists_of_typed_attrs(
-        defaults, min_size=min_attrs, kw_only=kw_only, newtypes=newtypes
+        defaults,
+        min_size=min_attrs,
+        kw_only=kw_only,
+        newtypes=newtypes,
+        allow_nan=allow_nan,
     ).flatmap(_create_hyp_class_and_strat)
 
 
@@ -111,7 +118,7 @@ def lists_of_typed_attrs(
     newtypes=True,
     text_codec="utf8",
     allow_infinity=None,
-    allow_nan=None,
+    allow_nan=True,
 ) -> SearchStrategy[List[Tuple[_CountingAttr, SearchStrategy[PosArg]]]]:
     # Python functions support up to 255 arguments.
     return lists(
@@ -142,7 +149,7 @@ def simple_typed_attrs(
     newtypes=True,
     text_codec="utf8",
     allow_infinity=None,
-    allow_nan=None,
+    allow_nan=True,
 ) -> SearchStrategy[Tuple[_CountingAttr, SearchStrategy[PosArgs]]]:
     if not is_39_or_later:
         res = (
@@ -400,7 +407,7 @@ def str_typed_attrs(draw, defaults=None, kw_only=None, codec: str = "utf8"):
 
 @composite
 def float_typed_attrs(
-    draw, defaults=None, kw_only=None, allow_infinity=None, allow_nan=None
+    draw, defaults=None, kw_only=None, allow_infinity=None, allow_nan=True
 ):
     """
     Generate a tuple of an attribute and a strategy that yields floats for that
@@ -832,7 +839,7 @@ def dict_of_class(
 
 
 def _create_hyp_nested_strategy(
-    simple_class_strategy: SearchStrategy, kw_only=None, newtypes=True
+    simple_class_strategy: SearchStrategy, kw_only=None, newtypes=True, allow_nan=True
 ) -> SearchStrategy[Tuple[Type, SearchStrategy[PosArgs], SearchStrategy[KwArgs]]]:
     """
     Create a recursive attrs class.
@@ -847,7 +854,8 @@ def _create_hyp_nested_strategy(
     attrs_and_classes: SearchStrategy[
         Tuple[List[Tuple[_CountingAttr, PosArgs]], Tuple[Type, SearchStrategy[PosArgs]]]
     ] = tuples(
-        lists_of_typed_attrs(kw_only=kw_only, newtypes=newtypes), simple_class_strategy
+        lists_of_typed_attrs(kw_only=kw_only, newtypes=newtypes, allow_nan=allow_nan),
+        simple_class_strategy,
     )
 
     return nested_classes(attrs_and_classes)
@@ -891,22 +899,37 @@ def nested_classes(
 
 
 def nested_typed_classes_and_strat(
-    defaults=None, min_attrs=0, kw_only=None, newtypes=True
+    defaults=None, min_attrs=0, kw_only=None, newtypes=True, allow_nan=True
 ) -> SearchStrategy[Tuple[Type, SearchStrategy[PosArgs]]]:
     return recursive(
         simple_typed_classes_and_strats(
-            defaults=defaults, min_attrs=min_attrs, kw_only=kw_only, newtypes=newtypes
+            defaults=defaults,
+            min_attrs=min_attrs,
+            kw_only=kw_only,
+            newtypes=newtypes,
+            allow_nan=allow_nan,
+        ),
+        partial(
+            _create_hyp_nested_strategy,
+            kw_only=kw_only,
+            newtypes=newtypes,
+            allow_nan=allow_nan,
         ),
-        partial(_create_hyp_nested_strategy, kw_only=kw_only, newtypes=newtypes),
         max_leaves=20,
     )
 
 
 @composite
-def nested_typed_classes(draw, defaults=None, min_attrs=0, kw_only=None, newtypes=True):
+def nested_typed_classes(
+    draw, defaults=None, min_attrs=0, kw_only=None, newtypes=True, allow_nan=True
+):
     cl, strat, kwarg_strat = draw(
         nested_typed_classes_and_strat(
-            defaults=defaults, min_attrs=min_attrs, kw_only=kw_only, newtypes=newtypes
+            defaults=defaults,
+            min_attrs=min_attrs,
+            kw_only=kw_only,
+            newtypes=newtypes,
+            allow_nan=allow_nan,
         )
     )
     return cl, draw(strat), draw(kwarg_strat)
diff --git a/tests/untyped.py b/tests/untyped.py
index 9dc815b0..0435d5e2 100644
--- a/tests/untyped.py
+++ b/tests/untyped.py
@@ -356,7 +356,7 @@ def float_attrs(draw, defaults=None, kw_only=None):
     """
     default = NOTHING
     if defaults is True or (defaults is None and draw(st.booleans())):
-        default = draw(st.floats())
+        default = draw(st.floats(allow_nan=False))
     return (
         attr.ib(
             default=default, kw_only=draw(st.booleans()) if kw_only is None else kw_only
