Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use less private imports on the testclient module #2709

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 81 additions & 75 deletions starlette/testclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import warnings
from concurrent.futures import Future
from functools import cached_property
from http.cookiejar import CookieJar
from types import GeneratorType
from urllib.parse import unquote, urljoin

Expand All @@ -25,9 +26,9 @@
from starlette.websockets import WebSocketDisconnect

if sys.version_info >= (3, 10): # pragma: no cover
from typing import TypeGuard
from typing import TypeAlias, TypeGuard
else: # pragma: no cover
from typing_extensions import TypeGuard
from typing_extensions import TypeAlias, TypeGuard

try:
import httpx
Expand All @@ -37,16 +38,29 @@
"You can install this with:\n"
" $ pip install httpx\n"
)


Auth: TypeAlias = "httpx.Auth | tuple[str | bytes, str | bytes]"
QueryParams: TypeAlias = "httpx.QueryParams | typing.Mapping[str, str] | None"
Cookies: TypeAlias = "httpx.Cookies | CookieJar | dict[str, str] | list[tuple[str, str]] | None"
URL: TypeAlias = "httpx.URL | str"
Timeout: TypeAlias = "float | httpx.Timeout | tuple[float | None, float | None, float | None, float | None] | None"
Headers = typing.Union[
httpx.Headers,
typing.Mapping[bytes, bytes],
typing.Mapping[str, str],
typing.Sequence[typing.Tuple[bytes, bytes]],
typing.Sequence[typing.Tuple[str, str]],
None,
]
Comment on lines +43 to +55
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pretty much have to do what httpx is doing on the _client module because I think we want to support the type possibilities that are there...


_PortalFactoryType = typing.Callable[[], typing.ContextManager[anyio.abc.BlockingPortal]]

ASGIInstance = typing.Callable[[Receive, Send], typing.Awaitable[None]]
ASGI2App = typing.Callable[[Scope], ASGIInstance]
ASGI3App = typing.Callable[[Scope, Receive, Send], typing.Awaitable[None]]


_RequestData = typing.Mapping[str, typing.Union[str, typing.Iterable[str], bytes]]


def _is_asgi3(app: ASGI2App | ASGI3App) -> TypeGuard[ASGI3App]:
if inspect.isclass(app):
return hasattr(app, "__await__")
Expand Down Expand Up @@ -76,23 +90,15 @@ def __init__(self, session: WebSocketTestSession) -> None:
self.session = session


class WebSocketDenialResponse( # type: ignore[misc]
httpx.Response,
WebSocketDisconnect,
):
class WebSocketDenialResponse(httpx.Response, WebSocketDisconnect): # type: ignore[misc]
"""
A special case of `WebSocketDisconnect`, raised in the `TestClient` if the
`WebSocket` is closed before being accepted with a `send_denial_response()`.
"""


class WebSocketTestSession:
def __init__(
self,
app: ASGI3App,
scope: Scope,
portal_factory: _PortalFactoryType,
) -> None:
def __init__(self, app: ASGI3App, scope: Scope, portal_factory: _PortalFactoryType) -> None:
self.app = app
self.scope = scope
self.accepted_subprotocol = None
Expand Down Expand Up @@ -464,19 +470,19 @@ def _choose_redirect_arg(
def request( # type: ignore[override]
self,
method: str,
url: httpx._types.URLTypes,
url: URL,
*,
content: httpx._types.RequestContent | None = None,
data: _RequestData | None = None,
files: httpx._types.RequestFiles | None = None,
content: typing.Any = None,
data: typing.Any = None,
files: typing.Any = None,
json: typing.Any = None,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly...

UseClientDefault = type(httpx.USE_CLIENT_DEFAULT)

...

auth: Auth | UseClientDefault = USE_CLIENT_DEFAULT

(I don't much like this style and I'd enjoy cleaning it up, tho would that be sufficient for now?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it works for the type checkers.. Does it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't work.

follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
url = self._merge_url(url)
Expand All @@ -499,15 +505,15 @@ def request( # type: ignore[override]

def get( # type: ignore[override]
self,
url: httpx._types.URLTypes,
url: URL | str,
*,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
Expand All @@ -524,15 +530,15 @@ def get( # type: ignore[override]

def options( # type: ignore[override]
self,
url: httpx._types.URLTypes,
url: URL | str,
*,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
Expand All @@ -549,15 +555,15 @@ def options( # type: ignore[override]

def head( # type: ignore[override]
self,
url: httpx._types.URLTypes,
url: URL | str,
*,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
Expand All @@ -574,19 +580,19 @@ def head( # type: ignore[override]

def post( # type: ignore[override]
self,
url: httpx._types.URLTypes,
url: URL | str,
*,
content: httpx._types.RequestContent | None = None,
data: _RequestData | None = None,
files: httpx._types.RequestFiles | None = None,
content: typing.Any = None,
data: typing.Any = None,
files: typing.Any = None,
json: typing.Any = None,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
Expand All @@ -607,19 +613,19 @@ def post( # type: ignore[override]

def put( # type: ignore[override]
self,
url: httpx._types.URLTypes,
url: URL | str,
*,
content: httpx._types.RequestContent | None = None,
data: _RequestData | None = None,
files: httpx._types.RequestFiles | None = None,
content: typing.Any = None,
data: typing.Any = None,
files: typing.Any = None,
json: typing.Any = None,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
Expand All @@ -640,19 +646,19 @@ def put( # type: ignore[override]

def patch( # type: ignore[override]
self,
url: httpx._types.URLTypes,
url: URL | str,
*,
content: httpx._types.RequestContent | None = None,
data: _RequestData | None = None,
files: httpx._types.RequestFiles | None = None,
content: typing.Any = None,
data: typing.Any = None,
files: typing.Any = None,
json: typing.Any = None,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
Expand All @@ -673,15 +679,15 @@ def patch( # type: ignore[override]

def delete( # type: ignore[override]
self,
url: httpx._types.URLTypes,
url: URL | str,
*,
params: httpx._types.QueryParamTypes | None = None,
headers: httpx._types.HeaderTypes | None = None,
cookies: httpx._types.CookieTypes | None = None,
auth: httpx._types.AuthTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
params: QueryParams | None = None,
headers: Headers | None = None,
cookies: Cookies | None = None,
auth: Auth | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
follow_redirects: bool | None = None,
allow_redirects: bool | None = None,
timeout: httpx._types.TimeoutTypes | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
timeout: Timeout | httpx._client.UseClientDefault = httpx._client.USE_CLIENT_DEFAULT,
extensions: dict[str, typing.Any] | None = None,
) -> httpx.Response:
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
Expand Down
Loading
Loading