From 349ada94064a0b5e0356314f2759f5af5f637292 Mon Sep 17 00:00:00 2001 From: Abhikr Date: Tue, 27 Oct 2026 20:00:52 +0530 Subject: [PATCH 1/3] gh-160761: Fix TypeError when pickling directly instantiated urllib.parse result objects --- Lib/test/test_urlparse.py | 6 ++++++ Lib/urllib/parse.py | 15 ++++++++------- ...2026-10-27-20-11-00.gh-issue-160761.aB3dEf.rst | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-27-20-11-00.gh-issue-160761.aB3dEf.rst diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index a5b7966c7780e9e..f3ded52f25ed543 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -1344,6 +1344,12 @@ def check(result): check(func(burl)) check(func(burl, missing_as_none=True)) + for cls in (urllib.parse.DefragResult, urllib.parse.SplitResult, urllib.parse.ParseResult): + check(cls(*[''] * len(cls._fields))) + for cls in (urllib.parse.DefragResultBytes, urllib.parse.SplitResultBytes, urllib.parse.ParseResultBytes): + check(cls(*[b''] * len(cls._fields))) + + def test_result_compat_unpickling(self): def check(result, pickles): for pickled in pickles: diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 4247b9a4b07fa3f..de25446b527f72e 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -307,13 +307,14 @@ def __deepcopy__(self, memo): def __getstate__(self): state = super().__getstate__() - try: - if state[1]['_keep_empty'] == _MISSING_AS_NONE_DEFAULT: - del state[1]['_keep_empty'] - if state == (None, {}): - state = None - except LookupError: - pass + if state is not None: + try: + if state[1]['_keep_empty'] == _MISSING_AS_NONE_DEFAULT: + del state[1]['_keep_empty'] + if state == (None, {}): + state = None + except LookupError: + pass return state diff --git a/Misc/NEWS.d/next/Library/2026-10-27-20-11-00.gh-issue-160761.aB3dEf.rst b/Misc/NEWS.d/next/Library/2026-10-27-20-11-00.gh-issue-160761.aB3dEf.rst new file mode 100644 index 000000000000000..840456e53d1cc4c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-27-20-11-00.gh-issue-160761.aB3dEf.rst @@ -0,0 +1 @@ +Fix :exc:`TypeError` when pickling directly instantiated :mod:`urllib.parse` result objects. From abb9e26a186b05d94c666ea50b73bc6c60e060aa Mon Sep 17 00:00:00 2001 From: Austin Aviv Date: Wed, 28 Oct 2026 20:58:20 +0530 Subject: [PATCH 2/3] Update Lib/urllib/parse.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/urllib/parse.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index de25446b527f72e..9e47234a21decb6 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -307,14 +307,15 @@ def __deepcopy__(self, memo): def __getstate__(self): state = super().__getstate__() - if state is not None: - try: - if state[1]['_keep_empty'] == _MISSING_AS_NONE_DEFAULT: - del state[1]['_keep_empty'] - if state == (None, {}): - state = None - except LookupError: - pass + if state is None: + return None + try: + if state[1]['_keep_empty'] == _MISSING_AS_NONE_DEFAULT: + del state[1]['_keep_empty'] + if state == (None, {}): + state = None + except LookupError: + pass return state From d807edfcefa63d001ed5273ec1f1939b124f895e Mon Sep 17 00:00:00 2001 From: Abhikr Date: Wed, 28 Oct 2026 21:28:51 +0530 Subject: [PATCH 3/3] Update Lib/test/test_urlparse.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/test/test_urlparse.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index f3ded52f25ed543..d2786ae89b5e644 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -1349,7 +1349,6 @@ def check(result): for cls in (urllib.parse.DefragResultBytes, urllib.parse.SplitResultBytes, urllib.parse.ParseResultBytes): check(cls(*[b''] * len(cls._fields))) - def test_result_compat_unpickling(self): def check(result, pickles): for pickled in pickles: