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

Set line-length to 120 on Ruff #2679

Merged
merged 4 commits into from
Sep 1, 2024
Merged
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
14 changes: 12 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,19 @@ Source = "https://github.com/encode/starlette"
[tool.hatch.version]
path = "starlette/__init__.py"

[tool.ruff]
line-length = 120

[tool.ruff.lint]
select = ["E", "F", "I", "FA", "UP"]
ignore = ["UP031"]
select = [
"E", # https://docs.astral.sh/ruff/rules/#error-e
"F", # https://docs.astral.sh/ruff/rules/#pyflakes-f
"I", # https://docs.astral.sh/ruff/rules/#isort-i
"FA", # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa
"UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up
"RUF100", # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
]
ignore = ["UP031"] # https://docs.astral.sh/ruff/rules/printf-string-formatting/

[tool.ruff.lint.isort]
combine-as-imports = true
Expand Down
4 changes: 1 addition & 3 deletions starlette/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
# that reject usedforsecurity=True
hashlib.md5(b"data", usedforsecurity=False) # type: ignore[call-arg]

def md5_hexdigest(
data: bytes, *, usedforsecurity: bool = True
) -> str: # pragma: no cover
def md5_hexdigest(data: bytes, *, usedforsecurity: bool = True) -> str: # pragma: no cover
return hashlib.md5( # type: ignore[call-arg]
data, usedforsecurity=usedforsecurity
).hexdigest()
Expand Down
4 changes: 1 addition & 3 deletions starlette/_exception_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@
StatusHandlers = typing.Dict[int, ExceptionHandler]


def _lookup_exception_handler(
exc_handlers: ExceptionHandlers, exc: Exception
) -> ExceptionHandler | None:
def _lookup_exception_handler(exc_handlers: ExceptionHandlers, exc: Exception) -> ExceptionHandler | None:
for cls in type(exc).__mro__:
if cls in exc_handlers:
return exc_handlers[cls]
Expand Down
12 changes: 3 additions & 9 deletions starlette/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,20 @@ def is_async_callable(obj: typing.Any) -> typing.Any:
while isinstance(obj, functools.partial):
obj = obj.func

return asyncio.iscoroutinefunction(obj) or (
callable(obj) and asyncio.iscoroutinefunction(obj.__call__)
)
return asyncio.iscoroutinefunction(obj) or (callable(obj) and asyncio.iscoroutinefunction(obj.__call__))


T_co = typing.TypeVar("T_co", covariant=True)


class AwaitableOrContextManager(
typing.Awaitable[T_co], typing.AsyncContextManager[T_co], typing.Protocol[T_co]
): ...
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


SupportsAsyncCloseType = typing.TypeVar(
"SupportsAsyncCloseType", bound=SupportsAsyncClose, covariant=False
)
SupportsAsyncCloseType = typing.TypeVar("SupportsAsyncCloseType", bound=SupportsAsyncClose, covariant=False)


class AwaitableOrContextManagerWrapper(typing.Generic[SupportsAsyncCloseType]):
Expand Down
56 changes: 20 additions & 36 deletions starlette/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,21 +72,15 @@ def __init__(

self.debug = debug
self.state = State()
self.router = Router(
routes, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan
)
self.exception_handlers = (
{} if exception_handlers is None else dict(exception_handlers)
)
self.router = Router(routes, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan)
self.exception_handlers = {} if exception_handlers is None else dict(exception_handlers)
self.user_middleware = [] if middleware is None else list(middleware)
self.middleware_stack: ASGIApp | None = None

def build_middleware_stack(self) -> ASGIApp:
debug = self.debug
error_handler = None
exception_handlers: dict[
typing.Any, typing.Callable[[Request, Exception], Response]
] = {}
exception_handlers: dict[typing.Any, typing.Callable[[Request, Exception], Response]] = {}

for key, value in self.exception_handlers.items():
if key in (500, Exception):
Expand All @@ -97,11 +91,7 @@ def build_middleware_stack(self) -> ASGIApp:
middleware = (
[Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)]
+ self.user_middleware
+ [
Middleware(
ExceptionMiddleware, handlers=exception_handlers, debug=debug
)
]
+ [Middleware(ExceptionMiddleware, handlers=exception_handlers, debug=debug)]
)

app = self.router
Expand Down Expand Up @@ -163,9 +153,7 @@ def add_route(
name: str | None = None,
include_in_schema: bool = True,
) -> None: # pragma: no cover
self.router.add_route(
path, route, methods=methods, name=name, include_in_schema=include_in_schema
)
self.router.add_route(path, route, methods=methods, name=name, include_in_schema=include_in_schema)

def add_websocket_route(
self,
Expand All @@ -175,16 +163,14 @@ def add_websocket_route(
) -> None: # pragma: no cover
self.router.add_websocket_route(path, route, name=name)

def exception_handler(
self, exc_class_or_status_code: int | type[Exception]
) -> typing.Callable: # type: ignore[type-arg]
def exception_handler(self, exc_class_or_status_code: int | type[Exception]) -> typing.Callable: # type: ignore[type-arg]
warnings.warn(
"The `exception_handler` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501
"Refer to https://www.starlette.io/exceptions/ for the recommended approach.", # noqa: E501
"The `exception_handler` decorator is deprecated, and will be removed in version 1.0.0. "
"Refer to https://www.starlette.io/exceptions/ for the recommended approach.",
DeprecationWarning,
)

def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg] # noqa: E501
def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg]
self.add_exception_handler(exc_class_or_status_code, func)
return func

Expand All @@ -205,12 +191,12 @@ def route(
>>> app = Starlette(routes=routes)
"""
warnings.warn(
"The `route` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501
"Refer to https://www.starlette.io/routing/ for the recommended approach.", # noqa: E501
"The `route` decorator is deprecated, and will be removed in version 1.0.0. "
"Refer to https://www.starlette.io/routing/ for the recommended approach.",
DeprecationWarning,
)

def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg] # noqa: E501
def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg]
self.router.add_route(
path,
func,
Expand All @@ -231,18 +217,18 @@ def websocket_route(self, path: str, name: str | None = None) -> typing.Callable
>>> app = Starlette(routes=routes)
"""
warnings.warn(
"The `websocket_route` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501
"Refer to https://www.starlette.io/routing/#websocket-routing for the recommended approach.", # noqa: E501
"The `websocket_route` decorator is deprecated, and will be removed in version 1.0.0. "
"Refer to https://www.starlette.io/routing/#websocket-routing for the recommended approach.",
DeprecationWarning,
)

def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg] # noqa: E501
def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg]
self.router.add_websocket_route(path, func, name=name)
return func

return decorator

def middleware(self, middleware_type: str) -> typing.Callable: # type: ignore[type-arg] # noqa: E501
def middleware(self, middleware_type: str) -> typing.Callable: # type: ignore[type-arg]
"""
We no longer document this decorator style API, and its usage is discouraged.
Instead you should use the following approach:
Expand All @@ -251,15 +237,13 @@ def middleware(self, middleware_type: str) -> typing.Callable: # type: ignore[t
>>> app = Starlette(middleware=middleware)
"""
warnings.warn(
"The `middleware` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501
"Refer to https://www.starlette.io/middleware/#using-middleware for recommended approach.", # noqa: E501
"The `middleware` decorator is deprecated, and will be removed in version 1.0.0. "
"Refer to https://www.starlette.io/middleware/#using-middleware for recommended approach.",
DeprecationWarning,
)
assert (
middleware_type == "http"
), 'Currently only middleware("http") is supported.'
assert middleware_type == "http", 'Currently only middleware("http") is supported.'

def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg] # noqa: E501
def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-arg]
self.add_middleware(BaseHTTPMiddleware, dispatch=func)
return func

Expand Down
16 changes: 4 additions & 12 deletions starlette/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ def requires(
scopes: str | typing.Sequence[str],
status_code: int = 403,
redirect: str | None = None,
) -> typing.Callable[
[typing.Callable[_P, typing.Any]], typing.Callable[_P, typing.Any]
]:
) -> typing.Callable[[typing.Callable[_P, typing.Any]], typing.Callable[_P, typing.Any]]:
scopes_list = [scopes] if isinstance(scopes, str) else list(scopes)

def decorator(
Expand All @@ -45,17 +43,13 @@ def decorator(
type_ = parameter.name
break
else:
raise Exception(
f'No "request" or "websocket" argument on function "{func}"'
)
raise Exception(f'No "request" or "websocket" argument on function "{func}"')

if type_ == "websocket":
# Handle websocket functions. (Always async)
@functools.wraps(func)
async def websocket_wrapper(*args: _P.args, **kwargs: _P.kwargs) -> None:
websocket = kwargs.get(
"websocket", args[idx] if idx < len(args) else None
)
websocket = kwargs.get("websocket", args[idx] if idx < len(args) else None)
assert isinstance(websocket, WebSocket)

if not has_required_scope(websocket, scopes_list):
Expand Down Expand Up @@ -107,9 +101,7 @@ class AuthenticationError(Exception):


class AuthenticationBackend:
async def authenticate(
self, conn: HTTPConnection
) -> tuple[AuthCredentials, BaseUser] | None:
async def authenticate(self, conn: HTTPConnection) -> tuple[AuthCredentials, BaseUser] | None:
raise NotImplementedError() # pragma: no cover


Expand Down
8 changes: 2 additions & 6 deletions starlette/background.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@


class BackgroundTask:
def __init__(
self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs
) -> None:
def __init__(self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs) -> None:
self.func = func
self.args = args
self.kwargs = kwargs
Expand All @@ -34,9 +32,7 @@ class BackgroundTasks(BackgroundTask):
def __init__(self, tasks: typing.Sequence[BackgroundTask] | None = None):
self.tasks = list(tasks) if tasks else []

def add_task(
self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs
) -> None:
def add_task(self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs) -> None:
task = BackgroundTask(func, *args, **kwargs)
self.tasks.append(task)

Expand Down
11 changes: 4 additions & 7 deletions starlette/concurrency.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,23 @@
T = typing.TypeVar("T")


async def run_until_first_complete(*args: tuple[typing.Callable, dict]) -> None: # type: ignore[type-arg] # noqa: E501
async def run_until_first_complete(*args: tuple[typing.Callable, dict]) -> None: # type: ignore[type-arg]
warnings.warn(
"run_until_first_complete is deprecated "
"and will be removed in a future version.",
"run_until_first_complete is deprecated and will be removed in a future version.",
DeprecationWarning,
)

async with anyio.create_task_group() as task_group:

async def run(func: typing.Callable[[], typing.Coroutine]) -> None: # type: ignore[type-arg] # noqa: E501
async def run(func: typing.Callable[[], typing.Coroutine]) -> None: # type: ignore[type-arg]
await func()
task_group.cancel_scope.cancel()

for func, kwargs in args:
task_group.start_soon(run, functools.partial(func, **kwargs))


async def run_in_threadpool(
func: typing.Callable[P, T], *args: P.args, **kwargs: P.kwargs
) -> T:
async def run_in_threadpool(func: typing.Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T:
if kwargs: # pragma: no cover
# run_sync doesn't accept 'kwargs', so bind them in here
func = functools.partial(func, **kwargs)
Expand Down
22 changes: 5 additions & 17 deletions starlette/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,12 @@ def __getitem__(self, key: str) -> str:

def __setitem__(self, key: str, value: str) -> None:
if key in self._has_been_read:
raise EnvironError(
f"Attempting to set environ['{key}'], but the value has already been "
"read."
)
raise EnvironError(f"Attempting to set environ['{key}'], but the value has already been read.")
self._environ.__setitem__(key, value)

def __delitem__(self, key: str) -> None:
if key in self._has_been_read:
raise EnvironError(
f"Attempting to delete environ['{key}'], but the value has already "
"been read."
)
raise EnvironError(f"Attempting to delete environ['{key}'], but the value has already been read.")
self._environ.__delitem__(key)

def __iter__(self) -> typing.Iterator[str]:
Expand Down Expand Up @@ -85,9 +79,7 @@ def __call__(
) -> 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,
Expand Down Expand Up @@ -138,13 +130,9 @@ def _perform_cast(
mapping = {"true": True, "1": True, "false": False, "0": False}
value = value.lower()
if value not in mapping:
raise ValueError(
f"Config '{key}' has value '{value}'. Not a valid bool."
)
raise ValueError(f"Config '{key}' has value '{value}'. Not a valid bool.")
return mapping[value]
try:
return cast(value)
except (TypeError, ValueError):
raise ValueError(
f"Config '{key}' has value '{value}'. Not a valid {cast.__name__}."
)
raise ValueError(f"Config '{key}' has value '{value}'. Not a valid {cast.__name__}.")
Loading