diff --git a/CHANGES b/CHANGES index 626fed61..fbd06dd1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +0.24.1 +------ + +* Reintroduced overloads for better typing in `CallList`. +* Added typing to `Call` attributes. + + 0.24.0 ------ diff --git a/responses/__init__.py b/responses/__init__.py index 0e74f9b9..4ef097d8 100644 --- a/responses/__init__.py +++ b/responses/__init__.py @@ -3,7 +3,6 @@ import json as json_module import logging import socket -from collections import namedtuple from functools import partialmethod from functools import wraps from http import client @@ -18,12 +17,14 @@ from typing import Iterator from typing import List from typing import Mapping +from typing import NamedTuple from typing import Optional from typing import Sequence from typing import Sized from typing import Tuple from typing import Type from typing import Union +from typing import overload from warnings import warn import yaml @@ -96,7 +97,11 @@ def __call__( ] -Call = namedtuple("Call", ["request", "response"]) +class Call(NamedTuple): + request: "PreparedRequest" + response: "_Body" + + _real_send = HTTPAdapter.send _UNSET = object() @@ -241,6 +246,14 @@ def __iter__(self) -> Iterator[Call]: def __len__(self) -> int: return len(self._calls) + @overload + def __getitem__(self, idx: int) -> Call: + ... + + @overload + def __getitem__(self, idx: slice) -> List[Call]: + ... + def __getitem__(self, idx: Union[int, slice]) -> Union[Call, List[Call]]: return self._calls[idx] diff --git a/responses/tests/test_responses.py b/responses/tests/test_responses.py index 7d3af31e..3617b739 100644 --- a/responses/tests/test_responses.py +++ b/responses/tests/test_responses.py @@ -5,6 +5,7 @@ from io import BufferedReader from io import BytesIO from typing import Any +from typing import List from typing import Optional from unittest.mock import Mock from unittest.mock import patch @@ -20,6 +21,7 @@ import responses from responses import BaseResponse +from responses import Call from responses import CallbackResponse from responses import PassthroughResponse from responses import Response @@ -2035,6 +2037,37 @@ def run(): assert_reset() +def test_response_calls_indexing_and_slicing(): + @responses.activate + def run(): + responses.add(responses.GET, "http://www.example.com") + responses.add(responses.GET, "http://www.example.com/1") + responses.add(responses.GET, "http://www.example.com/2") + + requests.get("http://www.example.com") + requests.get("http://www.example.com/1") + requests.get("http://www.example.com/2") + requests.get("http://www.example.com/1") + requests.get("http://www.example.com") + + # Use of a type hints here ensures mypy knows the difference between index and slice. + individual_call: Call = responses.calls[0] + call_slice: List[Call] = responses.calls[1:-1] + + assert individual_call.request.url == "http://www.example.com" + + assert call_slice == [ + responses.calls[1], + responses.calls[2], + responses.calls[3], + ] + assert [c.request.url for c in call_slice] == [ + "http://www.example.com/1", + "http://www.example.com/2", + "http://www.example.com/1", + ] + + def test_response_calls_and_registry_calls_are_equal(): @responses.activate def run():