Amrita09 commited on
Commit
71ccd7e
·
1 Parent(s): f0c74c4

Removed venv from tracking

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. venv/Lib/site-packages/__pycache__/google_auth_httplib2.cpython-311.pyc +0 -0
  2. venv/Lib/site-packages/__pycache__/typing_extensions.cpython-311.pyc +0 -0
  3. venv/Lib/site-packages/_distutils_hack/__init__.py +0 -222
  4. venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-311.pyc +0 -0
  5. venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-311.pyc +0 -0
  6. venv/Lib/site-packages/_distutils_hack/override.py +0 -1
  7. venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER +0 -1
  8. venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA +0 -295
  9. venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD +0 -10
  10. venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL +0 -4
  11. venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE +0 -21
  12. venv/Lib/site-packages/annotated_types/__init__.py +0 -432
  13. venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-311.pyc +0 -0
  14. venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-311.pyc +0 -0
  15. venv/Lib/site-packages/annotated_types/py.typed +0 -0
  16. venv/Lib/site-packages/annotated_types/test_cases.py +0 -151
  17. venv/Lib/site-packages/anyio-4.9.0.dist-info/INSTALLER +0 -1
  18. venv/Lib/site-packages/anyio-4.9.0.dist-info/LICENSE +0 -20
  19. venv/Lib/site-packages/anyio-4.9.0.dist-info/METADATA +0 -105
  20. venv/Lib/site-packages/anyio-4.9.0.dist-info/RECORD +0 -88
  21. venv/Lib/site-packages/anyio-4.9.0.dist-info/WHEEL +0 -5
  22. venv/Lib/site-packages/anyio-4.9.0.dist-info/entry_points.txt +0 -2
  23. venv/Lib/site-packages/anyio-4.9.0.dist-info/top_level.txt +0 -1
  24. venv/Lib/site-packages/anyio/__init__.py +0 -85
  25. venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-311.pyc +0 -0
  26. venv/Lib/site-packages/anyio/__pycache__/from_thread.cpython-311.pyc +0 -0
  27. venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-311.pyc +0 -0
  28. venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-311.pyc +0 -0
  29. venv/Lib/site-packages/anyio/__pycache__/to_interpreter.cpython-311.pyc +0 -0
  30. venv/Lib/site-packages/anyio/__pycache__/to_process.cpython-311.pyc +0 -0
  31. venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-311.pyc +0 -0
  32. venv/Lib/site-packages/anyio/_backends/__init__.py +0 -0
  33. venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-311.pyc +0 -0
  34. venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-311.pyc +0 -0
  35. venv/Lib/site-packages/anyio/_backends/__pycache__/_trio.cpython-311.pyc +0 -0
  36. venv/Lib/site-packages/anyio/_backends/_asyncio.py +0 -2816
  37. venv/Lib/site-packages/anyio/_backends/_trio.py +0 -1334
  38. venv/Lib/site-packages/anyio/_core/__init__.py +0 -0
  39. venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-311.pyc +0 -0
  40. venv/Lib/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-311.pyc +0 -0
  41. venv/Lib/site-packages/anyio/_core/__pycache__/_eventloop.cpython-311.pyc +0 -0
  42. venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-311.pyc +0 -0
  43. venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-311.pyc +0 -0
  44. venv/Lib/site-packages/anyio/_core/__pycache__/_resources.cpython-311.pyc +0 -0
  45. venv/Lib/site-packages/anyio/_core/__pycache__/_signals.cpython-311.pyc +0 -0
  46. venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-311.pyc +0 -0
  47. venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-311.pyc +0 -0
  48. venv/Lib/site-packages/anyio/_core/__pycache__/_subprocesses.cpython-311.pyc +0 -0
  49. venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-311.pyc +0 -0
  50. venv/Lib/site-packages/anyio/_core/__pycache__/_tasks.cpython-311.pyc +0 -0
venv/Lib/site-packages/__pycache__/google_auth_httplib2.cpython-311.pyc DELETED
Binary file (11.7 kB)
 
venv/Lib/site-packages/__pycache__/typing_extensions.cpython-311.pyc DELETED
Binary file (152 kB)
 
venv/Lib/site-packages/_distutils_hack/__init__.py DELETED
@@ -1,222 +0,0 @@
1
- # don't import any costly modules
2
- import sys
3
- import os
4
-
5
-
6
- is_pypy = '__pypy__' in sys.builtin_module_names
7
-
8
-
9
- def warn_distutils_present():
10
- if 'distutils' not in sys.modules:
11
- return
12
- if is_pypy and sys.version_info < (3, 7):
13
- # PyPy for 3.6 unconditionally imports distutils, so bypass the warning
14
- # https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
15
- return
16
- import warnings
17
-
18
- warnings.warn(
19
- "Distutils was imported before Setuptools, but importing Setuptools "
20
- "also replaces the `distutils` module in `sys.modules`. This may lead "
21
- "to undesirable behaviors or errors. To avoid these issues, avoid "
22
- "using distutils directly, ensure that setuptools is installed in the "
23
- "traditional way (e.g. not an editable install), and/or make sure "
24
- "that setuptools is always imported before distutils."
25
- )
26
-
27
-
28
- def clear_distutils():
29
- if 'distutils' not in sys.modules:
30
- return
31
- import warnings
32
-
33
- warnings.warn("Setuptools is replacing distutils.")
34
- mods = [
35
- name
36
- for name in sys.modules
37
- if name == "distutils" or name.startswith("distutils.")
38
- ]
39
- for name in mods:
40
- del sys.modules[name]
41
-
42
-
43
- def enabled():
44
- """
45
- Allow selection of distutils by environment variable.
46
- """
47
- which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local')
48
- return which == 'local'
49
-
50
-
51
- def ensure_local_distutils():
52
- import importlib
53
-
54
- clear_distutils()
55
-
56
- # With the DistutilsMetaFinder in place,
57
- # perform an import to cause distutils to be
58
- # loaded from setuptools._distutils. Ref #2906.
59
- with shim():
60
- importlib.import_module('distutils')
61
-
62
- # check that submodules load as expected
63
- core = importlib.import_module('distutils.core')
64
- assert '_distutils' in core.__file__, core.__file__
65
- assert 'setuptools._distutils.log' not in sys.modules
66
-
67
-
68
- def do_override():
69
- """
70
- Ensure that the local copy of distutils is preferred over stdlib.
71
-
72
- See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401
73
- for more motivation.
74
- """
75
- if enabled():
76
- warn_distutils_present()
77
- ensure_local_distutils()
78
-
79
-
80
- class _TrivialRe:
81
- def __init__(self, *patterns):
82
- self._patterns = patterns
83
-
84
- def match(self, string):
85
- return all(pat in string for pat in self._patterns)
86
-
87
-
88
- class DistutilsMetaFinder:
89
- def find_spec(self, fullname, path, target=None):
90
- # optimization: only consider top level modules and those
91
- # found in the CPython test suite.
92
- if path is not None and not fullname.startswith('test.'):
93
- return
94
-
95
- method_name = 'spec_for_{fullname}'.format(**locals())
96
- method = getattr(self, method_name, lambda: None)
97
- return method()
98
-
99
- def spec_for_distutils(self):
100
- if self.is_cpython():
101
- return
102
-
103
- import importlib
104
- import importlib.abc
105
- import importlib.util
106
-
107
- try:
108
- mod = importlib.import_module('setuptools._distutils')
109
- except Exception:
110
- # There are a couple of cases where setuptools._distutils
111
- # may not be present:
112
- # - An older Setuptools without a local distutils is
113
- # taking precedence. Ref #2957.
114
- # - Path manipulation during sitecustomize removes
115
- # setuptools from the path but only after the hook
116
- # has been loaded. Ref #2980.
117
- # In either case, fall back to stdlib behavior.
118
- return
119
-
120
- class DistutilsLoader(importlib.abc.Loader):
121
- def create_module(self, spec):
122
- mod.__name__ = 'distutils'
123
- return mod
124
-
125
- def exec_module(self, module):
126
- pass
127
-
128
- return importlib.util.spec_from_loader(
129
- 'distutils', DistutilsLoader(), origin=mod.__file__
130
- )
131
-
132
- @staticmethod
133
- def is_cpython():
134
- """
135
- Suppress supplying distutils for CPython (build and tests).
136
- Ref #2965 and #3007.
137
- """
138
- return os.path.isfile('pybuilddir.txt')
139
-
140
- def spec_for_pip(self):
141
- """
142
- Ensure stdlib distutils when running under pip.
143
- See pypa/pip#8761 for rationale.
144
- """
145
- if self.pip_imported_during_build():
146
- return
147
- clear_distutils()
148
- self.spec_for_distutils = lambda: None
149
-
150
- @classmethod
151
- def pip_imported_during_build(cls):
152
- """
153
- Detect if pip is being imported in a build script. Ref #2355.
154
- """
155
- import traceback
156
-
157
- return any(
158
- cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None)
159
- )
160
-
161
- @staticmethod
162
- def frame_file_is_setup(frame):
163
- """
164
- Return True if the indicated frame suggests a setup.py file.
165
- """
166
- # some frames may not have __file__ (#2940)
167
- return frame.f_globals.get('__file__', '').endswith('setup.py')
168
-
169
- def spec_for_sensitive_tests(self):
170
- """
171
- Ensure stdlib distutils when running select tests under CPython.
172
-
173
- python/cpython#91169
174
- """
175
- clear_distutils()
176
- self.spec_for_distutils = lambda: None
177
-
178
- sensitive_tests = (
179
- [
180
- 'test.test_distutils',
181
- 'test.test_peg_generator',
182
- 'test.test_importlib',
183
- ]
184
- if sys.version_info < (3, 10)
185
- else [
186
- 'test.test_distutils',
187
- ]
188
- )
189
-
190
-
191
- for name in DistutilsMetaFinder.sensitive_tests:
192
- setattr(
193
- DistutilsMetaFinder,
194
- f'spec_for_{name}',
195
- DistutilsMetaFinder.spec_for_sensitive_tests,
196
- )
197
-
198
-
199
- DISTUTILS_FINDER = DistutilsMetaFinder()
200
-
201
-
202
- def add_shim():
203
- DISTUTILS_FINDER in sys.meta_path or insert_shim()
204
-
205
-
206
- class shim:
207
- def __enter__(self):
208
- insert_shim()
209
-
210
- def __exit__(self, exc, value, tb):
211
- remove_shim()
212
-
213
-
214
- def insert_shim():
215
- sys.meta_path.insert(0, DISTUTILS_FINDER)
216
-
217
-
218
- def remove_shim():
219
- try:
220
- sys.meta_path.remove(DISTUTILS_FINDER)
221
- except ValueError:
222
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-311.pyc DELETED
Binary file (11.2 kB)
 
venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-311.pyc DELETED
Binary file (347 Bytes)
 
venv/Lib/site-packages/_distutils_hack/override.py DELETED
@@ -1 +0,0 @@
1
- __import__('_distutils_hack').do_override()
 
 
venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER DELETED
@@ -1 +0,0 @@
1
- pip
 
 
venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA DELETED
@@ -1,295 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: annotated-types
3
- Version: 0.7.0
4
- Summary: Reusable constraint types to use with typing.Annotated
5
- Project-URL: Homepage, https://github.com/annotated-types/annotated-types
6
- Project-URL: Source, https://github.com/annotated-types/annotated-types
7
- Project-URL: Changelog, https://github.com/annotated-types/annotated-types/releases
8
- Author-email: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>, Samuel Colvin <s@muelcolvin.com>, Zac Hatfield-Dodds <zac@zhd.dev>
9
- License-File: LICENSE
10
- Classifier: Development Status :: 4 - Beta
11
- Classifier: Environment :: Console
12
- Classifier: Environment :: MacOS X
13
- Classifier: Intended Audience :: Developers
14
- Classifier: Intended Audience :: Information Technology
15
- Classifier: License :: OSI Approved :: MIT License
16
- Classifier: Operating System :: POSIX :: Linux
17
- Classifier: Operating System :: Unix
18
- Classifier: Programming Language :: Python :: 3 :: Only
19
- Classifier: Programming Language :: Python :: 3.8
20
- Classifier: Programming Language :: Python :: 3.9
21
- Classifier: Programming Language :: Python :: 3.10
22
- Classifier: Programming Language :: Python :: 3.11
23
- Classifier: Programming Language :: Python :: 3.12
24
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
- Classifier: Typing :: Typed
26
- Requires-Python: >=3.8
27
- Requires-Dist: typing-extensions>=4.0.0; python_version < '3.9'
28
- Description-Content-Type: text/markdown
29
-
30
- # annotated-types
31
-
32
- [![CI](https://github.com/annotated-types/annotated-types/workflows/CI/badge.svg?event=push)](https://github.com/annotated-types/annotated-types/actions?query=event%3Apush+branch%3Amain+workflow%3ACI)
33
- [![pypi](https://img.shields.io/pypi/v/annotated-types.svg)](https://pypi.python.org/pypi/annotated-types)
34
- [![versions](https://img.shields.io/pypi/pyversions/annotated-types.svg)](https://github.com/annotated-types/annotated-types)
35
- [![license](https://img.shields.io/github/license/annotated-types/annotated-types.svg)](https://github.com/annotated-types/annotated-types/blob/main/LICENSE)
36
-
37
- [PEP-593](https://peps.python.org/pep-0593/) added `typing.Annotated` as a way of
38
- adding context-specific metadata to existing types, and specifies that
39
- `Annotated[T, x]` _should_ be treated as `T` by any tool or library without special
40
- logic for `x`.
41
-
42
- This package provides metadata objects which can be used to represent common
43
- constraints such as upper and lower bounds on scalar values and collection sizes,
44
- a `Predicate` marker for runtime checks, and
45
- descriptions of how we intend these metadata to be interpreted. In some cases,
46
- we also note alternative representations which do not require this package.
47
-
48
- ## Install
49
-
50
- ```bash
51
- pip install annotated-types
52
- ```
53
-
54
- ## Examples
55
-
56
- ```python
57
- from typing import Annotated
58
- from annotated_types import Gt, Len, Predicate
59
-
60
- class MyClass:
61
- age: Annotated[int, Gt(18)] # Valid: 19, 20, ...
62
- # Invalid: 17, 18, "19", 19.0, ...
63
- factors: list[Annotated[int, Predicate(is_prime)]] # Valid: 2, 3, 5, 7, 11, ...
64
- # Invalid: 4, 8, -2, 5.0, "prime", ...
65
-
66
- my_list: Annotated[list[int], Len(0, 10)] # Valid: [], [10, 20, 30, 40, 50]
67
- # Invalid: (1, 2), ["abc"], [0] * 20
68
- ```
69
-
70
- ## Documentation
71
-
72
- _While `annotated-types` avoids runtime checks for performance, users should not
73
- construct invalid combinations such as `MultipleOf("non-numeric")` or `Annotated[int, Len(3)]`.
74
- Downstream implementors may choose to raise an error, emit a warning, silently ignore
75
- a metadata item, etc., if the metadata objects described below are used with an
76
- incompatible type - or for any other reason!_
77
-
78
- ### Gt, Ge, Lt, Le
79
-
80
- Express inclusive and/or exclusive bounds on orderable values - which may be numbers,
81
- dates, times, strings, sets, etc. Note that the boundary value need not be of the
82
- same type that was annotated, so long as they can be compared: `Annotated[int, Gt(1.5)]`
83
- is fine, for example, and implies that the value is an integer x such that `x > 1.5`.
84
-
85
- We suggest that implementors may also interpret `functools.partial(operator.le, 1.5)`
86
- as being equivalent to `Gt(1.5)`, for users who wish to avoid a runtime dependency on
87
- the `annotated-types` package.
88
-
89
- To be explicit, these types have the following meanings:
90
-
91
- * `Gt(x)` - value must be "Greater Than" `x` - equivalent to exclusive minimum
92
- * `Ge(x)` - value must be "Greater than or Equal" to `x` - equivalent to inclusive minimum
93
- * `Lt(x)` - value must be "Less Than" `x` - equivalent to exclusive maximum
94
- * `Le(x)` - value must be "Less than or Equal" to `x` - equivalent to inclusive maximum
95
-
96
- ### Interval
97
-
98
- `Interval(gt, ge, lt, le)` allows you to specify an upper and lower bound with a single
99
- metadata object. `None` attributes should be ignored, and non-`None` attributes
100
- treated as per the single bounds above.
101
-
102
- ### MultipleOf
103
-
104
- `MultipleOf(multiple_of=x)` might be interpreted in two ways:
105
-
106
- 1. Python semantics, implying `value % multiple_of == 0`, or
107
- 2. [JSONschema semantics](https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.2.1),
108
- where `int(value / multiple_of) == value / multiple_of`.
109
-
110
- We encourage users to be aware of these two common interpretations and their
111
- distinct behaviours, especially since very large or non-integer numbers make
112
- it easy to cause silent data corruption due to floating-point imprecision.
113
-
114
- We encourage libraries to carefully document which interpretation they implement.
115
-
116
- ### MinLen, MaxLen, Len
117
-
118
- `Len()` implies that `min_length <= len(value) <= max_length` - lower and upper bounds are inclusive.
119
-
120
- As well as `Len()` which can optionally include upper and lower bounds, we also
121
- provide `MinLen(x)` and `MaxLen(y)` which are equivalent to `Len(min_length=x)`
122
- and `Len(max_length=y)` respectively.
123
-
124
- `Len`, `MinLen`, and `MaxLen` may be used with any type which supports `len(value)`.
125
-
126
- Examples of usage:
127
-
128
- * `Annotated[list, MaxLen(10)]` (or `Annotated[list, Len(max_length=10))`) - list must have a length of 10 or less
129
- * `Annotated[str, MaxLen(10)]` - string must have a length of 10 or less
130
- * `Annotated[list, MinLen(3))` (or `Annotated[list, Len(min_length=3))`) - list must have a length of 3 or more
131
- * `Annotated[list, Len(4, 6)]` - list must have a length of 4, 5, or 6
132
- * `Annotated[list, Len(8, 8)]` - list must have a length of exactly 8
133
-
134
- #### Changed in v0.4.0
135
-
136
- * `min_inclusive` has been renamed to `min_length`, no change in meaning
137
- * `max_exclusive` has been renamed to `max_length`, upper bound is now **inclusive** instead of **exclusive**
138
- * The recommendation that slices are interpreted as `Len` has been removed due to ambiguity and different semantic
139
- meaning of the upper bound in slices vs. `Len`
140
-
141
- See [issue #23](https://github.com/annotated-types/annotated-types/issues/23) for discussion.
142
-
143
- ### Timezone
144
-
145
- `Timezone` can be used with a `datetime` or a `time` to express which timezones
146
- are allowed. `Annotated[datetime, Timezone(None)]` must be a naive datetime.
147
- `Timezone[...]` ([literal ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis))
148
- expresses that any timezone-aware datetime is allowed. You may also pass a specific
149
- timezone string or [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects)
150
- object such as `Timezone(timezone.utc)` or `Timezone("Africa/Abidjan")` to express that you only
151
- allow a specific timezone, though we note that this is often a symptom of fragile design.
152
-
153
- #### Changed in v0.x.x
154
-
155
- * `Timezone` accepts [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects) objects instead of
156
- `timezone`, extending compatibility to [`zoneinfo`](https://docs.python.org/3/library/zoneinfo.html) and third party libraries.
157
-
158
- ### Unit
159
-
160
- `Unit(unit: str)` expresses that the annotated numeric value is the magnitude of
161
- a quantity with the specified unit. For example, `Annotated[float, Unit("m/s")]`
162
- would be a float representing a velocity in meters per second.
163
-
164
- Please note that `annotated_types` itself makes no attempt to parse or validate
165
- the unit string in any way. That is left entirely to downstream libraries,
166
- such as [`pint`](https://pint.readthedocs.io) or
167
- [`astropy.units`](https://docs.astropy.org/en/stable/units/).
168
-
169
- An example of how a library might use this metadata:
170
-
171
- ```python
172
- from annotated_types import Unit
173
- from typing import Annotated, TypeVar, Callable, Any, get_origin, get_args
174
-
175
- # given a type annotated with a unit:
176
- Meters = Annotated[float, Unit("m")]
177
-
178
-
179
- # you can cast the annotation to a specific unit type with any
180
- # callable that accepts a string and returns the desired type
181
- T = TypeVar("T")
182
- def cast_unit(tp: Any, unit_cls: Callable[[str], T]) -> T | None:
183
- if get_origin(tp) is Annotated:
184
- for arg in get_args(tp):
185
- if isinstance(arg, Unit):
186
- return unit_cls(arg.unit)
187
- return None
188
-
189
-
190
- # using `pint`
191
- import pint
192
- pint_unit = cast_unit(Meters, pint.Unit)
193
-
194
-
195
- # using `astropy.units`
196
- import astropy.units as u
197
- astropy_unit = cast_unit(Meters, u.Unit)
198
- ```
199
-
200
- ### Predicate
201
-
202
- `Predicate(func: Callable)` expresses that `func(value)` is truthy for valid values.
203
- Users should prefer the statically inspectable metadata above, but if you need
204
- the full power and flexibility of arbitrary runtime predicates... here it is.
205
-
206
- For some common constraints, we provide generic types:
207
-
208
- * `IsLower = Annotated[T, Predicate(str.islower)]`
209
- * `IsUpper = Annotated[T, Predicate(str.isupper)]`
210
- * `IsDigit = Annotated[T, Predicate(str.isdigit)]`
211
- * `IsFinite = Annotated[T, Predicate(math.isfinite)]`
212
- * `IsNotFinite = Annotated[T, Predicate(Not(math.isfinite))]`
213
- * `IsNan = Annotated[T, Predicate(math.isnan)]`
214
- * `IsNotNan = Annotated[T, Predicate(Not(math.isnan))]`
215
- * `IsInfinite = Annotated[T, Predicate(math.isinf)]`
216
- * `IsNotInfinite = Annotated[T, Predicate(Not(math.isinf))]`
217
-
218
- so that you can write e.g. `x: IsFinite[float] = 2.0` instead of the longer
219
- (but exactly equivalent) `x: Annotated[float, Predicate(math.isfinite)] = 2.0`.
220
-
221
- Some libraries might have special logic to handle known or understandable predicates,
222
- for example by checking for `str.isdigit` and using its presence to both call custom
223
- logic to enforce digit-only strings, and customise some generated external schema.
224
- Users are therefore encouraged to avoid indirection like `lambda s: s.lower()`, in
225
- favor of introspectable methods such as `str.lower` or `re.compile("pattern").search`.
226
-
227
- To enable basic negation of commonly used predicates like `math.isnan` without introducing introspection that makes it impossible for implementers to introspect the predicate we provide a `Not` wrapper that simply negates the predicate in an introspectable manner. Several of the predicates listed above are created in this manner.
228
-
229
- We do not specify what behaviour should be expected for predicates that raise
230
- an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently
231
- skip invalid constraints, or statically raise an error; or it might try calling it
232
- and then propagate or discard the resulting
233
- `TypeError: descriptor 'isdigit' for 'str' objects doesn't apply to a 'int' object`
234
- exception. We encourage libraries to document the behaviour they choose.
235
-
236
- ### Doc
237
-
238
- `doc()` can be used to add documentation information in `Annotated`, for function and method parameters, variables, class attributes, return types, and any place where `Annotated` can be used.
239
-
240
- It expects a value that can be statically analyzed, as the main use case is for static analysis, editors, documentation generators, and similar tools.
241
-
242
- It returns a `DocInfo` class with a single attribute `documentation` containing the value passed to `doc()`.
243
-
244
- This is the early adopter's alternative form of the [`typing-doc` proposal](https://github.com/tiangolo/fastapi/blob/typing-doc/typing_doc.md).
245
-
246
- ### Integrating downstream types with `GroupedMetadata`
247
-
248
- Implementers may choose to provide a convenience wrapper that groups multiple pieces of metadata.
249
- This can help reduce verbosity and cognitive overhead for users.
250
- For example, an implementer like Pydantic might provide a `Field` or `Meta` type that accepts keyword arguments and transforms these into low-level metadata:
251
-
252
- ```python
253
- from dataclasses import dataclass
254
- from typing import Iterator
255
- from annotated_types import GroupedMetadata, Ge
256
-
257
- @dataclass
258
- class Field(GroupedMetadata):
259
- ge: int | None = None
260
- description: str | None = None
261
-
262
- def __iter__(self) -> Iterator[object]:
263
- # Iterating over a GroupedMetadata object should yield annotated-types
264
- # constraint metadata objects which describe it as fully as possible,
265
- # and may include other unknown objects too.
266
- if self.ge is not None:
267
- yield Ge(self.ge)
268
- if self.description is not None:
269
- yield Description(self.description)
270
- ```
271
-
272
- Libraries consuming annotated-types constraints should check for `GroupedMetadata` and unpack it by iterating over the object and treating the results as if they had been "unpacked" in the `Annotated` type. The same logic should be applied to the [PEP 646 `Unpack` type](https://peps.python.org/pep-0646/), so that `Annotated[T, Field(...)]`, `Annotated[T, Unpack[Field(...)]]` and `Annotated[T, *Field(...)]` are all treated consistently.
273
-
274
- Libraries consuming annotated-types should also ignore any metadata they do not recongize that came from unpacking a `GroupedMetadata`, just like they ignore unrecognized metadata in `Annotated` itself.
275
-
276
- Our own `annotated_types.Interval` class is a `GroupedMetadata` which unpacks itself into `Gt`, `Lt`, etc., so this is not an abstract concern. Similarly, `annotated_types.Len` is a `GroupedMetadata` which unpacks itself into `MinLen` (optionally) and `MaxLen`.
277
-
278
- ### Consuming metadata
279
-
280
- We intend to not be prescriptive as to _how_ the metadata and constraints are used, but as an example of how one might parse constraints from types annotations see our [implementation in `test_main.py`](https://github.com/annotated-types/annotated-types/blob/f59cf6d1b5255a0fe359b93896759a180bec30ae/tests/test_main.py#L94-L103).
281
-
282
- It is up to the implementer to determine how this metadata is used.
283
- You could use the metadata for runtime type checking, for generating schemas or to generate example data, amongst other use cases.
284
-
285
- ## Design & History
286
-
287
- This package was designed at the PyCon 2022 sprints by the maintainers of Pydantic
288
- and Hypothesis, with the goal of making it as easy as possible for end-users to
289
- provide more informative annotations for use by runtime libraries.
290
-
291
- It is deliberately minimal, and following PEP-593 allows considerable downstream
292
- discretion in what (if anything!) they choose to support. Nonetheless, we expect
293
- that staying simple and covering _only_ the most common use-cases will give users
294
- and maintainers the best experience we can. If you'd like more constraints for your
295
- types - follow our lead, by defining them and documenting them downstream!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD DELETED
@@ -1,10 +0,0 @@
1
- annotated_types-0.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
2
- annotated_types-0.7.0.dist-info/METADATA,sha256=7ltqxksJJ0wCYFGBNIQCWTlWQGeAH0hRFdnK3CB895E,15046
3
- annotated_types-0.7.0.dist-info/RECORD,,
4
- annotated_types-0.7.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
5
- annotated_types-0.7.0.dist-info/licenses/LICENSE,sha256=_hBJiEsaDZNCkB6I4H8ykl0ksxIdmXK2poBfuYJLCV0,1083
6
- annotated_types/__init__.py,sha256=RynLsRKUEGI0KimXydlD1fZEfEzWwDo0Uon3zOKhG1Q,13819
7
- annotated_types/__pycache__/__init__.cpython-311.pyc,,
8
- annotated_types/__pycache__/test_cases.cpython-311.pyc,,
9
- annotated_types/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- annotated_types/test_cases.py,sha256=zHFX6EpcMbGJ8FzBYDbO56bPwx_DYIVSKbZM-4B3_lg,6421
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL DELETED
@@ -1,4 +0,0 @@
1
- Wheel-Version: 1.0
2
- Generator: hatchling 1.24.2
3
- Root-Is-Purelib: true
4
- Tag: py3-none-any
 
 
 
 
 
venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2022 the contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/annotated_types/__init__.py DELETED
@@ -1,432 +0,0 @@
1
- import math
2
- import sys
3
- import types
4
- from dataclasses import dataclass
5
- from datetime import tzinfo
6
- from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, SupportsFloat, SupportsIndex, TypeVar, Union
7
-
8
- if sys.version_info < (3, 8):
9
- from typing_extensions import Protocol, runtime_checkable
10
- else:
11
- from typing import Protocol, runtime_checkable
12
-
13
- if sys.version_info < (3, 9):
14
- from typing_extensions import Annotated, Literal
15
- else:
16
- from typing import Annotated, Literal
17
-
18
- if sys.version_info < (3, 10):
19
- EllipsisType = type(Ellipsis)
20
- KW_ONLY = {}
21
- SLOTS = {}
22
- else:
23
- from types import EllipsisType
24
-
25
- KW_ONLY = {"kw_only": True}
26
- SLOTS = {"slots": True}
27
-
28
-
29
- __all__ = (
30
- 'BaseMetadata',
31
- 'GroupedMetadata',
32
- 'Gt',
33
- 'Ge',
34
- 'Lt',
35
- 'Le',
36
- 'Interval',
37
- 'MultipleOf',
38
- 'MinLen',
39
- 'MaxLen',
40
- 'Len',
41
- 'Timezone',
42
- 'Predicate',
43
- 'LowerCase',
44
- 'UpperCase',
45
- 'IsDigits',
46
- 'IsFinite',
47
- 'IsNotFinite',
48
- 'IsNan',
49
- 'IsNotNan',
50
- 'IsInfinite',
51
- 'IsNotInfinite',
52
- 'doc',
53
- 'DocInfo',
54
- '__version__',
55
- )
56
-
57
- __version__ = '0.7.0'
58
-
59
-
60
- T = TypeVar('T')
61
-
62
-
63
- # arguments that start with __ are considered
64
- # positional only
65
- # see https://peps.python.org/pep-0484/#positional-only-arguments
66
-
67
-
68
- class SupportsGt(Protocol):
69
- def __gt__(self: T, __other: T) -> bool:
70
- ...
71
-
72
-
73
- class SupportsGe(Protocol):
74
- def __ge__(self: T, __other: T) -> bool:
75
- ...
76
-
77
-
78
- class SupportsLt(Protocol):
79
- def __lt__(self: T, __other: T) -> bool:
80
- ...
81
-
82
-
83
- class SupportsLe(Protocol):
84
- def __le__(self: T, __other: T) -> bool:
85
- ...
86
-
87
-
88
- class SupportsMod(Protocol):
89
- def __mod__(self: T, __other: T) -> T:
90
- ...
91
-
92
-
93
- class SupportsDiv(Protocol):
94
- def __div__(self: T, __other: T) -> T:
95
- ...
96
-
97
-
98
- class BaseMetadata:
99
- """Base class for all metadata.
100
-
101
- This exists mainly so that implementers
102
- can do `isinstance(..., BaseMetadata)` while traversing field annotations.
103
- """
104
-
105
- __slots__ = ()
106
-
107
-
108
- @dataclass(frozen=True, **SLOTS)
109
- class Gt(BaseMetadata):
110
- """Gt(gt=x) implies that the value must be greater than x.
111
-
112
- It can be used with any type that supports the ``>`` operator,
113
- including numbers, dates and times, strings, sets, and so on.
114
- """
115
-
116
- gt: SupportsGt
117
-
118
-
119
- @dataclass(frozen=True, **SLOTS)
120
- class Ge(BaseMetadata):
121
- """Ge(ge=x) implies that the value must be greater than or equal to x.
122
-
123
- It can be used with any type that supports the ``>=`` operator,
124
- including numbers, dates and times, strings, sets, and so on.
125
- """
126
-
127
- ge: SupportsGe
128
-
129
-
130
- @dataclass(frozen=True, **SLOTS)
131
- class Lt(BaseMetadata):
132
- """Lt(lt=x) implies that the value must be less than x.
133
-
134
- It can be used with any type that supports the ``<`` operator,
135
- including numbers, dates and times, strings, sets, and so on.
136
- """
137
-
138
- lt: SupportsLt
139
-
140
-
141
- @dataclass(frozen=True, **SLOTS)
142
- class Le(BaseMetadata):
143
- """Le(le=x) implies that the value must be less than or equal to x.
144
-
145
- It can be used with any type that supports the ``<=`` operator,
146
- including numbers, dates and times, strings, sets, and so on.
147
- """
148
-
149
- le: SupportsLe
150
-
151
-
152
- @runtime_checkable
153
- class GroupedMetadata(Protocol):
154
- """A grouping of multiple objects, like typing.Unpack.
155
-
156
- `GroupedMetadata` on its own is not metadata and has no meaning.
157
- All of the constraints and metadata should be fully expressable
158
- in terms of the `BaseMetadata`'s returned by `GroupedMetadata.__iter__()`.
159
-
160
- Concrete implementations should override `GroupedMetadata.__iter__()`
161
- to add their own metadata.
162
- For example:
163
-
164
- >>> @dataclass
165
- >>> class Field(GroupedMetadata):
166
- >>> gt: float | None = None
167
- >>> description: str | None = None
168
- ...
169
- >>> def __iter__(self) -> Iterable[object]:
170
- >>> if self.gt is not None:
171
- >>> yield Gt(self.gt)
172
- >>> if self.description is not None:
173
- >>> yield Description(self.gt)
174
-
175
- Also see the implementation of `Interval` below for an example.
176
-
177
- Parsers should recognize this and unpack it so that it can be used
178
- both with and without unpacking:
179
-
180
- - `Annotated[int, Field(...)]` (parser must unpack Field)
181
- - `Annotated[int, *Field(...)]` (PEP-646)
182
- """ # noqa: trailing-whitespace
183
-
184
- @property
185
- def __is_annotated_types_grouped_metadata__(self) -> Literal[True]:
186
- return True
187
-
188
- def __iter__(self) -> Iterator[object]:
189
- ...
190
-
191
- if not TYPE_CHECKING:
192
- __slots__ = () # allow subclasses to use slots
193
-
194
- def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None:
195
- # Basic ABC like functionality without the complexity of an ABC
196
- super().__init_subclass__(*args, **kwargs)
197
- if cls.__iter__ is GroupedMetadata.__iter__:
198
- raise TypeError("Can't subclass GroupedMetadata without implementing __iter__")
199
-
200
- def __iter__(self) -> Iterator[object]: # noqa: F811
201
- raise NotImplementedError # more helpful than "None has no attribute..." type errors
202
-
203
-
204
- @dataclass(frozen=True, **KW_ONLY, **SLOTS)
205
- class Interval(GroupedMetadata):
206
- """Interval can express inclusive or exclusive bounds with a single object.
207
-
208
- It accepts keyword arguments ``gt``, ``ge``, ``lt``, and/or ``le``, which
209
- are interpreted the same way as the single-bound constraints.
210
- """
211
-
212
- gt: Union[SupportsGt, None] = None
213
- ge: Union[SupportsGe, None] = None
214
- lt: Union[SupportsLt, None] = None
215
- le: Union[SupportsLe, None] = None
216
-
217
- def __iter__(self) -> Iterator[BaseMetadata]:
218
- """Unpack an Interval into zero or more single-bounds."""
219
- if self.gt is not None:
220
- yield Gt(self.gt)
221
- if self.ge is not None:
222
- yield Ge(self.ge)
223
- if self.lt is not None:
224
- yield Lt(self.lt)
225
- if self.le is not None:
226
- yield Le(self.le)
227
-
228
-
229
- @dataclass(frozen=True, **SLOTS)
230
- class MultipleOf(BaseMetadata):
231
- """MultipleOf(multiple_of=x) might be interpreted in two ways:
232
-
233
- 1. Python semantics, implying ``value % multiple_of == 0``, or
234
- 2. JSONschema semantics, where ``int(value / multiple_of) == value / multiple_of``
235
-
236
- We encourage users to be aware of these two common interpretations,
237
- and libraries to carefully document which they implement.
238
- """
239
-
240
- multiple_of: Union[SupportsDiv, SupportsMod]
241
-
242
-
243
- @dataclass(frozen=True, **SLOTS)
244
- class MinLen(BaseMetadata):
245
- """
246
- MinLen() implies minimum inclusive length,
247
- e.g. ``len(value) >= min_length``.
248
- """
249
-
250
- min_length: Annotated[int, Ge(0)]
251
-
252
-
253
- @dataclass(frozen=True, **SLOTS)
254
- class MaxLen(BaseMetadata):
255
- """
256
- MaxLen() implies maximum inclusive length,
257
- e.g. ``len(value) <= max_length``.
258
- """
259
-
260
- max_length: Annotated[int, Ge(0)]
261
-
262
-
263
- @dataclass(frozen=True, **SLOTS)
264
- class Len(GroupedMetadata):
265
- """
266
- Len() implies that ``min_length <= len(value) <= max_length``.
267
-
268
- Upper bound may be omitted or ``None`` to indicate no upper length bound.
269
- """
270
-
271
- min_length: Annotated[int, Ge(0)] = 0
272
- max_length: Optional[Annotated[int, Ge(0)]] = None
273
-
274
- def __iter__(self) -> Iterator[BaseMetadata]:
275
- """Unpack a Len into zone or more single-bounds."""
276
- if self.min_length > 0:
277
- yield MinLen(self.min_length)
278
- if self.max_length is not None:
279
- yield MaxLen(self.max_length)
280
-
281
-
282
- @dataclass(frozen=True, **SLOTS)
283
- class Timezone(BaseMetadata):
284
- """Timezone(tz=...) requires a datetime to be aware (or ``tz=None``, naive).
285
-
286
- ``Annotated[datetime, Timezone(None)]`` must be a naive datetime.
287
- ``Timezone[...]`` (the ellipsis literal) expresses that the datetime must be
288
- tz-aware but any timezone is allowed.
289
-
290
- You may also pass a specific timezone string or tzinfo object such as
291
- ``Timezone(timezone.utc)`` or ``Timezone("Africa/Abidjan")`` to express that
292
- you only allow a specific timezone, though we note that this is often
293
- a symptom of poor design.
294
- """
295
-
296
- tz: Union[str, tzinfo, EllipsisType, None]
297
-
298
-
299
- @dataclass(frozen=True, **SLOTS)
300
- class Unit(BaseMetadata):
301
- """Indicates that the value is a physical quantity with the specified unit.
302
-
303
- It is intended for usage with numeric types, where the value represents the
304
- magnitude of the quantity. For example, ``distance: Annotated[float, Unit('m')]``
305
- or ``speed: Annotated[float, Unit('m/s')]``.
306
-
307
- Interpretation of the unit string is left to the discretion of the consumer.
308
- It is suggested to follow conventions established by python libraries that work
309
- with physical quantities, such as
310
-
311
- - ``pint`` : <https://pint.readthedocs.io/en/stable/>
312
- - ``astropy.units``: <https://docs.astropy.org/en/stable/units/>
313
-
314
- For indicating a quantity with a certain dimensionality but without a specific unit
315
- it is recommended to use square brackets, e.g. `Annotated[float, Unit('[time]')]`.
316
- Note, however, ``annotated_types`` itself makes no use of the unit string.
317
- """
318
-
319
- unit: str
320
-
321
-
322
- @dataclass(frozen=True, **SLOTS)
323
- class Predicate(BaseMetadata):
324
- """``Predicate(func: Callable)`` implies `func(value)` is truthy for valid values.
325
-
326
- Users should prefer statically inspectable metadata, but if you need the full
327
- power and flexibility of arbitrary runtime predicates... here it is.
328
-
329
- We provide a few predefined predicates for common string constraints:
330
- ``IsLower = Predicate(str.islower)``, ``IsUpper = Predicate(str.isupper)``, and
331
- ``IsDigits = Predicate(str.isdigit)``. Users are encouraged to use methods which
332
- can be given special handling, and avoid indirection like ``lambda s: s.lower()``.
333
-
334
- Some libraries might have special logic to handle certain predicates, e.g. by
335
- checking for `str.isdigit` and using its presence to both call custom logic to
336
- enforce digit-only strings, and customise some generated external schema.
337
-
338
- We do not specify what behaviour should be expected for predicates that raise
339
- an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently
340
- skip invalid constraints, or statically raise an error; or it might try calling it
341
- and then propagate or discard the resulting exception.
342
- """
343
-
344
- func: Callable[[Any], bool]
345
-
346
- def __repr__(self) -> str:
347
- if getattr(self.func, "__name__", "<lambda>") == "<lambda>":
348
- return f"{self.__class__.__name__}({self.func!r})"
349
- if isinstance(self.func, (types.MethodType, types.BuiltinMethodType)) and (
350
- namespace := getattr(self.func.__self__, "__name__", None)
351
- ):
352
- return f"{self.__class__.__name__}({namespace}.{self.func.__name__})"
353
- if isinstance(self.func, type(str.isascii)): # method descriptor
354
- return f"{self.__class__.__name__}({self.func.__qualname__})"
355
- return f"{self.__class__.__name__}({self.func.__name__})"
356
-
357
-
358
- @dataclass
359
- class Not:
360
- func: Callable[[Any], bool]
361
-
362
- def __call__(self, __v: Any) -> bool:
363
- return not self.func(__v)
364
-
365
-
366
- _StrType = TypeVar("_StrType", bound=str)
367
-
368
- LowerCase = Annotated[_StrType, Predicate(str.islower)]
369
- """
370
- Return True if the string is a lowercase string, False otherwise.
371
-
372
- A string is lowercase if all cased characters in the string are lowercase and there is at least one cased character in the string.
373
- """ # noqa: E501
374
- UpperCase = Annotated[_StrType, Predicate(str.isupper)]
375
- """
376
- Return True if the string is an uppercase string, False otherwise.
377
-
378
- A string is uppercase if all cased characters in the string are uppercase and there is at least one cased character in the string.
379
- """ # noqa: E501
380
- IsDigit = Annotated[_StrType, Predicate(str.isdigit)]
381
- IsDigits = IsDigit # type: ignore # plural for backwards compatibility, see #63
382
- """
383
- Return True if the string is a digit string, False otherwise.
384
-
385
- A string is a digit string if all characters in the string are digits and there is at least one character in the string.
386
- """ # noqa: E501
387
- IsAscii = Annotated[_StrType, Predicate(str.isascii)]
388
- """
389
- Return True if all characters in the string are ASCII, False otherwise.
390
-
391
- ASCII characters have code points in the range U+0000-U+007F. Empty string is ASCII too.
392
- """
393
-
394
- _NumericType = TypeVar('_NumericType', bound=Union[SupportsFloat, SupportsIndex])
395
- IsFinite = Annotated[_NumericType, Predicate(math.isfinite)]
396
- """Return True if x is neither an infinity nor a NaN, and False otherwise."""
397
- IsNotFinite = Annotated[_NumericType, Predicate(Not(math.isfinite))]
398
- """Return True if x is one of infinity or NaN, and False otherwise"""
399
- IsNan = Annotated[_NumericType, Predicate(math.isnan)]
400
- """Return True if x is a NaN (not a number), and False otherwise."""
401
- IsNotNan = Annotated[_NumericType, Predicate(Not(math.isnan))]
402
- """Return True if x is anything but NaN (not a number), and False otherwise."""
403
- IsInfinite = Annotated[_NumericType, Predicate(math.isinf)]
404
- """Return True if x is a positive or negative infinity, and False otherwise."""
405
- IsNotInfinite = Annotated[_NumericType, Predicate(Not(math.isinf))]
406
- """Return True if x is neither a positive or negative infinity, and False otherwise."""
407
-
408
- try:
409
- from typing_extensions import DocInfo, doc # type: ignore [attr-defined]
410
- except ImportError:
411
-
412
- @dataclass(frozen=True, **SLOTS)
413
- class DocInfo: # type: ignore [no-redef]
414
- """ "
415
- The return value of doc(), mainly to be used by tools that want to extract the
416
- Annotated documentation at runtime.
417
- """
418
-
419
- documentation: str
420
- """The documentation string passed to doc()."""
421
-
422
- def doc(
423
- documentation: str,
424
- ) -> DocInfo:
425
- """
426
- Add documentation to a type annotation inside of Annotated.
427
-
428
- For example:
429
-
430
- >>> def hi(name: Annotated[int, doc("The name of the user")]) -> None: ...
431
- """
432
- return DocInfo(documentation)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-311.pyc DELETED
Binary file (20.6 kB)
 
venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-311.pyc DELETED
Binary file (15.5 kB)
 
venv/Lib/site-packages/annotated_types/py.typed DELETED
File without changes
venv/Lib/site-packages/annotated_types/test_cases.py DELETED
@@ -1,151 +0,0 @@
1
- import math
2
- import sys
3
- from datetime import date, datetime, timedelta, timezone
4
- from decimal import Decimal
5
- from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Set, Tuple
6
-
7
- if sys.version_info < (3, 9):
8
- from typing_extensions import Annotated
9
- else:
10
- from typing import Annotated
11
-
12
- import annotated_types as at
13
-
14
-
15
- class Case(NamedTuple):
16
- """
17
- A test case for `annotated_types`.
18
- """
19
-
20
- annotation: Any
21
- valid_cases: Iterable[Any]
22
- invalid_cases: Iterable[Any]
23
-
24
-
25
- def cases() -> Iterable[Case]:
26
- # Gt, Ge, Lt, Le
27
- yield Case(Annotated[int, at.Gt(4)], (5, 6, 1000), (4, 0, -1))
28
- yield Case(Annotated[float, at.Gt(0.5)], (0.6, 0.7, 0.8, 0.9), (0.5, 0.0, -0.1))
29
- yield Case(
30
- Annotated[datetime, at.Gt(datetime(2000, 1, 1))],
31
- [datetime(2000, 1, 2), datetime(2000, 1, 3)],
32
- [datetime(2000, 1, 1), datetime(1999, 12, 31)],
33
- )
34
- yield Case(
35
- Annotated[datetime, at.Gt(date(2000, 1, 1))],
36
- [date(2000, 1, 2), date(2000, 1, 3)],
37
- [date(2000, 1, 1), date(1999, 12, 31)],
38
- )
39
- yield Case(
40
- Annotated[datetime, at.Gt(Decimal('1.123'))],
41
- [Decimal('1.1231'), Decimal('123')],
42
- [Decimal('1.123'), Decimal('0')],
43
- )
44
-
45
- yield Case(Annotated[int, at.Ge(4)], (4, 5, 6, 1000, 4), (0, -1))
46
- yield Case(Annotated[float, at.Ge(0.5)], (0.5, 0.6, 0.7, 0.8, 0.9), (0.4, 0.0, -0.1))
47
- yield Case(
48
- Annotated[datetime, at.Ge(datetime(2000, 1, 1))],
49
- [datetime(2000, 1, 2), datetime(2000, 1, 3)],
50
- [datetime(1998, 1, 1), datetime(1999, 12, 31)],
51
- )
52
-
53
- yield Case(Annotated[int, at.Lt(4)], (0, -1), (4, 5, 6, 1000, 4))
54
- yield Case(Annotated[float, at.Lt(0.5)], (0.4, 0.0, -0.1), (0.5, 0.6, 0.7, 0.8, 0.9))
55
- yield Case(
56
- Annotated[datetime, at.Lt(datetime(2000, 1, 1))],
57
- [datetime(1999, 12, 31), datetime(1999, 12, 31)],
58
- [datetime(2000, 1, 2), datetime(2000, 1, 3)],
59
- )
60
-
61
- yield Case(Annotated[int, at.Le(4)], (4, 0, -1), (5, 6, 1000))
62
- yield Case(Annotated[float, at.Le(0.5)], (0.5, 0.0, -0.1), (0.6, 0.7, 0.8, 0.9))
63
- yield Case(
64
- Annotated[datetime, at.Le(datetime(2000, 1, 1))],
65
- [datetime(2000, 1, 1), datetime(1999, 12, 31)],
66
- [datetime(2000, 1, 2), datetime(2000, 1, 3)],
67
- )
68
-
69
- # Interval
70
- yield Case(Annotated[int, at.Interval(gt=4)], (5, 6, 1000), (4, 0, -1))
71
- yield Case(Annotated[int, at.Interval(gt=4, lt=10)], (5, 6), (4, 10, 1000, 0, -1))
72
- yield Case(Annotated[float, at.Interval(ge=0.5, le=1)], (0.5, 0.9, 1), (0.49, 1.1))
73
- yield Case(
74
- Annotated[datetime, at.Interval(gt=datetime(2000, 1, 1), le=datetime(2000, 1, 3))],
75
- [datetime(2000, 1, 2), datetime(2000, 1, 3)],
76
- [datetime(2000, 1, 1), datetime(2000, 1, 4)],
77
- )
78
-
79
- yield Case(Annotated[int, at.MultipleOf(multiple_of=3)], (0, 3, 9), (1, 2, 4))
80
- yield Case(Annotated[float, at.MultipleOf(multiple_of=0.5)], (0, 0.5, 1, 1.5), (0.4, 1.1))
81
-
82
- # lengths
83
-
84
- yield Case(Annotated[str, at.MinLen(3)], ('123', '1234', 'x' * 10), ('', '1', '12'))
85
- yield Case(Annotated[str, at.Len(3)], ('123', '1234', 'x' * 10), ('', '1', '12'))
86
- yield Case(Annotated[List[int], at.MinLen(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2]))
87
- yield Case(Annotated[List[int], at.Len(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2]))
88
-
89
- yield Case(Annotated[str, at.MaxLen(4)], ('', '1234'), ('12345', 'x' * 10))
90
- yield Case(Annotated[str, at.Len(0, 4)], ('', '1234'), ('12345', 'x' * 10))
91
- yield Case(Annotated[List[str], at.MaxLen(4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10))
92
- yield Case(Annotated[List[str], at.Len(0, 4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10))
93
-
94
- yield Case(Annotated[str, at.Len(3, 5)], ('123', '12345'), ('', '1', '12', '123456', 'x' * 10))
95
- yield Case(Annotated[str, at.Len(3, 3)], ('123',), ('12', '1234'))
96
-
97
- yield Case(Annotated[Dict[int, int], at.Len(2, 3)], [{1: 1, 2: 2}], [{}, {1: 1}, {1: 1, 2: 2, 3: 3, 4: 4}])
98
- yield Case(Annotated[Set[int], at.Len(2, 3)], ({1, 2}, {1, 2, 3}), (set(), {1}, {1, 2, 3, 4}))
99
- yield Case(Annotated[Tuple[int, ...], at.Len(2, 3)], ((1, 2), (1, 2, 3)), ((), (1,), (1, 2, 3, 4)))
100
-
101
- # Timezone
102
-
103
- yield Case(
104
- Annotated[datetime, at.Timezone(None)], [datetime(2000, 1, 1)], [datetime(2000, 1, 1, tzinfo=timezone.utc)]
105
- )
106
- yield Case(
107
- Annotated[datetime, at.Timezone(...)], [datetime(2000, 1, 1, tzinfo=timezone.utc)], [datetime(2000, 1, 1)]
108
- )
109
- yield Case(
110
- Annotated[datetime, at.Timezone(timezone.utc)],
111
- [datetime(2000, 1, 1, tzinfo=timezone.utc)],
112
- [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))],
113
- )
114
- yield Case(
115
- Annotated[datetime, at.Timezone('Europe/London')],
116
- [datetime(2000, 1, 1, tzinfo=timezone(timedelta(0), name='Europe/London'))],
117
- [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))],
118
- )
119
-
120
- # Quantity
121
-
122
- yield Case(Annotated[float, at.Unit(unit='m')], (5, 4.2), ('5m', '4.2m'))
123
-
124
- # predicate types
125
-
126
- yield Case(at.LowerCase[str], ['abc', 'foobar'], ['', 'A', 'Boom'])
127
- yield Case(at.UpperCase[str], ['ABC', 'DEFO'], ['', 'a', 'abc', 'AbC'])
128
- yield Case(at.IsDigit[str], ['123'], ['', 'ab', 'a1b2'])
129
- yield Case(at.IsAscii[str], ['123', 'foo bar'], ['£100', '😊', 'whatever 👀'])
130
-
131
- yield Case(Annotated[int, at.Predicate(lambda x: x % 2 == 0)], [0, 2, 4], [1, 3, 5])
132
-
133
- yield Case(at.IsFinite[float], [1.23], [math.nan, math.inf, -math.inf])
134
- yield Case(at.IsNotFinite[float], [math.nan, math.inf], [1.23])
135
- yield Case(at.IsNan[float], [math.nan], [1.23, math.inf])
136
- yield Case(at.IsNotNan[float], [1.23, math.inf], [math.nan])
137
- yield Case(at.IsInfinite[float], [math.inf], [math.nan, 1.23])
138
- yield Case(at.IsNotInfinite[float], [math.nan, 1.23], [math.inf])
139
-
140
- # check stacked predicates
141
- yield Case(at.IsInfinite[Annotated[float, at.Predicate(lambda x: x > 0)]], [math.inf], [-math.inf, 1.23, math.nan])
142
-
143
- # doc
144
- yield Case(Annotated[int, at.doc("A number")], [1, 2], [])
145
-
146
- # custom GroupedMetadata
147
- class MyCustomGroupedMetadata(at.GroupedMetadata):
148
- def __iter__(self) -> Iterator[at.Predicate]:
149
- yield at.Predicate(lambda x: float(x).is_integer())
150
-
151
- yield Case(Annotated[float, MyCustomGroupedMetadata()], [0, 2.0], [0.01, 1.5])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/anyio-4.9.0.dist-info/INSTALLER DELETED
@@ -1 +0,0 @@
1
- pip
 
 
venv/Lib/site-packages/anyio-4.9.0.dist-info/LICENSE DELETED
@@ -1,20 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2018 Alex Grönholm
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of
6
- this software and associated documentation files (the "Software"), to deal in
7
- the Software without restriction, including without limitation the rights to
8
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
- the Software, and to permit persons to whom the Software is furnished to do so,
10
- subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/anyio-4.9.0.dist-info/METADATA DELETED
@@ -1,105 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: anyio
3
- Version: 4.9.0
4
- Summary: High level compatibility layer for multiple asynchronous event loop implementations
5
- Author-email: Alex Grönholm <alex.gronholm@nextday.fi>
6
- License: MIT
7
- Project-URL: Documentation, https://anyio.readthedocs.io/en/latest/
8
- Project-URL: Changelog, https://anyio.readthedocs.io/en/stable/versionhistory.html
9
- Project-URL: Source code, https://github.com/agronholm/anyio
10
- Project-URL: Issue tracker, https://github.com/agronholm/anyio/issues
11
- Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Framework :: AnyIO
15
- Classifier: Typing :: Typed
16
- Classifier: Programming Language :: Python
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.9
19
- Classifier: Programming Language :: Python :: 3.10
20
- Classifier: Programming Language :: Python :: 3.11
21
- Classifier: Programming Language :: Python :: 3.12
22
- Classifier: Programming Language :: Python :: 3.13
23
- Requires-Python: >=3.9
24
- Description-Content-Type: text/x-rst
25
- License-File: LICENSE
26
- Requires-Dist: exceptiongroup>=1.0.2; python_version < "3.11"
27
- Requires-Dist: idna>=2.8
28
- Requires-Dist: sniffio>=1.1
29
- Requires-Dist: typing_extensions>=4.5; python_version < "3.13"
30
- Provides-Extra: trio
31
- Requires-Dist: trio>=0.26.1; extra == "trio"
32
- Provides-Extra: test
33
- Requires-Dist: anyio[trio]; extra == "test"
34
- Requires-Dist: blockbuster>=1.5.23; extra == "test"
35
- Requires-Dist: coverage[toml]>=7; extra == "test"
36
- Requires-Dist: exceptiongroup>=1.2.0; extra == "test"
37
- Requires-Dist: hypothesis>=4.0; extra == "test"
38
- Requires-Dist: psutil>=5.9; extra == "test"
39
- Requires-Dist: pytest>=7.0; extra == "test"
40
- Requires-Dist: trustme; extra == "test"
41
- Requires-Dist: truststore>=0.9.1; python_version >= "3.10" and extra == "test"
42
- Requires-Dist: uvloop>=0.21; (platform_python_implementation == "CPython" and platform_system != "Windows" and python_version < "3.14") and extra == "test"
43
- Provides-Extra: doc
44
- Requires-Dist: packaging; extra == "doc"
45
- Requires-Dist: Sphinx~=8.2; extra == "doc"
46
- Requires-Dist: sphinx_rtd_theme; extra == "doc"
47
- Requires-Dist: sphinx-autodoc-typehints>=1.2.0; extra == "doc"
48
-
49
- .. image:: https://github.com/agronholm/anyio/actions/workflows/test.yml/badge.svg
50
- :target: https://github.com/agronholm/anyio/actions/workflows/test.yml
51
- :alt: Build Status
52
- .. image:: https://coveralls.io/repos/github/agronholm/anyio/badge.svg?branch=master
53
- :target: https://coveralls.io/github/agronholm/anyio?branch=master
54
- :alt: Code Coverage
55
- .. image:: https://readthedocs.org/projects/anyio/badge/?version=latest
56
- :target: https://anyio.readthedocs.io/en/latest/?badge=latest
57
- :alt: Documentation
58
- .. image:: https://badges.gitter.im/gitterHQ/gitter.svg
59
- :target: https://gitter.im/python-trio/AnyIO
60
- :alt: Gitter chat
61
-
62
- AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio_ or
63
- trio_. It implements trio-like `structured concurrency`_ (SC) on top of asyncio and works in harmony
64
- with the native SC of trio itself.
65
-
66
- Applications and libraries written against AnyIO's API will run unmodified on either asyncio_ or
67
- trio_. AnyIO can also be adopted into a library or application incrementally – bit by bit, no full
68
- refactoring necessary. It will blend in with the native libraries of your chosen backend.
69
-
70
- Documentation
71
- -------------
72
-
73
- View full documentation at: https://anyio.readthedocs.io/
74
-
75
- Features
76
- --------
77
-
78
- AnyIO offers the following functionality:
79
-
80
- * Task groups (nurseries_ in trio terminology)
81
- * High-level networking (TCP, UDP and UNIX sockets)
82
-
83
- * `Happy eyeballs`_ algorithm for TCP connections (more robust than that of asyncio on Python
84
- 3.8)
85
- * async/await style UDP sockets (unlike asyncio where you still have to use Transports and
86
- Protocols)
87
-
88
- * A versatile API for byte streams and object streams
89
- * Inter-task synchronization and communication (locks, conditions, events, semaphores, object
90
- streams)
91
- * Worker threads
92
- * Subprocesses
93
- * Asynchronous file I/O (using worker threads)
94
- * Signal handling
95
-
96
- AnyIO also comes with its own pytest_ plugin which also supports asynchronous fixtures.
97
- It even works with the popular Hypothesis_ library.
98
-
99
- .. _asyncio: https://docs.python.org/3/library/asyncio.html
100
- .. _trio: https://github.com/python-trio/trio
101
- .. _structured concurrency: https://en.wikipedia.org/wiki/Structured_concurrency
102
- .. _nurseries: https://trio.readthedocs.io/en/stable/reference-core.html#nurseries-and-spawning
103
- .. _Happy eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs
104
- .. _pytest: https://docs.pytest.org/en/latest/
105
- .. _Hypothesis: https://hypothesis.works/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/anyio-4.9.0.dist-info/RECORD DELETED
@@ -1,88 +0,0 @@
1
- anyio-4.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
2
- anyio-4.9.0.dist-info/LICENSE,sha256=U2GsncWPLvX9LpsJxoKXwX8ElQkJu8gCO9uC6s8iwrA,1081
3
- anyio-4.9.0.dist-info/METADATA,sha256=vvkWPXXTbrpTCFK7zdcYwQcSQhx6Q4qITM9t_PEQCrY,4682
4
- anyio-4.9.0.dist-info/RECORD,,
5
- anyio-4.9.0.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
6
- anyio-4.9.0.dist-info/entry_points.txt,sha256=_d6Yu6uiaZmNe0CydowirE9Cmg7zUL2g08tQpoS3Qvc,39
7
- anyio-4.9.0.dist-info/top_level.txt,sha256=QglSMiWX8_5dpoVAEIHdEYzvqFMdSYWmCj6tYw2ITkQ,6
8
- anyio/__init__.py,sha256=t8bZuNXa5ncwXBaNKbv48BDgZt48RT_zCEtrnPmjNU8,4993
9
- anyio/__pycache__/__init__.cpython-311.pyc,,
10
- anyio/__pycache__/from_thread.cpython-311.pyc,,
11
- anyio/__pycache__/lowlevel.cpython-311.pyc,,
12
- anyio/__pycache__/pytest_plugin.cpython-311.pyc,,
13
- anyio/__pycache__/to_interpreter.cpython-311.pyc,,
14
- anyio/__pycache__/to_process.cpython-311.pyc,,
15
- anyio/__pycache__/to_thread.cpython-311.pyc,,
16
- anyio/_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- anyio/_backends/__pycache__/__init__.cpython-311.pyc,,
18
- anyio/_backends/__pycache__/_asyncio.cpython-311.pyc,,
19
- anyio/_backends/__pycache__/_trio.cpython-311.pyc,,
20
- anyio/_backends/_asyncio.py,sha256=AT1oaTfCE-9YFxooMlvld2yDqY5U2A-ANMcBDh9eRfI,93455
21
- anyio/_backends/_trio.py,sha256=HVfDqRGQ7Xj3JfTcYdgzmC7pZEplqU4NOO5kxNNSZnk,40429
22
- anyio/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- anyio/_core/__pycache__/__init__.cpython-311.pyc,,
24
- anyio/_core/__pycache__/_asyncio_selector_thread.cpython-311.pyc,,
25
- anyio/_core/__pycache__/_eventloop.cpython-311.pyc,,
26
- anyio/_core/__pycache__/_exceptions.cpython-311.pyc,,
27
- anyio/_core/__pycache__/_fileio.cpython-311.pyc,,
28
- anyio/_core/__pycache__/_resources.cpython-311.pyc,,
29
- anyio/_core/__pycache__/_signals.cpython-311.pyc,,
30
- anyio/_core/__pycache__/_sockets.cpython-311.pyc,,
31
- anyio/_core/__pycache__/_streams.cpython-311.pyc,,
32
- anyio/_core/__pycache__/_subprocesses.cpython-311.pyc,,
33
- anyio/_core/__pycache__/_synchronization.cpython-311.pyc,,
34
- anyio/_core/__pycache__/_tasks.cpython-311.pyc,,
35
- anyio/_core/__pycache__/_tempfile.cpython-311.pyc,,
36
- anyio/_core/__pycache__/_testing.cpython-311.pyc,,
37
- anyio/_core/__pycache__/_typedattr.cpython-311.pyc,,
38
- anyio/_core/_asyncio_selector_thread.py,sha256=2PdxFM3cs02Kp6BSppbvmRT7q7asreTW5FgBxEsflBo,5626
39
- anyio/_core/_eventloop.py,sha256=t_tAwBFPjF8jrZGjlJ6bbYy6KA3bjsbZxV9mvh9t1i0,4695
40
- anyio/_core/_exceptions.py,sha256=RlPRlwastdmfDPoskdXNO6SI8_l3fclA2wtW6cokU9I,3503
41
- anyio/_core/_fileio.py,sha256=qFZhkLIz0cGXluvih_vcPUTucgq8UFVgsTCtYbijZIg,23340
42
- anyio/_core/_resources.py,sha256=NbmU5O5UX3xEyACnkmYX28Fmwdl-f-ny0tHym26e0w0,435
43
- anyio/_core/_signals.py,sha256=vulT1M1xdLYtAR-eY5TamIgaf1WTlOwOrMGwswlTTr8,905
44
- anyio/_core/_sockets.py,sha256=5Okc_UThGDEN9KCnsIhqWPRHBNuSy6b4NmG1i51TVF4,27150
45
- anyio/_core/_streams.py,sha256=OnaKgoDD-FcMSwLvkoAUGP51sG2ZdRvMpxt9q2w1gYA,1804
46
- anyio/_core/_subprocesses.py,sha256=EXm5igL7dj55iYkPlbYVAqtbqxJxjU-6OndSTIx9SRg,8047
47
- anyio/_core/_synchronization.py,sha256=DwUh8Tl6cG_UMVC_GyzPoC_U9BpfDfjMl9SINSxcZN4,20320
48
- anyio/_core/_tasks.py,sha256=f3CuWwo06cCZ6jaOv-JHFKWkgpgf2cvaF25Oh4augMA,4757
49
- anyio/_core/_tempfile.py,sha256=s-_ucacXbxBH5Bo5eo65lN0lPwZQd5B8yNN_9nARpCM,19696
50
- anyio/_core/_testing.py,sha256=YUGwA5cgFFbUTv4WFd7cv_BSVr4ryTtPp8owQA3JdWE,2118
51
- anyio/_core/_typedattr.py,sha256=P4ozZikn3-DbpoYcvyghS_FOYAgbmUxeoU8-L_07pZM,2508
52
- anyio/abc/__init__.py,sha256=c2OQbTCS_fQowviMXanLPh8m29ccwkXmpDr7uyNZYOo,2652
53
- anyio/abc/__pycache__/__init__.cpython-311.pyc,,
54
- anyio/abc/__pycache__/_eventloop.cpython-311.pyc,,
55
- anyio/abc/__pycache__/_resources.cpython-311.pyc,,
56
- anyio/abc/__pycache__/_sockets.cpython-311.pyc,,
57
- anyio/abc/__pycache__/_streams.cpython-311.pyc,,
58
- anyio/abc/__pycache__/_subprocesses.cpython-311.pyc,,
59
- anyio/abc/__pycache__/_tasks.cpython-311.pyc,,
60
- anyio/abc/__pycache__/_testing.cpython-311.pyc,,
61
- anyio/abc/_eventloop.py,sha256=UmL8DZCvQTgxzmyBZcGm9kWj9VQY8BMWueLh5S8yWN4,9682
62
- anyio/abc/_resources.py,sha256=DrYvkNN1hH6Uvv5_5uKySvDsnknGVDe8FCKfko0VtN8,783
63
- anyio/abc/_sockets.py,sha256=KhWtJxan8jpBXKwPaFeQzI4iRXdFaOIn0HXtDZnaO7U,6262
64
- anyio/abc/_streams.py,sha256=He_JpkAW2g5veOzcUq0XsRC2nId_i35L-d8cs7Uj1ZQ,6598
65
- anyio/abc/_subprocesses.py,sha256=cumAPJTktOQtw63IqG0lDpyZqu_l1EElvQHMiwJgL08,2067
66
- anyio/abc/_tasks.py,sha256=yJWbMwowvqjlAX4oJ3l9Is1w-zwynr2lX1Z02AWJqsY,3080
67
- anyio/abc/_testing.py,sha256=tBJUzkSfOXJw23fe8qSJ03kJlShOYjjaEyFB6k6MYT8,1821
68
- anyio/from_thread.py,sha256=MbXHZpgM9wgsRkbGhMNMomEGYj7Y_QYq6a5BZ3c5Ev8,17478
69
- anyio/lowlevel.py,sha256=nkgmW--SdxGVp0cmLUYazjkigveRm5HY7-gW8Bpp9oY,4169
70
- anyio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- anyio/pytest_plugin.py,sha256=qXNwk9Pa7hPQKWocgLl9qijqKGMkGzdH2wJa-jPkGUM,9375
72
- anyio/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- anyio/streams/__pycache__/__init__.cpython-311.pyc,,
74
- anyio/streams/__pycache__/buffered.cpython-311.pyc,,
75
- anyio/streams/__pycache__/file.cpython-311.pyc,,
76
- anyio/streams/__pycache__/memory.cpython-311.pyc,,
77
- anyio/streams/__pycache__/stapled.cpython-311.pyc,,
78
- anyio/streams/__pycache__/text.cpython-311.pyc,,
79
- anyio/streams/__pycache__/tls.cpython-311.pyc,,
80
- anyio/streams/buffered.py,sha256=UCldKC168YuLvT7n3HtNPnQ2iWAMSTYQWbZvzLwMwkM,4500
81
- anyio/streams/file.py,sha256=6uoTNb5KbMoj-6gS3_xrrL8uZN8Q4iIvOS1WtGyFfKw,4383
82
- anyio/streams/memory.py,sha256=o1OVVx0OooteTTe2GytJreum93Ucuw5s4cAsr3X0-Ag,10560
83
- anyio/streams/stapled.py,sha256=U09pCrmOw9kkNhe6tKopsm1QIMT1lFTFvtb-A7SIe4k,4302
84
- anyio/streams/text.py,sha256=6x8w8xlfCZKTUWQoJiMPoMhSSJFUBRKgoBNSBtbd9yg,5094
85
- anyio/streams/tls.py,sha256=HxzpVmUgo8SUSIBass_lvef1pAI1uRSrnysM3iEGzl4,13199
86
- anyio/to_interpreter.py,sha256=UhuNCIucCRN7ZtyJg35Mlamzs1JpgDvK4xnL4TDWrAo,6527
87
- anyio/to_process.py,sha256=ZvruelRM-HNmqDaql4sdNODg2QD_uSlwSCxnV4OhsfQ,9595
88
- anyio/to_thread.py,sha256=WM2JQ2MbVsd5D5CM08bQiTwzZIvpsGjfH1Fy247KoDQ,2396
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/anyio-4.9.0.dist-info/WHEEL DELETED
@@ -1,5 +0,0 @@
1
- Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
3
- Root-Is-Purelib: true
4
- Tag: py3-none-any
5
-
 
 
 
 
 
 
venv/Lib/site-packages/anyio-4.9.0.dist-info/entry_points.txt DELETED
@@ -1,2 +0,0 @@
1
- [pytest11]
2
- anyio = anyio.pytest_plugin
 
 
 
venv/Lib/site-packages/anyio-4.9.0.dist-info/top_level.txt DELETED
@@ -1 +0,0 @@
1
- anyio
 
 
venv/Lib/site-packages/anyio/__init__.py DELETED
@@ -1,85 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from ._core._eventloop import current_time as current_time
4
- from ._core._eventloop import get_all_backends as get_all_backends
5
- from ._core._eventloop import get_cancelled_exc_class as get_cancelled_exc_class
6
- from ._core._eventloop import run as run
7
- from ._core._eventloop import sleep as sleep
8
- from ._core._eventloop import sleep_forever as sleep_forever
9
- from ._core._eventloop import sleep_until as sleep_until
10
- from ._core._exceptions import BrokenResourceError as BrokenResourceError
11
- from ._core._exceptions import BrokenWorkerIntepreter as BrokenWorkerIntepreter
12
- from ._core._exceptions import BrokenWorkerProcess as BrokenWorkerProcess
13
- from ._core._exceptions import BusyResourceError as BusyResourceError
14
- from ._core._exceptions import ClosedResourceError as ClosedResourceError
15
- from ._core._exceptions import DelimiterNotFound as DelimiterNotFound
16
- from ._core._exceptions import EndOfStream as EndOfStream
17
- from ._core._exceptions import IncompleteRead as IncompleteRead
18
- from ._core._exceptions import TypedAttributeLookupError as TypedAttributeLookupError
19
- from ._core._exceptions import WouldBlock as WouldBlock
20
- from ._core._fileio import AsyncFile as AsyncFile
21
- from ._core._fileio import Path as Path
22
- from ._core._fileio import open_file as open_file
23
- from ._core._fileio import wrap_file as wrap_file
24
- from ._core._resources import aclose_forcefully as aclose_forcefully
25
- from ._core._signals import open_signal_receiver as open_signal_receiver
26
- from ._core._sockets import connect_tcp as connect_tcp
27
- from ._core._sockets import connect_unix as connect_unix
28
- from ._core._sockets import create_connected_udp_socket as create_connected_udp_socket
29
- from ._core._sockets import (
30
- create_connected_unix_datagram_socket as create_connected_unix_datagram_socket,
31
- )
32
- from ._core._sockets import create_tcp_listener as create_tcp_listener
33
- from ._core._sockets import create_udp_socket as create_udp_socket
34
- from ._core._sockets import create_unix_datagram_socket as create_unix_datagram_socket
35
- from ._core._sockets import create_unix_listener as create_unix_listener
36
- from ._core._sockets import getaddrinfo as getaddrinfo
37
- from ._core._sockets import getnameinfo as getnameinfo
38
- from ._core._sockets import wait_readable as wait_readable
39
- from ._core._sockets import wait_socket_readable as wait_socket_readable
40
- from ._core._sockets import wait_socket_writable as wait_socket_writable
41
- from ._core._sockets import wait_writable as wait_writable
42
- from ._core._streams import create_memory_object_stream as create_memory_object_stream
43
- from ._core._subprocesses import open_process as open_process
44
- from ._core._subprocesses import run_process as run_process
45
- from ._core._synchronization import CapacityLimiter as CapacityLimiter
46
- from ._core._synchronization import (
47
- CapacityLimiterStatistics as CapacityLimiterStatistics,
48
- )
49
- from ._core._synchronization import Condition as Condition
50
- from ._core._synchronization import ConditionStatistics as ConditionStatistics
51
- from ._core._synchronization import Event as Event
52
- from ._core._synchronization import EventStatistics as EventStatistics
53
- from ._core._synchronization import Lock as Lock
54
- from ._core._synchronization import LockStatistics as LockStatistics
55
- from ._core._synchronization import ResourceGuard as ResourceGuard
56
- from ._core._synchronization import Semaphore as Semaphore
57
- from ._core._synchronization import SemaphoreStatistics as SemaphoreStatistics
58
- from ._core._tasks import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED
59
- from ._core._tasks import CancelScope as CancelScope
60
- from ._core._tasks import create_task_group as create_task_group
61
- from ._core._tasks import current_effective_deadline as current_effective_deadline
62
- from ._core._tasks import fail_after as fail_after
63
- from ._core._tasks import move_on_after as move_on_after
64
- from ._core._tempfile import NamedTemporaryFile as NamedTemporaryFile
65
- from ._core._tempfile import SpooledTemporaryFile as SpooledTemporaryFile
66
- from ._core._tempfile import TemporaryDirectory as TemporaryDirectory
67
- from ._core._tempfile import TemporaryFile as TemporaryFile
68
- from ._core._tempfile import gettempdir as gettempdir
69
- from ._core._tempfile import gettempdirb as gettempdirb
70
- from ._core._tempfile import mkdtemp as mkdtemp
71
- from ._core._tempfile import mkstemp as mkstemp
72
- from ._core._testing import TaskInfo as TaskInfo
73
- from ._core._testing import get_current_task as get_current_task
74
- from ._core._testing import get_running_tasks as get_running_tasks
75
- from ._core._testing import wait_all_tasks_blocked as wait_all_tasks_blocked
76
- from ._core._typedattr import TypedAttributeProvider as TypedAttributeProvider
77
- from ._core._typedattr import TypedAttributeSet as TypedAttributeSet
78
- from ._core._typedattr import typed_attribute as typed_attribute
79
-
80
- # Re-export imports so they look like they live directly in this package
81
- for __value in list(locals().values()):
82
- if getattr(__value, "__module__", "").startswith("anyio."):
83
- __value.__module__ = __name__
84
-
85
- del __value
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-311.pyc DELETED
Binary file (4.78 kB)
 
venv/Lib/site-packages/anyio/__pycache__/from_thread.cpython-311.pyc DELETED
Binary file (26.2 kB)
 
venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-311.pyc DELETED
Binary file (7.68 kB)
 
venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-311.pyc DELETED
Binary file (15.2 kB)
 
venv/Lib/site-packages/anyio/__pycache__/to_interpreter.cpython-311.pyc DELETED
Binary file (10 kB)
 
venv/Lib/site-packages/anyio/__pycache__/to_process.cpython-311.pyc DELETED
Binary file (13.7 kB)
 
venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-311.pyc DELETED
Binary file (3.22 kB)
 
venv/Lib/site-packages/anyio/_backends/__init__.py DELETED
File without changes
venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-311.pyc DELETED
Binary file (225 Bytes)
 
venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-311.pyc DELETED
Binary file (146 kB)
 
venv/Lib/site-packages/anyio/_backends/__pycache__/_trio.cpython-311.pyc DELETED
Binary file (77.9 kB)
 
venv/Lib/site-packages/anyio/_backends/_asyncio.py DELETED
@@ -1,2816 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import array
4
- import asyncio
5
- import concurrent.futures
6
- import contextvars
7
- import math
8
- import os
9
- import socket
10
- import sys
11
- import threading
12
- import weakref
13
- from asyncio import (
14
- AbstractEventLoop,
15
- CancelledError,
16
- all_tasks,
17
- create_task,
18
- current_task,
19
- get_running_loop,
20
- sleep,
21
- )
22
- from asyncio.base_events import _run_until_complete_cb # type: ignore[attr-defined]
23
- from collections import OrderedDict, deque
24
- from collections.abc import (
25
- AsyncGenerator,
26
- AsyncIterator,
27
- Awaitable,
28
- Callable,
29
- Collection,
30
- Coroutine,
31
- Iterable,
32
- Sequence,
33
- )
34
- from concurrent.futures import Future
35
- from contextlib import AbstractContextManager, suppress
36
- from contextvars import Context, copy_context
37
- from dataclasses import dataclass
38
- from functools import partial, wraps
39
- from inspect import (
40
- CORO_RUNNING,
41
- CORO_SUSPENDED,
42
- getcoroutinestate,
43
- iscoroutine,
44
- )
45
- from io import IOBase
46
- from os import PathLike
47
- from queue import Queue
48
- from signal import Signals
49
- from socket import AddressFamily, SocketKind
50
- from threading import Thread
51
- from types import CodeType, TracebackType
52
- from typing import (
53
- IO,
54
- TYPE_CHECKING,
55
- Any,
56
- Optional,
57
- TypeVar,
58
- cast,
59
- )
60
- from weakref import WeakKeyDictionary
61
-
62
- import sniffio
63
-
64
- from .. import (
65
- CapacityLimiterStatistics,
66
- EventStatistics,
67
- LockStatistics,
68
- TaskInfo,
69
- abc,
70
- )
71
- from .._core._eventloop import claim_worker_thread, threadlocals
72
- from .._core._exceptions import (
73
- BrokenResourceError,
74
- BusyResourceError,
75
- ClosedResourceError,
76
- EndOfStream,
77
- WouldBlock,
78
- iterate_exceptions,
79
- )
80
- from .._core._sockets import convert_ipv6_sockaddr
81
- from .._core._streams import create_memory_object_stream
82
- from .._core._synchronization import (
83
- CapacityLimiter as BaseCapacityLimiter,
84
- )
85
- from .._core._synchronization import Event as BaseEvent
86
- from .._core._synchronization import Lock as BaseLock
87
- from .._core._synchronization import (
88
- ResourceGuard,
89
- SemaphoreStatistics,
90
- )
91
- from .._core._synchronization import Semaphore as BaseSemaphore
92
- from .._core._tasks import CancelScope as BaseCancelScope
93
- from ..abc import (
94
- AsyncBackend,
95
- IPSockAddrType,
96
- SocketListener,
97
- UDPPacketType,
98
- UNIXDatagramPacketType,
99
- )
100
- from ..abc._eventloop import StrOrBytesPath
101
- from ..lowlevel import RunVar
102
- from ..streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
103
-
104
- if TYPE_CHECKING:
105
- from _typeshed import FileDescriptorLike
106
- else:
107
- FileDescriptorLike = object
108
-
109
- if sys.version_info >= (3, 10):
110
- from typing import ParamSpec
111
- else:
112
- from typing_extensions import ParamSpec
113
-
114
- if sys.version_info >= (3, 11):
115
- from asyncio import Runner
116
- from typing import TypeVarTuple, Unpack
117
- else:
118
- import contextvars
119
- import enum
120
- import signal
121
- from asyncio import coroutines, events, exceptions, tasks
122
-
123
- from exceptiongroup import BaseExceptionGroup
124
- from typing_extensions import TypeVarTuple, Unpack
125
-
126
- class _State(enum.Enum):
127
- CREATED = "created"
128
- INITIALIZED = "initialized"
129
- CLOSED = "closed"
130
-
131
- class Runner:
132
- # Copied from CPython 3.11
133
- def __init__(
134
- self,
135
- *,
136
- debug: bool | None = None,
137
- loop_factory: Callable[[], AbstractEventLoop] | None = None,
138
- ):
139
- self._state = _State.CREATED
140
- self._debug = debug
141
- self._loop_factory = loop_factory
142
- self._loop: AbstractEventLoop | None = None
143
- self._context = None
144
- self._interrupt_count = 0
145
- self._set_event_loop = False
146
-
147
- def __enter__(self) -> Runner:
148
- self._lazy_init()
149
- return self
150
-
151
- def __exit__(
152
- self,
153
- exc_type: type[BaseException],
154
- exc_val: BaseException,
155
- exc_tb: TracebackType,
156
- ) -> None:
157
- self.close()
158
-
159
- def close(self) -> None:
160
- """Shutdown and close event loop."""
161
- if self._state is not _State.INITIALIZED:
162
- return
163
- try:
164
- loop = self._loop
165
- _cancel_all_tasks(loop)
166
- loop.run_until_complete(loop.shutdown_asyncgens())
167
- if hasattr(loop, "shutdown_default_executor"):
168
- loop.run_until_complete(loop.shutdown_default_executor())
169
- else:
170
- loop.run_until_complete(_shutdown_default_executor(loop))
171
- finally:
172
- if self._set_event_loop:
173
- events.set_event_loop(None)
174
- loop.close()
175
- self._loop = None
176
- self._state = _State.CLOSED
177
-
178
- def get_loop(self) -> AbstractEventLoop:
179
- """Return embedded event loop."""
180
- self._lazy_init()
181
- return self._loop
182
-
183
- def run(self, coro: Coroutine[T_Retval], *, context=None) -> T_Retval:
184
- """Run a coroutine inside the embedded event loop."""
185
- if not coroutines.iscoroutine(coro):
186
- raise ValueError(f"a coroutine was expected, got {coro!r}")
187
-
188
- if events._get_running_loop() is not None:
189
- # fail fast with short traceback
190
- raise RuntimeError(
191
- "Runner.run() cannot be called from a running event loop"
192
- )
193
-
194
- self._lazy_init()
195
-
196
- if context is None:
197
- context = self._context
198
- task = context.run(self._loop.create_task, coro)
199
-
200
- if (
201
- threading.current_thread() is threading.main_thread()
202
- and signal.getsignal(signal.SIGINT) is signal.default_int_handler
203
- ):
204
- sigint_handler = partial(self._on_sigint, main_task=task)
205
- try:
206
- signal.signal(signal.SIGINT, sigint_handler)
207
- except ValueError:
208
- # `signal.signal` may throw if `threading.main_thread` does
209
- # not support signals (e.g. embedded interpreter with signals
210
- # not registered - see gh-91880)
211
- sigint_handler = None
212
- else:
213
- sigint_handler = None
214
-
215
- self._interrupt_count = 0
216
- try:
217
- return self._loop.run_until_complete(task)
218
- except exceptions.CancelledError:
219
- if self._interrupt_count > 0:
220
- uncancel = getattr(task, "uncancel", None)
221
- if uncancel is not None and uncancel() == 0:
222
- raise KeyboardInterrupt()
223
- raise # CancelledError
224
- finally:
225
- if (
226
- sigint_handler is not None
227
- and signal.getsignal(signal.SIGINT) is sigint_handler
228
- ):
229
- signal.signal(signal.SIGINT, signal.default_int_handler)
230
-
231
- def _lazy_init(self) -> None:
232
- if self._state is _State.CLOSED:
233
- raise RuntimeError("Runner is closed")
234
- if self._state is _State.INITIALIZED:
235
- return
236
- if self._loop_factory is None:
237
- self._loop = events.new_event_loop()
238
- if not self._set_event_loop:
239
- # Call set_event_loop only once to avoid calling
240
- # attach_loop multiple times on child watchers
241
- events.set_event_loop(self._loop)
242
- self._set_event_loop = True
243
- else:
244
- self._loop = self._loop_factory()
245
- if self._debug is not None:
246
- self._loop.set_debug(self._debug)
247
- self._context = contextvars.copy_context()
248
- self._state = _State.INITIALIZED
249
-
250
- def _on_sigint(self, signum, frame, main_task: asyncio.Task) -> None:
251
- self._interrupt_count += 1
252
- if self._interrupt_count == 1 and not main_task.done():
253
- main_task.cancel()
254
- # wakeup loop if it is blocked by select() with long timeout
255
- self._loop.call_soon_threadsafe(lambda: None)
256
- return
257
- raise KeyboardInterrupt()
258
-
259
- def _cancel_all_tasks(loop: AbstractEventLoop) -> None:
260
- to_cancel = tasks.all_tasks(loop)
261
- if not to_cancel:
262
- return
263
-
264
- for task in to_cancel:
265
- task.cancel()
266
-
267
- loop.run_until_complete(tasks.gather(*to_cancel, return_exceptions=True))
268
-
269
- for task in to_cancel:
270
- if task.cancelled():
271
- continue
272
- if task.exception() is not None:
273
- loop.call_exception_handler(
274
- {
275
- "message": "unhandled exception during asyncio.run() shutdown",
276
- "exception": task.exception(),
277
- "task": task,
278
- }
279
- )
280
-
281
- async def _shutdown_default_executor(loop: AbstractEventLoop) -> None:
282
- """Schedule the shutdown of the default executor."""
283
-
284
- def _do_shutdown(future: asyncio.futures.Future) -> None:
285
- try:
286
- loop._default_executor.shutdown(wait=True) # type: ignore[attr-defined]
287
- loop.call_soon_threadsafe(future.set_result, None)
288
- except Exception as ex:
289
- loop.call_soon_threadsafe(future.set_exception, ex)
290
-
291
- loop._executor_shutdown_called = True
292
- if loop._default_executor is None:
293
- return
294
- future = loop.create_future()
295
- thread = threading.Thread(target=_do_shutdown, args=(future,))
296
- thread.start()
297
- try:
298
- await future
299
- finally:
300
- thread.join()
301
-
302
-
303
- T_Retval = TypeVar("T_Retval")
304
- T_contra = TypeVar("T_contra", contravariant=True)
305
- PosArgsT = TypeVarTuple("PosArgsT")
306
- P = ParamSpec("P")
307
-
308
- _root_task: RunVar[asyncio.Task | None] = RunVar("_root_task")
309
-
310
-
311
- def find_root_task() -> asyncio.Task:
312
- root_task = _root_task.get(None)
313
- if root_task is not None and not root_task.done():
314
- return root_task
315
-
316
- # Look for a task that has been started via run_until_complete()
317
- for task in all_tasks():
318
- if task._callbacks and not task.done():
319
- callbacks = [cb for cb, context in task._callbacks]
320
- for cb in callbacks:
321
- if (
322
- cb is _run_until_complete_cb
323
- or getattr(cb, "__module__", None) == "uvloop.loop"
324
- ):
325
- _root_task.set(task)
326
- return task
327
-
328
- # Look up the topmost task in the AnyIO task tree, if possible
329
- task = cast(asyncio.Task, current_task())
330
- state = _task_states.get(task)
331
- if state:
332
- cancel_scope = state.cancel_scope
333
- while cancel_scope and cancel_scope._parent_scope is not None:
334
- cancel_scope = cancel_scope._parent_scope
335
-
336
- if cancel_scope is not None:
337
- return cast(asyncio.Task, cancel_scope._host_task)
338
-
339
- return task
340
-
341
-
342
- def get_callable_name(func: Callable) -> str:
343
- module = getattr(func, "__module__", None)
344
- qualname = getattr(func, "__qualname__", None)
345
- return ".".join([x for x in (module, qualname) if x])
346
-
347
-
348
- #
349
- # Event loop
350
- #
351
-
352
- _run_vars: WeakKeyDictionary[asyncio.AbstractEventLoop, Any] = WeakKeyDictionary()
353
-
354
-
355
- def _task_started(task: asyncio.Task) -> bool:
356
- """Return ``True`` if the task has been started and has not finished."""
357
- # The task coro should never be None here, as we never add finished tasks to the
358
- # task list
359
- coro = task.get_coro()
360
- assert coro is not None
361
- try:
362
- return getcoroutinestate(coro) in (CORO_RUNNING, CORO_SUSPENDED)
363
- except AttributeError:
364
- # task coro is async_genenerator_asend https://bugs.python.org/issue37771
365
- raise Exception(f"Cannot determine if task {task} has started or not") from None
366
-
367
-
368
- #
369
- # Timeouts and cancellation
370
- #
371
-
372
-
373
- def is_anyio_cancellation(exc: CancelledError) -> bool:
374
- # Sometimes third party frameworks catch a CancelledError and raise a new one, so as
375
- # a workaround we have to look at the previous ones in __context__ too for a
376
- # matching cancel message
377
- while True:
378
- if (
379
- exc.args
380
- and isinstance(exc.args[0], str)
381
- and exc.args[0].startswith("Cancelled by cancel scope ")
382
- ):
383
- return True
384
-
385
- if isinstance(exc.__context__, CancelledError):
386
- exc = exc.__context__
387
- continue
388
-
389
- return False
390
-
391
-
392
- class CancelScope(BaseCancelScope):
393
- def __new__(
394
- cls, *, deadline: float = math.inf, shield: bool = False
395
- ) -> CancelScope:
396
- return object.__new__(cls)
397
-
398
- def __init__(self, deadline: float = math.inf, shield: bool = False):
399
- self._deadline = deadline
400
- self._shield = shield
401
- self._parent_scope: CancelScope | None = None
402
- self._child_scopes: set[CancelScope] = set()
403
- self._cancel_called = False
404
- self._cancelled_caught = False
405
- self._active = False
406
- self._timeout_handle: asyncio.TimerHandle | None = None
407
- self._cancel_handle: asyncio.Handle | None = None
408
- self._tasks: set[asyncio.Task] = set()
409
- self._host_task: asyncio.Task | None = None
410
- if sys.version_info >= (3, 11):
411
- self._pending_uncancellations: int | None = 0
412
- else:
413
- self._pending_uncancellations = None
414
-
415
- def __enter__(self) -> CancelScope:
416
- if self._active:
417
- raise RuntimeError(
418
- "Each CancelScope may only be used for a single 'with' block"
419
- )
420
-
421
- self._host_task = host_task = cast(asyncio.Task, current_task())
422
- self._tasks.add(host_task)
423
- try:
424
- task_state = _task_states[host_task]
425
- except KeyError:
426
- task_state = TaskState(None, self)
427
- _task_states[host_task] = task_state
428
- else:
429
- self._parent_scope = task_state.cancel_scope
430
- task_state.cancel_scope = self
431
- if self._parent_scope is not None:
432
- # If using an eager task factory, the parent scope may not even contain
433
- # the host task
434
- self._parent_scope._child_scopes.add(self)
435
- self._parent_scope._tasks.discard(host_task)
436
-
437
- self._timeout()
438
- self._active = True
439
-
440
- # Start cancelling the host task if the scope was cancelled before entering
441
- if self._cancel_called:
442
- self._deliver_cancellation(self)
443
-
444
- return self
445
-
446
- def __exit__(
447
- self,
448
- exc_type: type[BaseException] | None,
449
- exc_val: BaseException | None,
450
- exc_tb: TracebackType | None,
451
- ) -> bool:
452
- del exc_tb
453
-
454
- if not self._active:
455
- raise RuntimeError("This cancel scope is not active")
456
- if current_task() is not self._host_task:
457
- raise RuntimeError(
458
- "Attempted to exit cancel scope in a different task than it was "
459
- "entered in"
460
- )
461
-
462
- assert self._host_task is not None
463
- host_task_state = _task_states.get(self._host_task)
464
- if host_task_state is None or host_task_state.cancel_scope is not self:
465
- raise RuntimeError(
466
- "Attempted to exit a cancel scope that isn't the current tasks's "
467
- "current cancel scope"
468
- )
469
-
470
- try:
471
- self._active = False
472
- if self._timeout_handle:
473
- self._timeout_handle.cancel()
474
- self._timeout_handle = None
475
-
476
- self._tasks.remove(self._host_task)
477
- if self._parent_scope is not None:
478
- self._parent_scope._child_scopes.remove(self)
479
- self._parent_scope._tasks.add(self._host_task)
480
-
481
- host_task_state.cancel_scope = self._parent_scope
482
-
483
- # Restart the cancellation effort in the closest visible, cancelled parent
484
- # scope if necessary
485
- self._restart_cancellation_in_parent()
486
-
487
- # We only swallow the exception iff it was an AnyIO CancelledError, either
488
- # directly as exc_val or inside an exception group and there are no cancelled
489
- # parent cancel scopes visible to us here
490
- if self._cancel_called and not self._parent_cancellation_is_visible_to_us:
491
- # For each level-cancel() call made on the host task, call uncancel()
492
- while self._pending_uncancellations:
493
- self._host_task.uncancel()
494
- self._pending_uncancellations -= 1
495
-
496
- # Update cancelled_caught and check for exceptions we must not swallow
497
- cannot_swallow_exc_val = False
498
- if exc_val is not None:
499
- for exc in iterate_exceptions(exc_val):
500
- if isinstance(exc, CancelledError) and is_anyio_cancellation(
501
- exc
502
- ):
503
- self._cancelled_caught = True
504
- else:
505
- cannot_swallow_exc_val = True
506
-
507
- return self._cancelled_caught and not cannot_swallow_exc_val
508
- else:
509
- if self._pending_uncancellations:
510
- assert self._parent_scope is not None
511
- assert self._parent_scope._pending_uncancellations is not None
512
- self._parent_scope._pending_uncancellations += (
513
- self._pending_uncancellations
514
- )
515
- self._pending_uncancellations = 0
516
-
517
- return False
518
- finally:
519
- self._host_task = None
520
- del exc_val
521
-
522
- @property
523
- def _effectively_cancelled(self) -> bool:
524
- cancel_scope: CancelScope | None = self
525
- while cancel_scope is not None:
526
- if cancel_scope._cancel_called:
527
- return True
528
-
529
- if cancel_scope.shield:
530
- return False
531
-
532
- cancel_scope = cancel_scope._parent_scope
533
-
534
- return False
535
-
536
- @property
537
- def _parent_cancellation_is_visible_to_us(self) -> bool:
538
- return (
539
- self._parent_scope is not None
540
- and not self.shield
541
- and self._parent_scope._effectively_cancelled
542
- )
543
-
544
- def _timeout(self) -> None:
545
- if self._deadline != math.inf:
546
- loop = get_running_loop()
547
- if loop.time() >= self._deadline:
548
- self.cancel()
549
- else:
550
- self._timeout_handle = loop.call_at(self._deadline, self._timeout)
551
-
552
- def _deliver_cancellation(self, origin: CancelScope) -> bool:
553
- """
554
- Deliver cancellation to directly contained tasks and nested cancel scopes.
555
-
556
- Schedule another run at the end if we still have tasks eligible for
557
- cancellation.
558
-
559
- :param origin: the cancel scope that originated the cancellation
560
- :return: ``True`` if the delivery needs to be retried on the next cycle
561
-
562
- """
563
- should_retry = False
564
- current = current_task()
565
- for task in self._tasks:
566
- should_retry = True
567
- if task._must_cancel: # type: ignore[attr-defined]
568
- continue
569
-
570
- # The task is eligible for cancellation if it has started
571
- if task is not current and (task is self._host_task or _task_started(task)):
572
- waiter = task._fut_waiter # type: ignore[attr-defined]
573
- if not isinstance(waiter, asyncio.Future) or not waiter.done():
574
- task.cancel(f"Cancelled by cancel scope {id(origin):x}")
575
- if (
576
- task is origin._host_task
577
- and origin._pending_uncancellations is not None
578
- ):
579
- origin._pending_uncancellations += 1
580
-
581
- # Deliver cancellation to child scopes that aren't shielded or running their own
582
- # cancellation callbacks
583
- for scope in self._child_scopes:
584
- if not scope._shield and not scope.cancel_called:
585
- should_retry = scope._deliver_cancellation(origin) or should_retry
586
-
587
- # Schedule another callback if there are still tasks left
588
- if origin is self:
589
- if should_retry:
590
- self._cancel_handle = get_running_loop().call_soon(
591
- self._deliver_cancellation, origin
592
- )
593
- else:
594
- self._cancel_handle = None
595
-
596
- return should_retry
597
-
598
- def _restart_cancellation_in_parent(self) -> None:
599
- """
600
- Restart the cancellation effort in the closest directly cancelled parent scope.
601
-
602
- """
603
- scope = self._parent_scope
604
- while scope is not None:
605
- if scope._cancel_called:
606
- if scope._cancel_handle is None:
607
- scope._deliver_cancellation(scope)
608
-
609
- break
610
-
611
- # No point in looking beyond any shielded scope
612
- if scope._shield:
613
- break
614
-
615
- scope = scope._parent_scope
616
-
617
- def cancel(self) -> None:
618
- if not self._cancel_called:
619
- if self._timeout_handle:
620
- self._timeout_handle.cancel()
621
- self._timeout_handle = None
622
-
623
- self._cancel_called = True
624
- if self._host_task is not None:
625
- self._deliver_cancellation(self)
626
-
627
- @property
628
- def deadline(self) -> float:
629
- return self._deadline
630
-
631
- @deadline.setter
632
- def deadline(self, value: float) -> None:
633
- self._deadline = float(value)
634
- if self._timeout_handle is not None:
635
- self._timeout_handle.cancel()
636
- self._timeout_handle = None
637
-
638
- if self._active and not self._cancel_called:
639
- self._timeout()
640
-
641
- @property
642
- def cancel_called(self) -> bool:
643
- return self._cancel_called
644
-
645
- @property
646
- def cancelled_caught(self) -> bool:
647
- return self._cancelled_caught
648
-
649
- @property
650
- def shield(self) -> bool:
651
- return self._shield
652
-
653
- @shield.setter
654
- def shield(self, value: bool) -> None:
655
- if self._shield != value:
656
- self._shield = value
657
- if not value:
658
- self._restart_cancellation_in_parent()
659
-
660
-
661
- #
662
- # Task states
663
- #
664
-
665
-
666
- class TaskState:
667
- """
668
- Encapsulates auxiliary task information that cannot be added to the Task instance
669
- itself because there are no guarantees about its implementation.
670
- """
671
-
672
- __slots__ = "parent_id", "cancel_scope", "__weakref__"
673
-
674
- def __init__(self, parent_id: int | None, cancel_scope: CancelScope | None):
675
- self.parent_id = parent_id
676
- self.cancel_scope = cancel_scope
677
-
678
-
679
- _task_states: WeakKeyDictionary[asyncio.Task, TaskState] = WeakKeyDictionary()
680
-
681
-
682
- #
683
- # Task groups
684
- #
685
-
686
-
687
- class _AsyncioTaskStatus(abc.TaskStatus):
688
- def __init__(self, future: asyncio.Future, parent_id: int):
689
- self._future = future
690
- self._parent_id = parent_id
691
-
692
- def started(self, value: T_contra | None = None) -> None:
693
- try:
694
- self._future.set_result(value)
695
- except asyncio.InvalidStateError:
696
- if not self._future.cancelled():
697
- raise RuntimeError(
698
- "called 'started' twice on the same task status"
699
- ) from None
700
-
701
- task = cast(asyncio.Task, current_task())
702
- _task_states[task].parent_id = self._parent_id
703
-
704
-
705
- if sys.version_info >= (3, 12):
706
- _eager_task_factory_code: CodeType | None = asyncio.eager_task_factory.__code__
707
- else:
708
- _eager_task_factory_code = None
709
-
710
-
711
- class TaskGroup(abc.TaskGroup):
712
- def __init__(self) -> None:
713
- self.cancel_scope: CancelScope = CancelScope()
714
- self._active = False
715
- self._exceptions: list[BaseException] = []
716
- self._tasks: set[asyncio.Task] = set()
717
- self._on_completed_fut: asyncio.Future[None] | None = None
718
-
719
- async def __aenter__(self) -> TaskGroup:
720
- self.cancel_scope.__enter__()
721
- self._active = True
722
- return self
723
-
724
- async def __aexit__(
725
- self,
726
- exc_type: type[BaseException] | None,
727
- exc_val: BaseException | None,
728
- exc_tb: TracebackType | None,
729
- ) -> bool | None:
730
- try:
731
- if exc_val is not None:
732
- self.cancel_scope.cancel()
733
- if not isinstance(exc_val, CancelledError):
734
- self._exceptions.append(exc_val)
735
-
736
- loop = get_running_loop()
737
- try:
738
- if self._tasks:
739
- with CancelScope() as wait_scope:
740
- while self._tasks:
741
- self._on_completed_fut = loop.create_future()
742
-
743
- try:
744
- await self._on_completed_fut
745
- except CancelledError as exc:
746
- # Shield the scope against further cancellation attempts,
747
- # as they're not productive (#695)
748
- wait_scope.shield = True
749
- self.cancel_scope.cancel()
750
-
751
- # Set exc_val from the cancellation exception if it was
752
- # previously unset. However, we should not replace a native
753
- # cancellation exception with one raise by a cancel scope.
754
- if exc_val is None or (
755
- isinstance(exc_val, CancelledError)
756
- and not is_anyio_cancellation(exc)
757
- ):
758
- exc_val = exc
759
-
760
- self._on_completed_fut = None
761
- else:
762
- # If there are no child tasks to wait on, run at least one checkpoint
763
- # anyway
764
- await AsyncIOBackend.cancel_shielded_checkpoint()
765
-
766
- self._active = False
767
- if self._exceptions:
768
- # The exception that got us here should already have been
769
- # added to self._exceptions so it's ok to break exception
770
- # chaining and avoid adding a "During handling of above..."
771
- # for each nesting level.
772
- raise BaseExceptionGroup(
773
- "unhandled errors in a TaskGroup", self._exceptions
774
- ) from None
775
- elif exc_val:
776
- raise exc_val
777
- except BaseException as exc:
778
- if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__):
779
- return True
780
-
781
- raise
782
-
783
- return self.cancel_scope.__exit__(exc_type, exc_val, exc_tb)
784
- finally:
785
- del exc_val, exc_tb, self._exceptions
786
-
787
- def _spawn(
788
- self,
789
- func: Callable[[Unpack[PosArgsT]], Awaitable[Any]],
790
- args: tuple[Unpack[PosArgsT]],
791
- name: object,
792
- task_status_future: asyncio.Future | None = None,
793
- ) -> asyncio.Task:
794
- def task_done(_task: asyncio.Task) -> None:
795
- task_state = _task_states[_task]
796
- assert task_state.cancel_scope is not None
797
- assert _task in task_state.cancel_scope._tasks
798
- task_state.cancel_scope._tasks.remove(_task)
799
- self._tasks.remove(task)
800
- del _task_states[_task]
801
-
802
- if self._on_completed_fut is not None and not self._tasks:
803
- try:
804
- self._on_completed_fut.set_result(None)
805
- except asyncio.InvalidStateError:
806
- pass
807
-
808
- try:
809
- exc = _task.exception()
810
- except CancelledError as e:
811
- while isinstance(e.__context__, CancelledError):
812
- e = e.__context__
813
-
814
- exc = e
815
-
816
- if exc is not None:
817
- # The future can only be in the cancelled state if the host task was
818
- # cancelled, so return immediately instead of adding one more
819
- # CancelledError to the exceptions list
820
- if task_status_future is not None and task_status_future.cancelled():
821
- return
822
-
823
- if task_status_future is None or task_status_future.done():
824
- if not isinstance(exc, CancelledError):
825
- self._exceptions.append(exc)
826
-
827
- if not self.cancel_scope._effectively_cancelled:
828
- self.cancel_scope.cancel()
829
- else:
830
- task_status_future.set_exception(exc)
831
- elif task_status_future is not None and not task_status_future.done():
832
- task_status_future.set_exception(
833
- RuntimeError("Child exited without calling task_status.started()")
834
- )
835
-
836
- if not self._active:
837
- raise RuntimeError(
838
- "This task group is not active; no new tasks can be started."
839
- )
840
-
841
- kwargs = {}
842
- if task_status_future:
843
- parent_id = id(current_task())
844
- kwargs["task_status"] = _AsyncioTaskStatus(
845
- task_status_future, id(self.cancel_scope._host_task)
846
- )
847
- else:
848
- parent_id = id(self.cancel_scope._host_task)
849
-
850
- coro = func(*args, **kwargs)
851
- if not iscoroutine(coro):
852
- prefix = f"{func.__module__}." if hasattr(func, "__module__") else ""
853
- raise TypeError(
854
- f"Expected {prefix}{func.__qualname__}() to return a coroutine, but "
855
- f"the return value ({coro!r}) is not a coroutine object"
856
- )
857
-
858
- name = get_callable_name(func) if name is None else str(name)
859
- loop = asyncio.get_running_loop()
860
- if (
861
- (factory := loop.get_task_factory())
862
- and getattr(factory, "__code__", None) is _eager_task_factory_code
863
- and (closure := getattr(factory, "__closure__", None))
864
- ):
865
- custom_task_constructor = closure[0].cell_contents
866
- task = custom_task_constructor(coro, loop=loop, name=name)
867
- else:
868
- task = create_task(coro, name=name)
869
-
870
- # Make the spawned task inherit the task group's cancel scope
871
- _task_states[task] = TaskState(
872
- parent_id=parent_id, cancel_scope=self.cancel_scope
873
- )
874
- self.cancel_scope._tasks.add(task)
875
- self._tasks.add(task)
876
- task.add_done_callback(task_done)
877
- return task
878
-
879
- def start_soon(
880
- self,
881
- func: Callable[[Unpack[PosArgsT]], Awaitable[Any]],
882
- *args: Unpack[PosArgsT],
883
- name: object = None,
884
- ) -> None:
885
- self._spawn(func, args, name)
886
-
887
- async def start(
888
- self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None
889
- ) -> Any:
890
- future: asyncio.Future = asyncio.Future()
891
- task = self._spawn(func, args, name, future)
892
-
893
- # If the task raises an exception after sending a start value without a switch
894
- # point between, the task group is cancelled and this method never proceeds to
895
- # process the completed future. That's why we have to have a shielded cancel
896
- # scope here.
897
- try:
898
- return await future
899
- except CancelledError:
900
- # Cancel the task and wait for it to exit before returning
901
- task.cancel()
902
- with CancelScope(shield=True), suppress(CancelledError):
903
- await task
904
-
905
- raise
906
-
907
-
908
- #
909
- # Threads
910
- #
911
-
912
- _Retval_Queue_Type = tuple[Optional[T_Retval], Optional[BaseException]]
913
-
914
-
915
- class WorkerThread(Thread):
916
- MAX_IDLE_TIME = 10 # seconds
917
-
918
- def __init__(
919
- self,
920
- root_task: asyncio.Task,
921
- workers: set[WorkerThread],
922
- idle_workers: deque[WorkerThread],
923
- ):
924
- super().__init__(name="AnyIO worker thread")
925
- self.root_task = root_task
926
- self.workers = workers
927
- self.idle_workers = idle_workers
928
- self.loop = root_task._loop
929
- self.queue: Queue[
930
- tuple[Context, Callable, tuple, asyncio.Future, CancelScope] | None
931
- ] = Queue(2)
932
- self.idle_since = AsyncIOBackend.current_time()
933
- self.stopping = False
934
-
935
- def _report_result(
936
- self, future: asyncio.Future, result: Any, exc: BaseException | None
937
- ) -> None:
938
- self.idle_since = AsyncIOBackend.current_time()
939
- if not self.stopping:
940
- self.idle_workers.append(self)
941
-
942
- if not future.cancelled():
943
- if exc is not None:
944
- if isinstance(exc, StopIteration):
945
- new_exc = RuntimeError("coroutine raised StopIteration")
946
- new_exc.__cause__ = exc
947
- exc = new_exc
948
-
949
- future.set_exception(exc)
950
- else:
951
- future.set_result(result)
952
-
953
- def run(self) -> None:
954
- with claim_worker_thread(AsyncIOBackend, self.loop):
955
- while True:
956
- item = self.queue.get()
957
- if item is None:
958
- # Shutdown command received
959
- return
960
-
961
- context, func, args, future, cancel_scope = item
962
- if not future.cancelled():
963
- result = None
964
- exception: BaseException | None = None
965
- threadlocals.current_cancel_scope = cancel_scope
966
- try:
967
- result = context.run(func, *args)
968
- except BaseException as exc:
969
- exception = exc
970
- finally:
971
- del threadlocals.current_cancel_scope
972
-
973
- if not self.loop.is_closed():
974
- self.loop.call_soon_threadsafe(
975
- self._report_result, future, result, exception
976
- )
977
-
978
- del result, exception
979
-
980
- self.queue.task_done()
981
- del item, context, func, args, future, cancel_scope
982
-
983
- def stop(self, f: asyncio.Task | None = None) -> None:
984
- self.stopping = True
985
- self.queue.put_nowait(None)
986
- self.workers.discard(self)
987
- try:
988
- self.idle_workers.remove(self)
989
- except ValueError:
990
- pass
991
-
992
-
993
- _threadpool_idle_workers: RunVar[deque[WorkerThread]] = RunVar(
994
- "_threadpool_idle_workers"
995
- )
996
- _threadpool_workers: RunVar[set[WorkerThread]] = RunVar("_threadpool_workers")
997
-
998
-
999
- class BlockingPortal(abc.BlockingPortal):
1000
- def __new__(cls) -> BlockingPortal:
1001
- return object.__new__(cls)
1002
-
1003
- def __init__(self) -> None:
1004
- super().__init__()
1005
- self._loop = get_running_loop()
1006
-
1007
- def _spawn_task_from_thread(
1008
- self,
1009
- func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
1010
- args: tuple[Unpack[PosArgsT]],
1011
- kwargs: dict[str, Any],
1012
- name: object,
1013
- future: Future[T_Retval],
1014
- ) -> None:
1015
- AsyncIOBackend.run_sync_from_thread(
1016
- partial(self._task_group.start_soon, name=name),
1017
- (self._call_func, func, args, kwargs, future),
1018
- self._loop,
1019
- )
1020
-
1021
-
1022
- #
1023
- # Subprocesses
1024
- #
1025
-
1026
-
1027
- @dataclass(eq=False)
1028
- class StreamReaderWrapper(abc.ByteReceiveStream):
1029
- _stream: asyncio.StreamReader
1030
-
1031
- async def receive(self, max_bytes: int = 65536) -> bytes:
1032
- data = await self._stream.read(max_bytes)
1033
- if data:
1034
- return data
1035
- else:
1036
- raise EndOfStream
1037
-
1038
- async def aclose(self) -> None:
1039
- self._stream.set_exception(ClosedResourceError())
1040
- await AsyncIOBackend.checkpoint()
1041
-
1042
-
1043
- @dataclass(eq=False)
1044
- class StreamWriterWrapper(abc.ByteSendStream):
1045
- _stream: asyncio.StreamWriter
1046
-
1047
- async def send(self, item: bytes) -> None:
1048
- self._stream.write(item)
1049
- await self._stream.drain()
1050
-
1051
- async def aclose(self) -> None:
1052
- self._stream.close()
1053
- await AsyncIOBackend.checkpoint()
1054
-
1055
-
1056
- @dataclass(eq=False)
1057
- class Process(abc.Process):
1058
- _process: asyncio.subprocess.Process
1059
- _stdin: StreamWriterWrapper | None
1060
- _stdout: StreamReaderWrapper | None
1061
- _stderr: StreamReaderWrapper | None
1062
-
1063
- async def aclose(self) -> None:
1064
- with CancelScope(shield=True) as scope:
1065
- if self._stdin:
1066
- await self._stdin.aclose()
1067
- if self._stdout:
1068
- await self._stdout.aclose()
1069
- if self._stderr:
1070
- await self._stderr.aclose()
1071
-
1072
- scope.shield = False
1073
- try:
1074
- await self.wait()
1075
- except BaseException:
1076
- scope.shield = True
1077
- self.kill()
1078
- await self.wait()
1079
- raise
1080
-
1081
- async def wait(self) -> int:
1082
- return await self._process.wait()
1083
-
1084
- def terminate(self) -> None:
1085
- self._process.terminate()
1086
-
1087
- def kill(self) -> None:
1088
- self._process.kill()
1089
-
1090
- def send_signal(self, signal: int) -> None:
1091
- self._process.send_signal(signal)
1092
-
1093
- @property
1094
- def pid(self) -> int:
1095
- return self._process.pid
1096
-
1097
- @property
1098
- def returncode(self) -> int | None:
1099
- return self._process.returncode
1100
-
1101
- @property
1102
- def stdin(self) -> abc.ByteSendStream | None:
1103
- return self._stdin
1104
-
1105
- @property
1106
- def stdout(self) -> abc.ByteReceiveStream | None:
1107
- return self._stdout
1108
-
1109
- @property
1110
- def stderr(self) -> abc.ByteReceiveStream | None:
1111
- return self._stderr
1112
-
1113
-
1114
- def _forcibly_shutdown_process_pool_on_exit(
1115
- workers: set[Process], _task: object
1116
- ) -> None:
1117
- """
1118
- Forcibly shuts down worker processes belonging to this event loop."""
1119
- child_watcher: asyncio.AbstractChildWatcher | None = None
1120
- if sys.version_info < (3, 12):
1121
- try:
1122
- child_watcher = asyncio.get_event_loop_policy().get_child_watcher()
1123
- except NotImplementedError:
1124
- pass
1125
-
1126
- # Close as much as possible (w/o async/await) to avoid warnings
1127
- for process in workers:
1128
- if process.returncode is None:
1129
- continue
1130
-
1131
- process._stdin._stream._transport.close() # type: ignore[union-attr]
1132
- process._stdout._stream._transport.close() # type: ignore[union-attr]
1133
- process._stderr._stream._transport.close() # type: ignore[union-attr]
1134
- process.kill()
1135
- if child_watcher:
1136
- child_watcher.remove_child_handler(process.pid)
1137
-
1138
-
1139
- async def _shutdown_process_pool_on_exit(workers: set[abc.Process]) -> None:
1140
- """
1141
- Shuts down worker processes belonging to this event loop.
1142
-
1143
- NOTE: this only works when the event loop was started using asyncio.run() or
1144
- anyio.run().
1145
-
1146
- """
1147
- process: abc.Process
1148
- try:
1149
- await sleep(math.inf)
1150
- except asyncio.CancelledError:
1151
- for process in workers:
1152
- if process.returncode is None:
1153
- process.kill()
1154
-
1155
- for process in workers:
1156
- await process.aclose()
1157
-
1158
-
1159
- #
1160
- # Sockets and networking
1161
- #
1162
-
1163
-
1164
- class StreamProtocol(asyncio.Protocol):
1165
- read_queue: deque[bytes]
1166
- read_event: asyncio.Event
1167
- write_event: asyncio.Event
1168
- exception: Exception | None = None
1169
- is_at_eof: bool = False
1170
-
1171
- def connection_made(self, transport: asyncio.BaseTransport) -> None:
1172
- self.read_queue = deque()
1173
- self.read_event = asyncio.Event()
1174
- self.write_event = asyncio.Event()
1175
- self.write_event.set()
1176
- cast(asyncio.Transport, transport).set_write_buffer_limits(0)
1177
-
1178
- def connection_lost(self, exc: Exception | None) -> None:
1179
- if exc:
1180
- self.exception = BrokenResourceError()
1181
- self.exception.__cause__ = exc
1182
-
1183
- self.read_event.set()
1184
- self.write_event.set()
1185
-
1186
- def data_received(self, data: bytes) -> None:
1187
- # ProactorEventloop sometimes sends bytearray instead of bytes
1188
- self.read_queue.append(bytes(data))
1189
- self.read_event.set()
1190
-
1191
- def eof_received(self) -> bool | None:
1192
- self.is_at_eof = True
1193
- self.read_event.set()
1194
- return True
1195
-
1196
- def pause_writing(self) -> None:
1197
- self.write_event = asyncio.Event()
1198
-
1199
- def resume_writing(self) -> None:
1200
- self.write_event.set()
1201
-
1202
-
1203
- class DatagramProtocol(asyncio.DatagramProtocol):
1204
- read_queue: deque[tuple[bytes, IPSockAddrType]]
1205
- read_event: asyncio.Event
1206
- write_event: asyncio.Event
1207
- exception: Exception | None = None
1208
-
1209
- def connection_made(self, transport: asyncio.BaseTransport) -> None:
1210
- self.read_queue = deque(maxlen=100) # arbitrary value
1211
- self.read_event = asyncio.Event()
1212
- self.write_event = asyncio.Event()
1213
- self.write_event.set()
1214
-
1215
- def connection_lost(self, exc: Exception | None) -> None:
1216
- self.read_event.set()
1217
- self.write_event.set()
1218
-
1219
- def datagram_received(self, data: bytes, addr: IPSockAddrType) -> None:
1220
- addr = convert_ipv6_sockaddr(addr)
1221
- self.read_queue.append((data, addr))
1222
- self.read_event.set()
1223
-
1224
- def error_received(self, exc: Exception) -> None:
1225
- self.exception = exc
1226
-
1227
- def pause_writing(self) -> None:
1228
- self.write_event.clear()
1229
-
1230
- def resume_writing(self) -> None:
1231
- self.write_event.set()
1232
-
1233
-
1234
- class SocketStream(abc.SocketStream):
1235
- def __init__(self, transport: asyncio.Transport, protocol: StreamProtocol):
1236
- self._transport = transport
1237
- self._protocol = protocol
1238
- self._receive_guard = ResourceGuard("reading from")
1239
- self._send_guard = ResourceGuard("writing to")
1240
- self._closed = False
1241
-
1242
- @property
1243
- def _raw_socket(self) -> socket.socket:
1244
- return self._transport.get_extra_info("socket")
1245
-
1246
- async def receive(self, max_bytes: int = 65536) -> bytes:
1247
- with self._receive_guard:
1248
- if (
1249
- not self._protocol.read_event.is_set()
1250
- and not self._transport.is_closing()
1251
- and not self._protocol.is_at_eof
1252
- ):
1253
- self._transport.resume_reading()
1254
- await self._protocol.read_event.wait()
1255
- self._transport.pause_reading()
1256
- else:
1257
- await AsyncIOBackend.checkpoint()
1258
-
1259
- try:
1260
- chunk = self._protocol.read_queue.popleft()
1261
- except IndexError:
1262
- if self._closed:
1263
- raise ClosedResourceError from None
1264
- elif self._protocol.exception:
1265
- raise self._protocol.exception from None
1266
- else:
1267
- raise EndOfStream from None
1268
-
1269
- if len(chunk) > max_bytes:
1270
- # Split the oversized chunk
1271
- chunk, leftover = chunk[:max_bytes], chunk[max_bytes:]
1272
- self._protocol.read_queue.appendleft(leftover)
1273
-
1274
- # If the read queue is empty, clear the flag so that the next call will
1275
- # block until data is available
1276
- if not self._protocol.read_queue:
1277
- self._protocol.read_event.clear()
1278
-
1279
- return chunk
1280
-
1281
- async def send(self, item: bytes) -> None:
1282
- with self._send_guard:
1283
- await AsyncIOBackend.checkpoint()
1284
-
1285
- if self._closed:
1286
- raise ClosedResourceError
1287
- elif self._protocol.exception is not None:
1288
- raise self._protocol.exception
1289
-
1290
- try:
1291
- self._transport.write(item)
1292
- except RuntimeError as exc:
1293
- if self._transport.is_closing():
1294
- raise BrokenResourceError from exc
1295
- else:
1296
- raise
1297
-
1298
- await self._protocol.write_event.wait()
1299
-
1300
- async def send_eof(self) -> None:
1301
- try:
1302
- self._transport.write_eof()
1303
- except OSError:
1304
- pass
1305
-
1306
- async def aclose(self) -> None:
1307
- if not self._transport.is_closing():
1308
- self._closed = True
1309
- try:
1310
- self._transport.write_eof()
1311
- except OSError:
1312
- pass
1313
-
1314
- self._transport.close()
1315
- await sleep(0)
1316
- self._transport.abort()
1317
-
1318
-
1319
- class _RawSocketMixin:
1320
- _receive_future: asyncio.Future | None = None
1321
- _send_future: asyncio.Future | None = None
1322
- _closing = False
1323
-
1324
- def __init__(self, raw_socket: socket.socket):
1325
- self.__raw_socket = raw_socket
1326
- self._receive_guard = ResourceGuard("reading from")
1327
- self._send_guard = ResourceGuard("writing to")
1328
-
1329
- @property
1330
- def _raw_socket(self) -> socket.socket:
1331
- return self.__raw_socket
1332
-
1333
- def _wait_until_readable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future:
1334
- def callback(f: object) -> None:
1335
- del self._receive_future
1336
- loop.remove_reader(self.__raw_socket)
1337
-
1338
- f = self._receive_future = asyncio.Future()
1339
- loop.add_reader(self.__raw_socket, f.set_result, None)
1340
- f.add_done_callback(callback)
1341
- return f
1342
-
1343
- def _wait_until_writable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future:
1344
- def callback(f: object) -> None:
1345
- del self._send_future
1346
- loop.remove_writer(self.__raw_socket)
1347
-
1348
- f = self._send_future = asyncio.Future()
1349
- loop.add_writer(self.__raw_socket, f.set_result, None)
1350
- f.add_done_callback(callback)
1351
- return f
1352
-
1353
- async def aclose(self) -> None:
1354
- if not self._closing:
1355
- self._closing = True
1356
- if self.__raw_socket.fileno() != -1:
1357
- self.__raw_socket.close()
1358
-
1359
- if self._receive_future:
1360
- self._receive_future.set_result(None)
1361
- if self._send_future:
1362
- self._send_future.set_result(None)
1363
-
1364
-
1365
- class UNIXSocketStream(_RawSocketMixin, abc.UNIXSocketStream):
1366
- async def send_eof(self) -> None:
1367
- with self._send_guard:
1368
- self._raw_socket.shutdown(socket.SHUT_WR)
1369
-
1370
- async def receive(self, max_bytes: int = 65536) -> bytes:
1371
- loop = get_running_loop()
1372
- await AsyncIOBackend.checkpoint()
1373
- with self._receive_guard:
1374
- while True:
1375
- try:
1376
- data = self._raw_socket.recv(max_bytes)
1377
- except BlockingIOError:
1378
- await self._wait_until_readable(loop)
1379
- except OSError as exc:
1380
- if self._closing:
1381
- raise ClosedResourceError from None
1382
- else:
1383
- raise BrokenResourceError from exc
1384
- else:
1385
- if not data:
1386
- raise EndOfStream
1387
-
1388
- return data
1389
-
1390
- async def send(self, item: bytes) -> None:
1391
- loop = get_running_loop()
1392
- await AsyncIOBackend.checkpoint()
1393
- with self._send_guard:
1394
- view = memoryview(item)
1395
- while view:
1396
- try:
1397
- bytes_sent = self._raw_socket.send(view)
1398
- except BlockingIOError:
1399
- await self._wait_until_writable(loop)
1400
- except OSError as exc:
1401
- if self._closing:
1402
- raise ClosedResourceError from None
1403
- else:
1404
- raise BrokenResourceError from exc
1405
- else:
1406
- view = view[bytes_sent:]
1407
-
1408
- async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]:
1409
- if not isinstance(msglen, int) or msglen < 0:
1410
- raise ValueError("msglen must be a non-negative integer")
1411
- if not isinstance(maxfds, int) or maxfds < 1:
1412
- raise ValueError("maxfds must be a positive integer")
1413
-
1414
- loop = get_running_loop()
1415
- fds = array.array("i")
1416
- await AsyncIOBackend.checkpoint()
1417
- with self._receive_guard:
1418
- while True:
1419
- try:
1420
- message, ancdata, flags, addr = self._raw_socket.recvmsg(
1421
- msglen, socket.CMSG_LEN(maxfds * fds.itemsize)
1422
- )
1423
- except BlockingIOError:
1424
- await self._wait_until_readable(loop)
1425
- except OSError as exc:
1426
- if self._closing:
1427
- raise ClosedResourceError from None
1428
- else:
1429
- raise BrokenResourceError from exc
1430
- else:
1431
- if not message and not ancdata:
1432
- raise EndOfStream
1433
-
1434
- break
1435
-
1436
- for cmsg_level, cmsg_type, cmsg_data in ancdata:
1437
- if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS:
1438
- raise RuntimeError(
1439
- f"Received unexpected ancillary data; message = {message!r}, "
1440
- f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}"
1441
- )
1442
-
1443
- fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
1444
-
1445
- return message, list(fds)
1446
-
1447
- async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None:
1448
- if not message:
1449
- raise ValueError("message must not be empty")
1450
- if not fds:
1451
- raise ValueError("fds must not be empty")
1452
-
1453
- loop = get_running_loop()
1454
- filenos: list[int] = []
1455
- for fd in fds:
1456
- if isinstance(fd, int):
1457
- filenos.append(fd)
1458
- elif isinstance(fd, IOBase):
1459
- filenos.append(fd.fileno())
1460
-
1461
- fdarray = array.array("i", filenos)
1462
- await AsyncIOBackend.checkpoint()
1463
- with self._send_guard:
1464
- while True:
1465
- try:
1466
- # The ignore can be removed after mypy picks up
1467
- # https://github.com/python/typeshed/pull/5545
1468
- self._raw_socket.sendmsg(
1469
- [message], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fdarray)]
1470
- )
1471
- break
1472
- except BlockingIOError:
1473
- await self._wait_until_writable(loop)
1474
- except OSError as exc:
1475
- if self._closing:
1476
- raise ClosedResourceError from None
1477
- else:
1478
- raise BrokenResourceError from exc
1479
-
1480
-
1481
- class TCPSocketListener(abc.SocketListener):
1482
- _accept_scope: CancelScope | None = None
1483
- _closed = False
1484
-
1485
- def __init__(self, raw_socket: socket.socket):
1486
- self.__raw_socket = raw_socket
1487
- self._loop = cast(asyncio.BaseEventLoop, get_running_loop())
1488
- self._accept_guard = ResourceGuard("accepting connections from")
1489
-
1490
- @property
1491
- def _raw_socket(self) -> socket.socket:
1492
- return self.__raw_socket
1493
-
1494
- async def accept(self) -> abc.SocketStream:
1495
- if self._closed:
1496
- raise ClosedResourceError
1497
-
1498
- with self._accept_guard:
1499
- await AsyncIOBackend.checkpoint()
1500
- with CancelScope() as self._accept_scope:
1501
- try:
1502
- client_sock, _addr = await self._loop.sock_accept(self._raw_socket)
1503
- except asyncio.CancelledError:
1504
- # Workaround for https://bugs.python.org/issue41317
1505
- try:
1506
- self._loop.remove_reader(self._raw_socket)
1507
- except (ValueError, NotImplementedError):
1508
- pass
1509
-
1510
- if self._closed:
1511
- raise ClosedResourceError from None
1512
-
1513
- raise
1514
- finally:
1515
- self._accept_scope = None
1516
-
1517
- client_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
1518
- transport, protocol = await self._loop.connect_accepted_socket(
1519
- StreamProtocol, client_sock
1520
- )
1521
- return SocketStream(transport, protocol)
1522
-
1523
- async def aclose(self) -> None:
1524
- if self._closed:
1525
- return
1526
-
1527
- self._closed = True
1528
- if self._accept_scope:
1529
- # Workaround for https://bugs.python.org/issue41317
1530
- try:
1531
- self._loop.remove_reader(self._raw_socket)
1532
- except (ValueError, NotImplementedError):
1533
- pass
1534
-
1535
- self._accept_scope.cancel()
1536
- await sleep(0)
1537
-
1538
- self._raw_socket.close()
1539
-
1540
-
1541
- class UNIXSocketListener(abc.SocketListener):
1542
- def __init__(self, raw_socket: socket.socket):
1543
- self.__raw_socket = raw_socket
1544
- self._loop = get_running_loop()
1545
- self._accept_guard = ResourceGuard("accepting connections from")
1546
- self._closed = False
1547
-
1548
- async def accept(self) -> abc.SocketStream:
1549
- await AsyncIOBackend.checkpoint()
1550
- with self._accept_guard:
1551
- while True:
1552
- try:
1553
- client_sock, _ = self.__raw_socket.accept()
1554
- client_sock.setblocking(False)
1555
- return UNIXSocketStream(client_sock)
1556
- except BlockingIOError:
1557
- f: asyncio.Future = asyncio.Future()
1558
- self._loop.add_reader(self.__raw_socket, f.set_result, None)
1559
- f.add_done_callback(
1560
- lambda _: self._loop.remove_reader(self.__raw_socket)
1561
- )
1562
- await f
1563
- except OSError as exc:
1564
- if self._closed:
1565
- raise ClosedResourceError from None
1566
- else:
1567
- raise BrokenResourceError from exc
1568
-
1569
- async def aclose(self) -> None:
1570
- self._closed = True
1571
- self.__raw_socket.close()
1572
-
1573
- @property
1574
- def _raw_socket(self) -> socket.socket:
1575
- return self.__raw_socket
1576
-
1577
-
1578
- class UDPSocket(abc.UDPSocket):
1579
- def __init__(
1580
- self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol
1581
- ):
1582
- self._transport = transport
1583
- self._protocol = protocol
1584
- self._receive_guard = ResourceGuard("reading from")
1585
- self._send_guard = ResourceGuard("writing to")
1586
- self._closed = False
1587
-
1588
- @property
1589
- def _raw_socket(self) -> socket.socket:
1590
- return self._transport.get_extra_info("socket")
1591
-
1592
- async def aclose(self) -> None:
1593
- if not self._transport.is_closing():
1594
- self._closed = True
1595
- self._transport.close()
1596
-
1597
- async def receive(self) -> tuple[bytes, IPSockAddrType]:
1598
- with self._receive_guard:
1599
- await AsyncIOBackend.checkpoint()
1600
-
1601
- # If the buffer is empty, ask for more data
1602
- if not self._protocol.read_queue and not self._transport.is_closing():
1603
- self._protocol.read_event.clear()
1604
- await self._protocol.read_event.wait()
1605
-
1606
- try:
1607
- return self._protocol.read_queue.popleft()
1608
- except IndexError:
1609
- if self._closed:
1610
- raise ClosedResourceError from None
1611
- else:
1612
- raise BrokenResourceError from None
1613
-
1614
- async def send(self, item: UDPPacketType) -> None:
1615
- with self._send_guard:
1616
- await AsyncIOBackend.checkpoint()
1617
- await self._protocol.write_event.wait()
1618
- if self._closed:
1619
- raise ClosedResourceError
1620
- elif self._transport.is_closing():
1621
- raise BrokenResourceError
1622
- else:
1623
- self._transport.sendto(*item)
1624
-
1625
-
1626
- class ConnectedUDPSocket(abc.ConnectedUDPSocket):
1627
- def __init__(
1628
- self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol
1629
- ):
1630
- self._transport = transport
1631
- self._protocol = protocol
1632
- self._receive_guard = ResourceGuard("reading from")
1633
- self._send_guard = ResourceGuard("writing to")
1634
- self._closed = False
1635
-
1636
- @property
1637
- def _raw_socket(self) -> socket.socket:
1638
- return self._transport.get_extra_info("socket")
1639
-
1640
- async def aclose(self) -> None:
1641
- if not self._transport.is_closing():
1642
- self._closed = True
1643
- self._transport.close()
1644
-
1645
- async def receive(self) -> bytes:
1646
- with self._receive_guard:
1647
- await AsyncIOBackend.checkpoint()
1648
-
1649
- # If the buffer is empty, ask for more data
1650
- if not self._protocol.read_queue and not self._transport.is_closing():
1651
- self._protocol.read_event.clear()
1652
- await self._protocol.read_event.wait()
1653
-
1654
- try:
1655
- packet = self._protocol.read_queue.popleft()
1656
- except IndexError:
1657
- if self._closed:
1658
- raise ClosedResourceError from None
1659
- else:
1660
- raise BrokenResourceError from None
1661
-
1662
- return packet[0]
1663
-
1664
- async def send(self, item: bytes) -> None:
1665
- with self._send_guard:
1666
- await AsyncIOBackend.checkpoint()
1667
- await self._protocol.write_event.wait()
1668
- if self._closed:
1669
- raise ClosedResourceError
1670
- elif self._transport.is_closing():
1671
- raise BrokenResourceError
1672
- else:
1673
- self._transport.sendto(item)
1674
-
1675
-
1676
- class UNIXDatagramSocket(_RawSocketMixin, abc.UNIXDatagramSocket):
1677
- async def receive(self) -> UNIXDatagramPacketType:
1678
- loop = get_running_loop()
1679
- await AsyncIOBackend.checkpoint()
1680
- with self._receive_guard:
1681
- while True:
1682
- try:
1683
- data = self._raw_socket.recvfrom(65536)
1684
- except BlockingIOError:
1685
- await self._wait_until_readable(loop)
1686
- except OSError as exc:
1687
- if self._closing:
1688
- raise ClosedResourceError from None
1689
- else:
1690
- raise BrokenResourceError from exc
1691
- else:
1692
- return data
1693
-
1694
- async def send(self, item: UNIXDatagramPacketType) -> None:
1695
- loop = get_running_loop()
1696
- await AsyncIOBackend.checkpoint()
1697
- with self._send_guard:
1698
- while True:
1699
- try:
1700
- self._raw_socket.sendto(*item)
1701
- except BlockingIOError:
1702
- await self._wait_until_writable(loop)
1703
- except OSError as exc:
1704
- if self._closing:
1705
- raise ClosedResourceError from None
1706
- else:
1707
- raise BrokenResourceError from exc
1708
- else:
1709
- return
1710
-
1711
-
1712
- class ConnectedUNIXDatagramSocket(_RawSocketMixin, abc.ConnectedUNIXDatagramSocket):
1713
- async def receive(self) -> bytes:
1714
- loop = get_running_loop()
1715
- await AsyncIOBackend.checkpoint()
1716
- with self._receive_guard:
1717
- while True:
1718
- try:
1719
- data = self._raw_socket.recv(65536)
1720
- except BlockingIOError:
1721
- await self._wait_until_readable(loop)
1722
- except OSError as exc:
1723
- if self._closing:
1724
- raise ClosedResourceError from None
1725
- else:
1726
- raise BrokenResourceError from exc
1727
- else:
1728
- return data
1729
-
1730
- async def send(self, item: bytes) -> None:
1731
- loop = get_running_loop()
1732
- await AsyncIOBackend.checkpoint()
1733
- with self._send_guard:
1734
- while True:
1735
- try:
1736
- self._raw_socket.send(item)
1737
- except BlockingIOError:
1738
- await self._wait_until_writable(loop)
1739
- except OSError as exc:
1740
- if self._closing:
1741
- raise ClosedResourceError from None
1742
- else:
1743
- raise BrokenResourceError from exc
1744
- else:
1745
- return
1746
-
1747
-
1748
- _read_events: RunVar[dict[int, asyncio.Event]] = RunVar("read_events")
1749
- _write_events: RunVar[dict[int, asyncio.Event]] = RunVar("write_events")
1750
-
1751
-
1752
- #
1753
- # Synchronization
1754
- #
1755
-
1756
-
1757
- class Event(BaseEvent):
1758
- def __new__(cls) -> Event:
1759
- return object.__new__(cls)
1760
-
1761
- def __init__(self) -> None:
1762
- self._event = asyncio.Event()
1763
-
1764
- def set(self) -> None:
1765
- self._event.set()
1766
-
1767
- def is_set(self) -> bool:
1768
- return self._event.is_set()
1769
-
1770
- async def wait(self) -> None:
1771
- if self.is_set():
1772
- await AsyncIOBackend.checkpoint()
1773
- else:
1774
- await self._event.wait()
1775
-
1776
- def statistics(self) -> EventStatistics:
1777
- return EventStatistics(len(self._event._waiters))
1778
-
1779
-
1780
- class Lock(BaseLock):
1781
- def __new__(cls, *, fast_acquire: bool = False) -> Lock:
1782
- return object.__new__(cls)
1783
-
1784
- def __init__(self, *, fast_acquire: bool = False) -> None:
1785
- self._fast_acquire = fast_acquire
1786
- self._owner_task: asyncio.Task | None = None
1787
- self._waiters: deque[tuple[asyncio.Task, asyncio.Future]] = deque()
1788
-
1789
- async def acquire(self) -> None:
1790
- task = cast(asyncio.Task, current_task())
1791
- if self._owner_task is None and not self._waiters:
1792
- await AsyncIOBackend.checkpoint_if_cancelled()
1793
- self._owner_task = task
1794
-
1795
- # Unless on the "fast path", yield control of the event loop so that other
1796
- # tasks can run too
1797
- if not self._fast_acquire:
1798
- try:
1799
- await AsyncIOBackend.cancel_shielded_checkpoint()
1800
- except CancelledError:
1801
- self.release()
1802
- raise
1803
-
1804
- return
1805
-
1806
- if self._owner_task == task:
1807
- raise RuntimeError("Attempted to acquire an already held Lock")
1808
-
1809
- fut: asyncio.Future[None] = asyncio.Future()
1810
- item = task, fut
1811
- self._waiters.append(item)
1812
- try:
1813
- await fut
1814
- except CancelledError:
1815
- self._waiters.remove(item)
1816
- if self._owner_task is task:
1817
- self.release()
1818
-
1819
- raise
1820
-
1821
- self._waiters.remove(item)
1822
-
1823
- def acquire_nowait(self) -> None:
1824
- task = cast(asyncio.Task, current_task())
1825
- if self._owner_task is None and not self._waiters:
1826
- self._owner_task = task
1827
- return
1828
-
1829
- if self._owner_task is task:
1830
- raise RuntimeError("Attempted to acquire an already held Lock")
1831
-
1832
- raise WouldBlock
1833
-
1834
- def locked(self) -> bool:
1835
- return self._owner_task is not None
1836
-
1837
- def release(self) -> None:
1838
- if self._owner_task != current_task():
1839
- raise RuntimeError("The current task is not holding this lock")
1840
-
1841
- for task, fut in self._waiters:
1842
- if not fut.cancelled():
1843
- self._owner_task = task
1844
- fut.set_result(None)
1845
- return
1846
-
1847
- self._owner_task = None
1848
-
1849
- def statistics(self) -> LockStatistics:
1850
- task_info = AsyncIOTaskInfo(self._owner_task) if self._owner_task else None
1851
- return LockStatistics(self.locked(), task_info, len(self._waiters))
1852
-
1853
-
1854
- class Semaphore(BaseSemaphore):
1855
- def __new__(
1856
- cls,
1857
- initial_value: int,
1858
- *,
1859
- max_value: int | None = None,
1860
- fast_acquire: bool = False,
1861
- ) -> Semaphore:
1862
- return object.__new__(cls)
1863
-
1864
- def __init__(
1865
- self,
1866
- initial_value: int,
1867
- *,
1868
- max_value: int | None = None,
1869
- fast_acquire: bool = False,
1870
- ):
1871
- super().__init__(initial_value, max_value=max_value)
1872
- self._value = initial_value
1873
- self._max_value = max_value
1874
- self._fast_acquire = fast_acquire
1875
- self._waiters: deque[asyncio.Future[None]] = deque()
1876
-
1877
- async def acquire(self) -> None:
1878
- if self._value > 0 and not self._waiters:
1879
- await AsyncIOBackend.checkpoint_if_cancelled()
1880
- self._value -= 1
1881
-
1882
- # Unless on the "fast path", yield control of the event loop so that other
1883
- # tasks can run too
1884
- if not self._fast_acquire:
1885
- try:
1886
- await AsyncIOBackend.cancel_shielded_checkpoint()
1887
- except CancelledError:
1888
- self.release()
1889
- raise
1890
-
1891
- return
1892
-
1893
- fut: asyncio.Future[None] = asyncio.Future()
1894
- self._waiters.append(fut)
1895
- try:
1896
- await fut
1897
- except CancelledError:
1898
- try:
1899
- self._waiters.remove(fut)
1900
- except ValueError:
1901
- self.release()
1902
-
1903
- raise
1904
-
1905
- def acquire_nowait(self) -> None:
1906
- if self._value == 0:
1907
- raise WouldBlock
1908
-
1909
- self._value -= 1
1910
-
1911
- def release(self) -> None:
1912
- if self._max_value is not None and self._value == self._max_value:
1913
- raise ValueError("semaphore released too many times")
1914
-
1915
- for fut in self._waiters:
1916
- if not fut.cancelled():
1917
- fut.set_result(None)
1918
- self._waiters.remove(fut)
1919
- return
1920
-
1921
- self._value += 1
1922
-
1923
- @property
1924
- def value(self) -> int:
1925
- return self._value
1926
-
1927
- @property
1928
- def max_value(self) -> int | None:
1929
- return self._max_value
1930
-
1931
- def statistics(self) -> SemaphoreStatistics:
1932
- return SemaphoreStatistics(len(self._waiters))
1933
-
1934
-
1935
- class CapacityLimiter(BaseCapacityLimiter):
1936
- _total_tokens: float = 0
1937
-
1938
- def __new__(cls, total_tokens: float) -> CapacityLimiter:
1939
- return object.__new__(cls)
1940
-
1941
- def __init__(self, total_tokens: float):
1942
- self._borrowers: set[Any] = set()
1943
- self._wait_queue: OrderedDict[Any, asyncio.Event] = OrderedDict()
1944
- self.total_tokens = total_tokens
1945
-
1946
- async def __aenter__(self) -> None:
1947
- await self.acquire()
1948
-
1949
- async def __aexit__(
1950
- self,
1951
- exc_type: type[BaseException] | None,
1952
- exc_val: BaseException | None,
1953
- exc_tb: TracebackType | None,
1954
- ) -> None:
1955
- self.release()
1956
-
1957
- @property
1958
- def total_tokens(self) -> float:
1959
- return self._total_tokens
1960
-
1961
- @total_tokens.setter
1962
- def total_tokens(self, value: float) -> None:
1963
- if not isinstance(value, int) and not math.isinf(value):
1964
- raise TypeError("total_tokens must be an int or math.inf")
1965
- if value < 1:
1966
- raise ValueError("total_tokens must be >= 1")
1967
-
1968
- waiters_to_notify = max(value - self._total_tokens, 0)
1969
- self._total_tokens = value
1970
-
1971
- # Notify waiting tasks that they have acquired the limiter
1972
- while self._wait_queue and waiters_to_notify:
1973
- event = self._wait_queue.popitem(last=False)[1]
1974
- event.set()
1975
- waiters_to_notify -= 1
1976
-
1977
- @property
1978
- def borrowed_tokens(self) -> int:
1979
- return len(self._borrowers)
1980
-
1981
- @property
1982
- def available_tokens(self) -> float:
1983
- return self._total_tokens - len(self._borrowers)
1984
-
1985
- def acquire_nowait(self) -> None:
1986
- self.acquire_on_behalf_of_nowait(current_task())
1987
-
1988
- def acquire_on_behalf_of_nowait(self, borrower: object) -> None:
1989
- if borrower in self._borrowers:
1990
- raise RuntimeError(
1991
- "this borrower is already holding one of this CapacityLimiter's tokens"
1992
- )
1993
-
1994
- if self._wait_queue or len(self._borrowers) >= self._total_tokens:
1995
- raise WouldBlock
1996
-
1997
- self._borrowers.add(borrower)
1998
-
1999
- async def acquire(self) -> None:
2000
- return await self.acquire_on_behalf_of(current_task())
2001
-
2002
- async def acquire_on_behalf_of(self, borrower: object) -> None:
2003
- await AsyncIOBackend.checkpoint_if_cancelled()
2004
- try:
2005
- self.acquire_on_behalf_of_nowait(borrower)
2006
- except WouldBlock:
2007
- event = asyncio.Event()
2008
- self._wait_queue[borrower] = event
2009
- try:
2010
- await event.wait()
2011
- except BaseException:
2012
- self._wait_queue.pop(borrower, None)
2013
- raise
2014
-
2015
- self._borrowers.add(borrower)
2016
- else:
2017
- try:
2018
- await AsyncIOBackend.cancel_shielded_checkpoint()
2019
- except BaseException:
2020
- self.release()
2021
- raise
2022
-
2023
- def release(self) -> None:
2024
- self.release_on_behalf_of(current_task())
2025
-
2026
- def release_on_behalf_of(self, borrower: object) -> None:
2027
- try:
2028
- self._borrowers.remove(borrower)
2029
- except KeyError:
2030
- raise RuntimeError(
2031
- "this borrower isn't holding any of this CapacityLimiter's tokens"
2032
- ) from None
2033
-
2034
- # Notify the next task in line if this limiter has free capacity now
2035
- if self._wait_queue and len(self._borrowers) < self._total_tokens:
2036
- event = self._wait_queue.popitem(last=False)[1]
2037
- event.set()
2038
-
2039
- def statistics(self) -> CapacityLimiterStatistics:
2040
- return CapacityLimiterStatistics(
2041
- self.borrowed_tokens,
2042
- self.total_tokens,
2043
- tuple(self._borrowers),
2044
- len(self._wait_queue),
2045
- )
2046
-
2047
-
2048
- _default_thread_limiter: RunVar[CapacityLimiter] = RunVar("_default_thread_limiter")
2049
-
2050
-
2051
- #
2052
- # Operating system signals
2053
- #
2054
-
2055
-
2056
- class _SignalReceiver:
2057
- def __init__(self, signals: tuple[Signals, ...]):
2058
- self._signals = signals
2059
- self._loop = get_running_loop()
2060
- self._signal_queue: deque[Signals] = deque()
2061
- self._future: asyncio.Future = asyncio.Future()
2062
- self._handled_signals: set[Signals] = set()
2063
-
2064
- def _deliver(self, signum: Signals) -> None:
2065
- self._signal_queue.append(signum)
2066
- if not self._future.done():
2067
- self._future.set_result(None)
2068
-
2069
- def __enter__(self) -> _SignalReceiver:
2070
- for sig in set(self._signals):
2071
- self._loop.add_signal_handler(sig, self._deliver, sig)
2072
- self._handled_signals.add(sig)
2073
-
2074
- return self
2075
-
2076
- def __exit__(
2077
- self,
2078
- exc_type: type[BaseException] | None,
2079
- exc_val: BaseException | None,
2080
- exc_tb: TracebackType | None,
2081
- ) -> None:
2082
- for sig in self._handled_signals:
2083
- self._loop.remove_signal_handler(sig)
2084
-
2085
- def __aiter__(self) -> _SignalReceiver:
2086
- return self
2087
-
2088
- async def __anext__(self) -> Signals:
2089
- await AsyncIOBackend.checkpoint()
2090
- if not self._signal_queue:
2091
- self._future = asyncio.Future()
2092
- await self._future
2093
-
2094
- return self._signal_queue.popleft()
2095
-
2096
-
2097
- #
2098
- # Testing and debugging
2099
- #
2100
-
2101
-
2102
- class AsyncIOTaskInfo(TaskInfo):
2103
- def __init__(self, task: asyncio.Task):
2104
- task_state = _task_states.get(task)
2105
- if task_state is None:
2106
- parent_id = None
2107
- else:
2108
- parent_id = task_state.parent_id
2109
-
2110
- coro = task.get_coro()
2111
- assert coro is not None, "created TaskInfo from a completed Task"
2112
- super().__init__(id(task), parent_id, task.get_name(), coro)
2113
- self._task = weakref.ref(task)
2114
-
2115
- def has_pending_cancellation(self) -> bool:
2116
- if not (task := self._task()):
2117
- # If the task isn't around anymore, it won't have a pending cancellation
2118
- return False
2119
-
2120
- if task._must_cancel: # type: ignore[attr-defined]
2121
- return True
2122
- elif (
2123
- isinstance(task._fut_waiter, asyncio.Future) # type: ignore[attr-defined]
2124
- and task._fut_waiter.cancelled() # type: ignore[attr-defined]
2125
- ):
2126
- return True
2127
-
2128
- if task_state := _task_states.get(task):
2129
- if cancel_scope := task_state.cancel_scope:
2130
- return cancel_scope._effectively_cancelled
2131
-
2132
- return False
2133
-
2134
-
2135
- class TestRunner(abc.TestRunner):
2136
- _send_stream: MemoryObjectSendStream[tuple[Awaitable[Any], asyncio.Future[Any]]]
2137
-
2138
- def __init__(
2139
- self,
2140
- *,
2141
- debug: bool | None = None,
2142
- use_uvloop: bool = False,
2143
- loop_factory: Callable[[], AbstractEventLoop] | None = None,
2144
- ) -> None:
2145
- if use_uvloop and loop_factory is None:
2146
- import uvloop
2147
-
2148
- loop_factory = uvloop.new_event_loop
2149
-
2150
- self._runner = Runner(debug=debug, loop_factory=loop_factory)
2151
- self._exceptions: list[BaseException] = []
2152
- self._runner_task: asyncio.Task | None = None
2153
-
2154
- def __enter__(self) -> TestRunner:
2155
- self._runner.__enter__()
2156
- self.get_loop().set_exception_handler(self._exception_handler)
2157
- return self
2158
-
2159
- def __exit__(
2160
- self,
2161
- exc_type: type[BaseException] | None,
2162
- exc_val: BaseException | None,
2163
- exc_tb: TracebackType | None,
2164
- ) -> None:
2165
- self._runner.__exit__(exc_type, exc_val, exc_tb)
2166
-
2167
- def get_loop(self) -> AbstractEventLoop:
2168
- return self._runner.get_loop()
2169
-
2170
- def _exception_handler(
2171
- self, loop: asyncio.AbstractEventLoop, context: dict[str, Any]
2172
- ) -> None:
2173
- if isinstance(context.get("exception"), Exception):
2174
- self._exceptions.append(context["exception"])
2175
- else:
2176
- loop.default_exception_handler(context)
2177
-
2178
- def _raise_async_exceptions(self) -> None:
2179
- # Re-raise any exceptions raised in asynchronous callbacks
2180
- if self._exceptions:
2181
- exceptions, self._exceptions = self._exceptions, []
2182
- if len(exceptions) == 1:
2183
- raise exceptions[0]
2184
- elif exceptions:
2185
- raise BaseExceptionGroup(
2186
- "Multiple exceptions occurred in asynchronous callbacks", exceptions
2187
- )
2188
-
2189
- async def _run_tests_and_fixtures(
2190
- self,
2191
- receive_stream: MemoryObjectReceiveStream[
2192
- tuple[Awaitable[T_Retval], asyncio.Future[T_Retval]]
2193
- ],
2194
- ) -> None:
2195
- from _pytest.outcomes import OutcomeException
2196
-
2197
- with receive_stream, self._send_stream:
2198
- async for coro, future in receive_stream:
2199
- try:
2200
- retval = await coro
2201
- except CancelledError as exc:
2202
- if not future.cancelled():
2203
- future.cancel(*exc.args)
2204
-
2205
- raise
2206
- except BaseException as exc:
2207
- if not future.cancelled():
2208
- future.set_exception(exc)
2209
-
2210
- if not isinstance(exc, (Exception, OutcomeException)):
2211
- raise
2212
- else:
2213
- if not future.cancelled():
2214
- future.set_result(retval)
2215
-
2216
- async def _call_in_runner_task(
2217
- self,
2218
- func: Callable[P, Awaitable[T_Retval]],
2219
- *args: P.args,
2220
- **kwargs: P.kwargs,
2221
- ) -> T_Retval:
2222
- if not self._runner_task:
2223
- self._send_stream, receive_stream = create_memory_object_stream[
2224
- tuple[Awaitable[Any], asyncio.Future]
2225
- ](1)
2226
- self._runner_task = self.get_loop().create_task(
2227
- self._run_tests_and_fixtures(receive_stream)
2228
- )
2229
-
2230
- coro = func(*args, **kwargs)
2231
- future: asyncio.Future[T_Retval] = self.get_loop().create_future()
2232
- self._send_stream.send_nowait((coro, future))
2233
- return await future
2234
-
2235
- def run_asyncgen_fixture(
2236
- self,
2237
- fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]],
2238
- kwargs: dict[str, Any],
2239
- ) -> Iterable[T_Retval]:
2240
- asyncgen = fixture_func(**kwargs)
2241
- fixturevalue: T_Retval = self.get_loop().run_until_complete(
2242
- self._call_in_runner_task(asyncgen.asend, None)
2243
- )
2244
- self._raise_async_exceptions()
2245
-
2246
- yield fixturevalue
2247
-
2248
- try:
2249
- self.get_loop().run_until_complete(
2250
- self._call_in_runner_task(asyncgen.asend, None)
2251
- )
2252
- except StopAsyncIteration:
2253
- self._raise_async_exceptions()
2254
- else:
2255
- self.get_loop().run_until_complete(asyncgen.aclose())
2256
- raise RuntimeError("Async generator fixture did not stop")
2257
-
2258
- def run_fixture(
2259
- self,
2260
- fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]],
2261
- kwargs: dict[str, Any],
2262
- ) -> T_Retval:
2263
- retval = self.get_loop().run_until_complete(
2264
- self._call_in_runner_task(fixture_func, **kwargs)
2265
- )
2266
- self._raise_async_exceptions()
2267
- return retval
2268
-
2269
- def run_test(
2270
- self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any]
2271
- ) -> None:
2272
- try:
2273
- self.get_loop().run_until_complete(
2274
- self._call_in_runner_task(test_func, **kwargs)
2275
- )
2276
- except Exception as exc:
2277
- self._exceptions.append(exc)
2278
-
2279
- self._raise_async_exceptions()
2280
-
2281
-
2282
- class AsyncIOBackend(AsyncBackend):
2283
- @classmethod
2284
- def run(
2285
- cls,
2286
- func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
2287
- args: tuple[Unpack[PosArgsT]],
2288
- kwargs: dict[str, Any],
2289
- options: dict[str, Any],
2290
- ) -> T_Retval:
2291
- @wraps(func)
2292
- async def wrapper() -> T_Retval:
2293
- task = cast(asyncio.Task, current_task())
2294
- task.set_name(get_callable_name(func))
2295
- _task_states[task] = TaskState(None, None)
2296
-
2297
- try:
2298
- return await func(*args)
2299
- finally:
2300
- del _task_states[task]
2301
-
2302
- debug = options.get("debug", None)
2303
- loop_factory = options.get("loop_factory", None)
2304
- if loop_factory is None and options.get("use_uvloop", False):
2305
- import uvloop
2306
-
2307
- loop_factory = uvloop.new_event_loop
2308
-
2309
- with Runner(debug=debug, loop_factory=loop_factory) as runner:
2310
- return runner.run(wrapper())
2311
-
2312
- @classmethod
2313
- def current_token(cls) -> object:
2314
- return get_running_loop()
2315
-
2316
- @classmethod
2317
- def current_time(cls) -> float:
2318
- return get_running_loop().time()
2319
-
2320
- @classmethod
2321
- def cancelled_exception_class(cls) -> type[BaseException]:
2322
- return CancelledError
2323
-
2324
- @classmethod
2325
- async def checkpoint(cls) -> None:
2326
- await sleep(0)
2327
-
2328
- @classmethod
2329
- async def checkpoint_if_cancelled(cls) -> None:
2330
- task = current_task()
2331
- if task is None:
2332
- return
2333
-
2334
- try:
2335
- cancel_scope = _task_states[task].cancel_scope
2336
- except KeyError:
2337
- return
2338
-
2339
- while cancel_scope:
2340
- if cancel_scope.cancel_called:
2341
- await sleep(0)
2342
- elif cancel_scope.shield:
2343
- break
2344
- else:
2345
- cancel_scope = cancel_scope._parent_scope
2346
-
2347
- @classmethod
2348
- async def cancel_shielded_checkpoint(cls) -> None:
2349
- with CancelScope(shield=True):
2350
- await sleep(0)
2351
-
2352
- @classmethod
2353
- async def sleep(cls, delay: float) -> None:
2354
- await sleep(delay)
2355
-
2356
- @classmethod
2357
- def create_cancel_scope(
2358
- cls, *, deadline: float = math.inf, shield: bool = False
2359
- ) -> CancelScope:
2360
- return CancelScope(deadline=deadline, shield=shield)
2361
-
2362
- @classmethod
2363
- def current_effective_deadline(cls) -> float:
2364
- if (task := current_task()) is None:
2365
- return math.inf
2366
-
2367
- try:
2368
- cancel_scope = _task_states[task].cancel_scope
2369
- except KeyError:
2370
- return math.inf
2371
-
2372
- deadline = math.inf
2373
- while cancel_scope:
2374
- deadline = min(deadline, cancel_scope.deadline)
2375
- if cancel_scope._cancel_called:
2376
- deadline = -math.inf
2377
- break
2378
- elif cancel_scope.shield:
2379
- break
2380
- else:
2381
- cancel_scope = cancel_scope._parent_scope
2382
-
2383
- return deadline
2384
-
2385
- @classmethod
2386
- def create_task_group(cls) -> abc.TaskGroup:
2387
- return TaskGroup()
2388
-
2389
- @classmethod
2390
- def create_event(cls) -> abc.Event:
2391
- return Event()
2392
-
2393
- @classmethod
2394
- def create_lock(cls, *, fast_acquire: bool) -> abc.Lock:
2395
- return Lock(fast_acquire=fast_acquire)
2396
-
2397
- @classmethod
2398
- def create_semaphore(
2399
- cls,
2400
- initial_value: int,
2401
- *,
2402
- max_value: int | None = None,
2403
- fast_acquire: bool = False,
2404
- ) -> abc.Semaphore:
2405
- return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire)
2406
-
2407
- @classmethod
2408
- def create_capacity_limiter(cls, total_tokens: float) -> abc.CapacityLimiter:
2409
- return CapacityLimiter(total_tokens)
2410
-
2411
- @classmethod
2412
- async def run_sync_in_worker_thread( # type: ignore[return]
2413
- cls,
2414
- func: Callable[[Unpack[PosArgsT]], T_Retval],
2415
- args: tuple[Unpack[PosArgsT]],
2416
- abandon_on_cancel: bool = False,
2417
- limiter: abc.CapacityLimiter | None = None,
2418
- ) -> T_Retval:
2419
- await cls.checkpoint()
2420
-
2421
- # If this is the first run in this event loop thread, set up the necessary
2422
- # variables
2423
- try:
2424
- idle_workers = _threadpool_idle_workers.get()
2425
- workers = _threadpool_workers.get()
2426
- except LookupError:
2427
- idle_workers = deque()
2428
- workers = set()
2429
- _threadpool_idle_workers.set(idle_workers)
2430
- _threadpool_workers.set(workers)
2431
-
2432
- async with limiter or cls.current_default_thread_limiter():
2433
- with CancelScope(shield=not abandon_on_cancel) as scope:
2434
- future = asyncio.Future[T_Retval]()
2435
- root_task = find_root_task()
2436
- if not idle_workers:
2437
- worker = WorkerThread(root_task, workers, idle_workers)
2438
- worker.start()
2439
- workers.add(worker)
2440
- root_task.add_done_callback(
2441
- worker.stop, context=contextvars.Context()
2442
- )
2443
- else:
2444
- worker = idle_workers.pop()
2445
-
2446
- # Prune any other workers that have been idle for MAX_IDLE_TIME
2447
- # seconds or longer
2448
- now = cls.current_time()
2449
- while idle_workers:
2450
- if (
2451
- now - idle_workers[0].idle_since
2452
- < WorkerThread.MAX_IDLE_TIME
2453
- ):
2454
- break
2455
-
2456
- expired_worker = idle_workers.popleft()
2457
- expired_worker.root_task.remove_done_callback(
2458
- expired_worker.stop
2459
- )
2460
- expired_worker.stop()
2461
-
2462
- context = copy_context()
2463
- context.run(sniffio.current_async_library_cvar.set, None)
2464
- if abandon_on_cancel or scope._parent_scope is None:
2465
- worker_scope = scope
2466
- else:
2467
- worker_scope = scope._parent_scope
2468
-
2469
- worker.queue.put_nowait((context, func, args, future, worker_scope))
2470
- return await future
2471
-
2472
- @classmethod
2473
- def check_cancelled(cls) -> None:
2474
- scope: CancelScope | None = threadlocals.current_cancel_scope
2475
- while scope is not None:
2476
- if scope.cancel_called:
2477
- raise CancelledError(f"Cancelled by cancel scope {id(scope):x}")
2478
-
2479
- if scope.shield:
2480
- return
2481
-
2482
- scope = scope._parent_scope
2483
-
2484
- @classmethod
2485
- def run_async_from_thread(
2486
- cls,
2487
- func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
2488
- args: tuple[Unpack[PosArgsT]],
2489
- token: object,
2490
- ) -> T_Retval:
2491
- async def task_wrapper(scope: CancelScope) -> T_Retval:
2492
- __tracebackhide__ = True
2493
- task = cast(asyncio.Task, current_task())
2494
- _task_states[task] = TaskState(None, scope)
2495
- scope._tasks.add(task)
2496
- try:
2497
- return await func(*args)
2498
- except CancelledError as exc:
2499
- raise concurrent.futures.CancelledError(str(exc)) from None
2500
- finally:
2501
- scope._tasks.discard(task)
2502
-
2503
- loop = cast(AbstractEventLoop, token)
2504
- context = copy_context()
2505
- context.run(sniffio.current_async_library_cvar.set, "asyncio")
2506
- wrapper = task_wrapper(threadlocals.current_cancel_scope)
2507
- f: concurrent.futures.Future[T_Retval] = context.run(
2508
- asyncio.run_coroutine_threadsafe, wrapper, loop
2509
- )
2510
- return f.result()
2511
-
2512
- @classmethod
2513
- def run_sync_from_thread(
2514
- cls,
2515
- func: Callable[[Unpack[PosArgsT]], T_Retval],
2516
- args: tuple[Unpack[PosArgsT]],
2517
- token: object,
2518
- ) -> T_Retval:
2519
- @wraps(func)
2520
- def wrapper() -> None:
2521
- try:
2522
- sniffio.current_async_library_cvar.set("asyncio")
2523
- f.set_result(func(*args))
2524
- except BaseException as exc:
2525
- f.set_exception(exc)
2526
- if not isinstance(exc, Exception):
2527
- raise
2528
-
2529
- f: concurrent.futures.Future[T_Retval] = Future()
2530
- loop = cast(AbstractEventLoop, token)
2531
- loop.call_soon_threadsafe(wrapper)
2532
- return f.result()
2533
-
2534
- @classmethod
2535
- def create_blocking_portal(cls) -> abc.BlockingPortal:
2536
- return BlockingPortal()
2537
-
2538
- @classmethod
2539
- async def open_process(
2540
- cls,
2541
- command: StrOrBytesPath | Sequence[StrOrBytesPath],
2542
- *,
2543
- stdin: int | IO[Any] | None,
2544
- stdout: int | IO[Any] | None,
2545
- stderr: int | IO[Any] | None,
2546
- **kwargs: Any,
2547
- ) -> Process:
2548
- await cls.checkpoint()
2549
- if isinstance(command, PathLike):
2550
- command = os.fspath(command)
2551
-
2552
- if isinstance(command, (str, bytes)):
2553
- process = await asyncio.create_subprocess_shell(
2554
- command,
2555
- stdin=stdin,
2556
- stdout=stdout,
2557
- stderr=stderr,
2558
- **kwargs,
2559
- )
2560
- else:
2561
- process = await asyncio.create_subprocess_exec(
2562
- *command,
2563
- stdin=stdin,
2564
- stdout=stdout,
2565
- stderr=stderr,
2566
- **kwargs,
2567
- )
2568
-
2569
- stdin_stream = StreamWriterWrapper(process.stdin) if process.stdin else None
2570
- stdout_stream = StreamReaderWrapper(process.stdout) if process.stdout else None
2571
- stderr_stream = StreamReaderWrapper(process.stderr) if process.stderr else None
2572
- return Process(process, stdin_stream, stdout_stream, stderr_stream)
2573
-
2574
- @classmethod
2575
- def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None:
2576
- create_task(
2577
- _shutdown_process_pool_on_exit(workers),
2578
- name="AnyIO process pool shutdown task",
2579
- )
2580
- find_root_task().add_done_callback(
2581
- partial(_forcibly_shutdown_process_pool_on_exit, workers) # type:ignore[arg-type]
2582
- )
2583
-
2584
- @classmethod
2585
- async def connect_tcp(
2586
- cls, host: str, port: int, local_address: IPSockAddrType | None = None
2587
- ) -> abc.SocketStream:
2588
- transport, protocol = cast(
2589
- tuple[asyncio.Transport, StreamProtocol],
2590
- await get_running_loop().create_connection(
2591
- StreamProtocol, host, port, local_addr=local_address
2592
- ),
2593
- )
2594
- transport.pause_reading()
2595
- return SocketStream(transport, protocol)
2596
-
2597
- @classmethod
2598
- async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream:
2599
- await cls.checkpoint()
2600
- loop = get_running_loop()
2601
- raw_socket = socket.socket(socket.AF_UNIX)
2602
- raw_socket.setblocking(False)
2603
- while True:
2604
- try:
2605
- raw_socket.connect(path)
2606
- except BlockingIOError:
2607
- f: asyncio.Future = asyncio.Future()
2608
- loop.add_writer(raw_socket, f.set_result, None)
2609
- f.add_done_callback(lambda _: loop.remove_writer(raw_socket))
2610
- await f
2611
- except BaseException:
2612
- raw_socket.close()
2613
- raise
2614
- else:
2615
- return UNIXSocketStream(raw_socket)
2616
-
2617
- @classmethod
2618
- def create_tcp_listener(cls, sock: socket.socket) -> SocketListener:
2619
- return TCPSocketListener(sock)
2620
-
2621
- @classmethod
2622
- def create_unix_listener(cls, sock: socket.socket) -> SocketListener:
2623
- return UNIXSocketListener(sock)
2624
-
2625
- @classmethod
2626
- async def create_udp_socket(
2627
- cls,
2628
- family: AddressFamily,
2629
- local_address: IPSockAddrType | None,
2630
- remote_address: IPSockAddrType | None,
2631
- reuse_port: bool,
2632
- ) -> UDPSocket | ConnectedUDPSocket:
2633
- transport, protocol = await get_running_loop().create_datagram_endpoint(
2634
- DatagramProtocol,
2635
- local_addr=local_address,
2636
- remote_addr=remote_address,
2637
- family=family,
2638
- reuse_port=reuse_port,
2639
- )
2640
- if protocol.exception:
2641
- transport.close()
2642
- raise protocol.exception
2643
-
2644
- if not remote_address:
2645
- return UDPSocket(transport, protocol)
2646
- else:
2647
- return ConnectedUDPSocket(transport, protocol)
2648
-
2649
- @classmethod
2650
- async def create_unix_datagram_socket( # type: ignore[override]
2651
- cls, raw_socket: socket.socket, remote_path: str | bytes | None
2652
- ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket:
2653
- await cls.checkpoint()
2654
- loop = get_running_loop()
2655
-
2656
- if remote_path:
2657
- while True:
2658
- try:
2659
- raw_socket.connect(remote_path)
2660
- except BlockingIOError:
2661
- f: asyncio.Future = asyncio.Future()
2662
- loop.add_writer(raw_socket, f.set_result, None)
2663
- f.add_done_callback(lambda _: loop.remove_writer(raw_socket))
2664
- await f
2665
- except BaseException:
2666
- raw_socket.close()
2667
- raise
2668
- else:
2669
- return ConnectedUNIXDatagramSocket(raw_socket)
2670
- else:
2671
- return UNIXDatagramSocket(raw_socket)
2672
-
2673
- @classmethod
2674
- async def getaddrinfo(
2675
- cls,
2676
- host: bytes | str | None,
2677
- port: str | int | None,
2678
- *,
2679
- family: int | AddressFamily = 0,
2680
- type: int | SocketKind = 0,
2681
- proto: int = 0,
2682
- flags: int = 0,
2683
- ) -> Sequence[
2684
- tuple[
2685
- AddressFamily,
2686
- SocketKind,
2687
- int,
2688
- str,
2689
- tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
2690
- ]
2691
- ]:
2692
- return await get_running_loop().getaddrinfo(
2693
- host, port, family=family, type=type, proto=proto, flags=flags
2694
- )
2695
-
2696
- @classmethod
2697
- async def getnameinfo(
2698
- cls, sockaddr: IPSockAddrType, flags: int = 0
2699
- ) -> tuple[str, str]:
2700
- return await get_running_loop().getnameinfo(sockaddr, flags)
2701
-
2702
- @classmethod
2703
- async def wait_readable(cls, obj: FileDescriptorLike) -> None:
2704
- await cls.checkpoint()
2705
- try:
2706
- read_events = _read_events.get()
2707
- except LookupError:
2708
- read_events = {}
2709
- _read_events.set(read_events)
2710
-
2711
- if not isinstance(obj, int):
2712
- obj = obj.fileno()
2713
-
2714
- if read_events.get(obj):
2715
- raise BusyResourceError("reading from")
2716
-
2717
- loop = get_running_loop()
2718
- event = asyncio.Event()
2719
- try:
2720
- loop.add_reader(obj, event.set)
2721
- except NotImplementedError:
2722
- from anyio._core._asyncio_selector_thread import get_selector
2723
-
2724
- selector = get_selector()
2725
- selector.add_reader(obj, event.set)
2726
- remove_reader = selector.remove_reader
2727
- else:
2728
- remove_reader = loop.remove_reader
2729
-
2730
- read_events[obj] = event
2731
- try:
2732
- await event.wait()
2733
- finally:
2734
- remove_reader(obj)
2735
- del read_events[obj]
2736
-
2737
- @classmethod
2738
- async def wait_writable(cls, obj: FileDescriptorLike) -> None:
2739
- await cls.checkpoint()
2740
- try:
2741
- write_events = _write_events.get()
2742
- except LookupError:
2743
- write_events = {}
2744
- _write_events.set(write_events)
2745
-
2746
- if not isinstance(obj, int):
2747
- obj = obj.fileno()
2748
-
2749
- if write_events.get(obj):
2750
- raise BusyResourceError("writing to")
2751
-
2752
- loop = get_running_loop()
2753
- event = asyncio.Event()
2754
- try:
2755
- loop.add_writer(obj, event.set)
2756
- except NotImplementedError:
2757
- from anyio._core._asyncio_selector_thread import get_selector
2758
-
2759
- selector = get_selector()
2760
- selector.add_writer(obj, event.set)
2761
- remove_writer = selector.remove_writer
2762
- else:
2763
- remove_writer = loop.remove_writer
2764
-
2765
- write_events[obj] = event
2766
- try:
2767
- await event.wait()
2768
- finally:
2769
- del write_events[obj]
2770
- remove_writer(obj)
2771
-
2772
- @classmethod
2773
- def current_default_thread_limiter(cls) -> CapacityLimiter:
2774
- try:
2775
- return _default_thread_limiter.get()
2776
- except LookupError:
2777
- limiter = CapacityLimiter(40)
2778
- _default_thread_limiter.set(limiter)
2779
- return limiter
2780
-
2781
- @classmethod
2782
- def open_signal_receiver(
2783
- cls, *signals: Signals
2784
- ) -> AbstractContextManager[AsyncIterator[Signals]]:
2785
- return _SignalReceiver(signals)
2786
-
2787
- @classmethod
2788
- def get_current_task(cls) -> TaskInfo:
2789
- return AsyncIOTaskInfo(current_task()) # type: ignore[arg-type]
2790
-
2791
- @classmethod
2792
- def get_running_tasks(cls) -> Sequence[TaskInfo]:
2793
- return [AsyncIOTaskInfo(task) for task in all_tasks() if not task.done()]
2794
-
2795
- @classmethod
2796
- async def wait_all_tasks_blocked(cls) -> None:
2797
- await cls.checkpoint()
2798
- this_task = current_task()
2799
- while True:
2800
- for task in all_tasks():
2801
- if task is this_task:
2802
- continue
2803
-
2804
- waiter = task._fut_waiter # type: ignore[attr-defined]
2805
- if waiter is None or waiter.done():
2806
- await sleep(0.1)
2807
- break
2808
- else:
2809
- return
2810
-
2811
- @classmethod
2812
- def create_test_runner(cls, options: dict[str, Any]) -> TestRunner:
2813
- return TestRunner(**options)
2814
-
2815
-
2816
- backend_class = AsyncIOBackend
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/anyio/_backends/_trio.py DELETED
@@ -1,1334 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import array
4
- import math
5
- import os
6
- import socket
7
- import sys
8
- import types
9
- import weakref
10
- from collections.abc import (
11
- AsyncGenerator,
12
- AsyncIterator,
13
- Awaitable,
14
- Callable,
15
- Collection,
16
- Coroutine,
17
- Iterable,
18
- Sequence,
19
- )
20
- from concurrent.futures import Future
21
- from contextlib import AbstractContextManager
22
- from dataclasses import dataclass
23
- from functools import partial
24
- from io import IOBase
25
- from os import PathLike
26
- from signal import Signals
27
- from socket import AddressFamily, SocketKind
28
- from types import TracebackType
29
- from typing import (
30
- IO,
31
- TYPE_CHECKING,
32
- Any,
33
- Generic,
34
- NoReturn,
35
- TypeVar,
36
- cast,
37
- overload,
38
- )
39
-
40
- import trio.from_thread
41
- import trio.lowlevel
42
- from outcome import Error, Outcome, Value
43
- from trio.lowlevel import (
44
- current_root_task,
45
- current_task,
46
- wait_readable,
47
- wait_writable,
48
- )
49
- from trio.socket import SocketType as TrioSocketType
50
- from trio.to_thread import run_sync
51
-
52
- from .. import (
53
- CapacityLimiterStatistics,
54
- EventStatistics,
55
- LockStatistics,
56
- TaskInfo,
57
- WouldBlock,
58
- abc,
59
- )
60
- from .._core._eventloop import claim_worker_thread
61
- from .._core._exceptions import (
62
- BrokenResourceError,
63
- BusyResourceError,
64
- ClosedResourceError,
65
- EndOfStream,
66
- )
67
- from .._core._sockets import convert_ipv6_sockaddr
68
- from .._core._streams import create_memory_object_stream
69
- from .._core._synchronization import (
70
- CapacityLimiter as BaseCapacityLimiter,
71
- )
72
- from .._core._synchronization import Event as BaseEvent
73
- from .._core._synchronization import Lock as BaseLock
74
- from .._core._synchronization import (
75
- ResourceGuard,
76
- SemaphoreStatistics,
77
- )
78
- from .._core._synchronization import Semaphore as BaseSemaphore
79
- from .._core._tasks import CancelScope as BaseCancelScope
80
- from ..abc import IPSockAddrType, UDPPacketType, UNIXDatagramPacketType
81
- from ..abc._eventloop import AsyncBackend, StrOrBytesPath
82
- from ..streams.memory import MemoryObjectSendStream
83
-
84
- if TYPE_CHECKING:
85
- from _typeshed import HasFileno
86
-
87
- if sys.version_info >= (3, 10):
88
- from typing import ParamSpec
89
- else:
90
- from typing_extensions import ParamSpec
91
-
92
- if sys.version_info >= (3, 11):
93
- from typing import TypeVarTuple, Unpack
94
- else:
95
- from exceptiongroup import BaseExceptionGroup
96
- from typing_extensions import TypeVarTuple, Unpack
97
-
98
- T = TypeVar("T")
99
- T_Retval = TypeVar("T_Retval")
100
- T_SockAddr = TypeVar("T_SockAddr", str, IPSockAddrType)
101
- PosArgsT = TypeVarTuple("PosArgsT")
102
- P = ParamSpec("P")
103
-
104
-
105
- #
106
- # Event loop
107
- #
108
-
109
- RunVar = trio.lowlevel.RunVar
110
-
111
-
112
- #
113
- # Timeouts and cancellation
114
- #
115
-
116
-
117
- class CancelScope(BaseCancelScope):
118
- def __new__(
119
- cls, original: trio.CancelScope | None = None, **kwargs: object
120
- ) -> CancelScope:
121
- return object.__new__(cls)
122
-
123
- def __init__(self, original: trio.CancelScope | None = None, **kwargs: Any) -> None:
124
- self.__original = original or trio.CancelScope(**kwargs)
125
-
126
- def __enter__(self) -> CancelScope:
127
- self.__original.__enter__()
128
- return self
129
-
130
- def __exit__(
131
- self,
132
- exc_type: type[BaseException] | None,
133
- exc_val: BaseException | None,
134
- exc_tb: TracebackType | None,
135
- ) -> bool:
136
- return self.__original.__exit__(exc_type, exc_val, exc_tb)
137
-
138
- def cancel(self) -> None:
139
- self.__original.cancel()
140
-
141
- @property
142
- def deadline(self) -> float:
143
- return self.__original.deadline
144
-
145
- @deadline.setter
146
- def deadline(self, value: float) -> None:
147
- self.__original.deadline = value
148
-
149
- @property
150
- def cancel_called(self) -> bool:
151
- return self.__original.cancel_called
152
-
153
- @property
154
- def cancelled_caught(self) -> bool:
155
- return self.__original.cancelled_caught
156
-
157
- @property
158
- def shield(self) -> bool:
159
- return self.__original.shield
160
-
161
- @shield.setter
162
- def shield(self, value: bool) -> None:
163
- self.__original.shield = value
164
-
165
-
166
- #
167
- # Task groups
168
- #
169
-
170
-
171
- class TaskGroup(abc.TaskGroup):
172
- def __init__(self) -> None:
173
- self._active = False
174
- self._nursery_manager = trio.open_nursery(strict_exception_groups=True)
175
- self.cancel_scope = None # type: ignore[assignment]
176
-
177
- async def __aenter__(self) -> TaskGroup:
178
- self._active = True
179
- self._nursery = await self._nursery_manager.__aenter__()
180
- self.cancel_scope = CancelScope(self._nursery.cancel_scope)
181
- return self
182
-
183
- async def __aexit__(
184
- self,
185
- exc_type: type[BaseException] | None,
186
- exc_val: BaseException | None,
187
- exc_tb: TracebackType | None,
188
- ) -> bool:
189
- try:
190
- # trio.Nursery.__exit__ returns bool; .open_nursery has wrong type
191
- return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) # type: ignore[return-value]
192
- except BaseExceptionGroup as exc:
193
- if not exc.split(trio.Cancelled)[1]:
194
- raise trio.Cancelled._create() from exc
195
-
196
- raise
197
- finally:
198
- del exc_val, exc_tb
199
- self._active = False
200
-
201
- def start_soon(
202
- self,
203
- func: Callable[[Unpack[PosArgsT]], Awaitable[Any]],
204
- *args: Unpack[PosArgsT],
205
- name: object = None,
206
- ) -> None:
207
- if not self._active:
208
- raise RuntimeError(
209
- "This task group is not active; no new tasks can be started."
210
- )
211
-
212
- self._nursery.start_soon(func, *args, name=name)
213
-
214
- async def start(
215
- self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None
216
- ) -> Any:
217
- if not self._active:
218
- raise RuntimeError(
219
- "This task group is not active; no new tasks can be started."
220
- )
221
-
222
- return await self._nursery.start(func, *args, name=name)
223
-
224
-
225
- #
226
- # Threads
227
- #
228
-
229
-
230
- class BlockingPortal(abc.BlockingPortal):
231
- def __new__(cls) -> BlockingPortal:
232
- return object.__new__(cls)
233
-
234
- def __init__(self) -> None:
235
- super().__init__()
236
- self._token = trio.lowlevel.current_trio_token()
237
-
238
- def _spawn_task_from_thread(
239
- self,
240
- func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
241
- args: tuple[Unpack[PosArgsT]],
242
- kwargs: dict[str, Any],
243
- name: object,
244
- future: Future[T_Retval],
245
- ) -> None:
246
- trio.from_thread.run_sync(
247
- partial(self._task_group.start_soon, name=name),
248
- self._call_func,
249
- func,
250
- args,
251
- kwargs,
252
- future,
253
- trio_token=self._token,
254
- )
255
-
256
-
257
- #
258
- # Subprocesses
259
- #
260
-
261
-
262
- @dataclass(eq=False)
263
- class ReceiveStreamWrapper(abc.ByteReceiveStream):
264
- _stream: trio.abc.ReceiveStream
265
-
266
- async def receive(self, max_bytes: int | None = None) -> bytes:
267
- try:
268
- data = await self._stream.receive_some(max_bytes)
269
- except trio.ClosedResourceError as exc:
270
- raise ClosedResourceError from exc.__cause__
271
- except trio.BrokenResourceError as exc:
272
- raise BrokenResourceError from exc.__cause__
273
-
274
- if data:
275
- return data
276
- else:
277
- raise EndOfStream
278
-
279
- async def aclose(self) -> None:
280
- await self._stream.aclose()
281
-
282
-
283
- @dataclass(eq=False)
284
- class SendStreamWrapper(abc.ByteSendStream):
285
- _stream: trio.abc.SendStream
286
-
287
- async def send(self, item: bytes) -> None:
288
- try:
289
- await self._stream.send_all(item)
290
- except trio.ClosedResourceError as exc:
291
- raise ClosedResourceError from exc.__cause__
292
- except trio.BrokenResourceError as exc:
293
- raise BrokenResourceError from exc.__cause__
294
-
295
- async def aclose(self) -> None:
296
- await self._stream.aclose()
297
-
298
-
299
- @dataclass(eq=False)
300
- class Process(abc.Process):
301
- _process: trio.Process
302
- _stdin: abc.ByteSendStream | None
303
- _stdout: abc.ByteReceiveStream | None
304
- _stderr: abc.ByteReceiveStream | None
305
-
306
- async def aclose(self) -> None:
307
- with CancelScope(shield=True):
308
- if self._stdin:
309
- await self._stdin.aclose()
310
- if self._stdout:
311
- await self._stdout.aclose()
312
- if self._stderr:
313
- await self._stderr.aclose()
314
-
315
- try:
316
- await self.wait()
317
- except BaseException:
318
- self.kill()
319
- with CancelScope(shield=True):
320
- await self.wait()
321
- raise
322
-
323
- async def wait(self) -> int:
324
- return await self._process.wait()
325
-
326
- def terminate(self) -> None:
327
- self._process.terminate()
328
-
329
- def kill(self) -> None:
330
- self._process.kill()
331
-
332
- def send_signal(self, signal: Signals) -> None:
333
- self._process.send_signal(signal)
334
-
335
- @property
336
- def pid(self) -> int:
337
- return self._process.pid
338
-
339
- @property
340
- def returncode(self) -> int | None:
341
- return self._process.returncode
342
-
343
- @property
344
- def stdin(self) -> abc.ByteSendStream | None:
345
- return self._stdin
346
-
347
- @property
348
- def stdout(self) -> abc.ByteReceiveStream | None:
349
- return self._stdout
350
-
351
- @property
352
- def stderr(self) -> abc.ByteReceiveStream | None:
353
- return self._stderr
354
-
355
-
356
- class _ProcessPoolShutdownInstrument(trio.abc.Instrument):
357
- def after_run(self) -> None:
358
- super().after_run()
359
-
360
-
361
- current_default_worker_process_limiter: trio.lowlevel.RunVar = RunVar(
362
- "current_default_worker_process_limiter"
363
- )
364
-
365
-
366
- async def _shutdown_process_pool(workers: set[abc.Process]) -> None:
367
- try:
368
- await trio.sleep(math.inf)
369
- except trio.Cancelled:
370
- for process in workers:
371
- if process.returncode is None:
372
- process.kill()
373
-
374
- with CancelScope(shield=True):
375
- for process in workers:
376
- await process.aclose()
377
-
378
-
379
- #
380
- # Sockets and networking
381
- #
382
-
383
-
384
- class _TrioSocketMixin(Generic[T_SockAddr]):
385
- def __init__(self, trio_socket: TrioSocketType) -> None:
386
- self._trio_socket = trio_socket
387
- self._closed = False
388
-
389
- def _check_closed(self) -> None:
390
- if self._closed:
391
- raise ClosedResourceError
392
- if self._trio_socket.fileno() < 0:
393
- raise BrokenResourceError
394
-
395
- @property
396
- def _raw_socket(self) -> socket.socket:
397
- return self._trio_socket._sock # type: ignore[attr-defined]
398
-
399
- async def aclose(self) -> None:
400
- if self._trio_socket.fileno() >= 0:
401
- self._closed = True
402
- self._trio_socket.close()
403
-
404
- def _convert_socket_error(self, exc: BaseException) -> NoReturn:
405
- if isinstance(exc, trio.ClosedResourceError):
406
- raise ClosedResourceError from exc
407
- elif self._trio_socket.fileno() < 0 and self._closed:
408
- raise ClosedResourceError from None
409
- elif isinstance(exc, OSError):
410
- raise BrokenResourceError from exc
411
- else:
412
- raise exc
413
-
414
-
415
- class SocketStream(_TrioSocketMixin, abc.SocketStream):
416
- def __init__(self, trio_socket: TrioSocketType) -> None:
417
- super().__init__(trio_socket)
418
- self._receive_guard = ResourceGuard("reading from")
419
- self._send_guard = ResourceGuard("writing to")
420
-
421
- async def receive(self, max_bytes: int = 65536) -> bytes:
422
- with self._receive_guard:
423
- try:
424
- data = await self._trio_socket.recv(max_bytes)
425
- except BaseException as exc:
426
- self._convert_socket_error(exc)
427
-
428
- if data:
429
- return data
430
- else:
431
- raise EndOfStream
432
-
433
- async def send(self, item: bytes) -> None:
434
- with self._send_guard:
435
- view = memoryview(item)
436
- while view:
437
- try:
438
- bytes_sent = await self._trio_socket.send(view)
439
- except BaseException as exc:
440
- self._convert_socket_error(exc)
441
-
442
- view = view[bytes_sent:]
443
-
444
- async def send_eof(self) -> None:
445
- self._trio_socket.shutdown(socket.SHUT_WR)
446
-
447
-
448
- class UNIXSocketStream(SocketStream, abc.UNIXSocketStream):
449
- async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]:
450
- if not isinstance(msglen, int) or msglen < 0:
451
- raise ValueError("msglen must be a non-negative integer")
452
- if not isinstance(maxfds, int) or maxfds < 1:
453
- raise ValueError("maxfds must be a positive integer")
454
-
455
- fds = array.array("i")
456
- await trio.lowlevel.checkpoint()
457
- with self._receive_guard:
458
- while True:
459
- try:
460
- message, ancdata, flags, addr = await self._trio_socket.recvmsg(
461
- msglen, socket.CMSG_LEN(maxfds * fds.itemsize)
462
- )
463
- except BaseException as exc:
464
- self._convert_socket_error(exc)
465
- else:
466
- if not message and not ancdata:
467
- raise EndOfStream
468
-
469
- break
470
-
471
- for cmsg_level, cmsg_type, cmsg_data in ancdata:
472
- if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS:
473
- raise RuntimeError(
474
- f"Received unexpected ancillary data; message = {message!r}, "
475
- f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}"
476
- )
477
-
478
- fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
479
-
480
- return message, list(fds)
481
-
482
- async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None:
483
- if not message:
484
- raise ValueError("message must not be empty")
485
- if not fds:
486
- raise ValueError("fds must not be empty")
487
-
488
- filenos: list[int] = []
489
- for fd in fds:
490
- if isinstance(fd, int):
491
- filenos.append(fd)
492
- elif isinstance(fd, IOBase):
493
- filenos.append(fd.fileno())
494
-
495
- fdarray = array.array("i", filenos)
496
- await trio.lowlevel.checkpoint()
497
- with self._send_guard:
498
- while True:
499
- try:
500
- await self._trio_socket.sendmsg(
501
- [message],
502
- [
503
- (
504
- socket.SOL_SOCKET,
505
- socket.SCM_RIGHTS,
506
- fdarray,
507
- )
508
- ],
509
- )
510
- break
511
- except BaseException as exc:
512
- self._convert_socket_error(exc)
513
-
514
-
515
- class TCPSocketListener(_TrioSocketMixin, abc.SocketListener):
516
- def __init__(self, raw_socket: socket.socket):
517
- super().__init__(trio.socket.from_stdlib_socket(raw_socket))
518
- self._accept_guard = ResourceGuard("accepting connections from")
519
-
520
- async def accept(self) -> SocketStream:
521
- with self._accept_guard:
522
- try:
523
- trio_socket, _addr = await self._trio_socket.accept()
524
- except BaseException as exc:
525
- self._convert_socket_error(exc)
526
-
527
- trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
528
- return SocketStream(trio_socket)
529
-
530
-
531
- class UNIXSocketListener(_TrioSocketMixin, abc.SocketListener):
532
- def __init__(self, raw_socket: socket.socket):
533
- super().__init__(trio.socket.from_stdlib_socket(raw_socket))
534
- self._accept_guard = ResourceGuard("accepting connections from")
535
-
536
- async def accept(self) -> UNIXSocketStream:
537
- with self._accept_guard:
538
- try:
539
- trio_socket, _addr = await self._trio_socket.accept()
540
- except BaseException as exc:
541
- self._convert_socket_error(exc)
542
-
543
- return UNIXSocketStream(trio_socket)
544
-
545
-
546
- class UDPSocket(_TrioSocketMixin[IPSockAddrType], abc.UDPSocket):
547
- def __init__(self, trio_socket: TrioSocketType) -> None:
548
- super().__init__(trio_socket)
549
- self._receive_guard = ResourceGuard("reading from")
550
- self._send_guard = ResourceGuard("writing to")
551
-
552
- async def receive(self) -> tuple[bytes, IPSockAddrType]:
553
- with self._receive_guard:
554
- try:
555
- data, addr = await self._trio_socket.recvfrom(65536)
556
- return data, convert_ipv6_sockaddr(addr)
557
- except BaseException as exc:
558
- self._convert_socket_error(exc)
559
-
560
- async def send(self, item: UDPPacketType) -> None:
561
- with self._send_guard:
562
- try:
563
- await self._trio_socket.sendto(*item)
564
- except BaseException as exc:
565
- self._convert_socket_error(exc)
566
-
567
-
568
- class ConnectedUDPSocket(_TrioSocketMixin[IPSockAddrType], abc.ConnectedUDPSocket):
569
- def __init__(self, trio_socket: TrioSocketType) -> None:
570
- super().__init__(trio_socket)
571
- self._receive_guard = ResourceGuard("reading from")
572
- self._send_guard = ResourceGuard("writing to")
573
-
574
- async def receive(self) -> bytes:
575
- with self._receive_guard:
576
- try:
577
- return await self._trio_socket.recv(65536)
578
- except BaseException as exc:
579
- self._convert_socket_error(exc)
580
-
581
- async def send(self, item: bytes) -> None:
582
- with self._send_guard:
583
- try:
584
- await self._trio_socket.send(item)
585
- except BaseException as exc:
586
- self._convert_socket_error(exc)
587
-
588
-
589
- class UNIXDatagramSocket(_TrioSocketMixin[str], abc.UNIXDatagramSocket):
590
- def __init__(self, trio_socket: TrioSocketType) -> None:
591
- super().__init__(trio_socket)
592
- self._receive_guard = ResourceGuard("reading from")
593
- self._send_guard = ResourceGuard("writing to")
594
-
595
- async def receive(self) -> UNIXDatagramPacketType:
596
- with self._receive_guard:
597
- try:
598
- data, addr = await self._trio_socket.recvfrom(65536)
599
- return data, addr
600
- except BaseException as exc:
601
- self._convert_socket_error(exc)
602
-
603
- async def send(self, item: UNIXDatagramPacketType) -> None:
604
- with self._send_guard:
605
- try:
606
- await self._trio_socket.sendto(*item)
607
- except BaseException as exc:
608
- self._convert_socket_error(exc)
609
-
610
-
611
- class ConnectedUNIXDatagramSocket(
612
- _TrioSocketMixin[str], abc.ConnectedUNIXDatagramSocket
613
- ):
614
- def __init__(self, trio_socket: TrioSocketType) -> None:
615
- super().__init__(trio_socket)
616
- self._receive_guard = ResourceGuard("reading from")
617
- self._send_guard = ResourceGuard("writing to")
618
-
619
- async def receive(self) -> bytes:
620
- with self._receive_guard:
621
- try:
622
- return await self._trio_socket.recv(65536)
623
- except BaseException as exc:
624
- self._convert_socket_error(exc)
625
-
626
- async def send(self, item: bytes) -> None:
627
- with self._send_guard:
628
- try:
629
- await self._trio_socket.send(item)
630
- except BaseException as exc:
631
- self._convert_socket_error(exc)
632
-
633
-
634
- #
635
- # Synchronization
636
- #
637
-
638
-
639
- class Event(BaseEvent):
640
- def __new__(cls) -> Event:
641
- return object.__new__(cls)
642
-
643
- def __init__(self) -> None:
644
- self.__original = trio.Event()
645
-
646
- def is_set(self) -> bool:
647
- return self.__original.is_set()
648
-
649
- async def wait(self) -> None:
650
- return await self.__original.wait()
651
-
652
- def statistics(self) -> EventStatistics:
653
- orig_statistics = self.__original.statistics()
654
- return EventStatistics(tasks_waiting=orig_statistics.tasks_waiting)
655
-
656
- def set(self) -> None:
657
- self.__original.set()
658
-
659
-
660
- class Lock(BaseLock):
661
- def __new__(cls, *, fast_acquire: bool = False) -> Lock:
662
- return object.__new__(cls)
663
-
664
- def __init__(self, *, fast_acquire: bool = False) -> None:
665
- self._fast_acquire = fast_acquire
666
- self.__original = trio.Lock()
667
-
668
- @staticmethod
669
- def _convert_runtime_error_msg(exc: RuntimeError) -> None:
670
- if exc.args == ("attempt to re-acquire an already held Lock",):
671
- exc.args = ("Attempted to acquire an already held Lock",)
672
-
673
- async def acquire(self) -> None:
674
- if not self._fast_acquire:
675
- try:
676
- await self.__original.acquire()
677
- except RuntimeError as exc:
678
- self._convert_runtime_error_msg(exc)
679
- raise
680
-
681
- return
682
-
683
- # This is the "fast path" where we don't let other tasks run
684
- await trio.lowlevel.checkpoint_if_cancelled()
685
- try:
686
- self.__original.acquire_nowait()
687
- except trio.WouldBlock:
688
- await self.__original._lot.park()
689
- except RuntimeError as exc:
690
- self._convert_runtime_error_msg(exc)
691
- raise
692
-
693
- def acquire_nowait(self) -> None:
694
- try:
695
- self.__original.acquire_nowait()
696
- except trio.WouldBlock:
697
- raise WouldBlock from None
698
- except RuntimeError as exc:
699
- self._convert_runtime_error_msg(exc)
700
- raise
701
-
702
- def locked(self) -> bool:
703
- return self.__original.locked()
704
-
705
- def release(self) -> None:
706
- self.__original.release()
707
-
708
- def statistics(self) -> LockStatistics:
709
- orig_statistics = self.__original.statistics()
710
- owner = TrioTaskInfo(orig_statistics.owner) if orig_statistics.owner else None
711
- return LockStatistics(
712
- orig_statistics.locked, owner, orig_statistics.tasks_waiting
713
- )
714
-
715
-
716
- class Semaphore(BaseSemaphore):
717
- def __new__(
718
- cls,
719
- initial_value: int,
720
- *,
721
- max_value: int | None = None,
722
- fast_acquire: bool = False,
723
- ) -> Semaphore:
724
- return object.__new__(cls)
725
-
726
- def __init__(
727
- self,
728
- initial_value: int,
729
- *,
730
- max_value: int | None = None,
731
- fast_acquire: bool = False,
732
- ) -> None:
733
- super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire)
734
- self.__original = trio.Semaphore(initial_value, max_value=max_value)
735
-
736
- async def acquire(self) -> None:
737
- if not self._fast_acquire:
738
- await self.__original.acquire()
739
- return
740
-
741
- # This is the "fast path" where we don't let other tasks run
742
- await trio.lowlevel.checkpoint_if_cancelled()
743
- try:
744
- self.__original.acquire_nowait()
745
- except trio.WouldBlock:
746
- await self.__original._lot.park()
747
-
748
- def acquire_nowait(self) -> None:
749
- try:
750
- self.__original.acquire_nowait()
751
- except trio.WouldBlock:
752
- raise WouldBlock from None
753
-
754
- @property
755
- def max_value(self) -> int | None:
756
- return self.__original.max_value
757
-
758
- @property
759
- def value(self) -> int:
760
- return self.__original.value
761
-
762
- def release(self) -> None:
763
- self.__original.release()
764
-
765
- def statistics(self) -> SemaphoreStatistics:
766
- orig_statistics = self.__original.statistics()
767
- return SemaphoreStatistics(orig_statistics.tasks_waiting)
768
-
769
-
770
- class CapacityLimiter(BaseCapacityLimiter):
771
- def __new__(
772
- cls,
773
- total_tokens: float | None = None,
774
- *,
775
- original: trio.CapacityLimiter | None = None,
776
- ) -> CapacityLimiter:
777
- return object.__new__(cls)
778
-
779
- def __init__(
780
- self,
781
- total_tokens: float | None = None,
782
- *,
783
- original: trio.CapacityLimiter | None = None,
784
- ) -> None:
785
- if original is not None:
786
- self.__original = original
787
- else:
788
- assert total_tokens is not None
789
- self.__original = trio.CapacityLimiter(total_tokens)
790
-
791
- async def __aenter__(self) -> None:
792
- return await self.__original.__aenter__()
793
-
794
- async def __aexit__(
795
- self,
796
- exc_type: type[BaseException] | None,
797
- exc_val: BaseException | None,
798
- exc_tb: TracebackType | None,
799
- ) -> None:
800
- await self.__original.__aexit__(exc_type, exc_val, exc_tb)
801
-
802
- @property
803
- def total_tokens(self) -> float:
804
- return self.__original.total_tokens
805
-
806
- @total_tokens.setter
807
- def total_tokens(self, value: float) -> None:
808
- self.__original.total_tokens = value
809
-
810
- @property
811
- def borrowed_tokens(self) -> int:
812
- return self.__original.borrowed_tokens
813
-
814
- @property
815
- def available_tokens(self) -> float:
816
- return self.__original.available_tokens
817
-
818
- def acquire_nowait(self) -> None:
819
- self.__original.acquire_nowait()
820
-
821
- def acquire_on_behalf_of_nowait(self, borrower: object) -> None:
822
- self.__original.acquire_on_behalf_of_nowait(borrower)
823
-
824
- async def acquire(self) -> None:
825
- await self.__original.acquire()
826
-
827
- async def acquire_on_behalf_of(self, borrower: object) -> None:
828
- await self.__original.acquire_on_behalf_of(borrower)
829
-
830
- def release(self) -> None:
831
- return self.__original.release()
832
-
833
- def release_on_behalf_of(self, borrower: object) -> None:
834
- return self.__original.release_on_behalf_of(borrower)
835
-
836
- def statistics(self) -> CapacityLimiterStatistics:
837
- orig = self.__original.statistics()
838
- return CapacityLimiterStatistics(
839
- borrowed_tokens=orig.borrowed_tokens,
840
- total_tokens=orig.total_tokens,
841
- borrowers=tuple(orig.borrowers),
842
- tasks_waiting=orig.tasks_waiting,
843
- )
844
-
845
-
846
- _capacity_limiter_wrapper: trio.lowlevel.RunVar = RunVar("_capacity_limiter_wrapper")
847
-
848
-
849
- #
850
- # Signal handling
851
- #
852
-
853
-
854
- class _SignalReceiver:
855
- _iterator: AsyncIterator[int]
856
-
857
- def __init__(self, signals: tuple[Signals, ...]):
858
- self._signals = signals
859
-
860
- def __enter__(self) -> _SignalReceiver:
861
- self._cm = trio.open_signal_receiver(*self._signals)
862
- self._iterator = self._cm.__enter__()
863
- return self
864
-
865
- def __exit__(
866
- self,
867
- exc_type: type[BaseException] | None,
868
- exc_val: BaseException | None,
869
- exc_tb: TracebackType | None,
870
- ) -> bool | None:
871
- return self._cm.__exit__(exc_type, exc_val, exc_tb)
872
-
873
- def __aiter__(self) -> _SignalReceiver:
874
- return self
875
-
876
- async def __anext__(self) -> Signals:
877
- signum = await self._iterator.__anext__()
878
- return Signals(signum)
879
-
880
-
881
- #
882
- # Testing and debugging
883
- #
884
-
885
-
886
- class TestRunner(abc.TestRunner):
887
- def __init__(self, **options: Any) -> None:
888
- from queue import Queue
889
-
890
- self._call_queue: Queue[Callable[[], object]] = Queue()
891
- self._send_stream: MemoryObjectSendStream | None = None
892
- self._options = options
893
-
894
- def __exit__(
895
- self,
896
- exc_type: type[BaseException] | None,
897
- exc_val: BaseException | None,
898
- exc_tb: types.TracebackType | None,
899
- ) -> None:
900
- if self._send_stream:
901
- self._send_stream.close()
902
- while self._send_stream is not None:
903
- self._call_queue.get()()
904
-
905
- async def _run_tests_and_fixtures(self) -> None:
906
- self._send_stream, receive_stream = create_memory_object_stream(1)
907
- with receive_stream:
908
- async for coro, outcome_holder in receive_stream:
909
- try:
910
- retval = await coro
911
- except BaseException as exc:
912
- outcome_holder.append(Error(exc))
913
- else:
914
- outcome_holder.append(Value(retval))
915
-
916
- def _main_task_finished(self, outcome: object) -> None:
917
- self._send_stream = None
918
-
919
- def _call_in_runner_task(
920
- self,
921
- func: Callable[P, Awaitable[T_Retval]],
922
- *args: P.args,
923
- **kwargs: P.kwargs,
924
- ) -> T_Retval:
925
- if self._send_stream is None:
926
- trio.lowlevel.start_guest_run(
927
- self._run_tests_and_fixtures,
928
- run_sync_soon_threadsafe=self._call_queue.put,
929
- done_callback=self._main_task_finished,
930
- **self._options,
931
- )
932
- while self._send_stream is None:
933
- self._call_queue.get()()
934
-
935
- outcome_holder: list[Outcome] = []
936
- self._send_stream.send_nowait((func(*args, **kwargs), outcome_holder))
937
- while not outcome_holder:
938
- self._call_queue.get()()
939
-
940
- return outcome_holder[0].unwrap()
941
-
942
- def run_asyncgen_fixture(
943
- self,
944
- fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]],
945
- kwargs: dict[str, Any],
946
- ) -> Iterable[T_Retval]:
947
- asyncgen = fixture_func(**kwargs)
948
- fixturevalue: T_Retval = self._call_in_runner_task(asyncgen.asend, None)
949
-
950
- yield fixturevalue
951
-
952
- try:
953
- self._call_in_runner_task(asyncgen.asend, None)
954
- except StopAsyncIteration:
955
- pass
956
- else:
957
- self._call_in_runner_task(asyncgen.aclose)
958
- raise RuntimeError("Async generator fixture did not stop")
959
-
960
- def run_fixture(
961
- self,
962
- fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]],
963
- kwargs: dict[str, Any],
964
- ) -> T_Retval:
965
- return self._call_in_runner_task(fixture_func, **kwargs)
966
-
967
- def run_test(
968
- self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any]
969
- ) -> None:
970
- self._call_in_runner_task(test_func, **kwargs)
971
-
972
-
973
- class TrioTaskInfo(TaskInfo):
974
- def __init__(self, task: trio.lowlevel.Task):
975
- parent_id = None
976
- if task.parent_nursery and task.parent_nursery.parent_task:
977
- parent_id = id(task.parent_nursery.parent_task)
978
-
979
- super().__init__(id(task), parent_id, task.name, task.coro)
980
- self._task = weakref.proxy(task)
981
-
982
- def has_pending_cancellation(self) -> bool:
983
- try:
984
- return self._task._cancel_status.effectively_cancelled
985
- except ReferenceError:
986
- # If the task is no longer around, it surely doesn't have a cancellation
987
- # pending
988
- return False
989
-
990
-
991
- class TrioBackend(AsyncBackend):
992
- @classmethod
993
- def run(
994
- cls,
995
- func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
996
- args: tuple[Unpack[PosArgsT]],
997
- kwargs: dict[str, Any],
998
- options: dict[str, Any],
999
- ) -> T_Retval:
1000
- return trio.run(func, *args)
1001
-
1002
- @classmethod
1003
- def current_token(cls) -> object:
1004
- return trio.lowlevel.current_trio_token()
1005
-
1006
- @classmethod
1007
- def current_time(cls) -> float:
1008
- return trio.current_time()
1009
-
1010
- @classmethod
1011
- def cancelled_exception_class(cls) -> type[BaseException]:
1012
- return trio.Cancelled
1013
-
1014
- @classmethod
1015
- async def checkpoint(cls) -> None:
1016
- await trio.lowlevel.checkpoint()
1017
-
1018
- @classmethod
1019
- async def checkpoint_if_cancelled(cls) -> None:
1020
- await trio.lowlevel.checkpoint_if_cancelled()
1021
-
1022
- @classmethod
1023
- async def cancel_shielded_checkpoint(cls) -> None:
1024
- await trio.lowlevel.cancel_shielded_checkpoint()
1025
-
1026
- @classmethod
1027
- async def sleep(cls, delay: float) -> None:
1028
- await trio.sleep(delay)
1029
-
1030
- @classmethod
1031
- def create_cancel_scope(
1032
- cls, *, deadline: float = math.inf, shield: bool = False
1033
- ) -> abc.CancelScope:
1034
- return CancelScope(deadline=deadline, shield=shield)
1035
-
1036
- @classmethod
1037
- def current_effective_deadline(cls) -> float:
1038
- return trio.current_effective_deadline()
1039
-
1040
- @classmethod
1041
- def create_task_group(cls) -> abc.TaskGroup:
1042
- return TaskGroup()
1043
-
1044
- @classmethod
1045
- def create_event(cls) -> abc.Event:
1046
- return Event()
1047
-
1048
- @classmethod
1049
- def create_lock(cls, *, fast_acquire: bool) -> Lock:
1050
- return Lock(fast_acquire=fast_acquire)
1051
-
1052
- @classmethod
1053
- def create_semaphore(
1054
- cls,
1055
- initial_value: int,
1056
- *,
1057
- max_value: int | None = None,
1058
- fast_acquire: bool = False,
1059
- ) -> abc.Semaphore:
1060
- return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire)
1061
-
1062
- @classmethod
1063
- def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter:
1064
- return CapacityLimiter(total_tokens)
1065
-
1066
- @classmethod
1067
- async def run_sync_in_worker_thread(
1068
- cls,
1069
- func: Callable[[Unpack[PosArgsT]], T_Retval],
1070
- args: tuple[Unpack[PosArgsT]],
1071
- abandon_on_cancel: bool = False,
1072
- limiter: abc.CapacityLimiter | None = None,
1073
- ) -> T_Retval:
1074
- def wrapper() -> T_Retval:
1075
- with claim_worker_thread(TrioBackend, token):
1076
- return func(*args)
1077
-
1078
- token = TrioBackend.current_token()
1079
- return await run_sync(
1080
- wrapper,
1081
- abandon_on_cancel=abandon_on_cancel,
1082
- limiter=cast(trio.CapacityLimiter, limiter),
1083
- )
1084
-
1085
- @classmethod
1086
- def check_cancelled(cls) -> None:
1087
- trio.from_thread.check_cancelled()
1088
-
1089
- @classmethod
1090
- def run_async_from_thread(
1091
- cls,
1092
- func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
1093
- args: tuple[Unpack[PosArgsT]],
1094
- token: object,
1095
- ) -> T_Retval:
1096
- return trio.from_thread.run(func, *args)
1097
-
1098
- @classmethod
1099
- def run_sync_from_thread(
1100
- cls,
1101
- func: Callable[[Unpack[PosArgsT]], T_Retval],
1102
- args: tuple[Unpack[PosArgsT]],
1103
- token: object,
1104
- ) -> T_Retval:
1105
- return trio.from_thread.run_sync(func, *args)
1106
-
1107
- @classmethod
1108
- def create_blocking_portal(cls) -> abc.BlockingPortal:
1109
- return BlockingPortal()
1110
-
1111
- @classmethod
1112
- async def open_process(
1113
- cls,
1114
- command: StrOrBytesPath | Sequence[StrOrBytesPath],
1115
- *,
1116
- stdin: int | IO[Any] | None,
1117
- stdout: int | IO[Any] | None,
1118
- stderr: int | IO[Any] | None,
1119
- **kwargs: Any,
1120
- ) -> Process:
1121
- def convert_item(item: StrOrBytesPath) -> str:
1122
- str_or_bytes = os.fspath(item)
1123
- if isinstance(str_or_bytes, str):
1124
- return str_or_bytes
1125
- else:
1126
- return os.fsdecode(str_or_bytes)
1127
-
1128
- if isinstance(command, (str, bytes, PathLike)):
1129
- process = await trio.lowlevel.open_process(
1130
- convert_item(command),
1131
- stdin=stdin,
1132
- stdout=stdout,
1133
- stderr=stderr,
1134
- shell=True,
1135
- **kwargs,
1136
- )
1137
- else:
1138
- process = await trio.lowlevel.open_process(
1139
- [convert_item(item) for item in command],
1140
- stdin=stdin,
1141
- stdout=stdout,
1142
- stderr=stderr,
1143
- shell=False,
1144
- **kwargs,
1145
- )
1146
-
1147
- stdin_stream = SendStreamWrapper(process.stdin) if process.stdin else None
1148
- stdout_stream = ReceiveStreamWrapper(process.stdout) if process.stdout else None
1149
- stderr_stream = ReceiveStreamWrapper(process.stderr) if process.stderr else None
1150
- return Process(process, stdin_stream, stdout_stream, stderr_stream)
1151
-
1152
- @classmethod
1153
- def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None:
1154
- trio.lowlevel.spawn_system_task(_shutdown_process_pool, workers)
1155
-
1156
- @classmethod
1157
- async def connect_tcp(
1158
- cls, host: str, port: int, local_address: IPSockAddrType | None = None
1159
- ) -> SocketStream:
1160
- family = socket.AF_INET6 if ":" in host else socket.AF_INET
1161
- trio_socket = trio.socket.socket(family)
1162
- trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
1163
- if local_address:
1164
- await trio_socket.bind(local_address)
1165
-
1166
- try:
1167
- await trio_socket.connect((host, port))
1168
- except BaseException:
1169
- trio_socket.close()
1170
- raise
1171
-
1172
- return SocketStream(trio_socket)
1173
-
1174
- @classmethod
1175
- async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream:
1176
- trio_socket = trio.socket.socket(socket.AF_UNIX)
1177
- try:
1178
- await trio_socket.connect(path)
1179
- except BaseException:
1180
- trio_socket.close()
1181
- raise
1182
-
1183
- return UNIXSocketStream(trio_socket)
1184
-
1185
- @classmethod
1186
- def create_tcp_listener(cls, sock: socket.socket) -> abc.SocketListener:
1187
- return TCPSocketListener(sock)
1188
-
1189
- @classmethod
1190
- def create_unix_listener(cls, sock: socket.socket) -> abc.SocketListener:
1191
- return UNIXSocketListener(sock)
1192
-
1193
- @classmethod
1194
- async def create_udp_socket(
1195
- cls,
1196
- family: socket.AddressFamily,
1197
- local_address: IPSockAddrType | None,
1198
- remote_address: IPSockAddrType | None,
1199
- reuse_port: bool,
1200
- ) -> UDPSocket | ConnectedUDPSocket:
1201
- trio_socket = trio.socket.socket(family=family, type=socket.SOCK_DGRAM)
1202
-
1203
- if reuse_port:
1204
- trio_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
1205
-
1206
- if local_address:
1207
- await trio_socket.bind(local_address)
1208
-
1209
- if remote_address:
1210
- await trio_socket.connect(remote_address)
1211
- return ConnectedUDPSocket(trio_socket)
1212
- else:
1213
- return UDPSocket(trio_socket)
1214
-
1215
- @classmethod
1216
- @overload
1217
- async def create_unix_datagram_socket(
1218
- cls, raw_socket: socket.socket, remote_path: None
1219
- ) -> abc.UNIXDatagramSocket: ...
1220
-
1221
- @classmethod
1222
- @overload
1223
- async def create_unix_datagram_socket(
1224
- cls, raw_socket: socket.socket, remote_path: str | bytes
1225
- ) -> abc.ConnectedUNIXDatagramSocket: ...
1226
-
1227
- @classmethod
1228
- async def create_unix_datagram_socket(
1229
- cls, raw_socket: socket.socket, remote_path: str | bytes | None
1230
- ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket:
1231
- trio_socket = trio.socket.from_stdlib_socket(raw_socket)
1232
-
1233
- if remote_path:
1234
- await trio_socket.connect(remote_path)
1235
- return ConnectedUNIXDatagramSocket(trio_socket)
1236
- else:
1237
- return UNIXDatagramSocket(trio_socket)
1238
-
1239
- @classmethod
1240
- async def getaddrinfo(
1241
- cls,
1242
- host: bytes | str | None,
1243
- port: str | int | None,
1244
- *,
1245
- family: int | AddressFamily = 0,
1246
- type: int | SocketKind = 0,
1247
- proto: int = 0,
1248
- flags: int = 0,
1249
- ) -> Sequence[
1250
- tuple[
1251
- AddressFamily,
1252
- SocketKind,
1253
- int,
1254
- str,
1255
- tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
1256
- ]
1257
- ]:
1258
- return await trio.socket.getaddrinfo(host, port, family, type, proto, flags)
1259
-
1260
- @classmethod
1261
- async def getnameinfo(
1262
- cls, sockaddr: IPSockAddrType, flags: int = 0
1263
- ) -> tuple[str, str]:
1264
- return await trio.socket.getnameinfo(sockaddr, flags)
1265
-
1266
- @classmethod
1267
- async def wait_readable(cls, obj: HasFileno | int) -> None:
1268
- try:
1269
- await wait_readable(obj)
1270
- except trio.ClosedResourceError as exc:
1271
- raise ClosedResourceError().with_traceback(exc.__traceback__) from None
1272
- except trio.BusyResourceError:
1273
- raise BusyResourceError("reading from") from None
1274
-
1275
- @classmethod
1276
- async def wait_writable(cls, obj: HasFileno | int) -> None:
1277
- try:
1278
- await wait_writable(obj)
1279
- except trio.ClosedResourceError as exc:
1280
- raise ClosedResourceError().with_traceback(exc.__traceback__) from None
1281
- except trio.BusyResourceError:
1282
- raise BusyResourceError("writing to") from None
1283
-
1284
- @classmethod
1285
- def current_default_thread_limiter(cls) -> CapacityLimiter:
1286
- try:
1287
- return _capacity_limiter_wrapper.get()
1288
- except LookupError:
1289
- limiter = CapacityLimiter(
1290
- original=trio.to_thread.current_default_thread_limiter()
1291
- )
1292
- _capacity_limiter_wrapper.set(limiter)
1293
- return limiter
1294
-
1295
- @classmethod
1296
- def open_signal_receiver(
1297
- cls, *signals: Signals
1298
- ) -> AbstractContextManager[AsyncIterator[Signals]]:
1299
- return _SignalReceiver(signals)
1300
-
1301
- @classmethod
1302
- def get_current_task(cls) -> TaskInfo:
1303
- task = current_task()
1304
- return TrioTaskInfo(task)
1305
-
1306
- @classmethod
1307
- def get_running_tasks(cls) -> Sequence[TaskInfo]:
1308
- root_task = current_root_task()
1309
- assert root_task
1310
- task_infos = [TrioTaskInfo(root_task)]
1311
- nurseries = root_task.child_nurseries
1312
- while nurseries:
1313
- new_nurseries: list[trio.Nursery] = []
1314
- for nursery in nurseries:
1315
- for task in nursery.child_tasks:
1316
- task_infos.append(TrioTaskInfo(task))
1317
- new_nurseries.extend(task.child_nurseries)
1318
-
1319
- nurseries = new_nurseries
1320
-
1321
- return task_infos
1322
-
1323
- @classmethod
1324
- async def wait_all_tasks_blocked(cls) -> None:
1325
- from trio.testing import wait_all_tasks_blocked
1326
-
1327
- await wait_all_tasks_blocked()
1328
-
1329
- @classmethod
1330
- def create_test_runner(cls, options: dict[str, Any]) -> TestRunner:
1331
- return TestRunner(**options)
1332
-
1333
-
1334
- backend_class = TrioBackend
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
venv/Lib/site-packages/anyio/_core/__init__.py DELETED
File without changes
venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-311.pyc DELETED
Binary file (221 Bytes)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-311.pyc DELETED
Binary file (9.12 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_eventloop.cpython-311.pyc DELETED
Binary file (6.96 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-311.pyc DELETED
Binary file (7.23 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-311.pyc DELETED
Binary file (42.2 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_resources.cpython-311.pyc DELETED
Binary file (1.15 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_signals.cpython-311.pyc DELETED
Binary file (1.39 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-311.pyc DELETED
Binary file (32.7 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-311.pyc DELETED
Binary file (2.69 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_subprocesses.cpython-311.pyc DELETED
Binary file (9.85 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-311.pyc DELETED
Binary file (35.7 kB)
 
venv/Lib/site-packages/anyio/_core/__pycache__/_tasks.cpython-311.pyc DELETED
Binary file (7.73 kB)