From 6e8886492bfedb40b8153a2c1fba8ce394acbf22 Mon Sep 17 00:00:00 2001 From: Alyssa Coghlan Date: Sun, 27 Apr 2025 01:05:36 +1000 Subject: [PATCH 1/3] Python 3.14: handle `typing.Union` immutability Attempting to [publish an experimental project](https://github.com/ncoghlan/tstrprocess/actions/runs/14682311907/job/41206490424#step:3:76) that will require Python 3.14's t-strings to run, I encountered the following exception from this code: ``` AttributeError: 'typing.Union' object has no attribute '__module__' and no __dict__ for setting new attributes. Did you mean: '__reduce__'? ``` This error is due to `typing.Union` instances becoming immutable in Python 3.14+: https://docs.python.org/3.14/whatsnew/3.14.html#typing The PR currently works by ignoring the exception raised (since that's the most robust option), but an alternative approach would be to add a `hasattr` check so only values that already have a `__module__` attribute get modified. --- httpx/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/httpx/__init__.py b/httpx/__init__.py index e9addde071..15a0692ada 100644 --- a/httpx/__init__.py +++ b/httpx/__init__.py @@ -102,4 +102,9 @@ def main() -> None: # type: ignore __locals = locals() for __name in __all__: if not __name.startswith("__"): - setattr(__locals[__name], "__module__", "httpx") # noqa + try: + setattr(__locals[__name], "__module__", "httpx") # noqa + except AttributeError: + # typing.Union instances are immutable in Python 3.14+, + # so don't fail if writing to "__module__" fails + continue From cffc78b90b65c52f2eb25805bf19b497831dea5e Mon Sep 17 00:00:00 2001 From: Alyssa Coghlan Date: Sun, 27 Apr 2025 01:21:27 +1000 Subject: [PATCH 2/3] No exception raised until Python 3.14 is tested --- httpx/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httpx/__init__.py b/httpx/__init__.py index 15a0692ada..970a0e7a55 100644 --- a/httpx/__init__.py +++ b/httpx/__init__.py @@ -104,7 +104,7 @@ def main() -> None: # type: ignore if not __name.startswith("__"): try: setattr(__locals[__name], "__module__", "httpx") # noqa - except AttributeError: + except AttributeError: # noqa # typing.Union instances are immutable in Python 3.14+, # so don't fail if writing to "__module__" fails - continue + continue # noqa From 278766c14bd597a66c4aa9d35799f4e0992362ee Mon Sep 17 00:00:00 2001 From: Alyssa Coghlan Date: Sun, 27 Apr 2025 01:30:10 +1000 Subject: [PATCH 3/3] Use coverage exclusion comment marker --- httpx/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httpx/__init__.py b/httpx/__init__.py index 970a0e7a55..1b61fc4f1a 100644 --- a/httpx/__init__.py +++ b/httpx/__init__.py @@ -104,7 +104,7 @@ def main() -> None: # type: ignore if not __name.startswith("__"): try: setattr(__locals[__name], "__module__", "httpx") # noqa - except AttributeError: # noqa + except AttributeError: # pragma: no cover # typing.Union instances are immutable in Python 3.14+, # so don't fail if writing to "__module__" fails - continue # noqa + continue # pragma: no cover