Skip to content

Commit

Permalink
Set line-length to 120 on Ruff (#2679)
Browse files Browse the repository at this point in the history
* Set `line-length` to 120 on Ruff

* Add links to selected rules

* Remove empty strings

* Fix more stuff
  • Loading branch information
Kludex committed Sep 1, 2024
1 parent 72c2334 commit b9db010
Show file tree
Hide file tree
Showing 53 changed files with 402 additions and 1,149 deletions.
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

0 comments on commit b9db010

Please sign in to comment.