From 5da41fcc11d7621633424b18b2804803319044a4 Mon Sep 17 00:00:00 2001 From: "Teemu R." Date: Thu, 31 Oct 2024 14:12:17 +0100 Subject: [PATCH] Use stacklevel=2 for warnings to report on callsites (#1219) Use stacklevel=2 for warnings, as this will correctly show the callsite instead of the line where the warning is reported. Currently: ``` kasa/__init__.py:110 /home/tpr/code/python-kasa/kasa/__init__.py:110: DeprecationWarning: SmartDevice is deprecated, use IotDevice from package kasa.iot instead or use Discover.discover_single() and Device.connect() to support new protocols warn( ``` After: ``` kasa/tests/smart/modules/test_contact.py:3 /home/tpr/code/python-kasa/kasa/tests/smart/modules/test_contact.py:3: DeprecationWarning: SmartDevice is deprecated, use IotDevice from package kasa.iot instead or use Discover.discover_single() and Device.connect() to support new protocols from kasa import Module, SmartDevice ``` Currently: ``` kasa/tests/test_lightstrip.py: 56 warnings /home/tpr/code/python-kasa/kasa/device.py:559: DeprecationWarning: effect is deprecated, use: Module.LightEffect in device.modules instead warn(msg, DeprecationWarning, stacklevel=1) ``` After: ``` kasa/tests/test_lightstrip.py::test_effects_lightstrip_set_effect_transition[500-KL430(US)_2.0_1.0.9.json] /home/tpr/code/python-kasa/kasa/tests/test_lightstrip.py:62: DeprecationWarning: set_effect is deprecated, use: Module.LightEffect in device.modules instead await dev.set_effect("Candy Cane") ``` --- kasa/__init__.py | 6 +++--- kasa/device.py | 4 ++-- kasa/interfaces/energy.py | 2 +- kasa/iot/iotdevice.py | 4 ++-- kasa/tests/fakeprotocol_smart.py | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kasa/__init__.py b/kasa/__init__.py index d383d3a7..11000419 100755 --- a/kasa/__init__.py +++ b/kasa/__init__.py @@ -102,7 +102,7 @@ deprecated_classes = { def __getattr__(name): if name in deprecated_names: - warn(f"{name} is deprecated", DeprecationWarning, stacklevel=1) + warn(f"{name} is deprecated", DeprecationWarning, stacklevel=2) return globals()[f"_deprecated_{name}"] if name in deprecated_smart_devices: new_class = deprecated_smart_devices[name] @@ -112,13 +112,13 @@ def __getattr__(name): + f"from package {package_name} instead or use Discover.discover_single()" + " and Device.connect() to support new protocols", DeprecationWarning, - stacklevel=1, + stacklevel=2, ) return new_class if name in deprecated_classes: new_class = deprecated_classes[name] msg = f"{name} is deprecated, use {new_class.__name__} instead" - warn(msg, DeprecationWarning, stacklevel=1) + warn(msg, DeprecationWarning, stacklevel=2) return new_class raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/kasa/device.py b/kasa/device.py index 5df1751c..08dcf2a1 100644 --- a/kasa/device.py +++ b/kasa/device.py @@ -545,7 +545,7 @@ class Device(ABC): msg = f"{name} is deprecated" if module: msg += f", use: {module} in device.modules instead" - warn(msg, DeprecationWarning, stacklevel=1) + warn(msg, DeprecationWarning, stacklevel=2) return self.device_type == dep_device_type_attr[1] # Other deprecated attributes if (dep_attr := self._deprecated_other_attributes.get(name)) and ( @@ -556,6 +556,6 @@ class Device(ABC): dev_or_mod = self.modules[mod] if mod else self replacing = f"Module.{mod} in device.modules" if mod else replacing_attr msg = f"{name} is deprecated, use: {replacing} instead" - warn(msg, DeprecationWarning, stacklevel=1) + warn(msg, DeprecationWarning, stacklevel=2) return getattr(dev_or_mod, replacing_attr) raise AttributeError(f"Device has no attribute {name!r}") diff --git a/kasa/interfaces/energy.py b/kasa/interfaces/energy.py index 51579322..4e040e6f 100644 --- a/kasa/interfaces/energy.py +++ b/kasa/interfaces/energy.py @@ -182,6 +182,6 @@ class Energy(Module, ABC): def __getattr__(self, name): if attr := self._deprecated_attributes.get(name): msg = f"{name} is deprecated, use {attr} instead" - warn(msg, DeprecationWarning, stacklevel=1) + warn(msg, DeprecationWarning, stacklevel=2) return getattr(self, attr) raise AttributeError(f"Energy module has no attribute {name!r}") diff --git a/kasa/iot/iotdevice.py b/kasa/iot/iotdevice.py index 84c4ff81..69296823 100755 --- a/kasa/iot/iotdevice.py +++ b/kasa/iot/iotdevice.py @@ -472,7 +472,7 @@ class IotDevice(Device): async def get_time(self) -> datetime: """Return current time from the device, if available.""" msg = "Use `time` property instead, this call will be removed in the future." - warn(msg, DeprecationWarning, stacklevel=1) + warn(msg, DeprecationWarning, stacklevel=2) return self.time async def get_timezone(self) -> tzinfo: @@ -480,7 +480,7 @@ class IotDevice(Device): msg = ( "Use `timezone` property instead, this call will be removed in the future." ) - warn(msg, DeprecationWarning, stacklevel=1) + warn(msg, DeprecationWarning, stacklevel=2) return self.timezone @property # type: ignore diff --git a/kasa/tests/fakeprotocol_smart.py b/kasa/tests/fakeprotocol_smart.py index c3d8104e..c5a7c11e 100644 --- a/kasa/tests/fakeprotocol_smart.py +++ b/kasa/tests/fakeprotocol_smart.py @@ -202,12 +202,12 @@ class FakeSmartTransport(BaseTransport): else: warn( f"Could not find child SMART fixture for {child_info}", - stacklevel=1, + stacklevel=2, ) else: warn( f"Child is a cameraprotocol which needs to be implemented {child_info}", - stacklevel=1, + stacklevel=2, ) # Replace parent child infos with the infos from the child fixtures so # that updates update both @@ -223,7 +223,7 @@ class FakeSmartTransport(BaseTransport): if device_id not in self.child_protocols: warn( f"Could not find child fixture {device_id} in {self.fixture_name}", - stacklevel=1, + stacklevel=2, ) return self._handle_control_child_missing(params)