Skip to content

Commit 1486479

Browse files
authored
Support HTTPX 0.23.1 (#223)
1 parent bd12f51 commit 1486479

File tree

6 files changed

+54
-15
lines changed

6 files changed

+54
-15
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
max-parallel: 4
1818
matrix:
19-
python-version: ["3.7", "3.8", "3.9", "3.10"]
19+
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
2020
steps:
2121
- uses: actions/checkout@v3
2222
- name: Set up Python ${{ matrix.python-version }}
@@ -35,9 +35,7 @@ jobs:
3535

3636
lint:
3737
name: Check Linting
38-
uses: less-action/reusables/.github/workflows/pre-commit.yaml@v6
39-
with:
40-
python-version: "3.10"
38+
uses: less-action/reusables/.github/workflows/pre-commit.yaml@v8
4139

4240
check-types:
4341
name: Check Typing

.pre-commit-config.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
default_language_version:
2-
python: python3.10
2+
python: python3.11
33
repos:
44
- repo: https://github.com/pre-commit/pre-commit-hooks
55
rev: v4.3.0
@@ -13,14 +13,14 @@ repos:
1313
- id: debug-statements
1414
- id: detect-private-key
1515
- repo: https://github.com/asottile/pyupgrade
16-
rev: v2.37.3
16+
rev: v3.2.2
1717
hooks:
1818
- id: pyupgrade
1919
args:
2020
- --py37-plus
2121
- --keep-runtime-typing
2222
- repo: https://github.com/pycqa/autoflake
23-
rev: v1.6.1
23+
rev: v1.7.7
2424
hooks:
2525
- id: autoflake
2626
args:
@@ -32,7 +32,7 @@ repos:
3232
hooks:
3333
- id: isort
3434
- repo: https://github.com/psf/black
35-
rev: 22.8.0
35+
rev: 22.10.0
3636
hooks:
3737
- id: black
3838
- repo: https://github.com/PyCQA/flake8
@@ -47,7 +47,7 @@ repos:
4747
- flake8-pytest-style
4848
- flake8-datetimez
4949
- repo: https://github.com/sirosen/check-jsonschema
50-
rev: 0.18.2
50+
rev: 0.19.2
5151
hooks:
5252
- id: check-github-workflows
5353
- repo: https://github.com/asottile/yesqa
@@ -62,7 +62,7 @@ repos:
6262
- flake8-pytest-style
6363
- flake8-datetimez
6464
- repo: https://github.com/pre-commit/mirrors-prettier
65-
rev: "v2.7.1"
65+
rev: "v3.0.0-alpha.4"
6666
hooks:
6767
- id: prettier
6868
alias: format-markdown

respx/mocks.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import httpcore
88
import httpx
99

10+
from respx.patterns import parse_url
11+
1012
from .models import AllMockedAssertionError, PassThrough
1113
from .transports import TryTransport
1214

@@ -303,7 +305,7 @@ def to_httpx_request(cls, **kwargs):
303305
)
304306
return httpx.Request(
305307
request.method,
306-
raw_url,
308+
parse_url(raw_url),
307309
headers=request.headers,
308310
stream=request.stream,
309311
extensions=request.extensions,

respx/patterns.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@
2525

2626
import httpx
2727

28-
from .types import CookieTypes, HeaderTypes, QueryParamTypes, URLPatternTypes
28+
from .types import (
29+
URL as RawURL,
30+
CookieTypes,
31+
HeaderTypes,
32+
QueryParamTypes,
33+
URLPatternTypes,
34+
)
2935

3036

3137
class Lookup(Enum):
@@ -448,7 +454,7 @@ class URL(Pattern):
448454
def clean(self, value: URLPatternTypes) -> Union[str, RegexPattern[str]]:
449455
url: Union[str, RegexPattern[str]]
450456
if self.lookup is Lookup.EQUAL and isinstance(value, (str, tuple, httpx.URL)):
451-
_url = httpx.URL(value)
457+
_url = parse_url(value)
452458
_url = self._ensure_path(_url)
453459
url = str(_url)
454460
elif self.lookup is Lookup.REGEX and isinstance(value, str):
@@ -586,6 +592,28 @@ def combine(patterns: Sequence[Pattern], op: Callable = operator.and_) -> Patter
586592
return reduce(op, patterns)
587593

588594

595+
def parse_url(value: Union[httpx.URL, str, RawURL]) -> httpx.URL:
596+
url: Union[httpx.URL, str]
597+
598+
if isinstance(value, tuple):
599+
# Handle "raw" httpcore urls. Borrowed from HTTPX prior to #2241
600+
raw_scheme, raw_host, port, raw_path = value
601+
scheme = raw_scheme.decode("ascii")
602+
host = raw_host.decode("ascii")
603+
if host and ":" in host and host[0] != "[":
604+
# it's an IPv6 address, so it should be enclosed in "[" and "]"
605+
# ref: https://tools.ietf.org/html/rfc2732#section-2
606+
# ref: https://tools.ietf.org/html/rfc3986#section-3.2.2
607+
host = f"[{host}]"
608+
port_str = "" if port is None else f":{port}"
609+
path = raw_path.decode("ascii")
610+
url = f"{scheme}://{host}{port_str}{path}"
611+
else:
612+
url = value
613+
614+
return httpx.URL(url)
615+
616+
589617
def parse_url_patterns(
590618
url: Optional[URLPatternTypes], exact: bool = True
591619
) -> Dict[str, Pattern]:
@@ -596,7 +624,7 @@ def parse_url_patterns(
596624
if isinstance(url, RegexPattern):
597625
return {"url": URL(url, lookup=Lookup.REGEX)}
598626

599-
url = httpx.URL(url)
627+
url = parse_url(url)
600628
scheme_port = get_scheme_port(url.scheme)
601629

602630
if url.scheme and url.scheme != "all":

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"Programming Language :: Python :: 3.8",
2828
"Programming Language :: Python :: 3.9",
2929
"Programming Language :: Python :: 3.10",
30+
"Programming Language :: Python :: 3.11",
3031
],
3132
project_urls={
3233
"GitHub": "https://github.com/lundberg/respx",

tests/test_patterns.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,8 @@ def test_path_pattern():
228228
[
229229
(Lookup.CONTAINS, "", "https://foo.bar/", True),
230230
(Lookup.CONTAINS, "x=1", "https://foo.bar/?x=1", True),
231-
(Lookup.CONTAINS, "x=", "https://foo.bar/?x=1", True), # query, not params
231+
(Lookup.CONTAINS, "x=", "https://foo.bar/?x=1", False), # False by httpx #2354
232+
(Lookup.CONTAINS, "x=", "https://foo.bar/?x=", True),
232233
(Lookup.CONTAINS, "y=2", "https://foo.bar/?x=1", False),
233234
(Lookup.CONTAINS, [("x", "1")], "https://foo.bar/?x=1", True),
234235
(Lookup.CONTAINS, {"x": "1"}, "https://foo.bar/?x=1", True),
@@ -239,6 +240,8 @@ def test_path_pattern():
239240
(Lookup.CONTAINS, [("x", ANY), ("x", "2")], "https://foo.bar/?x=2&x=3", False),
240241
(Lookup.CONTAINS, "x=1&y=2", "https://foo.bar/?x=1", False),
241242
(Lookup.EQUAL, "", "https://foo.bar/", True),
243+
(Lookup.EQUAL, "x", "https://foo.bar/?x", True),
244+
(Lookup.EQUAL, "x=", "https://foo.bar/?x=", True),
242245
(Lookup.EQUAL, "x=1", "https://foo.bar/?x=1", True),
243246
(Lookup.EQUAL, "y=2", "https://foo.bar/?x=1", False),
244247
(Lookup.EQUAL, {"x": ANY}, "https://foo.bar/?x=1", True),
@@ -275,6 +278,13 @@ def test_params_pattern_hash():
275278
(Lookup.EQUAL, "https://a.b/?x=y", {}, "https://a.b?x=y", True),
276279
(Lookup.STARTS_WITH, "https://a.b/b", {}, "https://a.b/baz/", True),
277280
(Lookup.STARTS_WITH, "http://a.b/baz/", {}, "https://a.b/baz/", False),
281+
(
282+
Lookup.EQUAL,
283+
(b"https", b"fake:ipv6", None, b""),
284+
{},
285+
"https://[fake:ipv6]",
286+
True,
287+
),
278288
],
279289
)
280290
def test_url_pattern(lookup, value, context, url, expected):

0 commit comments

Comments
 (0)