File: PR543.patch

package info (click to toggle)
python-cattrs 24.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,716 kB
  • sloc: python: 11,498; makefile: 216
file content (182 lines) | stat: -rw-r--r-- 6,470 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
From e441c384427fdc6bc0bc26fbb0aba70ececacac0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tin=20Tvrtkovi=C4=87?= <tinchester@gmail.com>
Date: Sun, 2 Jun 2024 00:20:03 +0200
Subject: [PATCH 1/6] Python 3.13 support

---
 .github/workflows/main.yml | 2 +-
 pyproject.toml             | 1 +
 src/cattrs/dispatch.py     | 3 +--
 tox.ini                    | 4 +++-
 4 files changed, 6 insertions(+), 4 deletions(-)

--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -14,7 +14,7 @@ jobs:
 
     strategy:
       matrix:
-        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.10"]
+        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy-3.10"]
       fail-fast: false
 
     steps:
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -43,7 +43,7 @@ authors = [
 ]
 dependencies = [
     "attrs>=23.1.0",
-    "typing-extensions>=4.1.0, !=4.6.3; python_version < '3.11'",
+    "typing-extensions>=4.12.2",
     "exceptiongroup>=1.1.1; python_version < '3.11'",
 ]
 requires-python = ">=3.8"
@@ -59,6 +59,7 @@ classifiers = [
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
+    "Programming Language :: Python :: 3.13",
     "Programming Language :: Python :: Implementation :: CPython",
     "Programming Language :: Python :: Implementation :: PyPy",
     "Typing :: Typed",
@@ -77,7 +78,7 @@ ujson = [
     "ujson>=5.7.0",
 ]
 orjson = [
-    "orjson>=3.9.2; implementation_name == \"cpython\"",
+    "orjson>=3.10.7; implementation_name == \"cpython\"",
 ]
 msgpack = [
     "msgpack>=1.0.5",
--- a/src/cattrs/dispatch.py
+++ b/src/cattrs/dispatch.py
@@ -91,9 +91,9 @@ class MultiStrategyDispatch(Generic[Hook
     MultiStrategyDispatch uses a combination of exact-match dispatch,
     singledispatch, and FunctionDispatch.
 
-    :param converter: A converter to be used for factories that require converters.
     :param fallback_factory: A hook factory to be called when a hook cannot be
         produced.
+    :param converter: A converter to be used for factories that require converters.
 
     .. versionchanged:: 23.2.0
         Fallbacks are now factories.
@@ -103,7 +103,6 @@ class MultiStrategyDispatch(Generic[Hook
     """
 
     _fallback_factory: HookFactory[Hook]
-    _converter: BaseConverter
     _direct_dispatch: dict[TargetType, Hook]
     _function_dispatch: FunctionDispatch
     _single_dispatch: Any
--- a/tox.ini
+++ b/tox.ini
@@ -6,10 +6,12 @@ python =
     3.10: py310
     3.11: py311, docs
     3.12: py312, lint
+    3.13: py313
     pypy-3: pypy3
 
+
 [tox]
-envlist = pypy3, py38, py39, py310, py311, py312, lint, docs
+envlist = pypy3, py38, py39, py310, py311, py312, py313, lint, docs
 isolated_build = true
 skipsdist = true
 
@@ -42,6 +44,15 @@ setenv =
     COVERAGE_PROCESS_START={toxinidir}/pyproject.toml
     COVERAGE_CORE=sysmon
 
+[testenv:py313]
+setenv =
+    PDM_IGNORE_SAVED_PYTHON="1"
+    COVERAGE_PROCESS_START={toxinidir}/pyproject.toml
+    COVERAGE_CORE=sysmon
+commands_pre =
+    pdm sync -G ujson,msgpack,pyyaml,tomlkit,cbor2,bson,orjson,test
+    python -c 'import pathlib; pathlib.Path("{env_site_packages_dir}/cov.pth").write_text("import coverage; coverage.process_startup()")'
+
 [testenv:pypy3]
 setenv =
     FAST = 1
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -37,3 +37,5 @@ if sys.version_info < (3, 12):
     collect_ignore_glob.append("*_695.py")
 if platform.python_implementation() == "PyPy":
     collect_ignore_glob.append("*_cpython.py")
+if sys.version_info >= (3, 13):  # Remove when msgspec supports 3.13.
+    collect_ignore_glob.append("*test_msgspec_cpython.py")
--- a/tests/test_preconf.py
+++ b/tests/test_preconf.py
@@ -4,7 +4,7 @@ from enum import Enum, IntEnum, unique
 from json import dumps as json_dumps
 from json import loads as json_loads
 from platform import python_implementation
-from typing import Any, Dict, List, NamedTuple, NewType, Tuple, Union
+from typing import Any, Dict, Final, List, NamedTuple, NewType, Tuple, Union
 
 import pytest
 from attrs import define
@@ -699,7 +699,10 @@ def test_cbor2_unions(union_and_val: tup
     assert converter.structure(val, type) == val
 
 
-@pytest.mark.skipif(python_implementation() == "PyPy", reason="no msgspec on PyPy")
+NO_MSGSPEC: Final = python_implementation() == "PyPy" or sys.version_info[:2] >= (3, 13)
+
+
+@pytest.mark.skipif(NO_MSGSPEC, reason="msgspec not available")
 @given(everythings(allow_inf=False))
 def test_msgspec_json_converter(everything: Everything):
     from cattrs.preconf.msgspec import make_converter as msgspec_make_converter
@@ -709,7 +712,7 @@ def test_msgspec_json_converter(everythi
     assert converter.loads(raw, Everything) == everything
 
 
-@pytest.mark.skipif(python_implementation() == "PyPy", reason="no msgspec on PyPy")
+@pytest.mark.skipif(NO_MSGSPEC, reason="msgspec not available")
 @given(everythings(allow_inf=False))
 def test_msgspec_json_unstruct_collection_overrides(everything: Everything):
     """Ensure collection overrides work."""
@@ -724,7 +727,7 @@ def test_msgspec_json_unstruct_collectio
     assert raw["a_frozenset"] == sorted(raw["a_frozenset"])
 
 
-@pytest.mark.skipif(python_implementation() == "PyPy", reason="no msgspec on PyPy")
+@pytest.mark.skipif(NO_MSGSPEC, reason="msgspec not available")
 @given(
     union_and_val=native_unions(
         include_datetimes=False,
--- a/src/cattrs/gen/__init__.py
+++ b/src/cattrs/gen/__init__.py
@@ -14,6 +14,7 @@ from typing import (
 )
 
 from attrs import NOTHING, Attribute, Factory, resolve_types
+from typing_extensions import NoDefault
 
 from .._compat import (
     ANIES,
@@ -1029,6 +1030,9 @@ def iterable_unstructure_factory(
     """A hook factory for unstructuring iterables.
 
     :param unstructure_to: Force unstructuring to this type, if provided.
+
+    ..  versionchanged:: 24.2.0
+        `typing.NoDefault` is now correctly handled as `Any`.
     """
     handler = converter.unstructure
 
@@ -1039,6 +1043,8 @@ def iterable_unstructure_factory(
         type_arg = cl.__args__[0]
         if isinstance(type_arg, TypeVar):
             type_arg = getattr(type_arg, "__default__", Any)
+            if type_arg is NoDefault:
+                type_arg = Any
         handler = converter.get_unstructure_hook(type_arg, cache_result=False)
         if handler == identity:
             # Save ourselves the trouble of iterating over it all.