Voice et bot modif
This commit is contained in:
parent
189d56026b
commit
7333a22bcd
10774 changed files with 634644 additions and 933308 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -53,7 +53,7 @@ from typing import (
|
|||
IO,
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Optional,
|
||||
ParamSpec,
|
||||
TypeVar,
|
||||
cast,
|
||||
)
|
||||
|
|
@ -78,7 +78,6 @@ from .._core._exceptions import (
|
|||
EndOfStream,
|
||||
RunFinishedError,
|
||||
WouldBlock,
|
||||
iterate_exceptions,
|
||||
)
|
||||
from .._core._sockets import convert_ipv6_sockaddr
|
||||
from .._core._streams import create_memory_object_stream
|
||||
|
|
@ -109,11 +108,6 @@ if TYPE_CHECKING:
|
|||
else:
|
||||
FileDescriptorLike = object
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import ParamSpec
|
||||
else:
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from asyncio import Runner
|
||||
from typing import TypeVarTuple, Unpack
|
||||
|
|
@ -498,17 +492,39 @@ class CancelScope(BaseCancelScope):
|
|||
self._pending_uncancellations -= 1
|
||||
|
||||
# Update cancelled_caught and check for exceptions we must not swallow
|
||||
cannot_swallow_exc_val = False
|
||||
if exc_val is not None:
|
||||
for exc in iterate_exceptions(exc_val):
|
||||
if isinstance(exc, CancelledError) and is_anyio_cancellation(
|
||||
exc
|
||||
):
|
||||
self._cancelled_caught = True
|
||||
else:
|
||||
cannot_swallow_exc_val = True
|
||||
if isinstance(exc_val, BaseExceptionGroup):
|
||||
cancelleds_caught, remaining = exc_val.split(
|
||||
lambda exc: (
|
||||
isinstance(exc, CancelledError)
|
||||
and is_anyio_cancellation(exc)
|
||||
)
|
||||
)
|
||||
|
||||
return self._cancelled_caught and not cannot_swallow_exc_val
|
||||
if cancelleds_caught is None:
|
||||
return False
|
||||
|
||||
self._cancelled_caught = True
|
||||
|
||||
if remaining is None:
|
||||
return True
|
||||
|
||||
context = remaining.__context__
|
||||
try:
|
||||
# Preserve __cause__ and __suppress_context__ by avoiding `raise
|
||||
# ... from ...`
|
||||
raise remaining
|
||||
finally:
|
||||
# Preserve __context__
|
||||
remaining.__context__ = context
|
||||
del context
|
||||
else:
|
||||
if isinstance(exc_val, CancelledError) and is_anyio_cancellation(
|
||||
exc_val
|
||||
):
|
||||
self._cancelled_caught = True
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
if self._pending_uncancellations:
|
||||
assert self._parent_scope is not None
|
||||
|
|
@ -928,7 +944,7 @@ class TaskGroup(abc.TaskGroup):
|
|||
# Threads
|
||||
#
|
||||
|
||||
_Retval_Queue_Type = tuple[Optional[T_Retval], Optional[BaseException]]
|
||||
_Retval_Queue_Type = tuple[T_Retval | None, BaseException | None]
|
||||
|
||||
|
||||
class WorkerThread(Thread):
|
||||
|
|
@ -1139,7 +1155,7 @@ def _forcibly_shutdown_process_pool_on_exit(
|
|||
|
||||
# Close as much as possible (w/o async/await) to avoid warnings
|
||||
for process in workers.copy():
|
||||
if process.returncode is None:
|
||||
if process.returncode is not None:
|
||||
continue
|
||||
|
||||
process._stdin._stream._transport.close() # type: ignore[union-attr]
|
||||
|
|
@ -1192,8 +1208,7 @@ class StreamProtocol(asyncio.Protocol):
|
|||
|
||||
def connection_lost(self, exc: Exception | None) -> None:
|
||||
if exc:
|
||||
self.exception = BrokenResourceError()
|
||||
self.exception.__cause__ = exc
|
||||
self.exception = exc
|
||||
|
||||
self.read_event.set()
|
||||
self.write_event.set()
|
||||
|
|
@ -1277,7 +1292,7 @@ class SocketStream(abc.SocketStream):
|
|||
if self._closed:
|
||||
raise ClosedResourceError from None
|
||||
elif self._protocol.exception:
|
||||
raise self._protocol.exception from None
|
||||
raise BrokenResourceError from self._protocol.exception
|
||||
else:
|
||||
raise EndOfStream from None
|
||||
|
||||
|
|
@ -1300,7 +1315,7 @@ class SocketStream(abc.SocketStream):
|
|||
if self._closed:
|
||||
raise ClosedResourceError
|
||||
elif self._protocol.exception is not None:
|
||||
raise self._protocol.exception
|
||||
raise BrokenResourceError from self._protocol.exception
|
||||
|
||||
try:
|
||||
self._transport.write(item)
|
||||
|
|
@ -2243,6 +2258,7 @@ class TestRunner(abc.TestRunner):
|
|||
async def _call_in_runner_task(
|
||||
self,
|
||||
func: Callable[P, Awaitable[T_Retval]],
|
||||
/,
|
||||
*args: P.args,
|
||||
**kwargs: P.kwargs,
|
||||
) -> T_Retval:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ from typing import (
|
|||
Any,
|
||||
Generic,
|
||||
NoReturn,
|
||||
ParamSpec,
|
||||
TypeVar,
|
||||
cast,
|
||||
overload,
|
||||
|
|
@ -84,11 +85,6 @@ from ..streams.memory import MemoryObjectSendStream
|
|||
if TYPE_CHECKING:
|
||||
from _typeshed import FileDescriptorLike
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import ParamSpec
|
||||
else:
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from typing import TypeVarTuple, Unpack
|
||||
else:
|
||||
|
|
@ -887,6 +883,7 @@ class TestRunner(abc.TestRunner):
|
|||
def _call_in_runner_task(
|
||||
self,
|
||||
func: Callable[P, Awaitable[T_Retval]],
|
||||
/,
|
||||
*args: P.args,
|
||||
**kwargs: P.kwargs,
|
||||
) -> T_Retval:
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -301,6 +301,11 @@ class Path:
|
|||
def __fspath__(self) -> str:
|
||||
return self._path.__fspath__()
|
||||
|
||||
if sys.version_info >= (3, 15):
|
||||
|
||||
def __vfspath__(self) -> str:
|
||||
return self._path.__vfspath__()
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self._path.__str__()
|
||||
|
||||
|
|
@ -561,8 +566,10 @@ class Path:
|
|||
os.path.ismount, self._path, abandon_on_cancel=True
|
||||
)
|
||||
|
||||
def is_reserved(self) -> bool:
|
||||
return self._path.is_reserved()
|
||||
if sys.version_info < (3, 15):
|
||||
|
||||
def is_reserved(self) -> bool:
|
||||
return self._path.is_reserved()
|
||||
|
||||
async def is_socket(self) -> bool:
|
||||
return await to_thread.run_sync(self._path.is_socket, abandon_on_cancel=True)
|
||||
|
|
@ -784,14 +791,9 @@ class Path:
|
|||
errors: str | None = None,
|
||||
newline: str | None = None,
|
||||
) -> int:
|
||||
# Path.write_text() does not support the "newline" parameter before Python 3.10
|
||||
def sync_write_text() -> int:
|
||||
with self._path.open(
|
||||
"w", encoding=encoding, errors=errors, newline=newline
|
||||
) as fp:
|
||||
return fp.write(data)
|
||||
|
||||
return await to_thread.run_sync(sync_write_text)
|
||||
return await to_thread.run_sync(
|
||||
self._path.write_text, data, encoding, errors, newline
|
||||
)
|
||||
|
||||
|
||||
PathLike.register(Path)
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from collections.abc import AsyncIterable, Iterable, Mapping, Sequence
|
||||
from io import BytesIO
|
||||
from os import PathLike
|
||||
from subprocess import PIPE, CalledProcessError, CompletedProcess
|
||||
from typing import IO, Any, Union, cast
|
||||
from typing import IO, Any, TypeAlias, cast
|
||||
|
||||
from ..abc import Process
|
||||
from ._eventloop import get_async_backend
|
||||
from ._tasks import create_task_group
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"]
|
||||
StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes]
|
||||
|
||||
|
||||
async def run_process(
|
||||
|
|
|
|||
|
|
@ -335,6 +335,10 @@ class Condition:
|
|||
except BaseException:
|
||||
if not event.is_set():
|
||||
self._waiters.remove(event)
|
||||
elif self._waiters:
|
||||
# This task was notified by could not act on it, so pass
|
||||
# it on to the next task
|
||||
self._waiters.popleft().set()
|
||||
|
||||
raise
|
||||
finally:
|
||||
|
|
|
|||
|
|
@ -463,7 +463,6 @@ class TemporaryDirectory(Generic[AnyStr]):
|
|||
:param prefix: Prefix to be added to the temporary directory name.
|
||||
:param dir: The parent directory where the temporary directory is created.
|
||||
:param ignore_cleanup_errors: Whether to ignore errors during cleanup
|
||||
(Python 3.10+).
|
||||
:param delete: Whether to delete the directory upon closing (Python 3.12+).
|
||||
"""
|
||||
|
||||
|
|
@ -489,10 +488,8 @@ class TemporaryDirectory(Generic[AnyStr]):
|
|||
"suffix": self.suffix,
|
||||
"prefix": self.prefix,
|
||||
"dir": self.dir,
|
||||
"ignore_cleanup_errors": self.ignore_cleanup_errors,
|
||||
}
|
||||
if sys.version_info >= (3, 10):
|
||||
params["ignore_cleanup_errors"] = self.ignore_cleanup_errors
|
||||
|
||||
if sys.version_info >= (3, 12):
|
||||
params["delete"] = self.delete
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -12,8 +12,8 @@ from typing import (
|
|||
IO,
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
TypeAlias,
|
||||
TypeVar,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
|
||||
|
|
@ -22,11 +22,6 @@ if sys.version_info >= (3, 11):
|
|||
else:
|
||||
from typing_extensions import TypeVarTuple, Unpack
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _typeshed import FileDescriptorLike
|
||||
|
||||
|
|
@ -49,7 +44,7 @@ if TYPE_CHECKING:
|
|||
|
||||
T_Retval = TypeVar("T_Retval")
|
||||
PosArgsT = TypeVarTuple("PosArgsT")
|
||||
StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"]
|
||||
StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes]
|
||||
|
||||
|
||||
class AsyncBackend(metaclass=ABCMeta):
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@ from __future__ import annotations
|
|||
|
||||
import errno
|
||||
import socket
|
||||
import sys
|
||||
from abc import abstractmethod
|
||||
from collections.abc import Callable, Collection, Mapping
|
||||
from contextlib import AsyncExitStack
|
||||
from io import IOBase
|
||||
from ipaddress import IPv4Address, IPv6Address
|
||||
from socket import AddressFamily
|
||||
from typing import Any, TypeVar, Union
|
||||
from typing import Any, TypeAlias, TypeVar
|
||||
|
||||
from .._core._eventloop import get_async_backend
|
||||
from .._core._typedattr import (
|
||||
|
|
@ -20,14 +19,9 @@ from .._core._typedattr import (
|
|||
from ._streams import ByteStream, Listener, UnreliableObjectStream
|
||||
from ._tasks import TaskGroup
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
IPAddressType: TypeAlias = Union[str, IPv4Address, IPv6Address]
|
||||
IPAddressType: TypeAlias = str | IPv4Address | IPv6Address
|
||||
IPSockAddrType: TypeAlias = tuple[str, int]
|
||||
SockAddrType: TypeAlias = Union[IPSockAddrType, str]
|
||||
SockAddrType: TypeAlias = IPSockAddrType | str
|
||||
UDPPacketType: TypeAlias = tuple[bytes, IPSockAddrType]
|
||||
UNIXDatagramPacketType: TypeAlias = tuple[bytes, str]
|
||||
T_Retval = TypeVar("T_Retval")
|
||||
|
|
@ -166,8 +160,8 @@ class _SocketProvider(TypedAttributeProvider):
|
|||
|
||||
# Provide local and remote ports for IP based sockets
|
||||
if self._raw_socket.family in (AddressFamily.AF_INET, AddressFamily.AF_INET6):
|
||||
attributes[SocketAttribute.local_port] = (
|
||||
lambda: self._raw_socket.getsockname()[1]
|
||||
attributes[SocketAttribute.local_port] = lambda: (
|
||||
self._raw_socket.getsockname()[1]
|
||||
)
|
||||
if peername is not None:
|
||||
remote_port = peername[1]
|
||||
|
|
|
|||
|
|
@ -1,20 +1,14 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from collections.abc import Callable
|
||||
from typing import Any, Generic, TypeVar, Union
|
||||
from typing import Any, Generic, TypeAlias, TypeVar
|
||||
|
||||
from .._core._exceptions import EndOfStream
|
||||
from .._core._typedattr import TypedAttributeProvider
|
||||
from ._resources import AsyncResource
|
||||
from ._tasks import TaskGroup
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
T_Item = TypeVar("T_Item")
|
||||
T_co = TypeVar("T_co", covariant=True)
|
||||
T_contra = TypeVar("T_contra", contravariant=True)
|
||||
|
|
@ -178,21 +172,21 @@ class ByteStream(ByteReceiveStream, ByteSendStream):
|
|||
|
||||
|
||||
#: Type alias for all unreliable bytes-oriented receive streams.
|
||||
AnyUnreliableByteReceiveStream: TypeAlias = Union[
|
||||
UnreliableObjectReceiveStream[bytes], ByteReceiveStream
|
||||
]
|
||||
AnyUnreliableByteReceiveStream: TypeAlias = (
|
||||
UnreliableObjectReceiveStream[bytes] | ByteReceiveStream
|
||||
)
|
||||
#: Type alias for all unreliable bytes-oriented send streams.
|
||||
AnyUnreliableByteSendStream: TypeAlias = Union[
|
||||
UnreliableObjectSendStream[bytes], ByteSendStream
|
||||
]
|
||||
AnyUnreliableByteSendStream: TypeAlias = (
|
||||
UnreliableObjectSendStream[bytes] | ByteSendStream
|
||||
)
|
||||
#: Type alias for all unreliable bytes-oriented streams.
|
||||
AnyUnreliableByteStream: TypeAlias = Union[UnreliableObjectStream[bytes], ByteStream]
|
||||
AnyUnreliableByteStream: TypeAlias = UnreliableObjectStream[bytes] | ByteStream
|
||||
#: Type alias for all bytes-oriented receive streams.
|
||||
AnyByteReceiveStream: TypeAlias = Union[ObjectReceiveStream[bytes], ByteReceiveStream]
|
||||
AnyByteReceiveStream: TypeAlias = ObjectReceiveStream[bytes] | ByteReceiveStream
|
||||
#: Type alias for all bytes-oriented send streams.
|
||||
AnyByteSendStream: TypeAlias = Union[ObjectSendStream[bytes], ByteSendStream]
|
||||
AnyByteSendStream: TypeAlias = ObjectSendStream[bytes] | ByteSendStream
|
||||
#: Type alias for all bytes-oriented streams.
|
||||
AnyByteStream: TypeAlias = Union[ObjectStream[bytes], ByteStream]
|
||||
AnyByteStream: TypeAlias = ObjectStream[bytes] | ByteStream
|
||||
|
||||
|
||||
class Listener(Generic[T_co], AsyncResource, TypedAttributeProvider):
|
||||
|
|
@ -234,6 +228,6 @@ class ByteStreamConnectable(metaclass=ABCMeta):
|
|||
|
||||
|
||||
#: Type alias for all connectables returning bytestreams or bytes-oriented object streams
|
||||
AnyByteStreamConnectable: TypeAlias = Union[
|
||||
ObjectStreamConnectable[bytes], ByteStreamConnectable
|
||||
]
|
||||
AnyByteStreamConnectable: TypeAlias = (
|
||||
ObjectStreamConnectable[bytes] | ByteStreamConnectable
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ from typing import (
|
|||
)
|
||||
from weakref import WeakKeyDictionary
|
||||
|
||||
from ._core._eventloop import current_time
|
||||
from ._core._synchronization import Lock
|
||||
from .lowlevel import RunVar, checkpoint
|
||||
|
||||
|
|
@ -48,7 +49,11 @@ P = ParamSpec("P")
|
|||
lru_cache_items: RunVar[
|
||||
WeakKeyDictionary[
|
||||
AsyncLRUCacheWrapper[Any, Any],
|
||||
OrderedDict[Hashable, tuple[_InitialMissingType, Lock] | tuple[Any, None]],
|
||||
OrderedDict[
|
||||
Hashable,
|
||||
tuple[_InitialMissingType, Lock, float | None]
|
||||
| tuple[Any, None, float | None],
|
||||
],
|
||||
]
|
||||
] = RunVar("lru_cache_items")
|
||||
|
||||
|
|
@ -65,12 +70,14 @@ class AsyncCacheInfo(NamedTuple):
|
|||
misses: int
|
||||
maxsize: int | None
|
||||
currsize: int
|
||||
ttl: int | None
|
||||
|
||||
|
||||
class AsyncCacheParameters(TypedDict):
|
||||
maxsize: int | None
|
||||
typed: bool
|
||||
always_checkpoint: bool
|
||||
ttl: int | None
|
||||
|
||||
|
||||
class _LRUMethodWrapper(Generic[T]):
|
||||
|
|
@ -102,6 +109,7 @@ class AsyncLRUCacheWrapper(Generic[P, T]):
|
|||
maxsize: int | None,
|
||||
typed: bool,
|
||||
always_checkpoint: bool,
|
||||
ttl: int | None,
|
||||
):
|
||||
self.__wrapped__ = func
|
||||
self._hits: int = 0
|
||||
|
|
@ -110,16 +118,20 @@ class AsyncLRUCacheWrapper(Generic[P, T]):
|
|||
self._currsize: int = 0
|
||||
self._typed = typed
|
||||
self._always_checkpoint = always_checkpoint
|
||||
self._ttl = ttl
|
||||
update_wrapper(self, func)
|
||||
|
||||
def cache_info(self) -> AsyncCacheInfo:
|
||||
return AsyncCacheInfo(self._hits, self._misses, self._maxsize, self._currsize)
|
||||
return AsyncCacheInfo(
|
||||
self._hits, self._misses, self._maxsize, self._currsize, self._ttl
|
||||
)
|
||||
|
||||
def cache_parameters(self) -> AsyncCacheParameters:
|
||||
return {
|
||||
"maxsize": self._maxsize,
|
||||
"typed": self._typed,
|
||||
"always_checkpoint": self._always_checkpoint,
|
||||
"ttl": self._ttl,
|
||||
}
|
||||
|
||||
def cache_clear(self) -> None:
|
||||
|
|
@ -158,23 +170,33 @@ class AsyncLRUCacheWrapper(Generic[P, T]):
|
|||
|
||||
cached_value: T | _InitialMissingType
|
||||
try:
|
||||
cached_value, lock = cache_entry[key]
|
||||
cached_value, lock, expires_at = cache_entry[key]
|
||||
except KeyError:
|
||||
# We're the first task to call this function
|
||||
cached_value, lock = (
|
||||
cached_value, lock, expires_at = (
|
||||
initial_missing,
|
||||
Lock(fast_acquire=not self._always_checkpoint),
|
||||
None,
|
||||
)
|
||||
cache_entry[key] = cached_value, lock
|
||||
cache_entry[key] = cached_value, lock, expires_at
|
||||
|
||||
if lock is None:
|
||||
# The value was already cached
|
||||
self._hits += 1
|
||||
cache_entry.move_to_end(key)
|
||||
if self._always_checkpoint:
|
||||
await checkpoint()
|
||||
if expires_at is not None and current_time() >= expires_at:
|
||||
self._currsize -= 1
|
||||
cached_value, lock, expires_at = (
|
||||
initial_missing,
|
||||
Lock(fast_acquire=not self._always_checkpoint),
|
||||
None,
|
||||
)
|
||||
cache_entry[key] = cached_value, lock, expires_at
|
||||
else:
|
||||
# The value was already cached
|
||||
self._hits += 1
|
||||
cache_entry.move_to_end(key)
|
||||
if self._always_checkpoint:
|
||||
await checkpoint()
|
||||
|
||||
return cast(T, cached_value)
|
||||
return cast(T, cached_value)
|
||||
|
||||
async with lock:
|
||||
# Check if another task filled the cache while we acquired the lock
|
||||
|
|
@ -186,7 +208,10 @@ class AsyncLRUCacheWrapper(Generic[P, T]):
|
|||
self._currsize += 1
|
||||
|
||||
value = await self.__wrapped__(*args, **kwargs)
|
||||
cache_entry[key] = value, None
|
||||
expires_at = (
|
||||
current_time() + self._ttl if self._ttl is not None else None
|
||||
)
|
||||
cache_entry[key] = value, None, expires_at
|
||||
else:
|
||||
# Another task filled the cache while we were waiting for the lock
|
||||
self._hits += 1
|
||||
|
|
@ -204,10 +229,13 @@ class AsyncLRUCacheWrapper(Generic[P, T]):
|
|||
|
||||
|
||||
class _LRUCacheWrapper(Generic[T]):
|
||||
def __init__(self, maxsize: int | None, typed: bool, always_checkpoint: bool):
|
||||
def __init__(
|
||||
self, maxsize: int | None, typed: bool, always_checkpoint: bool, ttl: int | None
|
||||
):
|
||||
self._maxsize = maxsize
|
||||
self._typed = typed
|
||||
self._always_checkpoint = always_checkpoint
|
||||
self._ttl = ttl
|
||||
|
||||
@overload
|
||||
def __call__( # type: ignore[overload-overlap]
|
||||
|
|
@ -224,7 +252,7 @@ class _LRUCacheWrapper(Generic[T]):
|
|||
) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]:
|
||||
if iscoroutinefunction(f):
|
||||
return AsyncLRUCacheWrapper(
|
||||
f, self._maxsize, self._typed, self._always_checkpoint
|
||||
f, self._maxsize, self._typed, self._always_checkpoint, self._ttl
|
||||
)
|
||||
|
||||
return functools.lru_cache(maxsize=self._maxsize, typed=self._typed)(f) # type: ignore[arg-type]
|
||||
|
|
@ -254,7 +282,11 @@ def cache(
|
|||
|
||||
@overload
|
||||
def lru_cache(
|
||||
*, maxsize: int | None = ..., typed: bool = ..., always_checkpoint: bool = ...
|
||||
*,
|
||||
maxsize: int | None = ...,
|
||||
typed: bool = ...,
|
||||
always_checkpoint: bool = ...,
|
||||
ttl: int | None = ...,
|
||||
) -> _LRUCacheWrapper[Any]: ...
|
||||
|
||||
|
||||
|
|
@ -275,6 +307,7 @@ def lru_cache(
|
|||
maxsize: int | None = 128,
|
||||
typed: bool = False,
|
||||
always_checkpoint: bool = False,
|
||||
ttl: int | None = None,
|
||||
) -> (
|
||||
AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T] | _LRUCacheWrapper[Any]
|
||||
):
|
||||
|
|
@ -286,17 +319,18 @@ def lru_cache(
|
|||
|
||||
:param always_checkpoint: if ``True``, every call to the cached function will be
|
||||
guaranteed to yield control to the event loop at least once
|
||||
:param ttl: time in seconds after which to invalidate cache entries
|
||||
|
||||
.. note:: Caches and locks are managed on a per-event loop basis.
|
||||
|
||||
"""
|
||||
if func is None:
|
||||
return _LRUCacheWrapper[Any](maxsize, typed, always_checkpoint)
|
||||
return _LRUCacheWrapper[Any](maxsize, typed, always_checkpoint, ttl)
|
||||
|
||||
if not callable(func):
|
||||
raise TypeError("the first argument must be callable")
|
||||
|
||||
return _LRUCacheWrapper[T](maxsize, typed, always_checkpoint)(func)
|
||||
return _LRUCacheWrapper[T](maxsize, typed, always_checkpoint, ttl)(func)
|
||||
|
||||
|
||||
@overload
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import socket
|
||||
import sys
|
||||
from collections.abc import Callable, Generator, Iterator
|
||||
|
|
@ -8,8 +9,10 @@ from inspect import isasyncgenfunction, iscoroutinefunction, ismethod
|
|||
from typing import Any, cast
|
||||
|
||||
import pytest
|
||||
from _pytest.fixtures import SubRequest
|
||||
from _pytest.fixtures import FuncFixtureInfo, SubRequest
|
||||
from _pytest.outcomes import Exit
|
||||
from _pytest.python import CallSpec2
|
||||
from _pytest.scope import Scope
|
||||
|
||||
from . import get_available_backends
|
||||
from ._core._eventloop import (
|
||||
|
|
@ -163,6 +166,64 @@ def pytest_pycollect_makeitem(
|
|||
pytest.mark.usefixtures("anyio_backend")(obj)
|
||||
|
||||
|
||||
def pytest_collection_finish(session: pytest.Session) -> None:
|
||||
for i, item in reversed(list(enumerate(session.items))):
|
||||
if (
|
||||
isinstance(item, pytest.Function)
|
||||
and iscoroutinefunction(item.function)
|
||||
and item.get_closest_marker("anyio") is not None
|
||||
and "anyio_backend" not in item.fixturenames
|
||||
):
|
||||
new_items = []
|
||||
try:
|
||||
cs_fields = {f.name for f in dataclasses.fields(CallSpec2)}
|
||||
except TypeError:
|
||||
cs_fields = set()
|
||||
|
||||
for param_index, backend in enumerate(get_available_backends()):
|
||||
if "_arg2scope" in cs_fields: # pytest >= 8
|
||||
callspec = CallSpec2(
|
||||
params={"anyio_backend": backend},
|
||||
indices={"anyio_backend": param_index},
|
||||
_arg2scope={"anyio_backend": Scope.Module},
|
||||
_idlist=[backend],
|
||||
marks=[],
|
||||
)
|
||||
else: # pytest 7.x
|
||||
callspec = CallSpec2( # type: ignore[call-arg]
|
||||
funcargs={},
|
||||
params={"anyio_backend": backend},
|
||||
indices={"anyio_backend": param_index},
|
||||
arg2scope={"anyio_backend": Scope.Module},
|
||||
idlist=[backend],
|
||||
marks=[],
|
||||
)
|
||||
|
||||
fi = item._fixtureinfo
|
||||
new_names_closure = list(fi.names_closure)
|
||||
if "anyio_backend" not in new_names_closure:
|
||||
new_names_closure.append("anyio_backend")
|
||||
|
||||
new_fixtureinfo = FuncFixtureInfo(
|
||||
argnames=fi.argnames,
|
||||
initialnames=fi.initialnames,
|
||||
names_closure=new_names_closure,
|
||||
name2fixturedefs=fi.name2fixturedefs,
|
||||
)
|
||||
new_item = pytest.Function.from_parent(
|
||||
item.parent,
|
||||
name=f"{item.originalname}[{backend}]",
|
||||
callspec=callspec,
|
||||
callobj=item.obj,
|
||||
fixtureinfo=new_fixtureinfo,
|
||||
keywords=item.keywords,
|
||||
originalname=item.originalname,
|
||||
)
|
||||
new_items.append(new_item)
|
||||
|
||||
session.items[i : i + 1] = new_items
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_pyfunc_call(pyfuncitem: Any) -> bool | None:
|
||||
def run_with_hypothesis(**kwargs: Any) -> None:
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -10,7 +10,7 @@ from collections.abc import Callable, Mapping
|
|||
from io import SEEK_SET, UnsupportedOperation
|
||||
from os import PathLike
|
||||
from pathlib import Path
|
||||
from typing import Any, BinaryIO, cast
|
||||
from typing import IO, Any
|
||||
|
||||
from .. import (
|
||||
BrokenResourceError,
|
||||
|
|
@ -25,7 +25,7 @@ from ..abc import ByteReceiveStream, ByteSendStream
|
|||
|
||||
class FileStreamAttribute(TypedAttributeSet):
|
||||
#: the open file descriptor
|
||||
file: BinaryIO = typed_attribute()
|
||||
file: IO[bytes] = typed_attribute()
|
||||
#: the path of the file on the file system, if available (file must be a real file)
|
||||
path: Path = typed_attribute()
|
||||
#: the file number, if available (file must be a real file or a TTY)
|
||||
|
|
@ -33,7 +33,7 @@ class FileStreamAttribute(TypedAttributeSet):
|
|||
|
||||
|
||||
class _BaseFileStream:
|
||||
def __init__(self, file: BinaryIO):
|
||||
def __init__(self, file: IO[bytes]):
|
||||
self._file = file
|
||||
|
||||
async def aclose(self) -> None:
|
||||
|
|
@ -76,7 +76,7 @@ class FileReadStream(_BaseFileStream, ByteReceiveStream):
|
|||
|
||||
"""
|
||||
file = await to_thread.run_sync(Path(path).open, "rb")
|
||||
return cls(cast(BinaryIO, file))
|
||||
return cls(file)
|
||||
|
||||
async def receive(self, max_bytes: int = 65536) -> bytes:
|
||||
try:
|
||||
|
|
@ -143,7 +143,7 @@ class FileWriteStream(_BaseFileStream, ByteSendStream):
|
|||
"""
|
||||
mode = "ab" if append else "wb"
|
||||
file = await to_thread.run_sync(Path(path).open, mode)
|
||||
return cls(cast(BinaryIO, file))
|
||||
return cls(file)
|
||||
|
||||
async def send(self, item: bytes) -> None:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from collections.abc import Callable, Mapping
|
|||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
from ssl import SSLContext
|
||||
from typing import Any, TypeVar
|
||||
from typing import Any, TypeAlias, TypeVar
|
||||
|
||||
from .. import (
|
||||
BrokenResourceError,
|
||||
|
|
@ -34,11 +34,6 @@ from ..abc import (
|
|||
TaskGroup,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from typing import TypeVarTuple, Unpack
|
||||
else:
|
||||
|
|
@ -279,9 +274,11 @@ class TLSStream(ByteStream):
|
|||
True
|
||||
),
|
||||
TLSAttribute.server_side: lambda: self._ssl_object.server_side,
|
||||
TLSAttribute.shared_ciphers: lambda: self._ssl_object.shared_ciphers()
|
||||
if self._ssl_object.server_side
|
||||
else None,
|
||||
TLSAttribute.shared_ciphers: lambda: (
|
||||
self._ssl_object.shared_ciphers()
|
||||
if self._ssl_object.server_side
|
||||
else None
|
||||
),
|
||||
TLSAttribute.standard_compatible: lambda: self.standard_compatible,
|
||||
TLSAttribute.ssl_object: lambda: self._ssl_object,
|
||||
TLSAttribute.tls_version: self._ssl_object.version,
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ async def run_sync(
|
|||
"""
|
||||
Call the given function with the given arguments in a worker thread.
|
||||
|
||||
If the ``cancellable`` option is enabled and the task waiting for its completion is
|
||||
cancelled, the thread will still run its course but its return value (or any raised
|
||||
exception) will be ignored.
|
||||
If the ``abandon_on_cancel`` option is enabled and the task waiting for its
|
||||
completion is cancelled, the thread will still run its course but its
|
||||
return value (or any raised exception) will be ignored.
|
||||
|
||||
:param func: a callable
|
||||
:param args: positional arguments for the callable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue