diff options
| author | robot-piglet <[email protected]> | 2026-06-05 09:20:51 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2026-06-05 09:48:46 +0300 |
| commit | 0d6add28adb1c47d194bafd90715fabe9a8794be (patch) | |
| tree | b054d6028895561a323a8de2bbfbde274bf12972 /contrib/python | |
| parent | ff67fbdaffbed2ee5bb5fc43321f0f186e0338c4 (diff) | |
Intermediate changes
commit_hash:c3acea57bb54000045b79aa660d7fca1bed47753
Diffstat (limited to 'contrib/python')
| -rw-r--r-- | contrib/python/responses/py3/.dist-info/METADATA | 2 | ||||
| -rw-r--r-- | contrib/python/responses/py3/responses/__init__.py | 17 | ||||
| -rw-r--r-- | contrib/python/responses/py3/responses/matchers.py | 41 | ||||
| -rw-r--r-- | contrib/python/responses/py3/ya.make | 2 |
4 files changed, 52 insertions, 10 deletions
diff --git a/contrib/python/responses/py3/.dist-info/METADATA b/contrib/python/responses/py3/.dist-info/METADATA index 209bb6c435e..aa5ba35288e 100644 --- a/contrib/python/responses/py3/.dist-info/METADATA +++ b/contrib/python/responses/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: responses -Version: 0.26.0 +Version: 0.26.1 Summary: A utility library for mocking out the `requests` Python library. Home-page: https://github.com/getsentry/responses Author: David Cramer diff --git a/contrib/python/responses/py3/responses/__init__.py b/contrib/python/responses/py3/responses/__init__.py index d719476d259..48ce6580e76 100644 --- a/contrib/python/responses/py3/responses/__init__.py +++ b/contrib/python/responses/py3/responses/__init__.py @@ -39,7 +39,7 @@ from responses.registries import FirstMatchRegistry try: from typing_extensions import Literal except ImportError: # pragma: no cover - from typing import Literal # pragma: no cover + from typing import Literal from io import BufferedReader from io import BytesIO @@ -249,7 +249,9 @@ class CallList(Sequence[Any], Sized): """Overload for scenario when index is provided.""" @overload - def __getitem__(self, idx: "slice[int, int, Optional[int]]") -> List[Call]: + def __getitem__( + self, idx: "slice[Optional[int], Optional[int], Optional[int]]" + ) -> List[Call]: """Overload for scenario when slice is provided.""" def __getitem__(self, idx: Union[int, slice]) -> Union[Call, List[Call]]: @@ -856,12 +858,21 @@ class RequestsMock: for rsp in data["responses"]: rsp = rsp["response"] + headers = rsp["headers"] if "headers" in rsp else None + + if headers is not None and "content_type" in rsp: + headers = { + k: v for k, v in headers.items() if k.lower() != "content-type" + } + if not headers: + headers = None + self.add( method=rsp["method"], url=rsp["url"], body=rsp["body"], status=rsp["status"], - headers=rsp["headers"] if "headers" in rsp else None, + headers=headers, content_type=rsp["content_type"], auto_calculate_content_length=rsp["auto_calculate_content_length"], ) diff --git a/contrib/python/responses/py3/responses/matchers.py b/contrib/python/responses/py3/responses/matchers.py index 40f3a83dde1..c33e9257373 100644 --- a/contrib/python/responses/py3/responses/matchers.py +++ b/contrib/python/responses/py3/responses/matchers.py @@ -21,6 +21,13 @@ from urllib3.util.url import parse_url def _filter_dict_recursively( dict1: Mapping[Any, Any], dict2: Mapping[Any, Any] ) -> Mapping[Any, Any]: + """ + Make a new dictionary using only keys that exist in both + dictionary arguments. It will also work with deeply nested keys. + :param dict1: dictionary to filter + :param dict2: dictionary to filter + :return: new dictionary based on `dict1` and `dict2` + """ filtered_dict = {} for k, val in dict1.items(): if k in dict2: @@ -47,29 +54,53 @@ def body_matcher(params: str, *, allow_blank: bool = False) -> Callable[..., Any def urlencoded_params_matcher( - params: Optional[Mapping[str, str]], *, allow_blank: bool = False + params: Optional[Mapping[str, str]], + *, + allow_blank: bool = False, + strict_match: bool = True, ) -> Callable[..., Any]: """ Matches URL encoded data :param params: (dict) data provided to 'data' arg of request + :param allow_blank If true, blank values are accounted as empty strings + :param strict_match If true, all keys must match; + otherwise, partial matches allowed :return: (func) matcher """ def match(request: PreparedRequest) -> Tuple[bool, str]: reason = "" request_body = request.body - qsl_body = ( + qsl_body: Mapping[Any, Any] = ( dict(parse_qsl(request_body, keep_blank_values=allow_blank)) # type: ignore[type-var] if request_body else {} ) - params_dict = params or {} - valid = params is None if request_body is None else params_dict == qsl_body + request_params = qsl_body + match_params = params or {} + + if not strict_match: + request_params = _filter_dict_recursively(qsl_body, match_params) + + valid = ( + params is None if request_body is None else match_params == request_params + ) + + # Prevents non-strict match of empty params with non-empty + # request body (due to dictionary filtering) + if not params and request_body: + valid = False + if not valid: reason = ( - f"request.body doesn't match: {qsl_body} doesn't match {params_dict}" + f"request.body doesn't match: {qsl_body} doesn't match {match_params}" ) + if strict_match: + reason += ( + "\nNote: You're using strict parameter check. " + "To try a partial match, use strict_match=False" + ) return valid, reason diff --git a/contrib/python/responses/py3/ya.make b/contrib/python/responses/py3/ya.make index 0f2f0b8099b..72d3451c0b9 100644 --- a/contrib/python/responses/py3/ya.make +++ b/contrib/python/responses/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(0.26.0) +VERSION(0.26.1) LICENSE(Apache-2.0) |
