Skip to content

Commit d7e2ab9

Browse files
authored
Typing fixes (#17000)
1 parent 3328b04 commit d7e2ab9

File tree

4 files changed

+156
-160
lines changed

4 files changed

+156
-160
lines changed

src/lightning/pytorch/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
153153
- Changed minimum supported version of `rich` from `10.14.0` to `12.13.0` ([#16798](https://github.com/Lightning-AI/lightning/pull/16798))
154154

155155

156+
- The `ServableModule` is now an abstract interface ([#17000](https://github.com/Lightning-AI/lightning/pull/17000))
157+
158+
156159
### Deprecated
157160

158161
-

src/lightning/pytorch/serve/servable_module.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
from abc import ABC, abstractmethod
12
from typing import Any, Callable, Dict, Tuple
23

34
import torch
45
from torch import Tensor
56

67

7-
class ServableModule(torch.nn.Module):
8+
class ServableModule(ABC, torch.nn.Module):
89

910
"""The ServableModule provides a simple API to make your model servable.
1011
@@ -56,9 +57,11 @@ def configure_response(self):
5657
assert serve_cb.resp.json() == {"output": [0, 1]}
5758
"""
5859

60+
@abstractmethod
5961
def configure_payload(self) -> Dict[str, Any]:
6062
"""Returns a request payload as a dictionary."""
6163

64+
@abstractmethod
6265
def configure_serialization(self) -> Tuple[Dict[str, Callable], Dict[str, Callable]]:
6366
"""Returns a tuple of dictionaries.
6467
@@ -69,6 +72,7 @@ def configure_serialization(self) -> Tuple[Dict[str, Callable], Dict[str, Callab
6972
and the associated serialization function (e.g function to convert a tensors into payload).
7073
"""
7174

75+
@abstractmethod
7276
def serve_step(self, *args: Tensor, **kwargs: Tensor) -> Dict[str, Tensor]:
7377
r"""
7478
Returns the predictions of your model as a dictionary.
@@ -86,5 +90,6 @@ def serve_step(self, x: torch.Tensor) -> Dict[str, torch.Tensor]:
8690
- ``dict`` - A dictionary with their associated tensors.
8791
"""
8892

93+
@abstractmethod
8994
def configure_response(self) -> Dict[str, Any]:
9095
"""Returns a response to validate the server response."""

src/lightning/pytorch/utilities/parsing.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,12 @@ def clean_namespace(hparams: MutableMapping) -> None:
4545
del hparams[k]
4646

4747

48-
def parse_class_init_keys(
49-
cls: Union[Type["pl.LightningModule"], Type["pl.LightningDataModule"]]
50-
) -> Tuple[str, Optional[str], Optional[str]]:
48+
def parse_class_init_keys(cls: Type) -> Tuple[str, Optional[str], Optional[str]]:
5149
"""Parse key words for standard ``self``, ``*args`` and ``**kwargs``.
5250
5351
Examples:
5452
55-
>>> class Model():
53+
>>> class Model:
5654
... def __init__(self, hparams, *my_args, anykw=42, **my_kwargs):
5755
... pass
5856
>>> parse_class_init_keys(Model)

src/lightning/pytorch/utilities/testing/_runif.py

Lines changed: 145 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from typing import Any, Optional
1818

1919
import torch
20-
from lightning_utilities.core.imports import compare_version, module_available, RequirementCache
20+
from lightning_utilities.core.imports import compare_version, RequirementCache
2121
from packaging.version import Version
2222

2323
from lightning.fabric.accelerators.cuda import num_cuda_devices
@@ -31,15 +31,28 @@
3131
from lightning.pytorch.strategies.deepspeed import _DEEPSPEED_AVAILABLE
3232
from lightning.pytorch.utilities.imports import _OMEGACONF_AVAILABLE, _PSUTIL_AVAILABLE
3333

34-
if module_available("_pytest"):
35-
from _pytest.mark import MarkDecorator
36-
else:
37-
MarkDecorator = Any
38-
3934
_SKLEARN_AVAILABLE = RequirementCache("scikit-learn")
4035

4136

42-
class _RunIf:
37+
def _RunIf(
38+
min_cuda_gpus: int = 0,
39+
min_torch: Optional[str] = None,
40+
max_torch: Optional[str] = None,
41+
min_python: Optional[str] = None,
42+
bf16_cuda: bool = False,
43+
tpu: bool = False,
44+
ipu: bool = False,
45+
hpu: bool = False,
46+
mps: Optional[bool] = None,
47+
skip_windows: bool = False,
48+
standalone: bool = False,
49+
deepspeed: bool = False,
50+
rich: bool = False,
51+
omegaconf: bool = False,
52+
psutil: bool = False,
53+
sklearn: bool = False,
54+
onnx: bool = False,
55+
) -> Any: # not the real return because it would require that pytest is available
4356
"""Wrapper around ``pytest.mark.skipif`` with specific conditions.
4457
4558
Example:
@@ -48,152 +61,129 @@ class _RunIf:
4861
@pytest.mark.parametrize("arg1", [1, 2.0])
4962
def test_wrapper(arg1):
5063
assert arg1 > 0.0
51-
"""
5264
53-
def __new__(
54-
self,
55-
min_cuda_gpus: int = 0,
56-
min_torch: Optional[str] = None,
57-
max_torch: Optional[str] = None,
58-
min_python: Optional[str] = None,
59-
bf16_cuda: bool = False,
60-
tpu: bool = False,
61-
ipu: bool = False,
62-
hpu: bool = False,
63-
mps: Optional[bool] = None,
64-
skip_windows: bool = False,
65-
standalone: bool = False,
66-
deepspeed: bool = False,
67-
rich: bool = False,
68-
omegaconf: bool = False,
69-
psutil: bool = False,
70-
sklearn: bool = False,
71-
onnx: bool = False,
72-
) -> MarkDecorator: # not the real return because it would require that pytest is available
73-
"""Configure.
74-
75-
Args:
76-
min_cuda_gpus: Require this number of gpus and that the ``PL_RUN_CUDA_TESTS=1`` environment variable is set.
77-
min_torch: Require that PyTorch is greater or equal than this version.
78-
max_torch: Require that PyTorch is less than this version.
79-
min_python: Require that Python is greater or equal than this version.
80-
bf16_cuda: Require that CUDA device supports bf16.
81-
tpu: Require that TPU is available.
82-
ipu: Require that IPU is available and that the ``PL_RUN_IPU_TESTS=1`` environment variable is set.
83-
hpu: Require that HPU is available.
84-
mps: If True: Require that MPS (Apple Silicon) is available,
85-
if False: Explicitly Require that MPS is not available
86-
skip_windows: Skip for Windows platform.
87-
standalone: Mark the test as standalone, our CI will run it in a separate process.
88-
This requires that the ``PL_RUN_STANDALONE_TESTS=1`` environment variable is set.
89-
deepspeed: Require that microsoft/DeepSpeed is installed.
90-
rich: Require that willmcgugan/rich is installed.
91-
omegaconf: Require that omry/omegaconf is installed.
92-
psutil: Require that psutil is installed.
93-
sklearn: Require that scikit-learn is installed.
94-
onnx: Require that onnx is installed.
95-
"""
96-
import pytest
97-
98-
conditions = []
99-
reasons = []
100-
kwargs: dict = {} # It's required for our CI to run under the different PL_RUN_X_TESTS
101-
102-
if min_cuda_gpus:
103-
conditions.append(num_cuda_devices() < min_cuda_gpus)
104-
reasons.append(f"GPUs>={min_cuda_gpus}")
105-
# used in conftest.py::pytest_collection_modifyitems
106-
kwargs["min_cuda_gpus"] = True
107-
108-
if min_torch:
109-
# set use_base_version for nightly support
110-
conditions.append(compare_version("torch", operator.lt, min_torch, use_base_version=True))
111-
reasons.append(f"torch>={min_torch}, {torch.__version__} installed")
112-
113-
if max_torch:
114-
# set use_base_version for nightly support
115-
conditions.append(compare_version("torch", operator.ge, max_torch, use_base_version=True))
116-
reasons.append(f"torch<{max_torch}, {torch.__version__} installed")
117-
118-
if min_python:
119-
py_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
120-
conditions.append(Version(py_version) < Version(min_python))
121-
reasons.append(f"python>={min_python}")
122-
123-
if bf16_cuda:
124-
try:
125-
cond = not (torch.cuda.is_available() and torch.cuda.is_bf16_supported())
126-
except (AssertionError, RuntimeError) as e:
127-
# AssertionError: Torch not compiled with CUDA enabled
128-
# RuntimeError: Found no NVIDIA driver on your system.
129-
is_unrelated = "Found no NVIDIA driver" not in str(e) or "Torch not compiled with CUDA" not in str(e)
130-
if is_unrelated:
131-
raise e
132-
cond = True
133-
134-
conditions.append(cond)
135-
reasons.append("CUDA device bf16")
136-
137-
if skip_windows:
138-
conditions.append(sys.platform == "win32")
139-
reasons.append("unimplemented on Windows")
140-
141-
if tpu:
142-
conditions.append(not TPUAccelerator.is_available())
143-
reasons.append("TPU")
144-
# used in conftest.py::pytest_collection_modifyitems
145-
kwargs["tpu"] = True
146-
147-
if ipu:
148-
conditions.append(not _IPU_AVAILABLE)
149-
reasons.append("IPU")
150-
# used in conftest.py::pytest_collection_modifyitems
151-
kwargs["ipu"] = True
152-
153-
if hpu:
154-
conditions.append(not _HPU_AVAILABLE)
155-
reasons.append("HPU")
156-
157-
if mps is not None:
158-
if mps:
159-
conditions.append(not MPSAccelerator.is_available())
160-
reasons.append("MPS")
161-
else:
162-
conditions.append(MPSAccelerator.is_available())
163-
reasons.append("not MPS")
164-
165-
if standalone:
166-
env_flag = os.getenv("PL_RUN_STANDALONE_TESTS", "0")
167-
conditions.append(env_flag != "1")
168-
reasons.append("Standalone execution")
169-
# used in conftest.py::pytest_collection_modifyitems
170-
kwargs["standalone"] = True
171-
172-
if deepspeed:
173-
conditions.append(not _DEEPSPEED_AVAILABLE)
174-
reasons.append("Deepspeed")
175-
176-
if rich:
177-
conditions.append(not _RICH_AVAILABLE)
178-
reasons.append("Rich")
179-
180-
if omegaconf:
181-
conditions.append(not _OMEGACONF_AVAILABLE)
182-
reasons.append("omegaconf")
183-
184-
if psutil:
185-
conditions.append(not _PSUTIL_AVAILABLE)
186-
reasons.append("psutil")
187-
188-
if sklearn:
189-
conditions.append(not _SKLEARN_AVAILABLE)
190-
reasons.append("scikit-learn")
191-
192-
if onnx:
193-
conditions.append(_TORCH_GREATER_EQUAL_2_0 and not _ONNX_AVAILABLE)
194-
reasons.append("onnx")
195-
196-
reasons = [rs for cond, rs in zip(conditions, reasons) if cond]
197-
kwargs.pop("condition", None)
198-
kwargs.pop("reason", None)
199-
return pytest.mark.skipif(condition=any(conditions), reason=f"Requires: [{' + '.join(reasons)}]", **kwargs)
65+
Args:
66+
min_cuda_gpus: Require this number of gpus and that the ``PL_RUN_CUDA_TESTS=1`` environment variable is set.
67+
min_torch: Require that PyTorch is greater or equal than this version.
68+
max_torch: Require that PyTorch is less than this version.
69+
min_python: Require that Python is greater or equal than this version.
70+
bf16_cuda: Require that CUDA device supports bf16.
71+
tpu: Require that TPU is available.
72+
ipu: Require that IPU is available and that the ``PL_RUN_IPU_TESTS=1`` environment variable is set.
73+
hpu: Require that HPU is available.
74+
mps: If True: Require that MPS (Apple Silicon) is available,
75+
if False: Explicitly Require that MPS is not available
76+
skip_windows: Skip for Windows platform.
77+
standalone: Mark the test as standalone, our CI will run it in a separate process.
78+
This requires that the ``PL_RUN_STANDALONE_TESTS=1`` environment variable is set.
79+
deepspeed: Require that microsoft/DeepSpeed is installed.
80+
rich: Require that willmcgugan/rich is installed.
81+
omegaconf: Require that omry/omegaconf is installed.
82+
psutil: Require that psutil is installed.
83+
sklearn: Require that scikit-learn is installed.
84+
onnx: Require that onnx is installed.
85+
"""
86+
import pytest
87+
88+
conditions = []
89+
reasons = []
90+
kwargs: dict = {} # It's required for our CI to run under the different PL_RUN_X_TESTS
91+
92+
if min_cuda_gpus:
93+
conditions.append(num_cuda_devices() < min_cuda_gpus)
94+
reasons.append(f"GPUs>={min_cuda_gpus}")
95+
# used in conftest.py::pytest_collection_modifyitems
96+
kwargs["min_cuda_gpus"] = True
97+
98+
if min_torch:
99+
# set use_base_version for nightly support
100+
conditions.append(compare_version("torch", operator.lt, min_torch, use_base_version=True))
101+
reasons.append(f"torch>={min_torch}, {torch.__version__} installed")
102+
103+
if max_torch:
104+
# set use_base_version for nightly support
105+
conditions.append(compare_version("torch", operator.ge, max_torch, use_base_version=True))
106+
reasons.append(f"torch<{max_torch}, {torch.__version__} installed")
107+
108+
if min_python:
109+
py_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
110+
conditions.append(Version(py_version) < Version(min_python))
111+
reasons.append(f"python>={min_python}")
112+
113+
if bf16_cuda:
114+
try:
115+
cond = not (torch.cuda.is_available() and torch.cuda.is_bf16_supported())
116+
except (AssertionError, RuntimeError) as e:
117+
# AssertionError: Torch not compiled with CUDA enabled
118+
# RuntimeError: Found no NVIDIA driver on your system.
119+
is_unrelated = "Found no NVIDIA driver" not in str(e) or "Torch not compiled with CUDA" not in str(e)
120+
if is_unrelated:
121+
raise e
122+
cond = True
123+
124+
conditions.append(cond)
125+
reasons.append("CUDA device bf16")
126+
127+
if skip_windows:
128+
conditions.append(sys.platform == "win32")
129+
reasons.append("unimplemented on Windows")
130+
131+
if tpu:
132+
conditions.append(not TPUAccelerator.is_available())
133+
reasons.append("TPU")
134+
# used in conftest.py::pytest_collection_modifyitems
135+
kwargs["tpu"] = True
136+
137+
if ipu:
138+
conditions.append(not _IPU_AVAILABLE)
139+
reasons.append("IPU")
140+
# used in conftest.py::pytest_collection_modifyitems
141+
kwargs["ipu"] = True
142+
143+
if hpu:
144+
conditions.append(not _HPU_AVAILABLE)
145+
reasons.append("HPU")
146+
147+
if mps is not None:
148+
if mps:
149+
conditions.append(not MPSAccelerator.is_available())
150+
reasons.append("MPS")
151+
else:
152+
conditions.append(MPSAccelerator.is_available())
153+
reasons.append("not MPS")
154+
155+
if standalone:
156+
env_flag = os.getenv("PL_RUN_STANDALONE_TESTS", "0")
157+
conditions.append(env_flag != "1")
158+
reasons.append("Standalone execution")
159+
# used in conftest.py::pytest_collection_modifyitems
160+
kwargs["standalone"] = True
161+
162+
if deepspeed:
163+
conditions.append(not _DEEPSPEED_AVAILABLE)
164+
reasons.append("Deepspeed")
165+
166+
if rich:
167+
conditions.append(not _RICH_AVAILABLE)
168+
reasons.append("Rich")
169+
170+
if omegaconf:
171+
conditions.append(not _OMEGACONF_AVAILABLE)
172+
reasons.append("omegaconf")
173+
174+
if psutil:
175+
conditions.append(not _PSUTIL_AVAILABLE)
176+
reasons.append("psutil")
177+
178+
if sklearn:
179+
conditions.append(not _SKLEARN_AVAILABLE)
180+
reasons.append("scikit-learn")
181+
182+
if onnx:
183+
conditions.append(_TORCH_GREATER_EQUAL_2_0 and not _ONNX_AVAILABLE)
184+
reasons.append("onnx")
185+
186+
reasons = [rs for cond, rs in zip(conditions, reasons) if cond]
187+
kwargs.pop("condition", None)
188+
kwargs.pop("reason", None)
189+
return pytest.mark.skipif(condition=any(conditions), reason=f"Requires: [{' + '.join(reasons)}]", **kwargs)

0 commit comments

Comments
 (0)