Skip to content

Commit

Permalink
Merge 3f317b5 into 4b8884e
Browse files Browse the repository at this point in the history
  • Loading branch information
jace committed Apr 25, 2024
2 parents 4b8884e + 3f317b5 commit 0f0b16a
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
12 changes: 8 additions & 4 deletions src/coaster/assets.py
Expand Up @@ -22,7 +22,7 @@
import warnings
from collections import defaultdict
from collections.abc import Iterator, Mapping, Sequence
from typing import Any, Optional, Union
from typing import Any, Final, Optional, Union
from urllib.parse import urljoin

from flask import Flask, current_app
Expand All @@ -37,6 +37,7 @@
'SimpleSpec',
'VersionedAssets',
'AssetNotFound',
'AssetNotFoundError',
'WebpackManifest',
]

Expand All @@ -52,10 +53,13 @@ def split_namespec(namespec: str) -> tuple[str, SimpleSpec]:
return name, spec


class AssetNotFound(Exception): # noqa: N818
class AssetNotFoundError(Exception):
"""No asset with this name."""


AssetNotFound = AssetNotFoundError


class VersionedAssets(defaultdict):
"""
Semantic-versioned asset registry.
Expand Down Expand Up @@ -186,7 +190,7 @@ def _require_recursive(self, *namespecs: str) -> list[tuple[str, Version, str]]:
if bundle is not None:
bundles.append((name, version, bundle))
else:
raise AssetNotFound(namespec)
raise AssetNotFoundError(namespec)
return bundles

def require(self, *namespecs: str) -> Bundle:
Expand All @@ -202,7 +206,7 @@ def require(self, *namespecs: str) -> Bundle:
)


EXTENSION_KEY = 'manifest.json'
EXTENSION_KEY: Final[str] = 'manifest.json'


def _get_assets_for_current_app() -> dict[str, str]:
Expand Down
8 changes: 4 additions & 4 deletions src/coaster/logger.py
Expand Up @@ -286,7 +286,7 @@ def emit(self, record: logging.LogRecord) -> None:
throttle_key = (record.module, record.lineno)
with self.throttle_lock:
if throttle_key in self.throttle_cache and (
(datetime.utcnow() - self.throttle_cache[throttle_key])
(datetime.now() - self.throttle_cache[throttle_key])
< timedelta(minutes=5)
):
return
Expand Down Expand Up @@ -349,7 +349,7 @@ def emit(self, record: logging.LogRecord) -> None:
daemon=True,
).start()
with self.throttle_lock:
self.throttle_cache[throttle_key] = datetime.utcnow()
self.throttle_cache[throttle_key] = datetime.now()
except Exception: # nosec # noqa: B902 # pylint: disable=broad-except
self.handleError(record)

Expand All @@ -375,7 +375,7 @@ def emit(self, record: logging.LogRecord) -> None:
throttle_key = (record.module, record.lineno)
with self.throttle_lock:
if throttle_key in self.throttle_cache and (
(datetime.utcnow() - self.throttle_cache[throttle_key])
(datetime.now() - self.throttle_cache[throttle_key])
< timedelta(minutes=5)
):
return
Expand Down Expand Up @@ -424,7 +424,7 @@ def emit(self, record: logging.LogRecord) -> None:
daemon=True,
).start()
with self.throttle_lock:
self.throttle_cache[throttle_key] = datetime.utcnow()
self.throttle_cache[throttle_key] = datetime.now()
except Exception: # noqa: B902 # pylint: disable=broad-except
self.handleError(record)

Expand Down
22 changes: 17 additions & 5 deletions src/coaster/sqlalchemy/registry.py
Expand Up @@ -46,6 +46,7 @@ class MyView(ModelView):
Optional,
TypeVar,
Union,
final,
overload,
)

Expand All @@ -56,7 +57,16 @@ class MyView(ModelView):

__all__ = ['Registry', 'InstanceRegistry', 'RegistryMixin']

_marker = object()

@final
class Unspecified:
pass


# This instance exists as a temporary workaround pending type-narrowing support for
# final classes in Mypy: https://github.com/python/mypy/issues/15553
unspecified = Unspecified()


_T = TypeVar('_T')
_RT = TypeVar('_RT', bound='Registry')
Expand Down Expand Up @@ -157,18 +167,19 @@ def __setattr__(self, name: str, value: Callable) -> None:
"""Incorporate a new registry member after validation."""
self.__call__(name)(value)

# types.EllipsisType was only introduced in Python 3.10, so we must silence Mypy
# for the use of ... as an undeclared sentinel value here
def __call__( # pylint: disable=redefined-builtin
self,
name: Optional[str] = None,
*,
kwarg: Union[str, None] = ..., # type: ignore[assignment]
kwarg: Union[Unspecified, str, None] = unspecified,
property: Optional[bool] = None, # noqa: A002 # pylint: disable=W0622
cached_property: Optional[bool] = None,
) -> ReturnDecorator:
"""Return decorator to aid class or function registration."""
use_kwarg = self._default_kwarg if kwarg is ... else kwarg
# Using the final-decorated Unspecified class as a sentinel value works in
# Pyright but not yet in Mypy as of 1.9.0. Therefore we use the non-singleton
# instance instead. Issue ticket: https://github.com/python/mypy/issues/15553
use_kwarg = self._default_kwarg if isinstance(kwarg, Unspecified) else kwarg
use_property = self._default_property if property is None else property
use_cached_property = (
self._default_cached_property
Expand Down Expand Up @@ -229,6 +240,7 @@ def __get__(
"(owner, name)"
)
with self._lock:
# Check in cache in case it was added by another thread
if name not in cache:
ir = InstanceRegistry(self, obj)
cache[name] = ir
Expand Down

0 comments on commit 0f0b16a

Please sign in to comment.