Skip to content

Commit

Permalink
Fix/calllist typing (#690)
Browse files Browse the repository at this point in the history
* fix: Reintroduce `overload`s in `CallList`
* test: Add coverage to ensure we can differentiate between indexing and slicing into `CallList`s
* feat: Better typing for `Call`
  • Loading branch information
howamith committed Nov 6, 2023
1 parent a0df27d commit c46cb06
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
7 changes: 7 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
0.24.1
------

* Reintroduced overloads for better typing in `CallList`.
* Added typing to `Call` attributes.


0.24.0
------

Expand Down
17 changes: 15 additions & 2 deletions responses/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -96,7 +97,11 @@ def __call__(
]


Call = namedtuple("Call", ["request", "response"])
class Call(NamedTuple):
request: "PreparedRequest"
response: "_Body"


_real_send = HTTPAdapter.send
_UNSET = object()

Expand Down Expand Up @@ -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]

Expand Down
33 changes: 33 additions & 0 deletions responses/tests/test_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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():
Expand Down

0 comments on commit c46cb06

Please sign in to comment.