diff --git a/scrapy/statscollectors.py b/scrapy/statscollectors.py index 02adef1e4..f74842ac9 100644 --- a/scrapy/statscollectors.py +++ b/scrapy/statscollectors.py @@ -28,9 +28,15 @@ class StatsCollector: self._crawler: Crawler = crawler def __getattribute__(self, name): + cached_name = f"_cached_{name}" + try: + return super().__getattribute__(cached_name) + except AttributeError: + pass + original_attr = super().__getattribute__(name) - if name in ( + if name in { "get_value", "get_stats", "set_value", @@ -41,8 +47,10 @@ class StatsCollector: "clear_stats", "open_spider", "close_spider", - ) and callable(original_attr): - return _warn_spider_arg(original_attr) + } and callable(original_attr): + wrapped = _warn_spider_arg(original_attr) + setattr(self, cached_name, wrapped) + return wrapped return original_attr diff --git a/scrapy/utils/decorators.py b/scrapy/utils/decorators.py index c4739bcee..374c8ecb8 100644 --- a/scrapy/utils/decorators.py +++ b/scrapy/utils/decorators.py @@ -93,8 +93,10 @@ def _warn_spider_arg( ): """Decorator to warn if a ``spider`` argument is passed to a function.""" + sig = inspect.signature(func) + def check_args(*args: _P.args, **kwargs: _P.kwargs) -> None: - bound = inspect.signature(func).bind(*args, **kwargs) + bound = sig.bind(*args, **kwargs) if "spider" in bound.arguments: warnings.warn( f"Passing a 'spider' argument to {func.__qualname__}() is deprecated and "