Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-starlette for
openSUSE:Factory checked in at 2024-08-15 09:57:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-starlette (Old)
and /work/SRC/openSUSE:Factory/.python-starlette.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-starlette"
Thu Aug 15 09:57:21 2024 rev:25 rq:1193696 version:0.38.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-starlette/python-starlette.changes
2024-04-30 17:26:04.755377224 +0200
+++
/work/SRC/openSUSE:Factory/.python-starlette.new.7232/python-starlette.changes
2024-08-15 09:57:23.376621654 +0200
@@ -1,0 +2,16 @@
+Tue Aug 13 09:41:53 UTC 2024 - Daniel Garcia <[email protected]>
+
+- Update to 0.38.2:
+ * Fix routing.get_name() not to assume all routines have __name__ #2648
+- 0.38.1:
+ * Revert "Add support for ASGI pathsend extension" #2649.
+- 0.38.0:
+ * Allow use of memoryview in StreamingResponse and Response #2576
+ and #2577.
+ * Send 404 instead of 500 when filename requested is too long on
+ StaticFiles #2583.
+ * Fail fast on invalid Jinja2Template instantiation parameters #2568.
+ * Check endpoint handler is async only once #2536.
+ * Add proper synchronization to WebSocketTestSession #2597.
+
+-------------------------------------------------------------------
Old:
----
starlette-0.37.2.tar.gz
New:
----
starlette-0.38.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-starlette.spec ++++++
--- /var/tmp/diff_new_pack.0OI44Y/_old 2024-08-15 09:57:24.180655304 +0200
+++ /var/tmp/diff_new_pack.0OI44Y/_new 2024-08-15 09:57:24.180655304 +0200
@@ -27,7 +27,7 @@
%{?sle15_python_module_pythons}
Name: python-starlette%{psuffix}
-Version: 0.37.2
+Version: 0.38.2
Release: 0
Summary: Lightweight ASGI framework/toolkit
License: BSD-3-Clause
++++++ starlette-0.37.2.tar.gz -> starlette-0.38.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/README.md
new/starlette-0.38.2/README.md
--- old/starlette-0.37.2/README.md 2024-03-05 17:08:44.000000000 +0100
+++ new/starlette-0.38.2/README.md 2024-07-27 19:55:52.000000000 +0200
@@ -45,7 +45,7 @@
$ pip3 install starlette
```
-You'll also want to install an ASGI server, such as
[uvicorn](http://www.uvicorn.org/),
[daphne](https://github.com/django/daphne/), or
[hypercorn](https://pgjones.gitlab.io/hypercorn/).
+You'll also want to install an ASGI server, such as
[uvicorn](http://www.uvicorn.org/),
[daphne](https://github.com/django/daphne/), or
[hypercorn](https://hypercorn.readthedocs.io/en/latest/).
```shell
$ pip3 install uvicorn
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/docs/index.md
new/starlette-0.38.2/docs/index.md
--- old/starlette-0.37.2/docs/index.md 2024-03-05 17:08:44.000000000 +0100
+++ new/starlette-0.38.2/docs/index.md 2024-07-27 19:55:52.000000000 +0200
@@ -46,7 +46,7 @@
$ pip3 install starlette
```
-You'll also want to install an ASGI server, such as
[uvicorn](http://www.uvicorn.org/),
[daphne](https://github.com/django/daphne/), or
[hypercorn](https://pgjones.gitlab.io/hypercorn/).
+You'll also want to install an ASGI server, such as
[uvicorn](http://www.uvicorn.org/),
[daphne](https://github.com/django/daphne/), or
[hypercorn](https://hypercorn.readthedocs.io/en/latest/).
```shell
$ pip3 install uvicorn
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/docs/middleware.md
new/starlette-0.38.2/docs/middleware.md
--- old/starlette-0.37.2/docs/middleware.md 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/docs/middleware.md 2024-07-27 19:55:52.000000000
+0200
@@ -104,8 +104,9 @@
* `session_cookie` - Defaults to "session".
* `max_age` - Session expiry time in seconds. Defaults to 2 weeks. If set to
`None` then the cookie will last as long as the browser session.
* `same_site` - SameSite flag prevents the browser from sending session cookie
along with cross-site requests. Defaults to `'lax'`.
+* `path` - The path set for the session cookie. Defaults to `'/'`.
* `https_only` - Indicate that Secure flag should be set (can be used with
HTTPS only). Defaults to `False`.
-* `domain` - Domain of the cookie used to share cookie between subdomains or
cross-domains. The browser defaults the domain to the same host that set the
cookie, excluding subdomains
[refrence](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#domain_attribute).
+* `domain` - Domain of the cookie used to share cookie between subdomains or
cross-domains. The browser defaults the domain to the same host that set the
cookie, excluding subdomains
([reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#domain_attribute)).
```python
@@ -167,6 +168,7 @@
* `allowed_hosts` - A list of domain names that should be allowed as
hostnames. Wildcard
domains such as `*.example.com` are supported for matching subdomains. To
allow any
hostname either use `allowed_hosts=["*"]` or omit the middleware.
+* `www_redirect` - If set to True, requests to non-www versions of the allowed
hosts will be redirected to their www counterparts. Defaults to `True`.
If an incoming request does not validate correctly then a 400 response will be
sent.
@@ -185,7 +187,7 @@
routes = ...
middleware = [
- Middleware(GZipMiddleware, minimum_size=1000)
+ Middleware(GZipMiddleware, minimum_size=1000, compresslevel=9)
]
app = Starlette(routes=routes, middleware=middleware)
@@ -194,6 +196,7 @@
The following arguments are supported:
* `minimum_size` - Do not GZip responses that are smaller than this minimum
size in bytes. Defaults to `500`.
+* `compresslevel` - Used during GZip compression. It is an integer ranging
from 1 to 9. Defaults to `9`. Lower value results in faster compression but
larger file sizes, while higher value results in slower compression but smaller
file sizes.
The middleware won't GZip responses that already have a `Content-Encoding`
set, to prevent them from being encoded twice.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/docs/release-notes.md
new/starlette-0.38.2/docs/release-notes.md
--- old/starlette-0.37.2/docs/release-notes.md 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/docs/release-notes.md 2024-07-27 19:55:52.000000000
+0200
@@ -1,3 +1,38 @@
+## 0.38.2
+
+July 27, 2024
+
+#### Fixed
+
+* Not assume all routines have `__name__` on `routing.get_name()`
[#2648](https://github.com/encode/starlette/pull/2648).
+
+## 0.38.1
+
+July 23, 2024
+
+#### Removed
+
+* Revert "Add support for ASGI pathsend extension"
[#2649](https://github.com/encode/starlette/pull/2649).
+
+## 0.38.0
+
+July 20, 2024
+
+#### Added
+
+* Allow use of `memoryview` in `StreamingResponse` and `Response`
[#2576](https://github.com/encode/starlette/pull/2576)
+ and [#2577](https://github.com/encode/starlette/pull/2577).
+* Send 404 instead of 500 when filename requested is too long on `StaticFiles`
[#2583](https://github.com/encode/starlette/pull/2583).
+
+#### Changed
+
+* Fail fast on invalid `Jinja2Template` instantiation parameters
[#2568](https://github.com/encode/starlette/pull/2568).
+* Check endpoint handler is async only once
[#2536](https://github.com/encode/starlette/pull/2536).
+
+#### Fixed
+
+* Add proper synchronization to `WebSocketTestSession`
[#2597](https://github.com/encode/starlette/pull/2597).
+
## 0.37.2
March 5, 2024
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/docs/requests.md
new/starlette-0.38.2/docs/requests.md
--- old/starlette-0.37.2/docs/requests.md 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/docs/requests.md 2024-07-27 19:55:52.000000000
+0200
@@ -60,8 +60,7 @@
#### Client Address
-The client's remote address is exposed as a named two-tuple `request.client`.
-Either item in the tuple may be `None`.
+The client's remote address is exposed as a named two-tuple `request.client`
(or `None`).
The hostname or IP address: `request.client.host`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/docs/third-party-packages.md
new/starlette-0.38.2/docs/third-party-packages.md
--- old/starlette-0.37.2/docs/third-party-packages.md 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/docs/third-party-packages.md 2024-07-27
19:55:52.000000000 +0200
@@ -66,6 +66,13 @@
Document your REST API built with Starlette by declaring OpenAPI (Swagger)
schemas in YAML format in your endpoint's docstrings.
+### Starlette Compress
+
+<a href="https://github.com/Zaczero/starlette-compress"
target="_blank">GitHub</a>
+
+Starlette-Compress is a fast and simple middleware for compressing responses
in Starlette.
+It adds ZStd, Brotli, and GZip compression support with sensible default
configuration.
+
### Starlette Context
<a href="https://github.com/tomwojcik/starlette-context"
target="_blank">GitHub</a>
@@ -148,6 +155,12 @@
to quickly generate fully customizable admin interface for your models. You
can export your data to many formats (*CSV*, *PDF*,
*Excel*, etc), filter your data with complex query including `AND` and `OR`
conditions, upload files, ...
+### Vellox
+
+<a href="https://github.com/junah201/vellox" target="_blank">GitHub</a>
+
+Serverless ASGI adapter for GCP Cloud Functions.
+
## Starlette Bridge
<a href="https://github.com/tarsil/starlette-bridge"
target="_blank">GitHub</a> |
@@ -168,17 +181,6 @@
High performance, easy to learn, fast to code, ready for production web API
framework.
Inspired by **APIStar**'s previous server system with type declarations for
route parameters, based on the OpenAPI specification version 3.0.0+ (with JSON
Schema), powered by **Pydantic** for the data handling.
-### Esmerald
-
-<a href="https://github.com/dymmond/esmerald" target="_blank">GitHub</a> |
-<a href="https://www.esmerald.dev" target="_blank">Documentation</a>
-
-Highly scalable, performant, easy to learn, easy to code and for every
application web framework.
-Inspired by a lot of frameworks out there, Esmerald provides what every
application needs, from the
-smallest to complex. Includes, routes, middlewares, permissions, scheduler,
interceptors and lot more.
-
-Powered by **Starlette** and **Pydantic** with OpenAPI specification.
-
### Flama
<a href="https://github.com/vortico/flama" target="_blank">GitHub</a> |
@@ -258,3 +260,10 @@
<a href="https://docs.sentry.io/platforms/python/guides/starlette/"
target="_blank">Documentation</a>
Sentry is a software error detection tool. It offers actionable insights for
resolving performance issues and errors, allowing users to diagnose, fix, and
optimize Python debugging. Additionally, it integrates seamlessly with
Starlette for Python application development. Sentry's capabilities include
error tracking, performance insights, contextual information, and
alerts/notifications.
+
+### Shiny
+
+<a href="https://github.com/posit-dev/py-shiny" target="_blank">GitHub</a> |
+<a href="https://shiny.posit.co/py/" target="_blank">Documentation</a>
+
+Leveraging Starlette and asyncio, Shiny allows developers to create effortless
Python web applications using the power of reactive programming. Shiny
eliminates the hassle of manual state management, automatically determining the
best execution path for your app at runtime while simultaneously minimizing
re-rendering. This means that Shiny can support everything from the simplest
dashboard to full-featured web apps.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/pyproject.toml
new/starlette-0.38.2/pyproject.toml
--- old/starlette-0.37.2/pyproject.toml 2024-03-05 17:08:44.000000000 +0100
+++ new/starlette-0.38.2/pyproject.toml 2024-07-27 19:55:52.000000000 +0200
@@ -51,6 +51,7 @@
[tool.ruff.lint]
select = ["E", "F", "I", "FA", "UP"]
+ignore = ["UP031"]
[tool.ruff.lint.isort]
combine-as-imports = true
@@ -65,7 +66,7 @@
implicit_optional = true
[tool.pytest.ini_options]
-addopts = "-rxXs --strict-config --strict-markers"
+addopts = "-rXs --strict-config --strict-markers"
xfail_strict = true
filterwarnings = [
# Turn warnings that aren't filtered into exceptions
@@ -78,6 +79,8 @@
"ignore: The `allow_redirects` argument is deprecated. Use
`follow_redirects` instead.:DeprecationWarning",
"ignore: 'cgi' is deprecated and slated for removal in Python
3.13:DeprecationWarning",
"ignore: You seem to already have a custom sys.excepthook handler
installed. I'll skip installing Trio's custom handler, but this means
MultiErrors will not show full tracebacks.:RuntimeWarning",
+ # TODO: This warning appeared when we bumped anyio to 4.4.0.
+ "ignore: Unclosed .MemoryObject(Send|Receive)Stream.:ResourceWarning",
]
[tool.coverage.run]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/requirements.txt
new/starlette-0.38.2/requirements.txt
--- old/starlette-0.37.2/requirements.txt 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/requirements.txt 2024-07-27 19:55:52.000000000
+0200
@@ -1,23 +1,26 @@
# Optionals
-e .[full]
+# TODO: We need to delete the following line when fixing the test suite for
anyio 4.4.0.
+anyio==4.4.0
+
# Testing
-coverage==7.4.3
-importlib-metadata==7.0.1
-mypy==1.8.0
-ruff==0.1.15
-typing_extensions==4.10.0
+coverage==7.5.4
+importlib-metadata==8.0.0
+mypy==1.10.1
+ruff==0.5.0
+typing_extensions==4.12.2
types-contextvars==2.4.7.3
-types-PyYAML==6.0.12.12
+types-PyYAML==6.0.12.20240311
types-dataclasses==0.6.6
-pytest==8.0.2
-trio==0.24.0
+pytest==8.2.2
+trio==0.25.1
# Documentation
-mkdocs==1.5.3
-mkdocs-material==9.5.12
+mkdocs==1.6.0
+mkdocs-material==9.5.27
mkautodoc==0.2.0
# Packaging
-build==1.1.1
-twine==5.0.0
+build==1.2.1
+twine==5.1.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/scripts/check
new/starlette-0.38.2/scripts/check
--- old/starlette-0.37.2/scripts/check 2024-03-05 17:08:44.000000000 +0100
+++ new/starlette-0.38.2/scripts/check 2024-07-27 19:55:52.000000000 +0200
@@ -10,7 +10,5 @@
./scripts/sync-version
${PREFIX}ruff format --check --diff $SOURCE_FILES
-# TODO: Use `[[tool.mypy.overrides]]` on the `pyproject.toml` when the mypy
issue is solved:
-# github.com/python/mypy/issues/10045. Check
github.com/encode/starlette/pull/2180 for more info.
${PREFIX}mypy $SOURCE_FILES
${PREFIX}ruff check $SOURCE_FILES
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/scripts/lint
new/starlette-0.38.2/scripts/lint
--- old/starlette-0.37.2/scripts/lint 2024-03-05 17:08:44.000000000 +0100
+++ new/starlette-0.38.2/scripts/lint 2024-07-27 19:55:52.000000000 +0200
@@ -9,4 +9,4 @@
set -x
${PREFIX}ruff format $SOURCE_FILES
-${PREFIX}ruff --fix $SOURCE_FILES
+${PREFIX}ruff check --fix $SOURCE_FILES
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/__init__.py
new/starlette-0.38.2/starlette/__init__.py
--- old/starlette-0.37.2/starlette/__init__.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/starlette/__init__.py 2024-07-27 19:55:52.000000000
+0200
@@ -1 +1 @@
-__version__ = "0.37.2"
+__version__ = "0.38.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/_utils.py
new/starlette-0.38.2/starlette/_utils.py
--- old/starlette-0.37.2/starlette/_utils.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/starlette/_utils.py 2024-07-27 19:55:52.000000000
+0200
@@ -26,13 +26,11 @@
@typing.overload
-def is_async_callable(obj: AwaitableCallable[T]) ->
TypeGuard[AwaitableCallable[T]]:
- ...
+def is_async_callable(obj: AwaitableCallable[T]) ->
TypeGuard[AwaitableCallable[T]]: ...
@typing.overload
-def is_async_callable(obj: typing.Any) ->
TypeGuard[AwaitableCallable[typing.Any]]:
- ...
+def is_async_callable(obj: typing.Any) ->
TypeGuard[AwaitableCallable[typing.Any]]: ...
def is_async_callable(obj: typing.Any) -> typing.Any:
@@ -49,13 +47,11 @@
class AwaitableOrContextManager(
typing.Awaitable[T_co], typing.AsyncContextManager[T_co],
typing.Protocol[T_co]
-):
- ...
+): ...
class SupportsAsyncClose(typing.Protocol):
- async def close(self) -> None:
- ... # pragma: no cover
+ async def close(self) -> None: ... # pragma: no cover
SupportsAsyncCloseType = typing.TypeVar(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/config.py
new/starlette-0.38.2/starlette/config.py
--- old/starlette-0.37.2/starlette/config.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/starlette/config.py 2024-07-27 19:55:52.000000000
+0200
@@ -68,16 +68,13 @@
self.file_values = self._read_file(env_file)
@typing.overload
- def __call__(self, key: str, *, default: None) -> str | None:
- ...
+ def __call__(self, key: str, *, default: None) -> str | None: ...
@typing.overload
- def __call__(self, key: str, cast: type[T], default: T = ...) -> T:
- ...
+ def __call__(self, key: str, cast: type[T], default: T = ...) -> T: ...
@typing.overload
- def __call__(self, key: str, cast: type[str] = ..., default: str = ...) ->
str:
- ...
+ def __call__(self, key: str, cast: type[str] = ..., default: str = ...) ->
str: ...
@typing.overload
def __call__(
@@ -85,12 +82,12 @@
key: str,
cast: typing.Callable[[typing.Any], T] = ...,
default: typing.Any = ...,
- ) -> T:
- ...
+ ) -> T: ...
@typing.overload
- def __call__(self, key: str, cast: type[str] = ..., default: T = ...) -> T
| str:
- ...
+ def __call__(
+ self, key: str, cast: type[str] = ..., default: T = ...
+ ) -> T | str: ...
def __call__(
self,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/middleware/__init__.py
new/starlette-0.38.2/starlette/middleware/__init__.py
--- old/starlette-0.37.2/starlette/middleware/__init__.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/starlette/middleware/__init__.py 2024-07-27
19:55:52.000000000 +0200
@@ -14,11 +14,13 @@
class _MiddlewareClass(Protocol[P]):
- def __init__(self, app: ASGIApp, *args: P.args, **kwargs: P.kwargs) ->
None:
- ... # pragma: no cover
+ def __init__(
+ self, app: ASGIApp, *args: P.args, **kwargs: P.kwargs
+ ) -> None: ... # pragma: no cover
- async def __call__(self, scope: Scope, receive: Receive, send: Send) ->
None:
- ... # pragma: no cover
+ async def __call__(
+ self, scope: Scope, receive: Receive, send: Send
+ ) -> None: ... # pragma: no cover
class Middleware:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/requests.py
new/starlette-0.38.2/starlette/requests.py
--- old/starlette-0.37.2/starlette/requests.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/starlette/requests.py 2024-07-27 19:55:52.000000000
+0200
@@ -145,7 +145,7 @@
@property
def client(self) -> Address | None:
- # client is a 2 item tuple of (host, port), None or missing
+ # client is a 2 item tuple of (host, port), None if missing
host_port = self.scope.get("client")
if host_port is not None:
return Address(*host_port)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/responses.py
new/starlette-0.38.2/starlette/responses.py
--- old/starlette-0.37.2/starlette/responses.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/starlette/responses.py 2024-07-27 19:55:52.000000000
+0200
@@ -41,10 +41,10 @@
self.body = self.render(content)
self.init_headers(headers)
- def render(self, content: typing.Any) -> bytes:
+ def render(self, content: typing.Any) -> bytes | memoryview:
if content is None:
return b""
- if isinstance(content, bytes):
+ if isinstance(content, (bytes, memoryview)):
return content
return content.encode(self.charset) # type: ignore
@@ -94,7 +94,7 @@
value: str = "",
max_age: int | None = None,
expires: datetime | str | int | None = None,
- path: str = "/",
+ path: str | None = "/",
domain: str | None = None,
secure: bool = False,
httponly: bool = False,
@@ -207,7 +207,7 @@
self.headers["location"] = quote(str(url), safe=":/%#?=@[]!$&'()*+,;")
-Content = typing.Union[str, bytes]
+Content = typing.Union[str, bytes, memoryview]
SyncContentStream = typing.Iterable[Content]
AsyncContentStream = typing.AsyncIterable[Content]
ContentStream = typing.Union[AsyncContentStream, SyncContentStream]
@@ -248,7 +248,7 @@
}
)
async for chunk in self.body_iterator:
- if not isinstance(chunk, bytes):
+ if not isinstance(chunk, (bytes, memoryview)):
chunk = chunk.encode(self.charset)
await send({"type": "http.response.body", "body": chunk,
"more_body": True})
@@ -299,12 +299,10 @@
if self.filename is not None:
content_disposition_filename = quote(self.filename)
if content_disposition_filename != self.filename:
- content_disposition = "{}; filename*=utf-8''{}".format(
- content_disposition_type, content_disposition_filename
- )
+ content_disposition = f"{content_disposition_type};
filename*=utf-8''{content_disposition_filename}" # noqa: E501
else:
- content_disposition = '{}; filename="{}"'.format(
- content_disposition_type, self.filename
+ content_disposition = (
+ f'{content_disposition_type}; filename="{self.filename}"'
)
self.headers.setdefault("content-disposition", content_disposition)
self.stat_result = stat_result
@@ -341,8 +339,6 @@
)
if scope["method"].upper() == "HEAD":
await send({"type": "http.response.body", "body": b"",
"more_body": False})
- elif "extensions" in scope and "http.response.pathsend" in
scope["extensions"]:
- await send({"type": "http.response.pathsend", "path":
str(self.path)})
else:
async with await anyio.open_file(self.path, mode="rb") as file:
more_body = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/routing.py
new/starlette-0.38.2/starlette/routing.py
--- old/starlette-0.37.2/starlette/routing.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/starlette/routing.py 2024-07-27 19:55:52.000000000
+0200
@@ -63,15 +63,15 @@
Takes a function or coroutine `func(request) -> response`,
and returns an ASGI application.
"""
+ f: typing.Callable[[Request], typing.Awaitable[Response]] = (
+ func if is_async_callable(func) else
functools.partial(run_in_threadpool, func) # type:ignore
+ )
async def app(scope: Scope, receive: Receive, send: Send) -> None:
request = Request(scope, receive, send)
async def app(scope: Scope, receive: Receive, send: Send) -> None:
- if is_async_callable(func):
- response = await func(request)
- else:
- response = await run_in_threadpool(func, request)
+ response = await f(request)
await response(scope, receive, send)
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
@@ -99,9 +99,7 @@
def get_name(endpoint: typing.Callable[..., typing.Any]) -> str:
- if inspect.isroutine(endpoint) or inspect.isclass(endpoint):
- return endpoint.__name__
- return endpoint.__class__.__name__
+ return getattr(endpoint, "__name__", endpoint.__class__.__name__)
def replace_params(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/staticfiles.py
new/starlette-0.38.2/starlette/staticfiles.py
--- old/starlette-0.37.2/starlette/staticfiles.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/starlette/staticfiles.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,5 +1,6 @@
from __future__ import annotations
+import errno
import importlib.util
import os
import stat
@@ -124,8 +125,12 @@
)
except PermissionError:
raise HTTPException(status_code=401)
- except OSError:
- raise
+ except OSError as exc:
+ # Filename is too long, so it can't be a valid static file.
+ if exc.errno == errno.ENAMETOOLONG:
+ raise HTTPException(status_code=404)
+
+ raise exc
if stat_result and stat.S_ISREG(stat_result.st_mode):
# We have a static file to serve.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/status.py
new/starlette-0.38.2/starlette/status.py
--- old/starlette-0.37.2/starlette/status.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/starlette/status.py 2024-07-27 19:55:52.000000000
+0200
@@ -5,6 +5,7 @@
And RFC 2324 - https://tools.ietf.org/html/rfc2324
"""
+
from __future__ import annotations
import warnings
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/templating.py
new/starlette-0.38.2/starlette/templating.py
--- old/starlette-0.37.2/starlette/templating.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/starlette/templating.py 2024-07-27
19:55:52.000000000 +0200
@@ -66,15 +66,12 @@
@typing.overload
def __init__(
self,
- directory: str
- | PathLike[typing.AnyStr]
- | typing.Sequence[str | PathLike[typing.AnyStr]],
+ directory: str | PathLike[str] | typing.Sequence[str | PathLike[str]],
*,
context_processors: list[typing.Callable[[Request], dict[str,
typing.Any]]]
| None = None,
**env_options: typing.Any,
- ) -> None:
- ...
+ ) -> None: ...
@typing.overload
def __init__(
@@ -83,14 +80,13 @@
env: jinja2.Environment,
context_processors: list[typing.Callable[[Request], dict[str,
typing.Any]]]
| None = None,
- ) -> None:
- ...
+ ) -> None: ...
def __init__(
self,
directory: str
- | PathLike[typing.AnyStr]
- | typing.Sequence[str | PathLike[typing.AnyStr]]
+ | PathLike[str]
+ | typing.Sequence[str | PathLike[str]]
| None = None,
*,
context_processors: list[typing.Callable[[Request], dict[str,
typing.Any]]]
@@ -104,7 +100,9 @@
DeprecationWarning,
)
assert jinja2 is not None, "jinja2 must be installed to use
Jinja2Templates"
- assert directory or env, "either 'directory' or 'env' arguments must
be passed"
+ assert bool(directory) ^ bool(
+ env
+ ), "either 'directory' or 'env' arguments must be passed"
self.context_processors = context_processors or []
if directory is not None:
self.env = self._create_env(directory, **env_options)
@@ -115,9 +113,7 @@
def _create_env(
self,
- directory: str
- | PathLike[typing.AnyStr]
- | typing.Sequence[str | PathLike[typing.AnyStr]],
+ directory: str | PathLike[str] | typing.Sequence[str | PathLike[str]],
**env_options: typing.Any,
) -> jinja2.Environment:
loader = jinja2.FileSystemLoader(directory)
@@ -152,8 +148,7 @@
headers: typing.Mapping[str, str] | None = None,
media_type: str | None = None,
background: BackgroundTask | None = None,
- ) -> _TemplateResponse:
- ...
+ ) -> _TemplateResponse: ...
@typing.overload
def TemplateResponse(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/starlette/testclient.py
new/starlette-0.38.2/starlette/testclient.py
--- old/starlette-0.37.2/starlette/testclient.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/starlette/testclient.py 2024-07-27
19:55:52.000000000 +0200
@@ -160,7 +160,8 @@
async def _asgi_receive(self) -> Message:
while self._receive_queue.empty():
- await anyio.sleep(0)
+ self._queue_event = anyio.Event()
+ await self._queue_event.wait()
return self._receive_queue.get()
async def _asgi_send(self, message: Message) -> None:
@@ -189,6 +190,8 @@
def send(self, message: Message) -> None:
self._receive_queue.put(message)
+ if hasattr(self, "_queue_event"):
+ self.portal.start_task_soon(self._queue_event.set)
def send_text(self, data: str) -> None:
self.send({"type": "websocket.receive", "text": data})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/conftest.py
new/starlette-0.38.2/tests/conftest.py
--- old/starlette-0.37.2/tests/conftest.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/tests/conftest.py 2024-07-27 19:55:52.000000000
+0200
@@ -1,13 +1,12 @@
from __future__ import annotations
import functools
-from typing import Any, Callable, Literal
+from typing import Any, Literal
import pytest
from starlette.testclient import TestClient
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
@pytest.fixture
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/middleware/test_base.py
new/starlette-0.38.2/tests/middleware/test_base.py
--- old/starlette-0.37.2/tests/middleware/test_base.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_base.py 2024-07-27
19:55:52.000000000 +0200
@@ -5,7 +5,6 @@
from typing import (
Any,
AsyncGenerator,
- Callable,
Generator,
)
@@ -23,8 +22,7 @@
from starlette.testclient import TestClient
from starlette.types import ASGIApp, Message, Receive, Scope, Send
from starlette.websockets import WebSocket
-
-TestClientFactory = Callable[[ASGIApp], TestClient]
+from tests.types import TestClientFactory
class CustomMiddleware(BaseHTTPMiddleware):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/middleware/test_cors.py
new/starlette-0.38.2/tests/middleware/test_cors.py
--- old/starlette-0.37.2/tests/middleware/test_cors.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_cors.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,15 +1,10 @@
-from typing import Callable
-
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.responses import PlainTextResponse
from starlette.routing import Route
-from starlette.testclient import TestClient
-from starlette.types import ASGIApp
-
-TestClientFactory = Callable[[ASGIApp], TestClient]
+from tests.types import TestClientFactory
def test_cors_allow_all(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/middleware/test_errors.py
new/starlette-0.38.2/tests/middleware/test_errors.py
--- old/starlette-0.37.2/tests/middleware/test_errors.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_errors.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,4 +1,4 @@
-from typing import Any, Callable
+from typing import Any
import pytest
@@ -8,10 +8,8 @@
from starlette.requests import Request
from starlette.responses import JSONResponse, Response
from starlette.routing import Route
-from starlette.testclient import TestClient
from starlette.types import Receive, Scope, Send
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_handler(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/middleware/test_gzip.py
new/starlette-0.38.2/tests/middleware/test_gzip.py
--- old/starlette-0.37.2/tests/middleware/test_gzip.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_gzip.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,15 +1,10 @@
-from typing import Callable
-
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.gzip import GZipMiddleware
from starlette.requests import Request
from starlette.responses import ContentStream, PlainTextResponse,
StreamingResponse
from starlette.routing import Route
-from starlette.testclient import TestClient
-from starlette.types import ASGIApp
-
-TestClientFactory = Callable[[ASGIApp], TestClient]
+from tests.types import TestClientFactory
def test_gzip_responses(test_client_factory: TestClientFactory) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/starlette-0.37.2/tests/middleware/test_https_redirect.py
new/starlette-0.38.2/tests/middleware/test_https_redirect.py
--- old/starlette-0.37.2/tests/middleware/test_https_redirect.py
2024-03-05 17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_https_redirect.py
2024-07-27 19:55:52.000000000 +0200
@@ -1,14 +1,10 @@
-from typing import Callable
-
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
from starlette.requests import Request
from starlette.responses import PlainTextResponse
from starlette.routing import Route
-from starlette.testclient import TestClient
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_https_redirect_middleware(test_client_factory: TestClientFactory) ->
None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/middleware/test_session.py
new/starlette-0.38.2/tests/middleware/test_session.py
--- old/starlette-0.37.2/tests/middleware/test_session.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_session.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,5 +1,4 @@
import re
-from typing import Callable
from starlette.applications import Starlette
from starlette.middleware import Middleware
@@ -8,8 +7,7 @@
from starlette.responses import JSONResponse
from starlette.routing import Mount, Route
from starlette.testclient import TestClient
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def view_session(request: Request) -> JSONResponse:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/starlette-0.37.2/tests/middleware/test_trusted_host.py
new/starlette-0.38.2/tests/middleware/test_trusted_host.py
--- old/starlette-0.37.2/tests/middleware/test_trusted_host.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_trusted_host.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,14 +1,10 @@
-from typing import Callable
-
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.trustedhost import TrustedHostMiddleware
from starlette.requests import Request
from starlette.responses import PlainTextResponse
from starlette.routing import Route
-from starlette.testclient import TestClient
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_trusted_host_middleware(test_client_factory: TestClientFactory) ->
None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/middleware/test_wsgi.py
new/starlette-0.38.2/tests/middleware/test_wsgi.py
--- old/starlette-0.37.2/tests/middleware/test_wsgi.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/middleware/test_wsgi.py 2024-07-27
19:55:52.000000000 +0200
@@ -5,10 +5,9 @@
from starlette._utils import collapse_excgroups
from starlette.middleware.wsgi import WSGIMiddleware, build_environ
-from starlette.testclient import TestClient
+from tests.types import TestClientFactory
WSGIResponse = Iterable[bytes]
-TestClientFactory = Callable[..., TestClient]
StartResponse = Callable[..., Any]
Environment = Dict[str, Any]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test__utils.py
new/starlette-0.38.2/tests/test__utils.py
--- old/starlette-0.37.2/tests/test__utils.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/tests/test__utils.py 2024-07-27 19:55:52.000000000
+0200
@@ -5,22 +5,18 @@
def test_async_func() -> None:
- async def async_func() -> None:
- ... # pragma: no cover
+ async def async_func() -> None: ... # pragma: no cover
- def func() -> None:
- ... # pragma: no cover
+ def func() -> None: ... # pragma: no cover
assert is_async_callable(async_func)
assert not is_async_callable(func)
def test_async_partial() -> None:
- async def async_func(a: Any, b: Any) -> None:
- ... # pragma: no cover
+ async def async_func(a: Any, b: Any) -> None: ... # pragma: no cover
- def func(a: Any, b: Any) -> None:
- ... # pragma: no cover
+ def func(a: Any, b: Any) -> None: ... # pragma: no cover
partial = functools.partial(async_func, 1)
assert is_async_callable(partial)
@@ -31,12 +27,10 @@
def test_async_method() -> None:
class Async:
- async def method(self) -> None:
- ... # pragma: no cover
+ async def method(self) -> None: ... # pragma: no cover
class Sync:
- def method(self) -> None:
- ... # pragma: no cover
+ def method(self) -> None: ... # pragma: no cover
assert is_async_callable(Async().method)
assert not is_async_callable(Sync().method)
@@ -44,12 +38,10 @@
def test_async_object_call() -> None:
class Async:
- async def __call__(self) -> None:
- ... # pragma: no cover
+ async def __call__(self) -> None: ... # pragma: no cover
class Sync:
- def __call__(self) -> None:
- ... # pragma: no cover
+ def __call__(self) -> None: ... # pragma: no cover
assert is_async_callable(Async())
assert not is_async_callable(Sync())
@@ -61,16 +53,14 @@
self,
a: Any,
b: Any,
- ) -> None:
- ... # pragma: no cover
+ ) -> None: ... # pragma: no cover
class Sync:
def __call__(
self,
a: Any,
b: Any,
- ) -> None:
- ... # pragma: no cover
+ ) -> None: ... # pragma: no cover
partial = functools.partial(Async(), 1)
assert is_async_callable(partial)
@@ -83,8 +73,7 @@
async def async_func(
a: Any,
b: Any,
- ) -> None:
- ... # pragma: no cover
+ ) -> None: ... # pragma: no cover
partial = functools.partial(async_func, b=2)
nested_partial = functools.partial(partial, a=1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_applications.py
new/starlette-0.38.2/tests/test_applications.py
--- old/starlette-0.37.2/tests/test_applications.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_applications.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,7 +1,7 @@
import os
from contextlib import asynccontextmanager
from pathlib import Path
-from typing import AsyncGenerator, AsyncIterator, Callable, Generator
+from typing import AsyncGenerator, AsyncIterator, Generator
import anyio
import pytest
@@ -20,8 +20,7 @@
from starlette.testclient import TestClient
from starlette.types import ASGIApp, Receive, Scope, Send
from starlette.websockets import WebSocket
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
async def error_500(request: Request, exc: HTTPException) -> JSONResponse:
@@ -463,8 +462,7 @@
async def middleware(
request: Request, call_next: RequestResponseEndpoint
- ) -> None:
- ... # pragma: no cover
+ ) -> None: ... # pragma: no cover
app.middleware("http")(middleware)
assert len(record) == 1
@@ -494,8 +492,7 @@
)
) as record:
- async def startup() -> None:
- ... # pragma: no cover
+ async def startup() -> None: ... # pragma: no cover
app.on_event("startup")(startup)
assert len(record) == 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_authentication.py
new/starlette-0.38.2/tests/test_authentication.py
--- old/starlette-0.37.2/tests/test_authentication.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_authentication.py 2024-07-27
19:55:52.000000000 +0200
@@ -21,10 +21,9 @@
from starlette.requests import HTTPConnection, Request
from starlette.responses import JSONResponse, Response
from starlette.routing import Route, WebSocketRoute
-from starlette.testclient import TestClient
from starlette.websockets import WebSocket, WebSocketDisconnect
+from tests.types import TestClientFactory
-TestClientFactory = Callable[..., TestClient]
AsyncEndpoint = Callable[..., Awaitable[Response]]
SyncEndpoint = Callable[..., Response]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_background.py
new/starlette-0.38.2/tests/test_background.py
--- old/starlette-0.37.2/tests/test_background.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_background.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,13 +1,9 @@
-from typing import Callable
-
import pytest
from starlette.background import BackgroundTask, BackgroundTasks
from starlette.responses import Response
-from starlette.testclient import TestClient
from starlette.types import Receive, Scope, Send
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_async_task(test_client_factory: TestClientFactory) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_concurrency.py
new/starlette-0.38.2/tests/test_concurrency.py
--- old/starlette-0.37.2/tests/test_concurrency.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_concurrency.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,5 +1,5 @@
from contextvars import ContextVar
-from typing import Callable, Iterator
+from typing import Iterator
import anyio
import pytest
@@ -9,9 +9,7 @@
from starlette.requests import Request
from starlette.responses import Response
from starlette.routing import Route
-from starlette.testclient import TestClient
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
@pytest.mark.anyio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_convertors.py
new/starlette-0.38.2/tests/test_convertors.py
--- old/starlette-0.37.2/tests/test_convertors.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_convertors.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,5 +1,5 @@
from datetime import datetime
-from typing import Callable, Iterator
+from typing import Iterator
import pytest
@@ -8,9 +8,7 @@
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route, Router
-from starlette.testclient import TestClient
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
@pytest.fixture(scope="module", autouse=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_datastructures.py
new/starlette-0.38.2/tests/test_datastructures.py
--- old/starlette-0.37.2/tests/test_datastructures.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_datastructures.py 2024-07-27
19:55:52.000000000 +0200
@@ -58,6 +58,9 @@
url = URL("http://u:p@host:80")
assert url.replace(port=88) == URL("http://u:p@host:88")
+ url = URL("http://host:80")
+ assert url.replace(username="u") == URL("http://u@host:80")
+
def test_url_query_params() -> None:
u = URL("https://example.org/path/?page=3")
@@ -70,6 +73,10 @@
assert str(u) == "https://example.org/path/?order=name"
u = u.remove_query_params("order")
assert str(u) == "https://example.org/path/"
+ u = u.include_query_params(page=4, search="testing")
+ assert str(u) == "https://example.org/path/?page=4&search=testing"
+ u = u.remove_query_params(["page", "search"])
+ assert str(u) == "https://example.org/path/"
def test_hidden_password() -> None:
@@ -138,6 +145,21 @@
assert u == "https://example.org/path/to/somewhere?abc=123"
assert repr(u) == "URL('https://example.org/path/to/somewhere?abc=123')"
+ u = URL(
+ scope={
+ "scheme": "http",
+ "path": "/some/path",
+ "query_string": b"query=string",
+ "headers": [
+ (b"content-type", b"text/html"),
+ (b"host", b"example.com:8000"),
+ (b"accept", b"text/html"),
+ ],
+ }
+ )
+ assert u == "http://example.com:8000/some/path?query=string"
+ assert repr(u) == "URL('http://example.com:8000/some/path?query=string')"
+
def test_headers() -> None:
h = Headers(raw=[(b"a", b"123"), (b"a", b"456"), (b"b", b"789")])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_endpoints.py
new/starlette-0.38.2/tests/test_endpoints.py
--- old/starlette-0.37.2/tests/test_endpoints.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_endpoints.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,4 +1,4 @@
-from typing import Callable, Iterator
+from typing import Iterator
import pytest
@@ -8,8 +8,7 @@
from starlette.routing import Route, Router
from starlette.testclient import TestClient
from starlette.websockets import WebSocket
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
class Homepage(HTTPEndpoint):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_exceptions.py
new/starlette-0.38.2/tests/test_exceptions.py
--- old/starlette-0.37.2/tests/test_exceptions.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_exceptions.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,5 +1,5 @@
import warnings
-from typing import Callable, Generator
+from typing import Generator
import pytest
@@ -10,8 +10,7 @@
from starlette.routing import Route, Router, WebSocketRoute
from starlette.testclient import TestClient
from starlette.types import Receive, Scope, Send
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def raise_runtime_error(request: Request) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_formparsers.py
new/starlette-0.38.2/tests/test_formparsers.py
--- old/starlette-0.37.2/tests/test_formparsers.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_formparsers.py 2024-07-27
19:55:52.000000000 +0200
@@ -13,10 +13,8 @@
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Mount
-from starlette.testclient import TestClient
from starlette.types import ASGIApp, Receive, Scope, Send
-
-TestClientFactory = typing.Callable[..., TestClient]
+from tests.types import TestClientFactory
class ForceMultipartDict(typing.Dict[typing.Any, typing.Any]):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_requests.py
new/starlette-0.38.2/tests/test_requests.py
--- old/starlette-0.37.2/tests/test_requests.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/tests/test_requests.py 2024-07-27 19:55:52.000000000
+0200
@@ -1,7 +1,7 @@
from __future__ import annotations
import sys
-from typing import Any, Callable, Iterator
+from typing import Any, Iterator
import anyio
import pytest
@@ -9,10 +9,8 @@
from starlette.datastructures import Address, State
from starlette.requests import ClientDisconnect, Request
from starlette.responses import JSONResponse, PlainTextResponse, Response
-from starlette.testclient import TestClient
from starlette.types import Message, Receive, Scope, Send
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_request_url(test_client_factory: TestClientFactory) -> None:
@@ -269,8 +267,8 @@
def test_request_is_disconnected(test_client_factory: TestClientFactory) ->
None:
"""
- If a client disconnect occurs while reading request body
- then ClientDisconnect should be raised.
+ If a client disconnect occurs after reading request body
+ then request will be set disconnected properly.
"""
disconnected_after_response = None
@@ -278,15 +276,15 @@
nonlocal disconnected_after_response
request = Request(scope, receive)
- await request.body()
+ body = await request.body()
disconnected = await request.is_disconnected()
- response = JSONResponse({"disconnected": disconnected})
+ response = JSONResponse({"body": body.decode(), "disconnected":
disconnected})
await response(scope, receive, send)
disconnected_after_response = await request.is_disconnected()
client = test_client_factory(app)
- response = client.get("/")
- assert response.json() == {"disconnected": False}
+ response = client.post("/", content="foo")
+ assert response.json() == {"body": "foo", "disconnected": False}
assert disconnected_after_response
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_responses.py
new/starlette-0.38.2/tests/test_responses.py
--- old/starlette-0.37.2/tests/test_responses.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_responses.py 2024-07-27
19:55:52.000000000 +0200
@@ -5,7 +5,7 @@
import time
from http.cookies import SimpleCookie
from pathlib import Path
-from typing import AsyncIterator, Callable, Iterator
+from typing import AsyncIterator, Iterator
import anyio
import pytest
@@ -23,8 +23,7 @@
)
from starlette.testclient import TestClient
from starlette.types import Message, Receive, Scope, Send
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_text_response(test_client_factory: TestClientFactory) -> None:
@@ -350,38 +349,6 @@
FileResponse(path=tmpdir, filename="example.png", method="GET")
[email protected]
-async def test_file_response_with_pathsend(tmpdir: Path) -> None:
- path = os.path.join(tmpdir, "xyz")
- content = b"<file content>" * 1000
- with open(path, "wb") as file:
- file.write(content)
-
- app = FileResponse(path=path, filename="example.png")
-
- async def receive() -> Message: # type: ignore[empty-body]
- ... # pragma: no cover
-
- async def send(message: Message) -> None:
- if message["type"] == "http.response.start":
- assert message["status"] == status.HTTP_200_OK
- headers = Headers(raw=message["headers"])
- assert headers["content-type"] == "image/png"
- assert "content-length" in headers
- assert "content-disposition" in headers
- assert "last-modified" in headers
- assert "etag" in headers
- elif message["type"] == "http.response.pathsend":
- assert message["path"] == str(path)
-
- # Since the TestClient doesn't support `pathsend`, we need to test this
directly.
- await app(
- {"type": "http", "method": "get", "extensions":
{"http.response.pathsend": {}}},
- receive,
- send,
- )
-
-
def test_set_cookie(
test_client_factory: TestClientFactory, monkeypatch: pytest.MonkeyPatch
) -> None:
@@ -541,6 +508,20 @@
assert response.headers["content-length"] == "10"
+def test_response_memoryview(test_client_factory: TestClientFactory) -> None:
+ app = Response(content=memoryview(b"\xc0"))
+ client: TestClient = test_client_factory(app)
+ response = client.get("/")
+ assert response.content == b"\xc0"
+
+
+def test_streaming_response_memoryview(test_client_factory: TestClientFactory)
-> None:
+ app = StreamingResponse(content=iter([memoryview(b"\xc0"),
memoryview(b"\xf5")]))
+ client: TestClient = test_client_factory(app)
+ response = client.get("/")
+ assert response.content == b"\xc0\xf5"
+
+
@pytest.mark.anyio
async def test_streaming_response_stops_if_receiving_http_disconnect() -> None:
streamed = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_routing.py
new/starlette-0.38.2/tests/test_routing.py
--- old/starlette-0.37.2/tests/test_routing.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/tests/test_routing.py 2024-07-27 19:55:52.000000000
+0200
@@ -17,8 +17,7 @@
from starlette.testclient import TestClient
from starlette.types import ASGIApp, Message, Receive, Scope, Send
from starlette.websockets import WebSocket, WebSocketDisconnect
-
-TestClientFactory = typing.Callable[..., TestClient]
+from tests.types import TestClientFactory
def homepage(request: Request) -> Response:
@@ -909,19 +908,15 @@
class Endpoint:
- async def my_method(self, request: Request) -> None:
- ... # pragma: no cover
+ async def my_method(self, request: Request) -> None: ... # pragma: no
cover
@classmethod
- async def my_classmethod(cls, request: Request) -> None:
- ... # pragma: no cover
+ async def my_classmethod(cls, request: Request) -> None: ... # pragma: no
cover
@staticmethod
- async def my_staticmethod(request: Request) -> None:
- ... # pragma: no cover
+ async def my_staticmethod(request: Request) -> None: ... # pragma: no
cover
- def __call__(self, request: Request) -> None:
- ... # pragma: no cover
+ def __call__(self, request: Request) -> None: ... # pragma: no cover
@pytest.mark.parametrize(
@@ -1254,8 +1249,7 @@
with pytest.deprecated_call():
- async def startup() -> None:
- ... # pragma: nocover
+ async def startup() -> None: ... # pragma: nocover
router.on_event("startup")(startup)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_schemas.py
new/starlette-0.38.2/tests/test_schemas.py
--- old/starlette-0.37.2/tests/test_schemas.py 2024-03-05 17:08:44.000000000
+0100
+++ new/starlette-0.38.2/tests/test_schemas.py 2024-07-27 19:55:52.000000000
+0200
@@ -1,20 +1,16 @@
-from typing import Callable
-
from starlette.applications import Starlette
from starlette.endpoints import HTTPEndpoint
from starlette.requests import Request
from starlette.responses import Response
from starlette.routing import Host, Mount, Route, Router, WebSocketRoute
from starlette.schemas import SchemaGenerator
-from starlette.testclient import TestClient
from starlette.websockets import WebSocket
+from tests.types import TestClientFactory
schemas = SchemaGenerator(
{"openapi": "3.0.0", "info": {"title": "Example API", "version": "1.0"}}
)
-TestClientFactory = Callable[..., TestClient]
-
def ws(session: WebSocket) -> None:
"""ws"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_staticfiles.py
new/starlette-0.38.2/tests/test_staticfiles.py
--- old/starlette-0.37.2/tests/test_staticfiles.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_staticfiles.py 2024-07-27
19:55:52.000000000 +0200
@@ -16,9 +16,7 @@
from starlette.responses import Response
from starlette.routing import Mount
from starlette.staticfiles import StaticFiles
-from starlette.testclient import TestClient
-
-TestClientFactory = typing.Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_staticfiles(tmpdir: Path, test_client_factory: TestClientFactory) ->
None:
@@ -468,6 +466,19 @@
assert response.status_code == 404
assert response.text == "Not Found"
+
+def test_staticfiles_filename_too_long(
+ tmpdir: Path, test_client_factory: TestClientFactory
+) -> None:
+ routes = [Mount("/", app=StaticFiles(directory=tmpdir), name="static")]
+ app = Starlette(routes=routes)
+ client = test_client_factory(app)
+
+ path_max_size = os.pathconf("/", "PC_PATH_MAX")
+ response = client.get(f"/{'a' * path_max_size}.txt")
+ assert response.status_code == 404
+ assert response.text == "Not Found"
+
def test_staticfiles_unhandled_os_error_returns_500(
tmpdir: Path,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_templates.py
new/starlette-0.38.2/tests/test_templates.py
--- old/starlette-0.37.2/tests/test_templates.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_templates.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,7 +1,6 @@
from __future__ import annotations
import os
-import typing
from pathlib import Path
from unittest import mock
@@ -16,9 +15,7 @@
from starlette.responses import Response
from starlette.routing import Route
from starlette.templating import Jinja2Templates
-from starlette.testclient import TestClient
-
-TestClientFactory = typing.Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_templates(tmpdir: Path, test_client_factory: TestClientFactory) ->
None:
@@ -143,6 +140,13 @@
Jinja2Templates() # type: ignore[call-overload]
+def test_templates_require_directory_or_enviroment_not_both() -> None:
+ with pytest.raises(
+ AssertionError, match="either 'directory' or 'env' arguments must be
passed"
+ ):
+ Jinja2Templates(directory="dir", env=jinja2.Environment())
+
+
def test_templates_with_directory(tmpdir: Path) -> None:
path = os.path.join(tmpdir, "index.html")
with open(path, "w") as file:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_testclient.py
new/starlette-0.38.2/tests/test_testclient.py
--- old/starlette-0.37.2/tests/test_testclient.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_testclient.py 2024-07-27
19:55:52.000000000 +0200
@@ -4,7 +4,7 @@
import sys
from asyncio import Task, current_task as asyncio_current_task
from contextlib import asynccontextmanager
-from typing import Any, AsyncGenerator, Callable
+from typing import Any, AsyncGenerator
import anyio
import anyio.lowlevel
@@ -20,8 +20,7 @@
from starlette.testclient import ASGIInstance, TestClient
from starlette.types import ASGIApp, Receive, Scope, Send
from starlette.websockets import WebSocket, WebSocketDisconnect
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def mock_service_endpoint(request: Request) -> JSONResponse:
@@ -212,7 +211,7 @@
return inner
- client = test_client_factory(app)
+ client = test_client_factory(app) # type: ignore
response = client.get("/")
assert response.text == "Hello, world!"
@@ -252,7 +251,7 @@
return asgi
- client = test_client_factory(app)
+ client = test_client_factory(app) # type: ignore
with client.websocket_connect("/") as websocket:
data = websocket.receive_json()
assert data == {"message": "test"}
@@ -268,7 +267,7 @@
return asgi
- client = test_client_factory(app)
+ client = test_client_factory(app) # type: ignore
with client.websocket_connect("/") as websocket:
...
assert websocket.should_close.is_set()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/test_websockets.py
new/starlette-0.38.2/tests/test_websockets.py
--- old/starlette-0.37.2/tests/test_websockets.py 2024-03-05
17:08:44.000000000 +0100
+++ new/starlette-0.38.2/tests/test_websockets.py 2024-07-27
19:55:52.000000000 +0200
@@ -1,5 +1,5 @@
import sys
-from typing import Any, Callable, MutableMapping
+from typing import Any, MutableMapping
import anyio
import pytest
@@ -7,11 +7,10 @@
from starlette import status
from starlette.responses import Response
-from starlette.testclient import TestClient, WebSocketDenialResponse
+from starlette.testclient import WebSocketDenialResponse
from starlette.types import Message, Receive, Scope, Send
from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState
-
-TestClientFactory = Callable[..., TestClient]
+from tests.types import TestClientFactory
def test_websocket_url(test_client_factory: TestClientFactory) -> None:
@@ -492,8 +491,7 @@
async def mock_receive() -> Message: # type: ignore
... # pragma: no cover
- async def mock_send(message: Message) -> None:
- ... # pragma: no cover
+ async def mock_send(message: Message) -> None: ... # pragma: no cover
websocket = WebSocket(
{"type": "websocket", "path": "/abc/", "headers": []},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/starlette-0.37.2/tests/types.py
new/starlette-0.38.2/tests/types.py
--- old/starlette-0.37.2/tests/types.py 1970-01-01 01:00:00.000000000 +0100
+++ new/starlette-0.38.2/tests/types.py 2024-07-27 19:55:52.000000000 +0200
@@ -0,0 +1,26 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Protocol
+
+import httpx
+
+from starlette.testclient import TestClient
+from starlette.types import ASGIApp
+
+if TYPE_CHECKING:
+
+ class TestClientFactory(Protocol): # pragma: no cover
+ def __call__(
+ self,
+ app: ASGIApp,
+ base_url: str = "http://testserver",
+ raise_server_exceptions: bool = True,
+ root_path: str = "",
+ cookies: httpx._types.CookieTypes | None = None,
+ headers: dict[str, str] | None = None,
+ follow_redirects: bool = True,
+ ) -> TestClient: ...
+else: # pragma: no cover
+
+ class TestClientFactory:
+ __test__ = False