diff --git a/src/requests/cookies.py b/src/requests/cookies.py index 24dd9a7829..b6987ab5ba 100644 --- a/src/requests/cookies.py +++ b/src/requests/cookies.py @@ -299,6 +299,20 @@ def items(self) -> list[tuple[str, str | None]]: # type: ignore[override] """ return list(self.iteritems()) + def popitem(self) -> tuple[str, str | None]: + """Dict-like popitem() that removes and returns a (name, value) pair, + or raises KeyError if the jar is empty. + + The inherited ``MutableMapping.popitem`` does not work here because + ``__iter__`` yields ``Cookie`` objects rather than names. + """ + try: + name, value = next(self.iteritems()) + except StopIteration: + raise KeyError("popitem(): cookie jar is empty") from None + del self[name] + return name, value + def list_domains(self) -> list[str]: """Utility method to list all the domains in the jar.""" domains: list[str] = [] diff --git a/tests/test_requests.py b/tests/test_requests.py index 8bcb81d8b1..794be0f63c 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1313,6 +1313,24 @@ def test_cookie_parameters(self): assert cookie.domain == domain assert cookie._rest["HttpOnly"] == rest["HttpOnly"] + def test_cookie_popitem(self): + jar = requests.cookies.RequestsCookieJar() + jar.set("some_cookie", "some_value") + jar.set("some_cookie1", "some_value1") + + items = dict(jar.items()) + + name, value = jar.popitem() + assert (name, value) in items.items() + assert name not in jar + assert len(jar) == 1 + + jar.popitem() + assert len(jar) == 0 + + with pytest.raises(KeyError): + jar.popitem() + def test_cookie_as_dict_keeps_len(self): key = "some_cookie" value = "some_value"