|
2 | 2 | import heapq |
3 | 3 | import itertools |
4 | 4 | import logging |
5 | | -import pickle |
6 | | -import sys |
7 | 5 | from http.cookies import BaseCookie, Morsel, SimpleCookie |
8 | 6 | from operator import not_ |
9 | 7 | from pathlib import Path |
|
17 | 15 | from aiohttp.typedefs import LooseCookies |
18 | 16 |
|
19 | 17 |
|
20 | | -def dump_cookiejar() -> bytes: # pragma: no cover |
21 | | - """Create pickled data for test_pickle_format().""" |
22 | | - cj = CookieJar() |
23 | | - cj.update_cookies(_cookies_to_send()) |
24 | | - return pickle.dumps(cj._cookies, pickle.HIGHEST_PROTOCOL) |
25 | | - |
26 | | - |
27 | 18 | def _cookies_to_send() -> SimpleCookie: |
28 | 19 | return SimpleCookie( |
29 | 20 | "shared-cookie=first; " |
@@ -1027,41 +1018,6 @@ async def test_cookie_jar_clear_domain() -> None: |
1027 | 1018 | next(iterator) |
1028 | 1019 |
|
1029 | 1020 |
|
1030 | | -def test_pickle_format(cookies_to_send: SimpleCookie) -> None: |
1031 | | - """Test if cookiejar pickle format breaks. |
1032 | | -
|
1033 | | - If this test fails, it may indicate that saved cookiejars will stop working. |
1034 | | - If that happens then: |
1035 | | - 1. Avoid releasing the change in a bugfix release. |
1036 | | - 2. Try to include a migration script in the release notes (example below). |
1037 | | - 3. Use dump_cookiejar() at the top of this file to update `pickled`. |
1038 | | -
|
1039 | | - Depending on the changes made, a migration script might look like: |
1040 | | - import pickle |
1041 | | - with file_path.open("rb") as f: |
1042 | | - cookies = pickle.load(f) |
1043 | | -
|
1044 | | - morsels = [(name, m) for c in cookies.values() for name, m in c.items()] |
1045 | | - cookies.clear() |
1046 | | - for name, m in morsels: |
1047 | | - cookies[(m["domain"], m["path"])][name] = m |
1048 | | -
|
1049 | | - with file_path.open("wb") as f: |
1050 | | - pickle.dump(cookies, f, pickle.HIGHEST_PROTOCOL) |
1051 | | - """ |
1052 | | - if sys.version_info < (3, 14): |
1053 | | - pickled = b"\x80\x04\x95\xc8\x0b\x00\x00\x00\x00\x00\x00\x8c\x0bcollections\x94\x8c\x0bdefaultdict\x94\x93\x94\x8c\x0chttp.cookies\x94\x8c\x0cSimpleCookie\x94\x93\x94\x85\x94R\x94(\x8c\x00\x94h\x08\x86\x94h\x05)\x81\x94\x8c\rshared-cookie\x94h\x03\x8c\x06Morsel\x94\x93\x94)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94\x8c\x01/\x94\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\x08\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(\x8c\x03key\x94h\x0b\x8c\x05value\x94\x8c\x05first\x94\x8c\x0bcoded_value\x94h\x1cubs\x8c\x0bexample.com\x94h\x08\x86\x94h\x05)\x81\x94(\x8c\rdomain-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\x1e\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah!h\x1b\x8c\x06second\x94h\x1dh-ub\x8c\x14dotted-domain-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94\x8c\x0bexample.com\x94\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah.h\x1b\x8c\x05fifth\x94h\x1dh;ubu\x8c\x11test1.example.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x11subdomain1-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94h<\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah?h\x1b\x8c\x05third\x94h\x1dhKubs\x8c\x11test2.example.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x11subdomain2-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94hL\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ahOh\x1b\x8c\x06fourth\x94h\x1dh[ubs\x8c\rdifferent.org\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x17different-domain-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\\\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah_h\x1b\x8c\x05sixth\x94h\x1dhkubs\x8c\nsecure.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\rsecure-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94hl\x8c\x07max-age\x94h\x08\x8c\x06secure\x94\x88\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ahoh\x1b\x8c\x07seventh\x94h\x1dh{ubs\x8c\x0cpathtest.com\x94h\x08\x86\x94h\x05)\x81\x94(\x8c\x0eno-path-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94h|\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\x7fh\x1b\x8c\x06eighth\x94h\x1dh\x8bub\x8c\x0cpath1-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94\x8c\x0cpathtest.com\x94\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\x8ch\x1b\x8c\x05ninth\x94h\x1dh\x99ubu\x8c\x0cpathtest.com\x94\x8c\x04/one\x94\x86\x94h\x05)\x81\x94\x8c\x0cpath2-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x9b\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\x9a\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\x9eh\x1b\x8c\x05tenth\x94h\x1dh\xaaubs\x8c\x0cpathtest.com\x94\x8c\x08/one/two\x94\x86\x94h\x05)\x81\x94(\x8c\x0cpath3-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\xac\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\xab\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\xafh\x1b\x8c\x08eleventh\x94h\x1dh\xbbub\x8c\x0cpath4-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94\x8c\t/one/two/\x94\x8c\x07comment\x94h\x08\x8c\x06domain\x94\x8c\x0cpathtest.com\x94\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\xbch\x1b\x8c\x07twelfth\x94h\x1dh\xcaubu\x8c\x0fexpirestest.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x0eexpires-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94\x8c\x1cTue, 1 Jan 2999 12:00:00 GMT\x94\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\xcb\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\xceh\x1b\x8c\nthirteenth\x94h\x1dh\xdbubs\x8c\x0emaxagetest.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x0emax-age-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\xdc\x8c\x07max-age\x94\x8c\x0260\x94\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\xdfh\x1b\x8c\nfourteenth\x94h\x1dh\xecubs\x8c\x12invalid-values.com\x94h\x08\x86\x94h\x05)\x81\x94(\x8c\x16invalid-max-age-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\xed\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\xf0h\x1b\x8c\tfifteenth\x94h\x1dh\xfcub\x8c\x16invalid-expires-cookie\x94h\r)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94h\x11\x8c\x07comment\x94h\x08\x8c\x06domain\x94\x8c\x12invalid-values.com\x94\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08u}\x94(h\x1ah\xfdh\x1b\x8c\tsixteenth\x94h\x1dj\n\x01\x00\x00ubuu." |
1054 | | - else: |
1055 | | - pickled = b'\x80\x05\x95\x06\x08\x00\x00\x00\x00\x00\x00\x8c\x0bcollections\x94\x8c\x0bdefaultdict\x94\x93\x94\x8c\x0chttp.cookies\x94\x8c\x0cSimpleCookie\x94\x93\x94\x85\x94R\x94(\x8c\x00\x94h\x08\x86\x94h\x05)\x81\x94\x8c\rshared-cookie\x94h\x03\x8c\x06Morsel\x94\x93\x94)\x81\x94(\x8c\x07expires\x94h\x08\x8c\x04path\x94\x8c\x01/\x94\x8c\x07comment\x94h\x08\x8c\x06domain\x94h\x08\x8c\x07max-age\x94h\x08\x8c\x06secure\x94h\x08\x8c\x08httponly\x94h\x08\x8c\x07version\x94h\x08\x8c\x08samesite\x94h\x08\x8c\x0bpartitioned\x94h\x08u}\x94(\x8c\x03key\x94h\x0b\x8c\x05value\x94\x8c\x05first\x94\x8c\x0bcoded_value\x94h\x1dubs\x8c\x0bexample.com\x94h\x08\x86\x94h\x05)\x81\x94(\x8c\rdomain-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13h\x1fh\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh"h\x1c\x8c\x06second\x94h\x1eh%ub\x8c\x14dotted-domain-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13\x8c\x0bexample.com\x94h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh&h\x1c\x8c\x05fifth\x94h\x1eh*ubu\x8c\x11test1.example.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x11subdomain1-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13h+h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh.h\x1c\x8c\x05third\x94h\x1eh1ubs\x8c\x11test2.example.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x11subdomain2-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13h2h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh5h\x1c\x8c\x06fourth\x94h\x1eh8ubs\x8c\rdifferent.org\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x17different-domain-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13h9h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh<h\x1c\x8c\x05sixth\x94h\x1eh?ubs\x8c\nsecure.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\rsecure-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13h@h\x14h\x08h\x15\x88h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bhCh\x1c\x8c\x07seventh\x94h\x1ehFubs\x8c\x0cpathtest.com\x94h\x08\x86\x94h\x05)\x81\x94(\x8c\x0eno-path-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13hGh\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bhJh\x1c\x8c\x06eighth\x94h\x1ehMub\x8c\x0cpath1-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13\x8c\x0cpathtest.com\x94h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bhNh\x1c\x8c\x05ninth\x94h\x1ehRubu\x8c\x0cpathtest.com\x94\x8c\x04/one\x94\x86\x94h\x05)\x81\x94\x8c\x0cpath2-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10hTh\x12h\x08h\x13hSh\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bhWh\x1c\x8c\x05tenth\x94h\x1ehZubs\x8c\x0cpathtest.com\x94\x8c\x08/one/two\x94\x86\x94h\x05)\x81\x94(\x8c\x0cpath3-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\\h\x12h\x08h\x13h[h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh_h\x1c\x8c\x08eleventh\x94h\x1ehbub\x8c\x0cpath4-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10\x8c\t/one/two/\x94h\x12h\x08h\x13\x8c\x0cpathtest.com\x94h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bhch\x1c\x8c\x07twelfth\x94h\x1ehhubu\x8c\x0fexpirestest.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x0eexpires-cookie\x94h\r)\x81\x94(h\x0f\x8c\x1cTue, 1 Jan 2999 12:00:00 GMT\x94h\x10h\x11h\x12h\x08h\x13hih\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bhlh\x1c\x8c\nthirteenth\x94h\x1ehpubs\x8c\x0emaxagetest.com\x94h\x08\x86\x94h\x05)\x81\x94\x8c\x0emax-age-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13hqh\x14\x8c\x0260\x94h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bhth\x1c\x8c\nfourteenth\x94h\x1ehxubs\x8c\x12invalid-values.com\x94h\x08\x86\x94h\x05)\x81\x94(\x8c\x16invalid-max-age-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13hyh\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh|h\x1c\x8c\tfifteenth\x94h\x1eh\x7fub\x8c\x16invalid-expires-cookie\x94h\r)\x81\x94(h\x0fh\x08h\x10h\x11h\x12h\x08h\x13\x8c\x12invalid-values.com\x94h\x14h\x08h\x15h\x08h\x16h\x08h\x17h\x08h\x18h\x08h\x19h\x08u}\x94(h\x1bh\x80h\x1c\x8c\tsixteenth\x94h\x1eh\x84ubuu.' |
1056 | | - |
1057 | | - cookies = pickle.loads(pickled) |
1058 | | - |
1059 | | - cj = CookieJar() |
1060 | | - cj.update_cookies(cookies_to_send) |
1061 | | - |
1062 | | - assert cookies == cj._cookies |
1063 | | - |
1064 | | - |
1065 | 1021 | @pytest.mark.parametrize( |
1066 | 1022 | "url", |
1067 | 1023 | [ |
@@ -1566,93 +1522,6 @@ async def test_shared_cookie_with_multiple_domains() -> None: |
1566 | 1522 | assert "universal" in jar._morsel_cache[("", "")] |
1567 | 1523 |
|
1568 | 1524 |
|
1569 | | -# === Security tests for restricted unpickler and JSON save/load === |
1570 | | - |
1571 | | - |
1572 | | -def test_load_rejects_malicious_pickle(tmp_path: Path) -> None: |
1573 | | - """Verify CookieJar.load() blocks arbitrary code execution via pickle. |
1574 | | -
|
1575 | | - A crafted pickle payload using os.system (or any non-cookie class) |
1576 | | - must be rejected by the restricted unpickler. |
1577 | | - """ |
1578 | | - import os |
1579 | | - |
1580 | | - file_path = tmp_path / "malicious.pkl" |
1581 | | - |
1582 | | - class RCEPayload: |
1583 | | - def __reduce__(self) -> tuple[object, ...]: |
1584 | | - return (os.system, ("echo PWNED",)) |
1585 | | - |
1586 | | - with open(file_path, "wb") as f: |
1587 | | - pickle.dump(RCEPayload(), f, pickle.HIGHEST_PROTOCOL) |
1588 | | - |
1589 | | - jar = CookieJar() |
1590 | | - with pytest.raises(pickle.UnpicklingError, match="Forbidden class"): |
1591 | | - jar.load(file_path) |
1592 | | - |
1593 | | - |
1594 | | -def test_load_rejects_eval_payload(tmp_path: Path) -> None: |
1595 | | - """Verify CookieJar.load() blocks eval-based pickle payloads.""" |
1596 | | - file_path = tmp_path / "eval_payload.pkl" |
1597 | | - |
1598 | | - class EvalPayload: |
1599 | | - def __reduce__(self) -> tuple[object, ...]: |
1600 | | - return (eval, ("__import__('os').system('echo PWNED')",)) |
1601 | | - |
1602 | | - with open(file_path, "wb") as f: |
1603 | | - pickle.dump(EvalPayload(), f, pickle.HIGHEST_PROTOCOL) |
1604 | | - |
1605 | | - jar = CookieJar() |
1606 | | - with pytest.raises(pickle.UnpicklingError, match="Forbidden class"): |
1607 | | - jar.load(file_path) |
1608 | | - |
1609 | | - |
1610 | | -def test_load_rejects_subprocess_payload(tmp_path: Path) -> None: |
1611 | | - """Verify CookieJar.load() blocks subprocess-based pickle payloads.""" |
1612 | | - import subprocess |
1613 | | - |
1614 | | - file_path = tmp_path / "subprocess_payload.pkl" |
1615 | | - |
1616 | | - class SubprocessPayload: |
1617 | | - def __reduce__(self) -> tuple[object, ...]: |
1618 | | - return (subprocess.call, (["echo", "PWNED"],)) |
1619 | | - |
1620 | | - with open(file_path, "wb") as f: |
1621 | | - pickle.dump(SubprocessPayload(), f, pickle.HIGHEST_PROTOCOL) |
1622 | | - |
1623 | | - jar = CookieJar() |
1624 | | - with pytest.raises(pickle.UnpicklingError, match="Forbidden class"): |
1625 | | - jar.load(file_path) |
1626 | | - |
1627 | | - |
1628 | | -def test_load_falls_back_to_pickle( |
1629 | | - tmp_path: Path, |
1630 | | - cookies_to_receive: SimpleCookie, |
1631 | | -) -> None: |
1632 | | - """Verify load() falls back to restricted pickle for legacy cookie files. |
1633 | | -
|
1634 | | - Existing cookie files saved with older versions of aiohttp used pickle. |
1635 | | - load() should detect that the file is not JSON and fall back to the |
1636 | | - restricted pickle unpickler for backward compatibility. |
1637 | | - """ |
1638 | | - file_path = tmp_path / "legit.pkl" |
1639 | | - |
1640 | | - # Write a legacy pickle file directly (as old aiohttp save() would) |
1641 | | - jar_save = CookieJar() |
1642 | | - jar_save.update_cookies(cookies_to_receive) |
1643 | | - with file_path.open(mode="wb") as f: |
1644 | | - pickle.dump(jar_save._cookies, f, pickle.HIGHEST_PROTOCOL) |
1645 | | - |
1646 | | - jar_load = CookieJar() |
1647 | | - jar_load.load(file_path=file_path) |
1648 | | - |
1649 | | - jar_test = SimpleCookie() |
1650 | | - for cookie in jar_load: |
1651 | | - jar_test[cookie.key] = cookie |
1652 | | - |
1653 | | - assert jar_test == cookies_to_receive |
1654 | | - |
1655 | | - |
1656 | 1525 | def test_save_load_json_roundtrip( |
1657 | 1526 | tmp_path: Path, |
1658 | 1527 | cookies_to_receive: SimpleCookie, |
|
0 commit comments