diff --git a/scrapy/utils/deprecate.py b/scrapy/utils/deprecate.py index 31e76fc3a..a53802291 100644 --- a/scrapy/utils/deprecate.py +++ b/scrapy/utils/deprecate.py @@ -65,10 +65,11 @@ def create_deprecated_class( # deprecated_class() takes the module of the alias from its calling frame, # which is this function and the decorator wrapping it, so skip past both. frame = inspect.currentframe() - while frame is not None and frame.f_globals.get("__name__") in _WRAPPER_MODULES: + assert frame is not None + while frame.f_globals.get("__name__") in _WRAPPER_MODULES: + assert frame.f_back is not None frame = frame.f_back - if frame is not None: - cls.__module__ = frame.f_globals.get("__name__", cls.__module__) + cls.__module__ = frame.f_globals.get("__name__", cls.__module__) return cls diff --git a/tests/test_utils_deprecate.py b/tests/test_utils_deprecate.py index df92bfa1e..5d95e4776 100644 --- a/tests/test_utils_deprecate.py +++ b/tests/test_utils_deprecate.py @@ -6,13 +6,22 @@ from unittest import mock import pytest from scrapy.exceptions import ScrapyDeprecationWarning -from scrapy.utils.deprecate import create_deprecated_class, update_classpath +from scrapy.utils.deprecate import attribute, create_deprecated_class, update_classpath class NewName: pass +def test_attribute(): + with pytest.warns( + ScrapyDeprecationWarning, + match=r"NewName\.old attribute is deprecated and will be no longer supported" + r" in Scrapy 1\.0, use NewName\.new attribute instead", + ): + attribute(NewName(), "old", "new", version="1.0") + + class TestCreateDeprecatedClass: def test_warns_about_itself(self): with pytest.warns(