Skip to content

Commit 9a2f146

Browse files
authored
Ignore partitioned attributes in cookies if it is not supported by http.cookie (#11529)
1 parent 230e1ee commit 9a2f146

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

CHANGES/11523.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix saved ``CookieJar`` fail to be loaded if cookies have ``partitioned`` flag when
2+
``http.cookie`` does not have partitioned cookies supports. -- by :user:`Cycloctane`.

aiohttp/_cookie_helpers.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"""
77

88
import re
9-
import sys
109
from http.cookies import Morsel
1110
from typing import List, Optional, Sequence, Tuple, cast
1211

@@ -270,11 +269,8 @@ def parse_set_cookie_headers(headers: Sequence[str]) -> List[Tuple[str, Morsel[s
270269
break
271270
if lower_key in _COOKIE_BOOL_ATTRS:
272271
# Boolean attribute with any value should be True
273-
if current_morsel is not None:
274-
if lower_key == "partitioned" and sys.version_info < (3, 14):
275-
dict.__setitem__(current_morsel, lower_key, True)
276-
else:
277-
current_morsel[lower_key] = True
272+
if current_morsel is not None and current_morsel.isReservedKey(key):
273+
current_morsel[lower_key] = True
278274
elif value is None:
279275
# Invalid cookie string - non-boolean attribute without value
280276
break

tests/test_cookie_helpers.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Tests for internal cookie helper functions."""
22

3+
import sys
34
from http.cookies import (
45
CookieError,
56
Morsel,
@@ -427,6 +428,10 @@ def test_parse_set_cookie_headers_boolean_attrs() -> None:
427428
assert morsel.get("httponly") is True, f"{name} should have httponly=True"
428429

429430

431+
@pytest.mark.skipif(
432+
sys.version_info < (3, 14),
433+
reason="Partitioned cookies support requires Python 3.14+",
434+
)
430435
def test_parse_set_cookie_headers_boolean_attrs_with_partitioned() -> None:
431436
"""Test that boolean attributes including partitioned work correctly."""
432437
# Test secure attribute variations
@@ -482,6 +487,10 @@ def test_parse_set_cookie_headers_encoded_values() -> None:
482487
assert result[2][1].value == "%21%40%23%24%25%5E%26*%28%29"
483488

484489

490+
@pytest.mark.skipif(
491+
sys.version_info < (3, 14),
492+
reason="Partitioned cookies support requires Python 3.14+",
493+
)
485494
def test_parse_set_cookie_headers_partitioned() -> None:
486495
"""
487496
Test that parse_set_cookie_headers handles partitioned attribute correctly.
@@ -518,6 +527,10 @@ def test_parse_set_cookie_headers_partitioned() -> None:
518527
assert result[4][1].get("path") == "/"
519528

520529

530+
@pytest.mark.skipif(
531+
sys.version_info < (3, 14),
532+
reason="Partitioned cookies support requires Python 3.14+",
533+
)
521534
def test_parse_set_cookie_headers_partitioned_case_insensitive() -> None:
522535
"""Test that partitioned attribute is recognized case-insensitively."""
523536
headers = [
@@ -555,6 +568,26 @@ def test_parse_set_cookie_headers_partitioned_not_set() -> None:
555568

556569

557570
# Tests that don't require partitioned support in SimpleCookie
571+
@pytest.mark.skipif(
572+
sys.version_info >= (3, 14),
573+
reason="Python 3.14+ has built-in partitioned cookie support",
574+
)
575+
def test_parse_set_cookie_headers_partitioned_not_set_if_no_support() -> None:
576+
headers = [
577+
"cookie1=value1; Partitioned",
578+
"cookie2=value2; Partitioned=",
579+
"cookie3=value3; Partitioned=true",
580+
]
581+
582+
result = parse_set_cookie_headers(headers)
583+
584+
assert len(result) == 3
585+
for i, (_, morsel) in enumerate(result):
586+
assert (
587+
morsel.get("partitioned") is None
588+
), f"Cookie {i+1} should not have partitioned flag"
589+
590+
558591
def test_parse_set_cookie_headers_partitioned_with_other_attrs_manual() -> None:
559592
"""
560593
Test parsing logic for partitioned cookies combined with all other attributes.

tests/test_cookiejar.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,19 @@ def test_save_load(
206206
assert jar_test == cookies_to_receive
207207

208208

209+
def test_save_load_partitioned_cookies(tmp_path: Path) -> None:
210+
file_path = Path(str(tmp_path)) / "aiohttp.test2.cookie"
211+
# export cookie jar
212+
jar_save = CookieJar()
213+
jar_save.update_cookies_from_headers(
214+
["session=cookie; Partitioned"], URL("https://example.com/")
215+
)
216+
jar_save.save(file_path=file_path)
217+
jar_load = CookieJar()
218+
jar_load.load(file_path=file_path)
219+
assert jar_save._cookies == jar_load._cookies
220+
221+
209222
async def test_update_cookie_with_unicode_domain() -> None:
210223
cookies = (
211224
"idna-domain-first=first; Domain=xn--9caa.com; Path=/;",

0 commit comments

Comments
 (0)