Skip to content

Commit

Permalink
Merge fdf3609 into 8aeca9c
Browse files Browse the repository at this point in the history
  • Loading branch information
jace authored Dec 12, 2023
2 parents 8aeca9c + fdf3609 commit ad89d1b
Show file tree
Hide file tree
Showing 24 changed files with 899 additions and 522 deletions.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import typing as t

sys.path.insert(0, os.path.abspath('../src'))
from coaster import _version # isort:skip # pylint: disable=wrong-import-position
from coaster import _version # isort:skip

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
Expand Down
15 changes: 7 additions & 8 deletions src/coaster/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
mod_tomli: t.Optional[types.ModuleType] = None
mod_yaml: t.Optional[types.ModuleType] = None

try: # pragma: no cover
try:
import toml as mod_toml # type: ignore[no-redef,unused-ignore]
except ModuleNotFoundError:
try:
Expand All @@ -52,7 +52,7 @@
pass


try: # pragma: no cover
try:
import yaml as mod_yaml
except ModuleNotFoundError:
pass
Expand Down Expand Up @@ -106,7 +106,7 @@ class ConfigLoader(NamedTuple):
# --- Key rotation wrapper -------------------------------------------------------------


class KeyRotationWrapper(t.Generic[_S]): # pylint: disable=too-few-public-methods
class KeyRotationWrapper(t.Generic[_S]):
"""
Wrapper to support multiple secret keys in itsdangerous.
Expand Down Expand Up @@ -193,7 +193,7 @@ class JSONProvider(DefaultJSONProvider):

@staticmethod
def default(o: t.Any) -> t.Any:
"""Expand default support to check for `__json__`."""
"""Expand default support to check for a ``__json__`` method."""
if hasattr(o, '__json__'):
return o.__json__()
if isinstance(o, abc.Mapping):
Expand Down Expand Up @@ -330,11 +330,10 @@ def load_config_from_file(
try:
if load is None:
return app.config.from_pyfile(filepath)
# The `text` parameter requires Flask 2.3. We still support Flask 2.2
# The `text` parameter was introduced in Flask 2.3, but its default value
# may change in a future release, so we only supply a value if we have a bool
if text is not None:
return app.config.from_file( # type: ignore[call-arg]
filepath, load=load, text=text
)
return app.config.from_file(filepath, load=load, text=text)
return app.config.from_file(filepath, load=load)
except OSError:
app.logger.warning(
Expand Down
24 changes: 13 additions & 11 deletions src/coaster/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
from threading import Lock
from typing import cast

from flask import Flask, current_app, g, request
from flask import Flask, current_app, g
from flask.globals import request_ctx
from werkzeug.local import LocalProxy
from werkzeug.wrappers import Response as BaseResponse

Expand Down Expand Up @@ -108,9 +109,9 @@ def request_has_auth() -> bool:
to set cookies or perform other housekeeping functions.
"""
return (
bool(request)
and hasattr(request, '_current_auth')
and 'actor' in request._current_auth.__dict__
bool(request_ctx)
and hasattr(request_ctx, 'current_auth')
and 'actor' in request_ctx.current_auth.__dict__
)


Expand Down Expand Up @@ -162,10 +163,10 @@ def __setattr__(self, attr: str, value: t.Any) -> t.NoReturn:
# This test is used to allow in-place mutations such as:
# current_auth.permissions |= {extra}
return # type: ignore[misc]
raise AttributeError('CurrentAuth is read-only')
raise TypeError('current_auth is read-only')

def __delattr__(self, attr: str) -> t.NoReturn:
raise AttributeError('CurrentAuth is read-only')
raise TypeError('current_auth is read-only')

def __contains__(self, attr: str) -> bool:
"""Check for presence of an attribute."""
Expand Down Expand Up @@ -197,12 +198,12 @@ def __getattr__(self, attr: str) -> t.Any:
def _call_login_manager(self) -> None:
"""Call the app's login manager on first access of user or actor (internal)."""
# Check for an existing user from Flask-Login
if not request:
if not request_ctx:
# There's no request context for a login manager to operate on
return
# If there's no existing user, look for a login manager
if (
request
request_ctx
and hasattr(current_app, 'login_manager')
and hasattr(current_app.login_manager, '_load_user')
):
Expand Down Expand Up @@ -258,13 +259,14 @@ def init_app(app: Flask) -> None:
def _get_current_auth() -> CurrentAuth:
"""Provide current_auth for the request context."""
# 1. Do we have a request context?
if request:
if request_ctx:
with _get_lock:
# 2. Does this request already have current_auth? If so, return it
ca = getattr(request, '_current_auth', None)
ca = getattr(request_ctx, 'current_auth', None)
if ca is None:
# 3. If not, create it
request._current_auth = ca = CurrentAuth() # type: ignore[attr-defined]
ca = CurrentAuth()
request_ctx.current_auth = ca # type: ignore[attr-defined]
# 4. Return current_auth
return ca

Expand Down
4 changes: 2 additions & 2 deletions src/coaster/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

from .sqlalchemy import Query

try: # pragma: no cover
try:
from psycopg2.extensions import connection as Psycopg2Connection # noqa: N812
except ModuleNotFoundError:
Psycopg2Connection = None

try: # pragma: no cover
try:
from psycopg import Connection as Psycopg3Connection
except ModuleNotFoundError:
Psycopg3Connection = None # type: ignore[assignment,misc]
Expand Down
2 changes: 1 addition & 1 deletion src/coaster/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from flask import g, request, session
from flask.config import Config

try: # Flask >= 3.0 # pragma: no cover
try: # Flask >= 3.0
from flask.sansio.app import App as FlaskApp
except ModuleNotFoundError:
from flask import Flask as FlaskApp
Expand Down
6 changes: 3 additions & 3 deletions src/coaster/sqlalchemy/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,17 @@ def make_timestamp_columns(


@overload
def failsafe_add(__session: session_type, __instance: t.Any) -> None:
def failsafe_add(__session: session_type, __instance: t.Any, /) -> None:
...


@overload
def failsafe_add(__session: session_type, __instance: T, **filters: t.Any) -> T:
def failsafe_add(__session: session_type, __instance: T, /, **filters: t.Any) -> T:
...


def failsafe_add(
__session: session_type, __instance: T, **filters: t.Any
__session: session_type, __instance: T, /, **filters: t.Any
) -> t.Optional[T]:
"""
Add and commit a new instance in a nested transaction (using SQL SAVEPOINT).
Expand Down
4 changes: 0 additions & 4 deletions src/coaster/sqlalchemy/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,6 @@ def __eq__(self, other: t.Any) -> bool:
self.__composite_values__() == other.__composite_values__()
)

def __ne__(self, other: t.Any) -> bool:
"""Compare for inequality."""
return not self.__eq__(other)

# Pickle support methods implemented as per SQLAlchemy documentation, but not
# tested here as we don't use them.
# https://docs.sqlalchemy.org/en/13/orm/extensions/mutable.html#id1
Expand Down
Loading

0 comments on commit ad89d1b

Please sign in to comment.