Repository: openai/openai-python
File: src/openai/_utils/_sync.py (Python)

Code before:
from __future__ import annotations

import sys
import asyncio
import functools
import contextvars
from typing import Any, Dict, List, TypeVar, Callable, Awaitable
from typing_extensions import ParamSpec

T_Retval = TypeVar("T_Retval")
T_ParamSpec = ParamSpec("T_ParamSpec")



if sys.version_info.minor < 9:
    async def _to_thread(
        func: Callable[..., Any], /, *args: List[Any], **kwargs: Dict[str, Any]
    ) -> Any:
        """Asynchronously run function *func* in a separate thread.

        Any *args and **kwargs supplied for this function are directly passed
        to *func*. Also, the current :class:`contextvars.Context` is propagated,
        allowing context variables from the main thread to be accessed in the
        separate thread.

        Return a coroutine that can be awaited to get the eventual result of *func*.
        """
        loop = asyncio.events.get_running_loop()
        ctx = contextvars.copy_context()
        func_call = functools.partial(ctx.run, func, *args, **kwargs)
        return await loop.run_in_executor(None, func_call)

    to_thread: Callable[..., Awaitable[Any]] = _to_thread
else:
    to_thread: Callable[..., Awaitable[Any]] = asyncio.to_thread # type: ignore - to_thread is only defined in python 3.9+

# copied from `asyncer`, https://github.com/tiangolo/asyncer
def asyncify(
    function: Callable[T_ParamSpec, T_Retval],
) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:

Review comment (refactor):
nit: I think you can simplify this by inverting the condition and using `sys.version_info` so that pyright can properly handle each branch without any type ignores
```py
if sys.version_info >= (3, 9):
  to_thread = asyncio.to_thread
else:
  ... # fallback impl here
```

Code after:
from __future__ import annotations

import sys
import asyncio
import functools
import contextvars
from typing import Any, TypeVar, Callable, Awaitable
from typing_extensions import ParamSpec

T_Retval = TypeVar("T_Retval")
T_ParamSpec = ParamSpec("T_ParamSpec")


if sys.version_info >= (3, 9):
    to_thread = asyncio.to_thread
else:
    async def _to_thread(
        func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs
    ) -> Any:
        """Asynchronously run function *func* in a separate thread.

        Any *args and **kwargs supplied for this function are directly passed
        to *func*. Also, the current :class:`contextvars.Context` is propagated,
        allowing context variables from the main thread to be accessed in the
        separate thread.

        Returns a coroutine that can be awaited to get the eventual result of *func*.
        """
        loop = asyncio.events.get_running_loop()
        ctx = contextvars.copy_context()
        func_call = functools.partial(ctx.run, func, *args, **kwargs)
        return await loop.run_in_executor(None, func_call)

    to_thread = _to_thread

# inspired by `asyncer`, https://github.com/tiangolo/asyncer
def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:
    """
    Take a blocking function and create an async one that receives the same
    positional and keyword arguments. For python version 3.9 and above, it uses