Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/changes/newsfragments/6946.breaking
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The QCoDeS deprecation utils including ``qcodes.utils.deprecate.deprecation_message``,
``qcodes.utils.deprecate.issue_deprecation_warning``, ``qcodes.utils.deprecate.deprecate`` ``qcodes.utils.deprecate.assert_not_deprecated``
and ``qcodes.utils.deprecate.assert_deprecated`` along with their reexports in `qcodes`, `qcodes.utils` and `qcodes.utils.helpers`
are all deprecated and will be removed in QCoDeS 0.54.0. We recommend using `typing_extensions.deprecate` as an alternative.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ ignore_missing_imports = true
include = ["src","tests"]
ignore = [
"src/qcodes/instrument_drivers/Harvard/Decadac.py",
"tests/test_deprecate.py"
]
reportMissingTypeStubs = true
reportDeprecated = true
Expand All @@ -218,6 +219,7 @@ markers = "serial"
# and error on all other warnings
filterwarnings = [
'error',
'ignore:QCoDeS deprecation logic is deprecated:qcodes.utils.deprecate.QCoDeSDeprecationWarning', # deprecation of internal qcodes deprecated.
'ignore:open_binary is deprecated:DeprecationWarning', # pyvisa-sim
'ignore:Jupyter is migrating its paths to use standard platformdirs:DeprecationWarning', # jupyter
'ignore:Parsing dates involving a day of month without a year specified is ambiguious:DeprecationWarning', # ipykernel 3.13+
Expand Down
2 changes: 1 addition & 1 deletion src/qcodes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
combine,
)
from qcodes.station import Station
from qcodes.utils import deprecate
from qcodes.utils import deprecate # pyright: ignore[reportDeprecated]

# ensure to close all instruments when interpreter is closed
atexit.register(Instrument.close_all)
Expand Down
6 changes: 5 additions & 1 deletion src/qcodes/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
)
from .deep_update_utils import deep_update
from .delaykeyboardinterrupt import DelayedKeyboardInterrupt
from .deprecate import QCoDeSDeprecationWarning, deprecate, issue_deprecation_warning
from .deprecate import (
QCoDeSDeprecationWarning,
deprecate, # pyright: ignore[reportDeprecated]
issue_deprecation_warning, # pyright: ignore[reportDeprecated]
)
from .full_class import full_class
from .function_helpers import is_function
from .installation_info import (
Expand Down
26 changes: 23 additions & 3 deletions src/qcodes/utils/deprecate.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import TYPE_CHECKING, Any, cast

import wrapt # type: ignore[import-untyped]
from typing_extensions import deprecated

Check warning on line 8 in src/qcodes/utils/deprecate.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/utils/deprecate.py#L8

Added line #L8 was not covered by tests

if TYPE_CHECKING:
from collections.abc import Iterator
Expand All @@ -17,6 +18,10 @@
"""


@deprecated(

Check warning on line 21 in src/qcodes/utils/deprecate.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/utils/deprecate.py#L21

Added line #L21 was not covered by tests
"QCoDeS deprecation logic is deprecated. Use `deprecated` decorator from `typing_extensions`/`warnings` modules as an alternative.",
category=QCoDeSDeprecationWarning,
)
def deprecation_message(
what: str, reason: str | None = None, alternative: str | None = None
) -> str:
Expand All @@ -29,6 +34,10 @@
return msg


@deprecated(

Check warning on line 37 in src/qcodes/utils/deprecate.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/utils/deprecate.py#L37

Added line #L37 was not covered by tests
"QCoDeS deprecation logic is deprecated. Use `deprecated` decorator from `typing_extensions`/`warnings` as an alternative.",
category=QCoDeSDeprecationWarning,
)
def issue_deprecation_warning(
what: str,
reason: str | None = None,
Expand All @@ -39,12 +48,16 @@
Issue a `QCoDeSDeprecationWarning` with a consistently formatted message
"""
warnings.warn(
deprecation_message(what, reason, alternative),
deprecation_message(what, reason, alternative), # pyright: ignore[reportDeprecated]
QCoDeSDeprecationWarning,
stacklevel=stacklevel,
)


@deprecated(

Check warning on line 57 in src/qcodes/utils/deprecate.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/utils/deprecate.py#L57

Added line #L57 was not covered by tests
"QCoDeS deprecation logic is deprecated. Use `deprecated` decorator from `typing_extensions`/`warnings` as an alternative.",
category=QCoDeSDeprecationWarning,
)
def deprecate(
reason: str | None = None, alternative: str | None = None
) -> Callable[..., Any]:
Expand All @@ -71,7 +84,7 @@
if func.__name__ == "__init__"
else ("function", func.__name__)
)
issue_deprecation_warning(f"{t} <{n}>", reason, alternative, stacklevel=3)
issue_deprecation_warning(f"{t} <{n}>", reason, alternative, stacklevel=3) # pyright: ignore[reportDeprecated]
return func(*args, **kwargs)

def actual_decorator(obj: Any) -> Any:
Expand Down Expand Up @@ -113,18 +126,25 @@
yield ws


@deprecated(

Check warning on line 129 in src/qcodes/utils/deprecate.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/utils/deprecate.py#L129

Added line #L129 was not covered by tests
"QCoDeS deprecation logic is deprecated. Use `deprecated` decorator from `typing_extensions`/`warnings` as an alternative.",
category=QCoDeSDeprecationWarning,
)
@contextmanager
def assert_not_deprecated() -> "Iterator[None]":
with _catch_deprecation_warnings() as ws:
yield
assert len(ws) == 0


@deprecated(

Check warning on line 140 in src/qcodes/utils/deprecate.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/utils/deprecate.py#L140

Added line #L140 was not covered by tests
"QCoDeS deprecation logic is deprecated. Use `deprecated` decorator from `typing_extensions`/`warnings` as an alternative.",
category=QCoDeSDeprecationWarning,
)
@contextmanager
def assert_deprecated(message: str) -> "Iterator[None]":
with _catch_deprecation_warnings() as ws:
yield
assert len(ws) == 1
recorded_message = ws[0].message
assert isinstance(recorded_message, Warning)
assert recorded_message.args[0] == message
2 changes: 1 addition & 1 deletion src/qcodes/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from qcodes.parameters.sequence_helpers import is_sequence, is_sequence_of
from qcodes.parameters.sweep_values import make_sweep
from qcodes.parameters.val_mapping import create_on_off_val_mapping
from qcodes.utils.deprecate import deprecate
from qcodes.utils.deprecate import deprecate # pyright: ignore[reportDeprecated]

Check warning on line 20 in src/qcodes/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/utils/helpers.py#L20

Added line #L20 was not covered by tests

from .abstractmethod import qcodes_abstractmethod as abstractmethod
from .attribute_helpers import (
Expand Down
8 changes: 4 additions & 4 deletions tests/sphinx_extension/test_parse_parameter_attr.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import pytest
from sphinx.util.inspect import safe_getattr
from typing_extensions import deprecated

from qcodes.instrument import InstrumentBase, VisaInstrument
from qcodes.sphinx_extensions.parse_parameter_attr import (
ParameterProxy,
qcodes_parameter_attr_getter,
)
from qcodes.utils import deprecate


class DummyTestClass(InstrumentBase):
Expand Down Expand Up @@ -40,7 +40,7 @@ class DummyDecoratedInitTestClass(InstrumentBase):
A class attribute
"""

@deprecate("Deprecate to test that decorated init is handled correctly")
@deprecated("Deprecate to test that decorated init is handled correctly")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

Expand All @@ -50,7 +50,7 @@ def __init__(self, *args, **kwargs):
"""


@deprecate("Deprecate to test that decorated class is handled correctly")
@deprecated("Deprecate to test that decorated class is handled correctly")
class DummyDecoratedClassTestClass(InstrumentBase):
myattr: str = "ClassAttribute"
"""
Expand Down Expand Up @@ -102,7 +102,7 @@ def test_decorated_init_func() -> None:


def test_decorated_class() -> None:
attr = qcodes_parameter_attr_getter(DummyDecoratedClassTestClass, "other_attr")
attr = qcodes_parameter_attr_getter(DummyDecoratedClassTestClass, "other_attr") # pyright: ignore[reportDeprecated]
assert isinstance(attr, ParameterProxy)
assert repr(attr) == '"InstanceAttribute"'

Expand Down
27 changes: 20 additions & 7 deletions tests/test_deprecate.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
import warnings
from contextlib import contextmanager
from typing import TYPE_CHECKING

import pytest

from qcodes.utils.deprecate import (
QCoDeSDeprecationWarning,
_catch_deprecation_warnings,
assert_deprecated,
assert_not_deprecated,
deprecate,
issue_deprecation_warning,
)

if TYPE_CHECKING:
from collections.abc import Iterator


@contextmanager
def assert_deprecated(message: str, n_warnings: int = 1) -> "Iterator[None]":
with _catch_deprecation_warnings() as ws:
yield
assert len(ws) == n_warnings


def test_assert_deprecated_raises() -> None:
with assert_deprecated(
"The use of this function is deprecated, because "
'of this being a test. Use "a real function" as an '
"alternative."
"alternative.",
3,
):
issue_deprecation_warning(
"use of this function", "of this being a test", "a real function"
Expand Down Expand Up @@ -57,7 +69,8 @@ def add_one(x):

with assert_deprecated(
"The function <add_one> is deprecated, because "
"this function is for private use only."
"this function is for private use only.",
n_warnings=3,
):
assert add_one(1) == _add_one(1)

Expand All @@ -68,12 +81,12 @@ def test_deprecated_context_manager() -> None:
issue_deprecation_warning("something")
issue_deprecation_warning("something more")
warnings.warn("Some other warning")
assert len(ws) == 2
assert len(ws) == 6

with pytest.warns(expected_warning=QCoDeSDeprecationWarning) as ws_2:
issue_deprecation_warning("something")
warnings.warn("Some other warning")
assert len(ws_2) == 2
assert len(ws_2) == 4


@deprecate(reason="this is a test")
Expand Down Expand Up @@ -108,7 +121,7 @@ def test_init_uninhibited() -> None:


def test_init_raises() -> None:
with assert_deprecated("The class <C> is deprecated, because this is a test."):
with assert_deprecated("The class <C> is deprecated, because this is a test.", 3):
C("pristine")


Expand All @@ -124,7 +137,7 @@ def test_method_raises() -> None:
c = C("pristine")

with assert_deprecated(
"The function <method> is deprecated, because this is a test."
"The function <method> is deprecated, because this is a test.", 3
):
c.method()

Expand Down
Loading