Skip to content

Commit 5f28474

Browse files
authored
uvloop fixes (#2297)
- Updates required for uvloop >= 0.22.1, following deprecations in the python API regarding async loop policies. - Updates to pytest to run tests using async correctly - Updates to runtimes so that pytest doesn't load the same module (conftest.py) multiple times. This involves adding __init__.py files in intermediate directories to explicitly define python packages.
1 parent 0679104 commit 5f28474

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2584
-1834
lines changed

mlserver/batching/requests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def _get_data(payload: Union[RequestInput, ResponseOutput]):
1818

1919
def _get_parameters(payload: ResponseOutput) -> DefaultDict[Any, Any]:
2020
parameters = defaultdict(list)
21+
payload_parameters = {}
2122
if payload.parameters is not None:
2223
payload_parameters = payload.parameters.model_dump()
2324
for param_name, param_values in payload_parameters.items():

mlserver/cli/main.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,40 @@
33
"""
44

55
import click
6-
import asyncio
76

87
from functools import wraps
98

109
from .init_project import init_cookiecutter_project
1110

1211
from ..server import MLServer
1312
from ..logging import logger, configure_logger
14-
from ..utils import install_uvloop_event_loop
13+
from ..utils import AsyncManager
1514

1615
from .build import generate_dockerfile, build_image, write_dockerfile
1716
from .serve import load_settings
1817
from ..batch_processing import process_batch, CHOICES_TRANSPORT
1918

19+
CTX_ASYNC_MGR_KEY = "async_manager"
20+
2021

2122
def click_async(f):
2223
@wraps(f)
2324
def wrapper(*args, **kwargs):
24-
return asyncio.run(f(*args, **kwargs))
25+
ctx = click.get_current_context()
26+
async_mgr = ctx.obj[CTX_ASYNC_MGR_KEY]
27+
return async_mgr.run(f(*args, **kwargs))
2528

2629
return wrapper
2730

2831

2932
@click.group()
3033
@click.version_option()
31-
def root():
34+
@click.pass_context
35+
def root(ctx):
3236
"""
3337
Command-line interface to manage MLServer models.
3438
"""
35-
pass
39+
ctx.ensure_object(dict)
3640

3741

3842
@root.command("start")
@@ -265,8 +269,8 @@ async def infer(
265269

266270
def main():
267271
configure_logger()
268-
install_uvloop_event_loop()
269-
root()
272+
async_mgr = AsyncManager()
273+
root(obj={CTX_ASYNC_MGR_KEY: async_mgr})
270274

271275

272276
if __name__ == "__main__":

mlserver/codecs/__init__.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from typing import TYPE_CHECKING
2+
13
from .numpy import NumpyCodec, NumpyRequestCodec
2-
from .pandas import PandasCodec
34
from .string import StringCodec, StringRequestCodec
45
from .base64 import Base64Codec
56
from .datetime import DatetimeCodec
@@ -24,6 +25,9 @@
2425
decode_inference_request,
2526
)
2627

28+
if TYPE_CHECKING: # pragma: no cover - type checking only
29+
from .pandas import PandasCodec # noqa: F401
30+
2731
__all__ = [
2832
"CodecError",
2933
"NumpyCodec",
@@ -49,3 +53,22 @@
4953
"decode_inference_request",
5054
"decode_args",
5155
]
56+
57+
58+
def __getattr__(name: str): # pragma: no cover - lightweight lazy import
59+
if name == "PandasCodec":
60+
return _load_pandas_codec()
61+
62+
raise AttributeError(f"module 'mlserver.codecs' has no attribute {name!r}")
63+
64+
65+
def _load_pandas_codec():
66+
try:
67+
from .pandas import PandasCodec as _PandasCodec # Local import to stay optional
68+
except Exception as exc: # pragma: no cover - propagate useful context
69+
raise ImportError(
70+
"PandasCodec requires the optional 'pandas' dependency"
71+
) from exc
72+
73+
globals()["PandasCodec"] = _PandasCodec
74+
return _PandasCodec

mlserver/codecs/pandas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def encode_response(
115115
payload: pd.DataFrame,
116116
model_version: Optional[str] = None,
117117
use_bytes: bool = True,
118-
**kwargs
118+
**kwargs,
119119
) -> InferenceResponse:
120120
outputs = cls.encode_outputs(payload, use_bytes=use_bytes)
121121

0 commit comments

Comments
 (0)