itruonghai commited on
Commit
5f610e6
·
verified ·
1 Parent(s): 75b362d

Upload folder using huggingface_hub (part 3)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +51 -0
  2. .venvs/kimodo/lib/python3.10/site-packages/antlr4_python3_runtime-4.9.3.dist-info/WHEEL +5 -0
  3. .venvs/kimodo/lib/python3.10/site-packages/antlr4_python3_runtime-4.9.3.dist-info/top_level.txt +1 -0
  4. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/INSTALLER +1 -0
  5. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/METADATA +108 -0
  6. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/RECORD +55 -0
  7. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/REQUESTED +0 -0
  8. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/WHEEL +5 -0
  9. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/entry_points.txt +2 -0
  10. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/licenses/LICENSE +20 -0
  11. .venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/top_level.txt +1 -0
  12. .venvs/kimodo/lib/python3.10/site-packages/anyio/__init__.py +154 -0
  13. .venvs/kimodo/lib/python3.10/site-packages/anyio/__pycache__/__init__.cpython-310.pyc +0 -0
  14. .venvs/kimodo/lib/python3.10/site-packages/anyio/__pycache__/_lazyimport.cpython-310.pyc +0 -0
  15. .venvs/kimodo/lib/python3.10/site-packages/anyio/_backends/__init__.py +0 -0
  16. .venvs/kimodo/lib/python3.10/site-packages/anyio/_backends/_asyncio.py +0 -0
  17. .venvs/kimodo/lib/python3.10/site-packages/anyio/_backends/_trio.py +1473 -0
  18. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/__init__.py +0 -0
  19. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_asyncio_selector_thread.py +167 -0
  20. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_concurrency_utils.py +156 -0
  21. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_contextmanagers.py +200 -0
  22. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_eventloop.py +240 -0
  23. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_exceptions.py +205 -0
  24. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_fileio.py +1045 -0
  25. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_futures.py +191 -0
  26. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_resources.py +18 -0
  27. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_signals.py +29 -0
  28. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_sockets.py +1011 -0
  29. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_streams.py +52 -0
  30. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_subprocesses.py +196 -0
  31. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_synchronization.py +778 -0
  32. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_tasks.py +464 -0
  33. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_tempfile.py +615 -0
  34. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_testing.py +82 -0
  35. .venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_typedattr.py +85 -0
  36. .venvs/kimodo/lib/python3.10/site-packages/anyio/_lazyimport.py +176 -0
  37. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/__init__.py +63 -0
  38. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_eventloop.py +428 -0
  39. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_resources.py +39 -0
  40. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_sockets.py +401 -0
  41. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_streams.py +237 -0
  42. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_subprocesses.py +82 -0
  43. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_tasks.py +223 -0
  44. .venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_testing.py +79 -0
  45. .venvs/kimodo/lib/python3.10/site-packages/anyio/from_thread.py +588 -0
  46. .venvs/kimodo/lib/python3.10/site-packages/anyio/functools.py +400 -0
  47. .venvs/kimodo/lib/python3.10/site-packages/anyio/itertools.py +629 -0
  48. .venvs/kimodo/lib/python3.10/site-packages/anyio/lowlevel.py +228 -0
  49. .venvs/kimodo/lib/python3.10/site-packages/anyio/py.typed +0 -0
  50. .venvs/kimodo/lib/python3.10/site-packages/anyio/pytest_plugin.py +404 -0
.gitattributes CHANGED
@@ -55,3 +55,54 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
55
  .venvs/kimodo/lib/python3.10/site-packages/_brotli.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
56
  .venvs/kimodo/lib/python3.10/site-packages/accelerate/__pycache__/accelerator.cpython-310.pyc filter=lfs diff=lfs merge=lfs -text
57
  .venvs/kimodo/lib/python3.10/site-packages/accelerate/utils/__pycache__/dataclasses.cpython-310.pyc filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  .venvs/kimodo/lib/python3.10/site-packages/_brotli.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
56
  .venvs/kimodo/lib/python3.10/site-packages/accelerate/__pycache__/accelerator.cpython-310.pyc filter=lfs diff=lfs merge=lfs -text
57
  .venvs/kimodo/lib/python3.10/site-packages/accelerate/utils/__pycache__/dataclasses.cpython-310.pyc filter=lfs diff=lfs merge=lfs -text
58
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libSvtAv1Enc.4.1.0.dylib filter=lfs diff=lfs merge=lfs -text
59
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libavcodec.62.28.101.dylib filter=lfs diff=lfs merge=lfs -text
60
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libavdevice.62.3.101.dylib filter=lfs diff=lfs merge=lfs -text
61
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libavfilter.11.14.101.dylib filter=lfs diff=lfs merge=lfs -text
62
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libavformat.62.12.101.dylib filter=lfs diff=lfs merge=lfs -text
63
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libavutil.60.26.101.dylib filter=lfs diff=lfs merge=lfs -text
64
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libdav1d.7.dylib filter=lfs diff=lfs merge=lfs -text
65
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libmp3lame.0.dylib filter=lfs diff=lfs merge=lfs -text
66
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libopencore-amrnb.0.dylib filter=lfs diff=lfs merge=lfs -text
67
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libopencore-amrwb.0.dylib filter=lfs diff=lfs merge=lfs -text
68
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libopus.0.dylib filter=lfs diff=lfs merge=lfs -text
69
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libswresample.6.3.101.dylib filter=lfs diff=lfs merge=lfs -text
70
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libswscale.9.5.101.dylib filter=lfs diff=lfs merge=lfs -text
71
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libvpx.12.dylib filter=lfs diff=lfs merge=lfs -text
72
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libwebp.7.2.0.dylib filter=lfs diff=lfs merge=lfs -text
73
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libx264.165.dylib filter=lfs diff=lfs merge=lfs -text
74
+ .venvs/kimodo/lib/python3.10/site-packages/av/.dylibs/libx265.216.dylib filter=lfs diff=lfs merge=lfs -text
75
+ .venvs/kimodo/lib/python3.10/site-packages/av/audio/codeccontext.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
76
+ .venvs/kimodo/lib/python3.10/site-packages/av/audio/fifo.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
77
+ .venvs/kimodo/lib/python3.10/site-packages/av/audio/format.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
78
+ .venvs/kimodo/lib/python3.10/site-packages/av/audio/frame.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
79
+ .venvs/kimodo/lib/python3.10/site-packages/av/audio/layout.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
80
+ .venvs/kimodo/lib/python3.10/site-packages/av/audio/resampler.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
81
+ .venvs/kimodo/lib/python3.10/site-packages/av/audio/stream.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
82
+ .venvs/kimodo/lib/python3.10/site-packages/av/bitstream.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
83
+ .venvs/kimodo/lib/python3.10/site-packages/av/buffer.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
84
+ .venvs/kimodo/lib/python3.10/site-packages/av/codec/codec.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
85
+ .venvs/kimodo/lib/python3.10/site-packages/av/codec/context.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
86
+ .venvs/kimodo/lib/python3.10/site-packages/av/codec/hwaccel.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
87
+ .venvs/kimodo/lib/python3.10/site-packages/av/container/core.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
88
+ .venvs/kimodo/lib/python3.10/site-packages/av/container/input.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
89
+ .venvs/kimodo/lib/python3.10/site-packages/av/container/output.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
90
+ .venvs/kimodo/lib/python3.10/site-packages/av/container/pyio.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
91
+ .venvs/kimodo/lib/python3.10/site-packages/av/container/streams.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
92
+ .venvs/kimodo/lib/python3.10/site-packages/av/device.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
93
+ .venvs/kimodo/lib/python3.10/site-packages/av/dictionary.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
94
+ .venvs/kimodo/lib/python3.10/site-packages/av/error.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
95
+ .venvs/kimodo/lib/python3.10/site-packages/av/filter/context.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
96
+ .venvs/kimodo/lib/python3.10/site-packages/av/filter/graph.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
97
+ .venvs/kimodo/lib/python3.10/site-packages/av/filter/link.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
98
+ .venvs/kimodo/lib/python3.10/site-packages/av/filter/loudnorm.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
99
+ .venvs/kimodo/lib/python3.10/site-packages/av/format.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
100
+ .venvs/kimodo/lib/python3.10/site-packages/av/frame.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
101
+ .venvs/kimodo/lib/python3.10/site-packages/av/index.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
102
+ .venvs/kimodo/lib/python3.10/site-packages/av/logging.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
103
+ .venvs/kimodo/lib/python3.10/site-packages/av/packet.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
104
+ .venvs/kimodo/lib/python3.10/site-packages/av/plane.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
105
+ .venvs/kimodo/lib/python3.10/site-packages/av/sidedata/encparams.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
106
+ .venvs/kimodo/lib/python3.10/site-packages/av/sidedata/motionvectors.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
107
+ .venvs/kimodo/lib/python3.10/site-packages/av/sidedata/sidedata.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
108
+ .venvs/kimodo/lib/python3.10/site-packages/av/stream.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
.venvs/kimodo/lib/python3.10/site-packages/antlr4_python3_runtime-4.9.3.dist-info/WHEEL ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
.venvs/kimodo/lib/python3.10/site-packages/antlr4_python3_runtime-4.9.3.dist-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ antlr4
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ uv
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/METADATA ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: anyio
3
+ Version: 4.15.1
4
+ Summary: High-level concurrency and networking framework on top of asyncio or Trio
5
+ Author-email: Alex Grönholm <alex.gronholm@nextday.fi>
6
+ License-Expression: 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: Framework :: AnyIO
14
+ Classifier: Typing :: Typed
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
23
+ Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/x-rst
26
+ License-File: LICENSE
27
+ Requires-Dist: exceptiongroup>=1.0.2; python_version < "3.11"
28
+ Requires-Dist: idna>=2.8
29
+ Requires-Dist: typing_extensions>=4.16.0; python_version < "3.15"
30
+ Provides-Extra: trio
31
+ Requires-Dist: trio>=0.32.0; extra == "trio"
32
+ Dynamic: license-file
33
+
34
+ .. image:: https://github.com/agronholm/anyio/actions/workflows/test.yml/badge.svg
35
+ :target: https://github.com/agronholm/anyio/actions/workflows/test.yml
36
+ :alt: Build Status
37
+ .. image:: https://coveralls.io/repos/github/agronholm/anyio/badge.svg?branch=master
38
+ :target: https://coveralls.io/github/agronholm/anyio?branch=master
39
+ :alt: Code Coverage
40
+ .. image:: https://readthedocs.org/projects/anyio/badge/?version=latest
41
+ :target: https://anyio.readthedocs.io/en/latest/?badge=latest
42
+ :alt: Documentation
43
+ .. image:: https://badges.gitter.im/gitterHQ/gitter.svg
44
+ :target: https://gitter.im/python-trio/AnyIO
45
+ :alt: Gitter chat
46
+ .. image:: https://tidelift.com/badges/package/pypi/anyio
47
+ :target: https://tidelift.com/subscription/pkg/pypi-anyio
48
+ :alt: Tidelift
49
+
50
+ AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio_ or
51
+ Trio_. It implements Trio-like `structured concurrency`_ (SC) on top of asyncio and works in harmony
52
+ with the native SC of Trio itself.
53
+
54
+ Applications and libraries written against AnyIO's API will run unmodified on either asyncio_ or
55
+ Trio_. AnyIO can also be adopted into a library or application incrementally – bit by bit, no full
56
+ refactoring necessary. It will blend in with the native libraries of your chosen backend.
57
+
58
+ To find out why you might want to use AnyIO's APIs instead of asyncio's, you can read about it
59
+ `here <https://anyio.readthedocs.io/en/stable/why.html>`_.
60
+
61
+ Documentation
62
+ -------------
63
+
64
+ View full documentation at: https://anyio.readthedocs.io/
65
+
66
+ Features
67
+ --------
68
+
69
+ AnyIO offers the following functionality:
70
+
71
+ * Task groups (nurseries_ in trio terminology)
72
+ * High-level networking (TCP, UDP and UNIX sockets)
73
+
74
+ * `Happy eyeballs`_ algorithm for TCP connections (more robust than that of asyncio on Python
75
+ 3.8)
76
+ * async/await style UDP sockets (unlike asyncio where you still have to use Transports and
77
+ Protocols)
78
+
79
+ * A versatile API for byte streams and object streams
80
+ * Inter-task synchronization and communication (locks, conditions, events, semaphores, object
81
+ streams and futures)
82
+ * Worker threads
83
+ * Subprocesses
84
+ * Subinterpreter support for code parallelization (on Python 3.13 and later)
85
+ * Asynchronous file I/O (using worker threads)
86
+ * Signal handling
87
+ * Asynchronous versions of the functools_ and itertools_ modules
88
+
89
+ AnyIO also comes with its own pytest_ plugin which also supports asynchronous fixtures.
90
+ It even works with the popular Hypothesis_ library.
91
+
92
+ .. _asyncio: https://docs.python.org/3/library/asyncio.html
93
+ .. _Trio: https://github.com/python-trio/trio
94
+ .. _structured concurrency: https://en.wikipedia.org/wiki/Structured_concurrency
95
+ .. _nurseries: https://trio.readthedocs.io/en/stable/reference-core.html#nurseries-and-spawning
96
+ .. _Happy eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs
97
+ .. _pytest: https://docs.pytest.org/en/latest/
98
+ .. _functools: https://docs.python.org/3/library/functools.html
99
+ .. _itertools: https://docs.python.org/3/library/itertools.html
100
+ .. _Hypothesis: https://hypothesis.works/
101
+
102
+ Security contact information
103
+ ----------------------------
104
+
105
+ To report a security vulnerability, please use the `Tidelift security contact`_.
106
+ Tidelift will coordinate the fix and disclosure.
107
+
108
+ .. _Tidelift security contact: https://tidelift.com/security
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/RECORD ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ anyio-4.15.1.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
2
+ anyio-4.15.1.dist-info/METADATA,sha256=BDrstXGvcYnopsUo9djjJUXxss36r3YdUebVtn6jyoE,4733
3
+ anyio-4.15.1.dist-info/RECORD,,
4
+ anyio-4.15.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ anyio-4.15.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
6
+ anyio-4.15.1.dist-info/entry_points.txt,sha256=_d6Yu6uiaZmNe0CydowirE9Cmg7zUL2g08tQpoS3Qvc,39
7
+ anyio-4.15.1.dist-info/licenses/LICENSE,sha256=U2GsncWPLvX9LpsJxoKXwX8ElQkJu8gCO9uC6s8iwrA,1081
8
+ anyio-4.15.1.dist-info/top_level.txt,sha256=QglSMiWX8_5dpoVAEIHdEYzvqFMdSYWmCj6tYw2ITkQ,6
9
+ anyio/__init__.py,sha256=OfroYRjIUw_JFj0Zwh1JAaajMQg4VqtoAt0XoOHDRwE,7602
10
+ anyio/_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ anyio/_backends/_asyncio.py,sha256=Vqy7O1ymmEpxTiPzehSuBCVTziGALNV-BbsIRaKXsg4,107767
12
+ anyio/_backends/_trio.py,sha256=Gs8XzX0IeBvje8IEZtJmpNylKCUAChKv7I_YZi3wlmg,45715
13
+ anyio/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ anyio/_core/_asyncio_selector_thread.py,sha256=2PdxFM3cs02Kp6BSppbvmRT7q7asreTW5FgBxEsflBo,5626
15
+ anyio/_core/_concurrency_utils.py,sha256=kvRXMrnDqgQTBkZc-f279-lBnZM4YbSToXqhnAUCfSc,4522
16
+ anyio/_core/_contextmanagers.py,sha256=YInBCabiEeS-UaP_Jdxa1CaFC71ETPW8HZTHIM8Rsc8,7215
17
+ anyio/_core/_eventloop.py,sha256=ByZUeJD9alMfcyTseRo5IzTO0IltEul_Gyq9iqSjqDk,6658
18
+ anyio/_core/_exceptions.py,sha256=B4ZhLkBQT4tI6vShv4-GJui492IJsoIDTw1FQJEkmAI,5618
19
+ anyio/_core/_fileio.py,sha256=q--ft9h5Y_FRLzhAnoYrXf3tOuZ8ZyIN2A9mCfMbZRc,34163
20
+ anyio/_core/_futures.py,sha256=YQq5uhnCnKQMQD62tOLfzEm7dUXY3GQorJdH6ghfgIQ,6177
21
+ anyio/_core/_resources.py,sha256=Ld5duCe9NwgPfI7EIOh3CMIBYQ7rq6ZQEa7CFS0u9Ec,450
22
+ anyio/_core/_signals.py,sha256=mjTBB2hTKNPRlU0IhnijeQedpWOGERDiMjSlJQsFrug,1016
23
+ anyio/_core/_sockets.py,sha256=C8b-3w5H9n0Fo4g7X8WJvk0m6CGh6NVAAFtieBGHK3g,35289
24
+ anyio/_core/_streams.py,sha256=FczFwIgDpnkK0bODWJXMpsUJYdvAD04kaUaGzJU8DK0,1806
25
+ anyio/_core/_subprocesses.py,sha256=TMBuGNILz-47w5t9vayJ1GpCpDT6LxsMohJDFCewIRc,7938
26
+ anyio/_core/_synchronization.py,sha256=ggsd74QPd846faA2HQeT07ONQ5HQ1S78gy8mvB3qCrw,21658
27
+ anyio/_core/_tasks.py,sha256=J2dhM_Jq3Grsfg_enNWpRz2SxfM15uLt-pEfvoQq3uA,15391
28
+ anyio/_core/_tempfile.py,sha256=IgoBCFaPhrFvsF9KHcCcrnCRn-UqMfw0WRdSDWgxAiI,19726
29
+ anyio/_core/_testing.py,sha256=ZRucLh5kqhiFWAJMMbd8yZ6uIvz0rq3WwL72ldosxAU,2340
30
+ anyio/_core/_typedattr.py,sha256=gt9Dzn-IL0QW14aHPDD8PAtq95FYKNNupHyf37xZGPQ,2607
31
+ anyio/_lazyimport.py,sha256=LCjnYanIfYE9G-Dv_EsqNLDuVRppNicWZjCTfS9-sJU,6082
32
+ anyio/abc/__init__.py,sha256=XIVvCI2c6oyaOcqXe94k2rzU5_s7-ZNnlxGTk34H4T0,3050
33
+ anyio/abc/_eventloop.py,sha256=0-UwgB351rkocCt8m3fjTmcNx2Fxn52nUoujG5DzMvU,11127
34
+ anyio/abc/_resources.py,sha256=hrb0LXUgHSp3i8G6W8JJchdzKXgg1m0T-L7udXmv2y0,900
35
+ anyio/abc/_sockets.py,sha256=jQWnPX7iDIDyvyvVkbuFhjezw4oI2WggzbW6Vl2-eqs,13162
36
+ anyio/abc/_streams.py,sha256=IMeOPPutFXRbyeAutxV1HJe7FUQZYp2qKrJJpP1DCv0,7620
37
+ anyio/abc/_subprocesses.py,sha256=CDqU1p0HuBS0pXUzBW_hbfhihTJRM67n__7qZmoPU84,2123
38
+ anyio/abc/_tasks.py,sha256=HBPpT72aOy0bwMAxBCKmnXsR328wCYRjYm3iaVw2fQo,7070
39
+ anyio/abc/_testing.py,sha256=A9Y8RAClIPn1A0aNHBN8YoaRy_MKOpbFGEbTHAXgB6U,2145
40
+ anyio/from_thread.py,sha256=iZZbfcNySi4wAcx1_cxAQE4J0YZC88qRMIYqQ6SF9sc,19415
41
+ anyio/functools.py,sha256=T4JS8IXq-x1S0Lbo2owF8l9fza2KypO147QLeyz4cjs,11797
42
+ anyio/itertools.py,sha256=TS7_UCa2Y3cggtaLlWHbjOyf6QhPfQUdPduNW-ddXTE,16255
43
+ anyio/lowlevel.py,sha256=QyWkvfetbCH0mHkqv1yxGwOaiZ7fyxhpZkHWOXPV5JU,6280
44
+ anyio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
+ anyio/pytest_plugin.py,sha256=oLXyOstvRZW3VVbqIODhZsPt4jSz2UGh44YeG2nJXx0,14516
46
+ anyio/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ anyio/streams/buffered.py,sha256=u7hCD8SNrYHcutG6K5wEiy1F88-pizgjvEFM22Kq2Cw,6746
48
+ anyio/streams/file.py,sha256=6jujI2m-QJITqqKFamrupX_DNsU7y2Fz3omLZxOLuY0,4524
49
+ anyio/streams/memory.py,sha256=rpxNzDMag9PCOynBqN64KyuAfAPB41vFyRP-Npo-lE0,10793
50
+ anyio/streams/stapled.py,sha256=UJ2Rgt0NUmM1VovRNOoZoic960lcbDjb3vhfZg3b_Z0,4845
51
+ anyio/streams/text.py,sha256=BcVAGJw1VRvtIqnv-o0Rb0pwH7p8vwlvl21xHq522ag,5765
52
+ anyio/streams/tls.py,sha256=fqLmxvULFO9rvxGyJ33VPrOIN7E3eiU1q90BkmKigQ8,15818
53
+ anyio/to_interpreter.py,sha256=ATnoT6kei9wDmQZtXTA3SsY4CK7XKr8Ta4_x5i6pbTw,7100
54
+ anyio/to_process.py,sha256=p6n8j0nreJUl1DEkR_9PL6KRoKtNqFxORTn8qZBvn94,9850
55
+ anyio/to_thread.py,sha256=8MPVrrQq8ttGvV21cSd68rMto5bhxJ0-i9CupXag5Gs,2750
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/REQUESTED ADDED
File without changes
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/WHEEL ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/entry_points.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ [pytest11]
2
+ anyio = anyio.pytest_plugin
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/licenses/LICENSE ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.
.venvs/kimodo/lib/python3.10/site-packages/anyio-4.15.1.dist-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ anyio
.venvs/kimodo/lib/python3.10/site-packages/anyio/__init__.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ._lazyimport import (
6
+ fix_package_names,
7
+ install_lazy_importer,
8
+ set_deprecated_aliases,
9
+ )
10
+
11
+ if TYPE_CHECKING or not install_lazy_importer():
12
+ from ._core._concurrency_utils import amap as amap
13
+ from ._core._concurrency_utils import as_completed as as_completed
14
+ from ._core._concurrency_utils import gather as gather
15
+ from ._core._contextmanagers import (
16
+ AsyncContextManagerMixin as AsyncContextManagerMixin,
17
+ )
18
+ from ._core._contextmanagers import ContextManagerMixin as ContextManagerMixin
19
+ from ._core._eventloop import current_time as current_time
20
+ from ._core._eventloop import get_all_backends as get_all_backends
21
+ from ._core._eventloop import get_available_backends as get_available_backends
22
+ from ._core._eventloop import get_cancelled_exc_class as get_cancelled_exc_class
23
+ from ._core._eventloop import run as run
24
+ from ._core._eventloop import sleep as sleep
25
+ from ._core._eventloop import sleep_forever as sleep_forever
26
+ from ._core._eventloop import sleep_until as sleep_until
27
+ from ._core._exceptions import BrokenResourceError as BrokenResourceError
28
+ from ._core._exceptions import BrokenWorkerInterpreter as BrokenWorkerInterpreter
29
+ from ._core._exceptions import BrokenWorkerProcess as BrokenWorkerProcess
30
+ from ._core._exceptions import BusyResourceError as BusyResourceError
31
+ from ._core._exceptions import ClosedResourceError as ClosedResourceError
32
+ from ._core._exceptions import ConnectionFailed as ConnectionFailed
33
+ from ._core._exceptions import DelimiterNotFound as DelimiterNotFound
34
+ from ._core._exceptions import EndOfStream as EndOfStream
35
+ from ._core._exceptions import FutureAlreadyFinished as FutureAlreadyFinished
36
+ from ._core._exceptions import FutureCancelled as FutureCancelled
37
+ from ._core._exceptions import FutureFailed as FutureFailed
38
+ from ._core._exceptions import FutureNotFinished as FutureNotFinished
39
+ from ._core._exceptions import IncompleteRead as IncompleteRead
40
+ from ._core._exceptions import NoEventLoopError as NoEventLoopError
41
+ from ._core._exceptions import RunFinishedError as RunFinishedError
42
+ from ._core._exceptions import TaskCancelled as TaskCancelled
43
+ from ._core._exceptions import TaskFailed as TaskFailed
44
+ from ._core._exceptions import TaskNotFinished as TaskNotFinished
45
+ from ._core._exceptions import (
46
+ TypedAttributeLookupError as TypedAttributeLookupError,
47
+ )
48
+ from ._core._exceptions import WouldBlock as WouldBlock
49
+ from ._core._fileio import AsyncFile as AsyncFile
50
+ from ._core._fileio import Path as Path
51
+ from ._core._fileio import open_file as open_file
52
+ from ._core._fileio import wrap_file as wrap_file
53
+ from ._core._futures import Future as Future
54
+ from ._core._resources import aclose_forcefully as aclose_forcefully
55
+ from ._core._signals import open_signal_receiver as open_signal_receiver
56
+ from ._core._sockets import TCPConnectable as TCPConnectable
57
+ from ._core._sockets import UNIXConnectable as UNIXConnectable
58
+ from ._core._sockets import as_connectable as as_connectable
59
+ from ._core._sockets import connect_tcp as connect_tcp
60
+ from ._core._sockets import connect_unix as connect_unix
61
+ from ._core._sockets import (
62
+ create_connected_udp_socket as create_connected_udp_socket,
63
+ )
64
+ from ._core._sockets import (
65
+ create_connected_unix_datagram_socket as create_connected_unix_datagram_socket,
66
+ )
67
+ from ._core._sockets import create_tcp_listener as create_tcp_listener
68
+ from ._core._sockets import create_udp_socket as create_udp_socket
69
+ from ._core._sockets import (
70
+ create_unix_datagram_socket as create_unix_datagram_socket,
71
+ )
72
+ from ._core._sockets import create_unix_listener as create_unix_listener
73
+ from ._core._sockets import getaddrinfo as getaddrinfo
74
+ from ._core._sockets import getnameinfo as getnameinfo
75
+ from ._core._sockets import notify_closing as notify_closing
76
+ from ._core._sockets import wait_readable as wait_readable
77
+ from ._core._sockets import wait_socket_readable as wait_socket_readable
78
+ from ._core._sockets import wait_socket_writable as wait_socket_writable
79
+ from ._core._sockets import wait_writable as wait_writable
80
+ from ._core._streams import (
81
+ create_memory_object_stream as create_memory_object_stream,
82
+ )
83
+ from ._core._subprocesses import open_process as open_process
84
+ from ._core._subprocesses import run_process as run_process
85
+ from ._core._synchronization import CapacityLimiter as CapacityLimiter
86
+ from ._core._synchronization import (
87
+ CapacityLimiterStatistics as CapacityLimiterStatistics,
88
+ )
89
+ from ._core._synchronization import Condition as Condition
90
+ from ._core._synchronization import ConditionStatistics as ConditionStatistics
91
+ from ._core._synchronization import Event as Event
92
+ from ._core._synchronization import EventStatistics as EventStatistics
93
+ from ._core._synchronization import Lock as Lock
94
+ from ._core._synchronization import LockStatistics as LockStatistics
95
+ from ._core._synchronization import ResourceGuard as ResourceGuard
96
+ from ._core._synchronization import Semaphore as Semaphore
97
+ from ._core._synchronization import SemaphoreStatistics as SemaphoreStatistics
98
+ from ._core._tasks import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED
99
+ from ._core._tasks import CancelScope as CancelScope
100
+ from ._core._tasks import TaskHandle as TaskHandle
101
+ from ._core._tasks import create_task_group as create_task_group
102
+ from ._core._tasks import current_effective_deadline as current_effective_deadline
103
+ from ._core._tasks import fail_after as fail_after
104
+ from ._core._tasks import fail_at as fail_at
105
+ from ._core._tasks import move_on_after as move_on_after
106
+ from ._core._tasks import move_on_at as move_on_at
107
+ from ._core._tempfile import NamedTemporaryFile as NamedTemporaryFile
108
+ from ._core._tempfile import SpooledTemporaryFile as SpooledTemporaryFile
109
+ from ._core._tempfile import TemporaryDirectory as TemporaryDirectory
110
+ from ._core._tempfile import TemporaryFile as TemporaryFile
111
+ from ._core._tempfile import gettempdir as gettempdir
112
+ from ._core._tempfile import gettempdirb as gettempdirb
113
+ from ._core._tempfile import mkdtemp as mkdtemp
114
+ from ._core._tempfile import mkstemp as mkstemp
115
+ from ._core._testing import TaskInfo as TaskInfo
116
+ from ._core._testing import get_current_task as get_current_task
117
+ from ._core._testing import get_running_tasks as get_running_tasks
118
+ from ._core._testing import wait_all_tasks_blocked as wait_all_tasks_blocked
119
+ from ._core._typedattr import TypedAttributeProvider as TypedAttributeProvider
120
+ from ._core._typedattr import TypedAttributeSet as TypedAttributeSet
121
+ from ._core._typedattr import typed_attribute as typed_attribute
122
+
123
+ # ruff: isort: off
124
+ from . import (
125
+ abc as abc,
126
+ )
127
+ from . import (
128
+ from_thread as from_thread,
129
+ )
130
+ from . import (
131
+ functools as functools,
132
+ )
133
+ from . import (
134
+ itertools as itertools,
135
+ )
136
+ from . import (
137
+ lowlevel as lowlevel,
138
+ )
139
+ from . import (
140
+ to_interpreter as to_interpreter,
141
+ )
142
+ from . import (
143
+ to_process as to_process,
144
+ )
145
+ from . import (
146
+ to_thread as to_thread,
147
+ )
148
+
149
+ fix_package_names()
150
+ set_deprecated_aliases(
151
+ {
152
+ "BrokenWorkerIntepreter": "anyio.BrokenWorkerInterpreter",
153
+ }
154
+ )
.venvs/kimodo/lib/python3.10/site-packages/anyio/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (4.71 kB). View file
 
.venvs/kimodo/lib/python3.10/site-packages/anyio/__pycache__/_lazyimport.cpython-310.pyc ADDED
Binary file (5.02 kB). View file
 
.venvs/kimodo/lib/python3.10/site-packages/anyio/_backends/__init__.py ADDED
File without changes
.venvs/kimodo/lib/python3.10/site-packages/anyio/_backends/_asyncio.py ADDED
The diff for this file is too large to render. See raw diff
 
.venvs/kimodo/lib/python3.10/site-packages/anyio/_backends/_trio.py ADDED
@@ -0,0 +1,1473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 contextlib import AbstractContextManager
21
+ from contextvars import Context
22
+ from dataclasses import dataclass
23
+ from functools import partial, wraps
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
+ Literal,
35
+ NoReturn,
36
+ ParamSpec,
37
+ TypeVar,
38
+ cast,
39
+ overload,
40
+ )
41
+
42
+ import trio.from_thread
43
+ import trio.lowlevel
44
+ from outcome import Error, Outcome, Value
45
+ from trio.lowlevel import (
46
+ current_root_task,
47
+ current_task,
48
+ notify_closing,
49
+ wait_readable,
50
+ wait_writable,
51
+ )
52
+ from trio.socket import SocketType as TrioSocketType
53
+ from trio.to_thread import run_sync
54
+
55
+ from .. import (
56
+ CapacityLimiterStatistics,
57
+ EventStatistics,
58
+ LockStatistics,
59
+ RunFinishedError,
60
+ TaskInfo,
61
+ WouldBlock,
62
+ abc,
63
+ )
64
+ from .._core._eventloop import claim_worker_thread
65
+ from .._core._exceptions import (
66
+ BrokenResourceError,
67
+ BusyResourceError,
68
+ ClosedResourceError,
69
+ EndOfStream,
70
+ )
71
+ from .._core._sockets import convert_ipv6_sockaddr
72
+ from .._core._streams import create_memory_object_stream
73
+ from .._core._synchronization import (
74
+ CapacityLimiter as BaseCapacityLimiter,
75
+ )
76
+ from .._core._synchronization import Event as BaseEvent
77
+ from .._core._synchronization import Lock as BaseLock
78
+ from .._core._synchronization import (
79
+ ResourceGuard,
80
+ SemaphoreStatistics,
81
+ )
82
+ from .._core._synchronization import Semaphore as BaseSemaphore
83
+ from .._core._tasks import CancelScope as BaseCancelScope
84
+ from .._core._tasks import TaskHandle
85
+ from ..abc import IPSockAddrType, UDPPacketType, UNIXDatagramPacketType
86
+ from ..abc._eventloop import AsyncBackend, StrOrBytesPath
87
+ from ..abc._tasks import T_contra, call_for_coroutine, get_callable_name, get_coro_name
88
+
89
+ if TYPE_CHECKING:
90
+ from _typeshed import FileDescriptorLike
91
+
92
+ from ..streams.memory import MemoryObjectSendStream
93
+
94
+ if sys.version_info < (3, 15):
95
+ from typing_extensions import sentinel
96
+
97
+ if sys.version_info >= (3, 11):
98
+ from typing import Self, TypeVarTuple, Unpack
99
+ else:
100
+ from exceptiongroup import BaseExceptionGroup
101
+ from typing_extensions import Self, TypeVarTuple, Unpack
102
+
103
+ T = TypeVar("T")
104
+ T_Retval = TypeVar("T_Retval")
105
+ T_co = TypeVar("T_co", covariant=True)
106
+ T_SockAddr = TypeVar("T_SockAddr", str, IPSockAddrType)
107
+ PosArgsT = TypeVarTuple("PosArgsT")
108
+ P = ParamSpec("P")
109
+
110
+
111
+ def ensure_returns_coro(
112
+ func: Callable[P, Awaitable[T_Retval]],
113
+ ) -> Callable[P, Coroutine[Any, Any, T_Retval]]:
114
+ @wraps(func)
115
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> Coroutine[Any, Any, T_Retval]:
116
+ awaitable = func(*args, **kwargs)
117
+ # Check the common case first.
118
+ if isinstance(awaitable, Coroutine):
119
+ return awaitable
120
+ elif not isinstance(awaitable, Awaitable):
121
+ # The user violated the type annotations. Still, we should pass this on to
122
+ # Trio so it can raise with an appropriate message.
123
+ return awaitable
124
+ else:
125
+
126
+ @wraps(func)
127
+ async def inner_wrapper() -> T_Retval:
128
+ return await awaitable
129
+
130
+ return inner_wrapper()
131
+
132
+ return wrapper
133
+
134
+
135
+ #
136
+ # Event loop
137
+ #
138
+
139
+ RunVar = trio.lowlevel.RunVar
140
+
141
+
142
+ #
143
+ # Timeouts and cancellation
144
+ #
145
+
146
+
147
+ class CancelScope(BaseCancelScope):
148
+ __slots__ = ("__original",)
149
+
150
+ def __new__(
151
+ cls, original: trio.CancelScope | None = None, **kwargs: object
152
+ ) -> Self:
153
+ return object.__new__(cls)
154
+
155
+ def __init__(self, original: trio.CancelScope | None = None, **kwargs: Any) -> None:
156
+ self.__original = original or trio.CancelScope(**kwargs)
157
+
158
+ def __enter__(self) -> Self:
159
+ self.__original.__enter__()
160
+ return self
161
+
162
+ def __exit__(
163
+ self,
164
+ exc_type: type[BaseException] | None,
165
+ exc_val: BaseException | None,
166
+ exc_tb: TracebackType | None,
167
+ ) -> bool:
168
+ return self.__original.__exit__(exc_type, exc_val, exc_tb)
169
+
170
+ def cancel(self, reason: str | None = None) -> None:
171
+ self.__original.cancel(reason)
172
+
173
+ @property
174
+ def deadline(self) -> float:
175
+ return self.__original.deadline
176
+
177
+ @deadline.setter
178
+ def deadline(self, value: float) -> None:
179
+ self.__original.deadline = value
180
+
181
+ @property
182
+ def cancel_called(self) -> bool:
183
+ return self.__original.cancel_called
184
+
185
+ @property
186
+ def cancelled_caught(self) -> bool:
187
+ return self.__original.cancelled_caught
188
+
189
+ @property
190
+ def shield(self) -> bool:
191
+ return self.__original.shield
192
+
193
+ @shield.setter
194
+ def shield(self, value: bool) -> None:
195
+ self.__original.shield = value
196
+
197
+
198
+ #
199
+ # Task groups
200
+ #
201
+
202
+ empty_start_value = sentinel("empty_start_value")
203
+
204
+
205
+ class _TrioTaskStatus(abc.TaskStatus[T_contra], Generic[T_contra]):
206
+ early_start_value: T_contra | object = empty_start_value
207
+ real_task_status: trio.TaskStatus[T_contra | None] | None = None
208
+
209
+ def started(self, value: T_contra | None = None) -> None:
210
+ if self.real_task_status is None:
211
+ if self.early_start_value is not empty_start_value:
212
+ raise RuntimeError("called 'started' twice on the same task status")
213
+
214
+ self.early_start_value = value
215
+ else:
216
+ self.real_task_status.started(value)
217
+
218
+
219
+ class TaskGroup(abc.TaskGroup):
220
+ def __init__(self) -> None:
221
+ self._entered = False
222
+ self._active = False
223
+ self._nursery_manager = trio.open_nursery(strict_exception_groups=True)
224
+ self.cancel_scope = None # type: ignore[assignment]
225
+
226
+ async def __aenter__(self) -> Self:
227
+ if self._entered:
228
+ raise RuntimeError("TaskGroup cannot be entered more than once")
229
+
230
+ self._entered = True
231
+ self._active = True
232
+ self._nursery = await self._nursery_manager.__aenter__()
233
+ self.cancel_scope = CancelScope(self._nursery.cancel_scope)
234
+ return self
235
+
236
+ async def __aexit__(
237
+ self,
238
+ exc_type: type[BaseException] | None,
239
+ exc_val: BaseException | None,
240
+ exc_tb: TracebackType | None,
241
+ ) -> bool:
242
+ try:
243
+ # trio.Nursery.__exit__ returns bool; .open_nursery has wrong type
244
+ return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) # type: ignore[return-value]
245
+ except BaseExceptionGroup as exc:
246
+ if not exc.split(trio.Cancelled)[1]:
247
+ raise trio.Cancelled._create() from exc
248
+
249
+ raise
250
+ finally:
251
+ del exc_val, exc_tb
252
+ self._active = False
253
+
254
+ def _check_active(self, coro: Coroutine | None = None) -> None:
255
+ if not self._active:
256
+ if coro is not None:
257
+ coro.close()
258
+
259
+ raise RuntimeError(
260
+ "This task group is not active; no new tasks can be started."
261
+ )
262
+
263
+ def create_task(
264
+ self,
265
+ coro: Coroutine[Any, Any, T_co],
266
+ *,
267
+ name: object = None,
268
+ context: Context | None = None,
269
+ ) -> TaskHandle[T_co]:
270
+ if not isinstance(coro, Coroutine):
271
+ raise TypeError(f"expected a coroutine, got {coro.__class__.__qualname__}")
272
+
273
+ self._check_active(coro)
274
+ final_name = get_coro_name(coro, name)
275
+ handle = TaskHandle(coro, final_name)
276
+ if context is not None:
277
+ context.run(
278
+ partial(self._nursery.start_soon, handle._run_coro, name=handle.name)
279
+ )
280
+ else:
281
+ self._nursery.start_soon(handle._run_coro, name=handle.name)
282
+
283
+ return handle
284
+
285
+ async def start(
286
+ self,
287
+ func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]],
288
+ *args: Unpack[PosArgsT],
289
+ name: object = None,
290
+ return_handle: Literal[False, True] = False,
291
+ ) -> Any:
292
+ handle: TaskHandle[T_co]
293
+
294
+ async def run_coro_with_task_status(
295
+ *, task_status: trio.TaskStatus[Any]
296
+ ) -> None:
297
+ nonlocal handle
298
+ wrapper_task_status = _TrioTaskStatus()
299
+ coro = call_for_coroutine(func, args, task_status=wrapper_task_status)
300
+ if wrapper_task_status.early_start_value is not empty_start_value:
301
+ task_status.started(wrapper_task_status.early_start_value)
302
+ else:
303
+ wrapper_task_status.real_task_status = task_status
304
+
305
+ handle = TaskHandle(coro, final_name)
306
+ await handle._run_coro()
307
+
308
+ self._check_active()
309
+ final_name = get_callable_name(func, name)
310
+ start_value = await self._nursery.start(
311
+ run_coro_with_task_status, name=final_name
312
+ )
313
+ if return_handle:
314
+ handle._start_value = start_value
315
+ return handle
316
+ else:
317
+ return start_value
318
+
319
+
320
+ #
321
+ # Subprocesses
322
+ #
323
+
324
+
325
+ @dataclass(eq=False)
326
+ class ReceiveStreamWrapper(abc.ByteReceiveStream):
327
+ _stream: trio.abc.ReceiveStream
328
+
329
+ async def receive(self, max_bytes: int | None = None) -> bytes:
330
+ if max_bytes is not None and max_bytes < 1:
331
+ raise ValueError("max_bytes must be a positive integer")
332
+
333
+ try:
334
+ data = await self._stream.receive_some(max_bytes)
335
+ except trio.ClosedResourceError as exc:
336
+ raise ClosedResourceError from exc.__cause__
337
+ except trio.BrokenResourceError as exc:
338
+ raise BrokenResourceError from exc.__cause__
339
+
340
+ if data:
341
+ return bytes(data)
342
+ else:
343
+ raise EndOfStream
344
+
345
+ async def aclose(self) -> None:
346
+ await self._stream.aclose()
347
+
348
+
349
+ @dataclass(eq=False)
350
+ class SendStreamWrapper(abc.ByteSendStream):
351
+ _stream: trio.abc.SendStream
352
+
353
+ async def send(self, item: bytes) -> None:
354
+ try:
355
+ await self._stream.send_all(item)
356
+ except trio.ClosedResourceError as exc:
357
+ raise ClosedResourceError from exc.__cause__
358
+ except trio.BrokenResourceError as exc:
359
+ raise BrokenResourceError from exc.__cause__
360
+
361
+ async def aclose(self) -> None:
362
+ await self._stream.aclose()
363
+
364
+
365
+ @dataclass(eq=False)
366
+ class Process(abc.Process):
367
+ _process: trio.Process
368
+ _stdin: abc.ByteSendStream | None
369
+ _stdout: abc.ByteReceiveStream | None
370
+ _stderr: abc.ByteReceiveStream | None
371
+
372
+ async def aclose(self) -> None:
373
+ with CancelScope(shield=True):
374
+ if self._stdin:
375
+ await self._stdin.aclose()
376
+ if self._stdout:
377
+ await self._stdout.aclose()
378
+ if self._stderr:
379
+ await self._stderr.aclose()
380
+
381
+ try:
382
+ await self.wait()
383
+ except BaseException:
384
+ self.kill()
385
+ with CancelScope(shield=True):
386
+ await self.wait()
387
+ raise
388
+
389
+ async def wait(self) -> int:
390
+ return await self._process.wait()
391
+
392
+ def terminate(self) -> None:
393
+ self._process.terminate()
394
+
395
+ def kill(self) -> None:
396
+ self._process.kill()
397
+
398
+ def send_signal(self, signal: Signals) -> None:
399
+ self._process.send_signal(signal)
400
+
401
+ @property
402
+ def pid(self) -> int:
403
+ return self._process.pid
404
+
405
+ @property
406
+ def returncode(self) -> int | None:
407
+ return self._process.returncode
408
+
409
+ @property
410
+ def stdin(self) -> abc.ByteSendStream | None:
411
+ return self._stdin
412
+
413
+ @property
414
+ def stdout(self) -> abc.ByteReceiveStream | None:
415
+ return self._stdout
416
+
417
+ @property
418
+ def stderr(self) -> abc.ByteReceiveStream | None:
419
+ return self._stderr
420
+
421
+
422
+ class _ProcessPoolShutdownInstrument(trio.abc.Instrument):
423
+ def after_run(self) -> None:
424
+ super().after_run()
425
+
426
+
427
+ current_default_worker_process_limiter: trio.lowlevel.RunVar = RunVar(
428
+ "current_default_worker_process_limiter"
429
+ )
430
+
431
+
432
+ async def _shutdown_process_pool(workers: set[abc.Process]) -> None:
433
+ try:
434
+ await trio.sleep(math.inf)
435
+ except trio.Cancelled:
436
+ for process in workers:
437
+ if process.returncode is None:
438
+ process.kill()
439
+
440
+ with CancelScope(shield=True):
441
+ for process in workers:
442
+ await process.aclose()
443
+
444
+
445
+ #
446
+ # Sockets and networking
447
+ #
448
+
449
+
450
+ class _TrioSocketMixin(Generic[T_SockAddr]):
451
+ def __init__(self, trio_socket: TrioSocketType) -> None:
452
+ self._trio_socket = trio_socket
453
+ self._closed = False
454
+
455
+ def _check_closed(self) -> None:
456
+ if self._closed:
457
+ raise ClosedResourceError
458
+ if self._trio_socket.fileno() < 0:
459
+ raise BrokenResourceError
460
+
461
+ @property
462
+ def _raw_socket(self) -> socket.socket:
463
+ return self._trio_socket._sock # type: ignore[attr-defined]
464
+
465
+ async def aclose(self) -> None:
466
+ if self._trio_socket.fileno() >= 0:
467
+ self._closed = True
468
+ self._trio_socket.close()
469
+
470
+ def _convert_socket_error(self, exc: BaseException) -> NoReturn:
471
+ if isinstance(exc, trio.ClosedResourceError):
472
+ raise ClosedResourceError from exc
473
+ elif self._trio_socket.fileno() < 0 and self._closed:
474
+ raise ClosedResourceError from None
475
+ elif isinstance(exc, OSError):
476
+ raise BrokenResourceError from exc
477
+ else:
478
+ raise exc
479
+
480
+
481
+ class SocketStream(_TrioSocketMixin, abc.SocketStream):
482
+ def __init__(self, trio_socket: TrioSocketType) -> None:
483
+ super().__init__(trio_socket)
484
+ self._receive_guard = ResourceGuard("reading from")
485
+ self._send_guard = ResourceGuard("writing to")
486
+
487
+ async def receive(self, max_bytes: int = 65536) -> bytes:
488
+ if max_bytes < 1:
489
+ raise ValueError("max_bytes must be a positive integer")
490
+
491
+ with self._receive_guard:
492
+ try:
493
+ data = await self._trio_socket.recv(max_bytes)
494
+ except BaseException as exc:
495
+ self._convert_socket_error(exc)
496
+
497
+ if data:
498
+ return data
499
+ else:
500
+ raise EndOfStream
501
+
502
+ async def send(self, item: bytes) -> None:
503
+ with self._send_guard:
504
+ view = memoryview(item)
505
+ while view:
506
+ try:
507
+ bytes_sent = await self._trio_socket.send(view)
508
+ except BaseException as exc:
509
+ self._convert_socket_error(exc)
510
+
511
+ view = view[bytes_sent:]
512
+
513
+ async def send_eof(self) -> None:
514
+ self._trio_socket.shutdown(socket.SHUT_WR)
515
+
516
+
517
+ class UNIXSocketStream(SocketStream, abc.UNIXSocketStream):
518
+ async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]:
519
+ if not isinstance(msglen, int) or msglen < 0:
520
+ raise ValueError("msglen must be a non-negative integer")
521
+ if not isinstance(maxfds, int) or maxfds < 1:
522
+ raise ValueError("maxfds must be a positive integer")
523
+
524
+ fds = array.array("i")
525
+ await trio.lowlevel.checkpoint()
526
+ with self._receive_guard:
527
+ while True:
528
+ try:
529
+ message, ancdata, _flags, _addr = await self._trio_socket.recvmsg(
530
+ msglen, socket.CMSG_LEN(maxfds * fds.itemsize)
531
+ )
532
+ except BaseException as exc:
533
+ self._convert_socket_error(exc)
534
+ else:
535
+ if not message and not ancdata:
536
+ raise EndOfStream
537
+
538
+ break
539
+
540
+ for cmsg_level, cmsg_type, cmsg_data in ancdata:
541
+ if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS:
542
+ raise RuntimeError(
543
+ f"Received unexpected ancillary data; message = {message!r}, "
544
+ f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}"
545
+ )
546
+
547
+ fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
548
+
549
+ return message, list(fds)
550
+
551
+ async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None:
552
+ if not message:
553
+ raise ValueError("message must not be empty")
554
+ if not fds:
555
+ raise ValueError("fds must not be empty")
556
+
557
+ filenos: list[int] = []
558
+ for fd in fds:
559
+ if isinstance(fd, int):
560
+ filenos.append(fd)
561
+ elif isinstance(fd, IOBase):
562
+ filenos.append(fd.fileno())
563
+
564
+ fdarray = array.array("i", filenos)
565
+ await trio.lowlevel.checkpoint()
566
+ with self._send_guard:
567
+ while True:
568
+ try:
569
+ await self._trio_socket.sendmsg(
570
+ [message],
571
+ [
572
+ (
573
+ socket.SOL_SOCKET,
574
+ socket.SCM_RIGHTS,
575
+ fdarray,
576
+ )
577
+ ],
578
+ )
579
+ break
580
+ except BaseException as exc:
581
+ self._convert_socket_error(exc)
582
+
583
+
584
+ class TCPSocketListener(_TrioSocketMixin, abc.SocketListener):
585
+ def __init__(self, raw_socket: socket.socket):
586
+ super().__init__(trio.socket.from_stdlib_socket(raw_socket))
587
+ self._accept_guard = ResourceGuard("accepting connections from")
588
+
589
+ async def accept(self) -> SocketStream:
590
+ with self._accept_guard:
591
+ try:
592
+ trio_socket, _addr = await self._trio_socket.accept()
593
+ except BaseException as exc:
594
+ self._convert_socket_error(exc)
595
+
596
+ trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
597
+ return SocketStream(trio_socket)
598
+
599
+
600
+ class UNIXSocketListener(_TrioSocketMixin, abc.SocketListener):
601
+ def __init__(self, raw_socket: socket.socket):
602
+ super().__init__(trio.socket.from_stdlib_socket(raw_socket))
603
+ self._accept_guard = ResourceGuard("accepting connections from")
604
+
605
+ async def accept(self) -> UNIXSocketStream:
606
+ with self._accept_guard:
607
+ try:
608
+ trio_socket, _addr = await self._trio_socket.accept()
609
+ except BaseException as exc:
610
+ self._convert_socket_error(exc)
611
+
612
+ return UNIXSocketStream(trio_socket)
613
+
614
+
615
+ class UDPSocket(_TrioSocketMixin[IPSockAddrType], abc.UDPSocket):
616
+ def __init__(self, trio_socket: TrioSocketType) -> None:
617
+ super().__init__(trio_socket)
618
+ self._receive_guard = ResourceGuard("reading from")
619
+ self._send_guard = ResourceGuard("writing to")
620
+
621
+ async def receive(self) -> tuple[bytes, IPSockAddrType]:
622
+ with self._receive_guard:
623
+ try:
624
+ data, addr = await self._trio_socket.recvfrom(65536)
625
+ return data, convert_ipv6_sockaddr(addr)
626
+ except BaseException as exc:
627
+ self._convert_socket_error(exc)
628
+
629
+ async def send(self, item: UDPPacketType) -> None:
630
+ with self._send_guard:
631
+ try:
632
+ await self._trio_socket.sendto(*item)
633
+ except BaseException as exc:
634
+ self._convert_socket_error(exc)
635
+
636
+
637
+ class ConnectedUDPSocket(_TrioSocketMixin[IPSockAddrType], abc.ConnectedUDPSocket):
638
+ def __init__(self, trio_socket: TrioSocketType) -> None:
639
+ super().__init__(trio_socket)
640
+ self._receive_guard = ResourceGuard("reading from")
641
+ self._send_guard = ResourceGuard("writing to")
642
+
643
+ async def receive(self) -> bytes:
644
+ with self._receive_guard:
645
+ try:
646
+ return await self._trio_socket.recv(65536)
647
+ except BaseException as exc:
648
+ self._convert_socket_error(exc)
649
+
650
+ async def send(self, item: bytes) -> None:
651
+ with self._send_guard:
652
+ try:
653
+ await self._trio_socket.send(item)
654
+ except BaseException as exc:
655
+ self._convert_socket_error(exc)
656
+
657
+
658
+ class UNIXDatagramSocket(_TrioSocketMixin[str], abc.UNIXDatagramSocket):
659
+ def __init__(self, trio_socket: TrioSocketType) -> None:
660
+ super().__init__(trio_socket)
661
+ self._receive_guard = ResourceGuard("reading from")
662
+ self._send_guard = ResourceGuard("writing to")
663
+
664
+ async def receive(self) -> UNIXDatagramPacketType:
665
+ with self._receive_guard:
666
+ try:
667
+ data, addr = await self._trio_socket.recvfrom(65536)
668
+ return data, addr
669
+ except BaseException as exc:
670
+ self._convert_socket_error(exc)
671
+
672
+ async def send(self, item: UNIXDatagramPacketType) -> None:
673
+ with self._send_guard:
674
+ try:
675
+ await self._trio_socket.sendto(*item)
676
+ except BaseException as exc:
677
+ self._convert_socket_error(exc)
678
+
679
+
680
+ class ConnectedUNIXDatagramSocket(
681
+ _TrioSocketMixin[str], abc.ConnectedUNIXDatagramSocket
682
+ ):
683
+ def __init__(self, trio_socket: TrioSocketType) -> None:
684
+ super().__init__(trio_socket)
685
+ self._receive_guard = ResourceGuard("reading from")
686
+ self._send_guard = ResourceGuard("writing to")
687
+
688
+ async def receive(self) -> bytes:
689
+ with self._receive_guard:
690
+ try:
691
+ return await self._trio_socket.recv(65536)
692
+ except BaseException as exc:
693
+ self._convert_socket_error(exc)
694
+
695
+ async def send(self, item: bytes) -> None:
696
+ with self._send_guard:
697
+ try:
698
+ await self._trio_socket.send(item)
699
+ except BaseException as exc:
700
+ self._convert_socket_error(exc)
701
+
702
+
703
+ #
704
+ # Synchronization
705
+ #
706
+
707
+
708
+ class Event(BaseEvent):
709
+ __slots__ = ("__original",)
710
+
711
+ def __new__(cls) -> Self:
712
+ return object.__new__(cls)
713
+
714
+ def __init__(self) -> None:
715
+ self.__original = trio.Event()
716
+
717
+ def is_set(self) -> bool:
718
+ return self.__original.is_set()
719
+
720
+ async def wait(self) -> None:
721
+ return await self.__original.wait()
722
+
723
+ def statistics(self) -> EventStatistics:
724
+ orig_statistics = self.__original.statistics()
725
+ return EventStatistics(tasks_waiting=orig_statistics.tasks_waiting)
726
+
727
+ def set(self) -> None:
728
+ self.__original.set()
729
+
730
+
731
+ class Lock(BaseLock):
732
+ __slots__ = "__original", "_fast_acquire"
733
+
734
+ def __new__(cls, *, fast_acquire: bool = False) -> Self:
735
+ return object.__new__(cls)
736
+
737
+ def __init__(self, *, fast_acquire: bool = False) -> None:
738
+ self._fast_acquire = fast_acquire
739
+ self.__original = trio.Lock()
740
+
741
+ @staticmethod
742
+ def _convert_runtime_error_msg(exc: RuntimeError) -> None:
743
+ if exc.args == ("attempt to re-acquire an already held Lock",):
744
+ exc.args = ("Attempted to acquire an already held Lock",)
745
+
746
+ async def acquire(self) -> None:
747
+ if not self._fast_acquire:
748
+ try:
749
+ await self.__original.acquire()
750
+ except RuntimeError as exc:
751
+ self._convert_runtime_error_msg(exc)
752
+ raise
753
+
754
+ return
755
+
756
+ # This is the "fast path" where we don't let other tasks run
757
+ await trio.lowlevel.checkpoint_if_cancelled()
758
+ try:
759
+ self.__original.acquire_nowait()
760
+ except trio.WouldBlock:
761
+ await self.__original._lot.park()
762
+ except RuntimeError as exc:
763
+ self._convert_runtime_error_msg(exc)
764
+ raise
765
+
766
+ def acquire_nowait(self) -> None:
767
+ try:
768
+ self.__original.acquire_nowait()
769
+ except trio.WouldBlock:
770
+ raise WouldBlock from None
771
+ except RuntimeError as exc:
772
+ self._convert_runtime_error_msg(exc)
773
+ raise
774
+
775
+ def locked(self) -> bool:
776
+ return self.__original.locked()
777
+
778
+ def release(self) -> None:
779
+ self.__original.release()
780
+
781
+ def statistics(self) -> LockStatistics:
782
+ orig_statistics = self.__original.statistics()
783
+ owner = TrioTaskInfo(orig_statistics.owner) if orig_statistics.owner else None
784
+ return LockStatistics(
785
+ orig_statistics.locked, owner, orig_statistics.tasks_waiting
786
+ )
787
+
788
+
789
+ class Semaphore(BaseSemaphore):
790
+ __slots__ = ("__original",)
791
+
792
+ def __new__(
793
+ cls,
794
+ initial_value: int,
795
+ *,
796
+ max_value: int | None = None,
797
+ fast_acquire: bool = False,
798
+ ) -> Self:
799
+ return object.__new__(cls)
800
+
801
+ def __init__(
802
+ self,
803
+ initial_value: int,
804
+ *,
805
+ max_value: int | None = None,
806
+ fast_acquire: bool = False,
807
+ ) -> None:
808
+ super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire)
809
+ self.__original = trio.Semaphore(initial_value, max_value=max_value)
810
+
811
+ async def acquire(self) -> None:
812
+ if not self._fast_acquire:
813
+ await self.__original.acquire()
814
+ return
815
+
816
+ # This is the "fast path" where we don't let other tasks run
817
+ await trio.lowlevel.checkpoint_if_cancelled()
818
+ try:
819
+ self.__original.acquire_nowait()
820
+ except trio.WouldBlock:
821
+ await self.__original._lot.park()
822
+
823
+ def acquire_nowait(self) -> None:
824
+ try:
825
+ self.__original.acquire_nowait()
826
+ except trio.WouldBlock:
827
+ raise WouldBlock from None
828
+
829
+ @property
830
+ def max_value(self) -> int | None:
831
+ return self.__original.max_value
832
+
833
+ @property
834
+ def value(self) -> int:
835
+ return self.__original.value
836
+
837
+ def release(self) -> None:
838
+ self.__original.release()
839
+
840
+ def statistics(self) -> SemaphoreStatistics:
841
+ orig_statistics = self.__original.statistics()
842
+ return SemaphoreStatistics(orig_statistics.tasks_waiting)
843
+
844
+
845
+ class CapacityLimiter(BaseCapacityLimiter):
846
+ __slots__ = ("__original",)
847
+
848
+ def __new__(
849
+ cls,
850
+ total_tokens: float | None = None,
851
+ *,
852
+ original: trio.CapacityLimiter | None = None,
853
+ ) -> Self:
854
+ return object.__new__(cls)
855
+
856
+ def __init__(
857
+ self,
858
+ total_tokens: float | None = None,
859
+ *,
860
+ original: trio.CapacityLimiter | None = None,
861
+ ) -> None:
862
+ if original is not None:
863
+ self.__original = original
864
+ else:
865
+ assert total_tokens is not None
866
+ self.__original = trio.CapacityLimiter(total_tokens)
867
+
868
+ async def __aenter__(self) -> None:
869
+ return await self.__original.__aenter__()
870
+
871
+ async def __aexit__(
872
+ self,
873
+ exc_type: type[BaseException] | None,
874
+ exc_val: BaseException | None,
875
+ exc_tb: TracebackType | None,
876
+ ) -> None:
877
+ await self.__original.__aexit__(exc_type, exc_val, exc_tb)
878
+
879
+ @property
880
+ def total_tokens(self) -> float:
881
+ return self.__original.total_tokens
882
+
883
+ @total_tokens.setter
884
+ def total_tokens(self, value: float) -> None:
885
+ self.__original.total_tokens = value
886
+
887
+ @property
888
+ def borrowed_tokens(self) -> int:
889
+ return self.__original.borrowed_tokens
890
+
891
+ @property
892
+ def available_tokens(self) -> float:
893
+ return self.__original.available_tokens
894
+
895
+ def acquire_nowait(self) -> None:
896
+ try:
897
+ self.__original.acquire_nowait()
898
+ except trio.WouldBlock:
899
+ raise WouldBlock from None
900
+
901
+ def acquire_on_behalf_of_nowait(self, borrower: object) -> None:
902
+ try:
903
+ self.__original.acquire_on_behalf_of_nowait(borrower)
904
+ except trio.WouldBlock:
905
+ raise WouldBlock from None
906
+
907
+ async def acquire(self) -> None:
908
+ await self.__original.acquire()
909
+
910
+ async def acquire_on_behalf_of(self, borrower: object) -> None:
911
+ await self.__original.acquire_on_behalf_of(borrower)
912
+
913
+ def release(self) -> None:
914
+ return self.__original.release()
915
+
916
+ def release_on_behalf_of(self, borrower: object) -> None:
917
+ return self.__original.release_on_behalf_of(borrower)
918
+
919
+ def statistics(self) -> CapacityLimiterStatistics:
920
+ orig = self.__original.statistics()
921
+ return CapacityLimiterStatistics(
922
+ borrowed_tokens=orig.borrowed_tokens,
923
+ total_tokens=orig.total_tokens,
924
+ borrowers=tuple(orig.borrowers),
925
+ tasks_waiting=orig.tasks_waiting,
926
+ )
927
+
928
+
929
+ _capacity_limiter_wrapper: trio.lowlevel.RunVar = RunVar("_capacity_limiter_wrapper")
930
+
931
+
932
+ #
933
+ # Signal handling
934
+ #
935
+
936
+
937
+ class _SignalReceiver:
938
+ _iterator: AsyncIterator[int]
939
+
940
+ def __init__(self, signals: tuple[Signals, ...]):
941
+ self._signals = signals
942
+
943
+ def __enter__(self) -> Self:
944
+ self._cm = trio.open_signal_receiver(*self._signals)
945
+ self._iterator = self._cm.__enter__()
946
+ return self
947
+
948
+ def __exit__(
949
+ self,
950
+ exc_type: type[BaseException] | None,
951
+ exc_val: BaseException | None,
952
+ exc_tb: TracebackType | None,
953
+ ) -> bool | None:
954
+ return self._cm.__exit__(exc_type, exc_val, exc_tb)
955
+
956
+ def __aiter__(self) -> _SignalReceiver:
957
+ return self
958
+
959
+ async def __anext__(self) -> Signals:
960
+ signum = await self._iterator.__anext__()
961
+ return Signals(signum)
962
+
963
+
964
+ #
965
+ # Testing and debugging
966
+ #
967
+
968
+
969
+ class TestRunner(abc.TestRunner):
970
+ def __init__(self, **options: Any) -> None:
971
+ from queue import Queue
972
+
973
+ self._call_queue: Queue[Callable[[], object]] = Queue()
974
+ self._send_stream: (
975
+ MemoryObjectSendStream[tuple[Awaitable[Any], list[Outcome]]] | None
976
+ ) = None
977
+ self._options = options
978
+
979
+ def __exit__(
980
+ self,
981
+ exc_type: type[BaseException] | None,
982
+ exc_val: BaseException | None,
983
+ exc_tb: types.TracebackType | None,
984
+ ) -> None:
985
+ if self._send_stream:
986
+ self._send_stream.close()
987
+ while self._send_stream is not None:
988
+ self._call_queue.get()()
989
+
990
+ def is_running(self) -> bool:
991
+ return trio.lowlevel.in_trio_task()
992
+
993
+ async def _run_tests_and_fixtures(self) -> None:
994
+ self._send_stream, receive_stream = create_memory_object_stream[
995
+ tuple[Awaitable[Any], list[Outcome]]
996
+ ](1)
997
+ with receive_stream:
998
+ async for awaitable, outcome_holder in receive_stream:
999
+ try:
1000
+ retval = await awaitable
1001
+ except BaseException as exc:
1002
+ outcome_holder.append(Error(exc))
1003
+ else:
1004
+ outcome_holder.append(Value(retval))
1005
+
1006
+ def _main_task_finished(self, outcome: object) -> None:
1007
+ self._send_stream = None
1008
+
1009
+ def _call_in_runner_task(
1010
+ self,
1011
+ func: Callable[P, Awaitable[T_Retval]],
1012
+ /,
1013
+ *args: P.args,
1014
+ **kwargs: P.kwargs,
1015
+ ) -> T_Retval:
1016
+ if self._send_stream is None:
1017
+ trio.lowlevel.start_guest_run(
1018
+ self._run_tests_and_fixtures,
1019
+ run_sync_soon_threadsafe=self._call_queue.put,
1020
+ done_callback=self._main_task_finished,
1021
+ **self._options,
1022
+ )
1023
+ while self._send_stream is None:
1024
+ self._call_queue.get()()
1025
+
1026
+ outcome_holder: list[Outcome] = []
1027
+ self._send_stream.send_nowait((func(*args, **kwargs), outcome_holder))
1028
+ while not outcome_holder:
1029
+ self._call_queue.get()()
1030
+
1031
+ return outcome_holder[0].unwrap()
1032
+
1033
+ def run_asyncgen_fixture(
1034
+ self,
1035
+ fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]],
1036
+ kwargs: dict[str, Any],
1037
+ ) -> Iterable[T_Retval]:
1038
+ asyncgen = fixture_func(**kwargs)
1039
+ fixturevalue: T_Retval = self._call_in_runner_task(asyncgen.asend, None)
1040
+
1041
+ yield fixturevalue
1042
+
1043
+ try:
1044
+ self._call_in_runner_task(asyncgen.asend, None)
1045
+ except StopAsyncIteration:
1046
+ pass
1047
+ else:
1048
+ self._call_in_runner_task(asyncgen.aclose)
1049
+ raise RuntimeError("Async generator fixture did not stop")
1050
+
1051
+ def run_fixture(
1052
+ self,
1053
+ fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]],
1054
+ kwargs: dict[str, Any],
1055
+ ) -> T_Retval:
1056
+ return self._call_in_runner_task(fixture_func, **kwargs)
1057
+
1058
+ def run_test(
1059
+ self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any]
1060
+ ) -> None:
1061
+ self._call_in_runner_task(test_func, **kwargs)
1062
+
1063
+
1064
+ class TrioTaskInfo(TaskInfo):
1065
+ def __init__(self, task: trio.lowlevel.Task):
1066
+ parent_id = None
1067
+ if task.parent_nursery and task.parent_nursery.parent_task:
1068
+ parent_id = id(task.parent_nursery.parent_task)
1069
+
1070
+ super().__init__(id(task), parent_id, task.name, task.coro)
1071
+ self._task = weakref.proxy(task)
1072
+
1073
+ def has_pending_cancellation(self) -> bool:
1074
+ try:
1075
+ return self._task._cancel_status.effectively_cancelled
1076
+ except ReferenceError:
1077
+ # If the task is no longer around, it surely doesn't have a cancellation
1078
+ # pending
1079
+ return False
1080
+
1081
+
1082
+ class TrioBackend(AsyncBackend):
1083
+ @classmethod
1084
+ def run(
1085
+ cls,
1086
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
1087
+ args: tuple[Unpack[PosArgsT]],
1088
+ kwargs: dict[str, Any],
1089
+ options: dict[str, Any],
1090
+ ) -> T_Retval:
1091
+ assert not kwargs, "unreachable, and not supported by Trio"
1092
+ return trio.run(ensure_returns_coro(func), *args, **options)
1093
+
1094
+ @classmethod
1095
+ def current_token(cls) -> object:
1096
+ return trio.lowlevel.current_trio_token()
1097
+
1098
+ @classmethod
1099
+ def current_time(cls) -> float:
1100
+ return trio.current_time()
1101
+
1102
+ @classmethod
1103
+ def cancelled_exception_class(cls) -> type[BaseException]:
1104
+ return trio.Cancelled
1105
+
1106
+ @classmethod
1107
+ async def checkpoint(cls) -> None:
1108
+ await trio.lowlevel.checkpoint()
1109
+
1110
+ @classmethod
1111
+ async def checkpoint_if_cancelled(cls) -> None:
1112
+ await trio.lowlevel.checkpoint_if_cancelled()
1113
+
1114
+ @classmethod
1115
+ async def cancel_shielded_checkpoint(cls) -> None:
1116
+ await trio.lowlevel.cancel_shielded_checkpoint()
1117
+
1118
+ @classmethod
1119
+ async def sleep(cls, delay: float) -> None:
1120
+ await trio.sleep(delay)
1121
+
1122
+ @classmethod
1123
+ def create_cancel_scope(
1124
+ cls, *, deadline: float = math.inf, shield: bool = False
1125
+ ) -> BaseCancelScope:
1126
+ return CancelScope(deadline=deadline, shield=shield)
1127
+
1128
+ @classmethod
1129
+ def current_effective_deadline(cls) -> float:
1130
+ return trio.current_effective_deadline()
1131
+
1132
+ @classmethod
1133
+ def create_task_group(cls) -> abc.TaskGroup:
1134
+ return TaskGroup()
1135
+
1136
+ @classmethod
1137
+ def create_event(cls) -> BaseEvent:
1138
+ return Event()
1139
+
1140
+ @classmethod
1141
+ def create_lock(cls, *, fast_acquire: bool) -> Lock:
1142
+ return Lock(fast_acquire=fast_acquire)
1143
+
1144
+ @classmethod
1145
+ def create_semaphore(
1146
+ cls,
1147
+ initial_value: int,
1148
+ *,
1149
+ max_value: int | None = None,
1150
+ fast_acquire: bool = False,
1151
+ ) -> BaseSemaphore:
1152
+ return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire)
1153
+
1154
+ @classmethod
1155
+ def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter:
1156
+ return CapacityLimiter(total_tokens)
1157
+
1158
+ @classmethod
1159
+ async def run_sync_in_worker_thread(
1160
+ cls,
1161
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
1162
+ args: tuple[Unpack[PosArgsT]],
1163
+ abandon_on_cancel: bool = False,
1164
+ limiter: BaseCapacityLimiter | None = None,
1165
+ ) -> T_Retval:
1166
+ def wrapper() -> T_Retval:
1167
+ with claim_worker_thread(TrioBackend, token):
1168
+ return func(*args)
1169
+
1170
+ token = TrioBackend.current_token()
1171
+ return await run_sync(
1172
+ wrapper,
1173
+ abandon_on_cancel=abandon_on_cancel,
1174
+ limiter=cast(trio.CapacityLimiter, limiter),
1175
+ )
1176
+
1177
+ @classmethod
1178
+ def check_cancelled(cls) -> None:
1179
+ trio.from_thread.check_cancelled()
1180
+
1181
+ @classmethod
1182
+ def run_async_from_thread(
1183
+ cls,
1184
+ func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]],
1185
+ args: tuple[Unpack[PosArgsT]],
1186
+ token: object,
1187
+ ) -> T_co:
1188
+ trio_token = cast("trio.lowlevel.TrioToken | None", token)
1189
+ try:
1190
+ return trio.from_thread.run(func, *args, trio_token=trio_token)
1191
+ except trio.RunFinishedError:
1192
+ raise RunFinishedError from None
1193
+
1194
+ @classmethod
1195
+ def run_sync_from_thread(
1196
+ cls,
1197
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
1198
+ args: tuple[Unpack[PosArgsT]],
1199
+ token: object,
1200
+ ) -> T_Retval:
1201
+ trio_token = cast("trio.lowlevel.TrioToken | None", token)
1202
+ try:
1203
+ return trio.from_thread.run_sync(func, *args, trio_token=trio_token)
1204
+ except trio.RunFinishedError:
1205
+ raise RunFinishedError from None
1206
+
1207
+ @classmethod
1208
+ async def open_process(
1209
+ cls,
1210
+ command: StrOrBytesPath | Sequence[StrOrBytesPath],
1211
+ *,
1212
+ stdin: int | IO[Any] | None,
1213
+ stdout: int | IO[Any] | None,
1214
+ stderr: int | IO[Any] | None,
1215
+ **kwargs: Any,
1216
+ ) -> Process:
1217
+ def convert_item(item: StrOrBytesPath) -> str:
1218
+ str_or_bytes = os.fspath(item)
1219
+ if isinstance(str_or_bytes, str):
1220
+ return str_or_bytes
1221
+ else:
1222
+ return os.fsdecode(str_or_bytes)
1223
+
1224
+ if isinstance(command, (str, bytes, PathLike)):
1225
+ process = await trio.lowlevel.open_process(
1226
+ convert_item(command),
1227
+ stdin=stdin,
1228
+ stdout=stdout,
1229
+ stderr=stderr,
1230
+ shell=True,
1231
+ **kwargs,
1232
+ )
1233
+ else:
1234
+ process = await trio.lowlevel.open_process(
1235
+ [convert_item(item) for item in command],
1236
+ stdin=stdin,
1237
+ stdout=stdout,
1238
+ stderr=stderr,
1239
+ shell=False,
1240
+ **kwargs,
1241
+ )
1242
+
1243
+ stdin_stream = SendStreamWrapper(process.stdin) if process.stdin else None
1244
+ stdout_stream = ReceiveStreamWrapper(process.stdout) if process.stdout else None
1245
+ stderr_stream = ReceiveStreamWrapper(process.stderr) if process.stderr else None
1246
+ return Process(process, stdin_stream, stdout_stream, stderr_stream)
1247
+
1248
+ @classmethod
1249
+ def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None:
1250
+ trio.lowlevel.spawn_system_task(_shutdown_process_pool, workers)
1251
+
1252
+ @classmethod
1253
+ async def connect_tcp(
1254
+ cls, host: str, port: int, local_address: IPSockAddrType | None = None
1255
+ ) -> SocketStream:
1256
+ family = socket.AF_INET6 if ":" in host else socket.AF_INET
1257
+ trio_socket = trio.socket.socket(family)
1258
+ trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
1259
+ if local_address:
1260
+ await trio_socket.bind(local_address)
1261
+
1262
+ try:
1263
+ await trio_socket.connect((host, port))
1264
+ except BaseException:
1265
+ trio_socket.close()
1266
+ raise
1267
+
1268
+ return SocketStream(trio_socket)
1269
+
1270
+ @classmethod
1271
+ async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream:
1272
+ trio_socket = trio.socket.socket(socket.AF_UNIX)
1273
+ try:
1274
+ await trio_socket.connect(path)
1275
+ except BaseException:
1276
+ trio_socket.close()
1277
+ raise
1278
+
1279
+ return UNIXSocketStream(trio_socket)
1280
+
1281
+ @classmethod
1282
+ def create_tcp_listener(cls, sock: socket.socket) -> abc.SocketListener:
1283
+ return TCPSocketListener(sock)
1284
+
1285
+ @classmethod
1286
+ def create_unix_listener(cls, sock: socket.socket) -> abc.SocketListener:
1287
+ return UNIXSocketListener(sock)
1288
+
1289
+ @classmethod
1290
+ async def create_udp_socket(
1291
+ cls,
1292
+ family: socket.AddressFamily,
1293
+ local_address: IPSockAddrType | None,
1294
+ remote_address: IPSockAddrType | None,
1295
+ reuse_port: bool,
1296
+ ) -> UDPSocket | ConnectedUDPSocket:
1297
+ trio_socket = trio.socket.socket(family=family, type=socket.SOCK_DGRAM)
1298
+
1299
+ if reuse_port:
1300
+ trio_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
1301
+
1302
+ if local_address:
1303
+ await trio_socket.bind(local_address)
1304
+
1305
+ if remote_address:
1306
+ await trio_socket.connect(remote_address)
1307
+ return ConnectedUDPSocket(trio_socket)
1308
+ else:
1309
+ return UDPSocket(trio_socket)
1310
+
1311
+ @classmethod
1312
+ @overload
1313
+ async def create_unix_datagram_socket(
1314
+ cls, raw_socket: socket.socket, remote_path: None
1315
+ ) -> abc.UNIXDatagramSocket: ...
1316
+
1317
+ @classmethod
1318
+ @overload
1319
+ async def create_unix_datagram_socket(
1320
+ cls, raw_socket: socket.socket, remote_path: str | bytes
1321
+ ) -> abc.ConnectedUNIXDatagramSocket: ...
1322
+
1323
+ @classmethod
1324
+ async def create_unix_datagram_socket(
1325
+ cls, raw_socket: socket.socket, remote_path: str | bytes | None
1326
+ ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket:
1327
+ trio_socket = trio.socket.from_stdlib_socket(raw_socket)
1328
+
1329
+ if remote_path:
1330
+ await trio_socket.connect(remote_path)
1331
+ return ConnectedUNIXDatagramSocket(trio_socket)
1332
+ else:
1333
+ return UNIXDatagramSocket(trio_socket)
1334
+
1335
+ @classmethod
1336
+ async def getaddrinfo(
1337
+ cls,
1338
+ host: bytes | str | None,
1339
+ port: str | int | None,
1340
+ *,
1341
+ family: int | AddressFamily = 0,
1342
+ type: int | SocketKind = 0,
1343
+ proto: int = 0,
1344
+ flags: int = 0,
1345
+ ) -> Sequence[
1346
+ tuple[
1347
+ AddressFamily,
1348
+ SocketKind,
1349
+ int,
1350
+ str,
1351
+ tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
1352
+ ]
1353
+ ]:
1354
+ return await trio.socket.getaddrinfo(host, port, family, type, proto, flags)
1355
+
1356
+ @classmethod
1357
+ async def getnameinfo(
1358
+ cls, sockaddr: IPSockAddrType, flags: int = 0
1359
+ ) -> tuple[str, str]:
1360
+ return await trio.socket.getnameinfo(sockaddr, flags)
1361
+
1362
+ @classmethod
1363
+ async def wait_readable(cls, obj: FileDescriptorLike) -> None:
1364
+ try:
1365
+ await wait_readable(obj)
1366
+ except trio.ClosedResourceError as exc:
1367
+ raise ClosedResourceError().with_traceback(exc.__traceback__) from None
1368
+ except trio.BusyResourceError:
1369
+ raise BusyResourceError("reading from") from None
1370
+
1371
+ @classmethod
1372
+ async def wait_writable(cls, obj: FileDescriptorLike) -> None:
1373
+ try:
1374
+ await wait_writable(obj)
1375
+ except trio.ClosedResourceError as exc:
1376
+ raise ClosedResourceError().with_traceback(exc.__traceback__) from None
1377
+ except trio.BusyResourceError:
1378
+ raise BusyResourceError("writing to") from None
1379
+
1380
+ @classmethod
1381
+ def notify_closing(cls, obj: FileDescriptorLike) -> None:
1382
+ notify_closing(obj)
1383
+
1384
+ @classmethod
1385
+ async def wrap_listener_socket(cls, sock: socket.socket) -> abc.SocketListener:
1386
+ if hasattr(socket, "AF_UNIX") and sock.family == socket.AF_UNIX:
1387
+ return UNIXSocketListener(sock)
1388
+
1389
+ return TCPSocketListener(sock)
1390
+
1391
+ @classmethod
1392
+ async def wrap_stream_socket(cls, sock: socket.socket) -> SocketStream:
1393
+ trio_sock = trio.socket.from_stdlib_socket(sock)
1394
+ return SocketStream(trio_sock)
1395
+
1396
+ @classmethod
1397
+ async def wrap_unix_stream_socket(cls, sock: socket.socket) -> UNIXSocketStream:
1398
+ trio_sock = trio.socket.from_stdlib_socket(sock)
1399
+ return UNIXSocketStream(trio_sock)
1400
+
1401
+ @classmethod
1402
+ async def wrap_udp_socket(cls, sock: socket.socket) -> UDPSocket:
1403
+ trio_sock = trio.socket.from_stdlib_socket(sock)
1404
+ return UDPSocket(trio_sock)
1405
+
1406
+ @classmethod
1407
+ async def wrap_connected_udp_socket(cls, sock: socket.socket) -> ConnectedUDPSocket:
1408
+ trio_sock = trio.socket.from_stdlib_socket(sock)
1409
+ return ConnectedUDPSocket(trio_sock)
1410
+
1411
+ @classmethod
1412
+ async def wrap_unix_datagram_socket(cls, sock: socket.socket) -> UNIXDatagramSocket:
1413
+ trio_sock = trio.socket.from_stdlib_socket(sock)
1414
+ return UNIXDatagramSocket(trio_sock)
1415
+
1416
+ @classmethod
1417
+ async def wrap_connected_unix_datagram_socket(
1418
+ cls, sock: socket.socket
1419
+ ) -> ConnectedUNIXDatagramSocket:
1420
+ trio_sock = trio.socket.from_stdlib_socket(sock)
1421
+ return ConnectedUNIXDatagramSocket(trio_sock)
1422
+
1423
+ @classmethod
1424
+ def current_default_thread_limiter(cls) -> CapacityLimiter:
1425
+ try:
1426
+ return _capacity_limiter_wrapper.get()
1427
+ except LookupError:
1428
+ limiter = CapacityLimiter(
1429
+ original=trio.to_thread.current_default_thread_limiter()
1430
+ )
1431
+ _capacity_limiter_wrapper.set(limiter)
1432
+ return limiter
1433
+
1434
+ @classmethod
1435
+ def open_signal_receiver(
1436
+ cls, *signals: Signals
1437
+ ) -> AbstractContextManager[AsyncIterator[Signals]]:
1438
+ return _SignalReceiver(signals)
1439
+
1440
+ @classmethod
1441
+ def get_current_task(cls) -> TaskInfo:
1442
+ task = current_task()
1443
+ return TrioTaskInfo(task)
1444
+
1445
+ @classmethod
1446
+ def get_running_tasks(cls) -> Sequence[TaskInfo]:
1447
+ root_task = current_root_task()
1448
+ assert root_task
1449
+ task_infos = [TrioTaskInfo(root_task)]
1450
+ nurseries = root_task.child_nurseries
1451
+ while nurseries:
1452
+ new_nurseries: list[trio.Nursery] = []
1453
+ for nursery in nurseries:
1454
+ for task in nursery.child_tasks:
1455
+ task_infos.append(TrioTaskInfo(task))
1456
+ new_nurseries.extend(task.child_nurseries)
1457
+
1458
+ nurseries = new_nurseries
1459
+
1460
+ return task_infos
1461
+
1462
+ @classmethod
1463
+ async def wait_all_tasks_blocked(cls) -> None:
1464
+ from trio.testing import wait_all_tasks_blocked
1465
+
1466
+ await wait_all_tasks_blocked()
1467
+
1468
+ @classmethod
1469
+ def create_test_runner(cls, options: dict[str, Any]) -> TestRunner:
1470
+ return TestRunner(**options)
1471
+
1472
+
1473
+ backend_class = TrioBackend
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/__init__.py ADDED
File without changes
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_asyncio_selector_thread.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import socket
5
+ import threading
6
+ from collections.abc import Callable
7
+ from selectors import EVENT_READ, EVENT_WRITE, DefaultSelector
8
+ from typing import TYPE_CHECKING, Any
9
+
10
+ if TYPE_CHECKING:
11
+ from _typeshed import FileDescriptorLike
12
+
13
+ _selector_lock = threading.Lock()
14
+ _selector: Selector | None = None
15
+
16
+
17
+ class Selector:
18
+ def __init__(self) -> None:
19
+ self._thread = threading.Thread(target=self.run, name="AnyIO socket selector")
20
+ self._selector = DefaultSelector()
21
+ self._send, self._receive = socket.socketpair()
22
+ self._send.setblocking(False)
23
+ self._receive.setblocking(False)
24
+ # This somewhat reduces the amount of memory wasted queueing up data
25
+ # for wakeups. With these settings, maximum number of 1-byte sends
26
+ # before getting BlockingIOError:
27
+ # Linux 4.8: 6
28
+ # macOS (darwin 15.5): 1
29
+ # Windows 10: 525347
30
+ # Windows you're weird. (And on Windows setting SNDBUF to 0 makes send
31
+ # blocking, even on non-blocking sockets, so don't do that.)
32
+ self._receive.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1)
33
+ self._send.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1)
34
+ # On Windows this is a TCP socket so this might matter. On other
35
+ # platforms this fails b/c AF_UNIX sockets aren't actually TCP.
36
+ try:
37
+ self._send.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
38
+ except OSError:
39
+ pass
40
+
41
+ self._selector.register(self._receive, EVENT_READ)
42
+ self._closed = False
43
+
44
+ def start(self) -> None:
45
+ self._thread.start()
46
+ threading._register_atexit(self._stop) # type: ignore[attr-defined]
47
+
48
+ def _stop(self) -> None:
49
+ global _selector
50
+ self._closed = True
51
+ self._notify_self()
52
+ self._send.close()
53
+ self._thread.join()
54
+ self._selector.unregister(self._receive)
55
+ self._receive.close()
56
+ self._selector.close()
57
+ _selector = None
58
+ assert not self._selector.get_map(), (
59
+ "selector still has registered file descriptors after shutdown"
60
+ )
61
+
62
+ def _notify_self(self) -> None:
63
+ try:
64
+ self._send.send(b"\x00")
65
+ except BlockingIOError:
66
+ pass
67
+
68
+ def add_reader(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None:
69
+ loop = asyncio.get_running_loop()
70
+ try:
71
+ key = self._selector.get_key(fd)
72
+ except KeyError:
73
+ self._selector.register(fd, EVENT_READ, {EVENT_READ: (loop, callback)})
74
+ else:
75
+ if EVENT_READ in key.data:
76
+ raise ValueError(
77
+ "this file descriptor is already registered for reading"
78
+ )
79
+
80
+ key.data[EVENT_READ] = loop, callback
81
+ self._selector.modify(fd, key.events | EVENT_READ, key.data)
82
+
83
+ self._notify_self()
84
+
85
+ def add_writer(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None:
86
+ loop = asyncio.get_running_loop()
87
+ try:
88
+ key = self._selector.get_key(fd)
89
+ except KeyError:
90
+ self._selector.register(fd, EVENT_WRITE, {EVENT_WRITE: (loop, callback)})
91
+ else:
92
+ if EVENT_WRITE in key.data:
93
+ raise ValueError(
94
+ "this file descriptor is already registered for writing"
95
+ )
96
+
97
+ key.data[EVENT_WRITE] = loop, callback
98
+ self._selector.modify(fd, key.events | EVENT_WRITE, key.data)
99
+
100
+ self._notify_self()
101
+
102
+ def remove_reader(self, fd: FileDescriptorLike) -> bool:
103
+ try:
104
+ key = self._selector.get_key(fd)
105
+ except KeyError:
106
+ return False
107
+
108
+ if new_events := key.events ^ EVENT_READ:
109
+ del key.data[EVENT_READ]
110
+ self._selector.modify(fd, new_events, key.data)
111
+ else:
112
+ self._selector.unregister(fd)
113
+
114
+ return True
115
+
116
+ def remove_writer(self, fd: FileDescriptorLike) -> bool:
117
+ try:
118
+ key = self._selector.get_key(fd)
119
+ except KeyError:
120
+ return False
121
+
122
+ if new_events := key.events ^ EVENT_WRITE:
123
+ del key.data[EVENT_WRITE]
124
+ self._selector.modify(fd, new_events, key.data)
125
+ else:
126
+ self._selector.unregister(fd)
127
+
128
+ return True
129
+
130
+ def run(self) -> None:
131
+ while not self._closed:
132
+ for key, events in self._selector.select():
133
+ if key.fileobj is self._receive:
134
+ try:
135
+ while self._receive.recv(4096):
136
+ pass
137
+ except BlockingIOError:
138
+ pass
139
+
140
+ continue
141
+
142
+ if events & EVENT_READ:
143
+ loop, callback = key.data[EVENT_READ]
144
+ self.remove_reader(key.fd)
145
+ try:
146
+ loop.call_soon_threadsafe(callback)
147
+ except RuntimeError:
148
+ pass # the loop was already closed
149
+
150
+ if events & EVENT_WRITE:
151
+ loop, callback = key.data[EVENT_WRITE]
152
+ self.remove_writer(key.fd)
153
+ try:
154
+ loop.call_soon_threadsafe(callback)
155
+ except RuntimeError:
156
+ pass # the loop was already closed
157
+
158
+
159
+ def get_selector() -> Selector:
160
+ global _selector
161
+
162
+ with _selector_lock:
163
+ if _selector is None:
164
+ _selector = Selector()
165
+ _selector.start()
166
+
167
+ return _selector
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_concurrency_utils.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from inspect import iscoroutine
4
+
5
+ __all__ = ("amap", "as_completed", "gather")
6
+
7
+ from collections.abc import AsyncGenerator, Awaitable, Callable, Coroutine, Iterable
8
+ from contextlib import asynccontextmanager
9
+ from typing import TYPE_CHECKING, Any, TypeVar, overload
10
+
11
+ from ..abc._tasks import get_coro_name
12
+ from ._exceptions import BrokenResourceError
13
+ from ._streams import create_memory_object_stream
14
+ from ._tasks import TaskHandle, create_task_group
15
+
16
+ if TYPE_CHECKING:
17
+ from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
18
+
19
+ R = TypeVar("R")
20
+ S = TypeVar("S")
21
+ T = TypeVar("T")
22
+ U = TypeVar("U")
23
+ V = TypeVar("V")
24
+ W = TypeVar("W")
25
+
26
+
27
+ @overload
28
+ async def gather(
29
+ coro1: Coroutine[Any, Any, R], coro2: Coroutine[Any, Any, S], /
30
+ ) -> tuple[R, S]: ...
31
+
32
+
33
+ @overload
34
+ async def gather(
35
+ coro1: Coroutine[Any, Any, R],
36
+ coro2: Coroutine[Any, Any, S],
37
+ coro3: Coroutine[Any, Any, T],
38
+ /,
39
+ ) -> tuple[R, S, T]: ...
40
+
41
+
42
+ @overload
43
+ async def gather(
44
+ coro1: Coroutine[Any, Any, R],
45
+ coro2: Coroutine[Any, Any, S],
46
+ coro3: Coroutine[Any, Any, T],
47
+ coro4: Coroutine[Any, Any, U],
48
+ /,
49
+ ) -> tuple[R, S, T, U]: ...
50
+
51
+
52
+ @overload
53
+ async def gather(
54
+ coro1: Coroutine[Any, Any, R],
55
+ coro2: Coroutine[Any, Any, S],
56
+ coro3: Coroutine[Any, Any, T],
57
+ coro4: Coroutine[Any, Any, U],
58
+ coro5: Coroutine[Any, Any, V],
59
+ /,
60
+ ) -> tuple[R, S, T, U, V]: ...
61
+
62
+
63
+ @overload
64
+ async def gather(
65
+ coro1: Coroutine[Any, Any, R],
66
+ coro2: Coroutine[Any, Any, S],
67
+ coro3: Coroutine[Any, Any, T],
68
+ coro4: Coroutine[Any, Any, U],
69
+ coro5: Coroutine[Any, Any, V],
70
+ coro6: Coroutine[Any, Any, W],
71
+ /,
72
+ ) -> tuple[R, S, T, U, V, W]: ...
73
+
74
+
75
+ # handle arbitrary length if awaitables are all of the same type
76
+ @overload
77
+ async def gather(*coros: Coroutine[Any, Any, R]) -> tuple[R, ...]: ...
78
+
79
+
80
+ async def gather(*coros: Coroutine[Any, Any, Any]) -> tuple[Any, ...]:
81
+ """
82
+ Run coroutines concurrently in a task group. The order of result values corresponds
83
+ to the order of coroutines passed.
84
+
85
+ :param coros: coroutine objects to run as tasks
86
+ :return: task results for each argument in the same order as they were passed
87
+
88
+ """
89
+ handles: list[TaskHandle[Any]] = []
90
+ async with create_task_group() as tg:
91
+ handles.extend(tg.create_task(coro) for coro in coros)
92
+
93
+ return tuple(h.return_value for h in handles)
94
+
95
+
96
+ @asynccontextmanager
97
+ async def as_completed(
98
+ *awaitables: Awaitable[R],
99
+ ) -> AsyncGenerator[MemoryObjectReceiveStream[TaskHandle[R]]]:
100
+ """
101
+ Run awaitable objects concurrently in a task group, returning an iterator which can
102
+ be used to get finished task handles in the order they complete.
103
+
104
+ :param awaitables: awaitable objects to run as tasks
105
+ :return: MemoryObjectReceiveStream for iterating over task handles as tasks complete.
106
+
107
+ """
108
+ if not awaitables:
109
+ raise ValueError("as_completed() takes at least one awaitable")
110
+
111
+ send, recv = create_memory_object_stream[TaskHandle[R]](len(awaitables))
112
+ task_handles: list[TaskHandle[R]] = []
113
+
114
+ async def runner(
115
+ awaitable: Awaitable[R],
116
+ index: int,
117
+ _send: MemoryObjectSendStream[TaskHandle[R]],
118
+ ) -> R:
119
+ async with _send:
120
+ try:
121
+ return await awaitable
122
+ finally:
123
+ try:
124
+ _send.send_nowait(task_handles[index])
125
+ except BrokenResourceError:
126
+ pass
127
+
128
+ async with recv, create_task_group() as tg:
129
+ async with send:
130
+ for i, awaitable in enumerate(awaitables):
131
+ name = get_coro_name(awaitable) if iscoroutine(awaitable) else None
132
+ task_handles.append(
133
+ tg.start_soon(runner, awaitable, i, send.clone(), name=name)
134
+ )
135
+ try:
136
+ yield recv
137
+ finally:
138
+ tg.cancel_scope.cancel()
139
+
140
+
141
+ async def amap(
142
+ func: Callable[[T], Coroutine[Any, Any, R]], args: Iterable[T]
143
+ ) -> list[R]:
144
+ """
145
+ Run the given coroutine function concurrently for multiple argument values.
146
+
147
+ :param func: a coroutine function that takes a single argument
148
+ :param args: a sequence of argument values to pass to ``func``
149
+ :return: task results for each argument in the same order as they were passed
150
+
151
+ """
152
+ handles: list[TaskHandle[R]] = []
153
+ async with create_task_group() as tg:
154
+ handles.extend(tg.start_soon(func, arg) for arg in args)
155
+
156
+ return [h.return_value for h in handles]
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_contextmanagers.py ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from abc import abstractmethod
4
+ from contextlib import AbstractAsyncContextManager, AbstractContextManager
5
+ from inspect import isasyncgen, iscoroutine, isgenerator
6
+ from types import TracebackType
7
+ from typing import Protocol, TypeVar, cast, final
8
+
9
+ _T_co = TypeVar("_T_co", covariant=True)
10
+ _ExitT_co = TypeVar("_ExitT_co", covariant=True, bound="bool | None")
11
+
12
+
13
+ class _SupportsCtxMgr(Protocol[_T_co, _ExitT_co]):
14
+ def __contextmanager__(self) -> AbstractContextManager[_T_co, _ExitT_co]: ...
15
+
16
+
17
+ class _SupportsAsyncCtxMgr(Protocol[_T_co, _ExitT_co]):
18
+ def __asynccontextmanager__(
19
+ self,
20
+ ) -> AbstractAsyncContextManager[_T_co, _ExitT_co]: ...
21
+
22
+
23
+ class ContextManagerMixin:
24
+ """
25
+ Mixin class providing context manager functionality via a generator-based
26
+ implementation.
27
+
28
+ This class allows you to implement a context manager via :meth:`__contextmanager__`
29
+ which should return a generator. The mechanics are meant to mirror those of
30
+ :func:`@contextmanager <contextlib.contextmanager>`.
31
+
32
+ .. note:: Classes using this mix-in are not reentrant as context managers, meaning
33
+ that once you enter it, you can't re-enter before first exiting it.
34
+
35
+ .. seealso:: :doc:`contextmanagers`
36
+ """
37
+
38
+ __cm: AbstractContextManager[object, bool | None] | None = None
39
+
40
+ @final
41
+ def __enter__(self: _SupportsCtxMgr[_T_co, bool | None]) -> _T_co:
42
+ # Needed for mypy to assume self still has the __cm member
43
+ assert isinstance(self, ContextManagerMixin)
44
+ if self.__cm is not None:
45
+ raise RuntimeError(
46
+ f"this {self.__class__.__qualname__} has already been entered"
47
+ )
48
+
49
+ cm = self.__contextmanager__()
50
+ if not isinstance(cm, AbstractContextManager):
51
+ if isgenerator(cm):
52
+ raise TypeError(
53
+ "__contextmanager__() returned a generator object instead of "
54
+ "a context manager. Did you forget to add the @contextmanager "
55
+ "decorator?"
56
+ )
57
+
58
+ raise TypeError(
59
+ f"__contextmanager__() did not return a context manager object, "
60
+ f"but {cm.__class__!r}"
61
+ )
62
+
63
+ if cm is self:
64
+ raise TypeError(
65
+ f"{self.__class__.__qualname__}.__contextmanager__() returned "
66
+ f"self. Did you forget to add the @contextmanager decorator and a "
67
+ f"'yield' statement?"
68
+ )
69
+
70
+ value = cm.__enter__()
71
+ self.__cm = cm
72
+ return value
73
+
74
+ @final
75
+ def __exit__(
76
+ self: _SupportsCtxMgr[object, _ExitT_co],
77
+ exc_type: type[BaseException] | None,
78
+ exc_val: BaseException | None,
79
+ exc_tb: TracebackType | None,
80
+ ) -> _ExitT_co:
81
+ # Needed for mypy to assume self still has the __cm member
82
+ assert isinstance(self, ContextManagerMixin)
83
+ if self.__cm is None:
84
+ raise RuntimeError(
85
+ f"this {self.__class__.__qualname__} has not been entered yet"
86
+ )
87
+
88
+ # Prevent circular references
89
+ cm = self.__cm
90
+ del self.__cm
91
+
92
+ return cast(_ExitT_co, cm.__exit__(exc_type, exc_val, exc_tb))
93
+
94
+ @abstractmethod
95
+ def __contextmanager__(self) -> AbstractContextManager[object, bool | None]:
96
+ """
97
+ Implement your context manager logic here.
98
+
99
+ This method **must** be decorated with
100
+ :func:`@contextmanager <contextlib.contextmanager>`.
101
+
102
+ .. note:: Remember that the ``yield`` will raise any exception raised in the
103
+ enclosed context block, so use a ``finally:`` block to clean up resources!
104
+
105
+ :return: a context manager object
106
+ """
107
+
108
+
109
+ class AsyncContextManagerMixin:
110
+ """
111
+ Mixin class providing async context manager functionality via a generator-based
112
+ implementation.
113
+
114
+ This class allows you to implement a context manager via
115
+ :meth:`__asynccontextmanager__`. The mechanics are meant to mirror those of
116
+ :func:`@asynccontextmanager <contextlib.asynccontextmanager>`.
117
+
118
+ .. note:: Classes using this mix-in are not reentrant as context managers, meaning
119
+ that once you enter it, you can't re-enter before first exiting it.
120
+
121
+ .. seealso:: :doc:`contextmanagers`
122
+ """
123
+
124
+ __cm: AbstractAsyncContextManager[object, bool | None] | None = None
125
+
126
+ @final
127
+ async def __aenter__(self: _SupportsAsyncCtxMgr[_T_co, bool | None]) -> _T_co:
128
+ # Needed for mypy to assume self still has the __cm member
129
+ assert isinstance(self, AsyncContextManagerMixin)
130
+ if self.__cm is not None:
131
+ raise RuntimeError(
132
+ f"this {self.__class__.__qualname__} has already been entered"
133
+ )
134
+
135
+ cm = self.__asynccontextmanager__()
136
+ if not isinstance(cm, AbstractAsyncContextManager):
137
+ if isasyncgen(cm):
138
+ raise TypeError(
139
+ "__asynccontextmanager__() returned an async generator instead of "
140
+ "an async context manager. Did you forget to add the "
141
+ "@asynccontextmanager decorator?"
142
+ )
143
+ elif iscoroutine(cm):
144
+ cm.close()
145
+ raise TypeError(
146
+ "__asynccontextmanager__() returned a coroutine object instead of "
147
+ "an async context manager. Did you forget to add the "
148
+ "@asynccontextmanager decorator and a 'yield' statement?"
149
+ )
150
+
151
+ raise TypeError(
152
+ f"__asynccontextmanager__() did not return an async context manager, "
153
+ f"but {cm.__class__!r}"
154
+ )
155
+
156
+ if cm is self:
157
+ raise TypeError(
158
+ f"{self.__class__.__qualname__}.__asynccontextmanager__() returned "
159
+ f"self. Did you forget to add the @asynccontextmanager decorator and a "
160
+ f"'yield' statement?"
161
+ )
162
+
163
+ value = await cm.__aenter__()
164
+ self.__cm = cm
165
+ return value
166
+
167
+ @final
168
+ async def __aexit__(
169
+ self: _SupportsAsyncCtxMgr[object, _ExitT_co],
170
+ exc_type: type[BaseException] | None,
171
+ exc_val: BaseException | None,
172
+ exc_tb: TracebackType | None,
173
+ ) -> _ExitT_co:
174
+ assert isinstance(self, AsyncContextManagerMixin)
175
+ if self.__cm is None:
176
+ raise RuntimeError(
177
+ f"this {self.__class__.__qualname__} has not been entered yet"
178
+ )
179
+
180
+ # Prevent circular references
181
+ cm = self.__cm
182
+ del self.__cm
183
+
184
+ return cast(_ExitT_co, await cm.__aexit__(exc_type, exc_val, exc_tb))
185
+
186
+ @abstractmethod
187
+ def __asynccontextmanager__(
188
+ self,
189
+ ) -> AbstractAsyncContextManager[object, bool | None]:
190
+ """
191
+ Implement your async context manager logic here.
192
+
193
+ This method **must** be decorated with
194
+ :func:`@asynccontextmanager <contextlib.asynccontextmanager>`.
195
+
196
+ .. note:: Remember that the ``yield`` will raise any exception raised in the
197
+ enclosed context block, so use a ``finally:`` block to clean up resources!
198
+
199
+ :return: an async context manager object
200
+ """
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_eventloop.py ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import sys
5
+ import threading
6
+ from collections.abc import Awaitable, Callable, Generator
7
+ from contextlib import contextmanager
8
+ from contextvars import Token
9
+ from importlib import import_module
10
+ from typing import TYPE_CHECKING, Any, TypeVar
11
+
12
+ from ._exceptions import NoEventLoopError
13
+
14
+ if sys.version_info >= (3, 11):
15
+ from typing import TypeVarTuple, Unpack
16
+ else:
17
+ from typing_extensions import TypeVarTuple, Unpack
18
+
19
+ sniffio: Any
20
+ try:
21
+ import sniffio
22
+ except ModuleNotFoundError:
23
+ sniffio = None
24
+
25
+ if TYPE_CHECKING:
26
+ from ..abc import AsyncBackend
27
+
28
+ # This must be updated when new backends are introduced
29
+ BACKENDS = "asyncio", "trio"
30
+
31
+ T_Retval = TypeVar("T_Retval")
32
+ PosArgsT = TypeVarTuple("PosArgsT")
33
+
34
+ threadlocals = threading.local()
35
+ loaded_backends: dict[str, type[AsyncBackend]] = {}
36
+
37
+
38
+ def run(
39
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
40
+ *args: Unpack[PosArgsT],
41
+ backend: str = "asyncio",
42
+ backend_options: dict[str, Any] | None = None,
43
+ ) -> T_Retval:
44
+ """
45
+ Run the given coroutine function in an asynchronous event loop.
46
+
47
+ The current thread must not be already running an event loop.
48
+
49
+ :param func: a coroutine function
50
+ :param args: positional arguments to ``func``
51
+ :param backend: name of the asynchronous event loop implementation – currently
52
+ either ``asyncio`` or ``trio``
53
+ :param backend_options: keyword arguments to call the backend ``run()``
54
+ implementation with (documented :ref:`here <backend options>`)
55
+ :return: the return value of the coroutine function
56
+ :raises RuntimeError: if an asynchronous event loop is already running in this
57
+ thread
58
+ :raises LookupError: if the named backend is not found
59
+
60
+ """
61
+ if asynclib_name := current_async_library():
62
+ raise RuntimeError(f"Already running {asynclib_name} in this thread")
63
+
64
+ try:
65
+ async_backend = get_async_backend(backend)
66
+ except ImportError as exc:
67
+ if backend in BACKENDS:
68
+ raise LookupError(
69
+ f"Backend {backend!r} is not available. "
70
+ f"Install it with: pip install anyio[{backend}]"
71
+ ) from exc
72
+
73
+ raise LookupError(f"No such backend: {backend}") from exc
74
+
75
+ token = None
76
+ if asynclib_name is None:
77
+ # Since we're in control of the event loop, we can cache the name of the async
78
+ # library
79
+ token = set_current_async_library(backend)
80
+
81
+ try:
82
+ backend_options = backend_options or {}
83
+ return async_backend.run(func, args, {}, backend_options)
84
+ finally:
85
+ reset_current_async_library(token)
86
+
87
+
88
+ async def sleep(delay: float) -> None:
89
+ """
90
+ Pause the current task for the specified duration.
91
+
92
+ :param delay: the duration, in seconds
93
+
94
+ """
95
+ return await get_async_backend().sleep(delay)
96
+
97
+
98
+ async def sleep_forever() -> None:
99
+ """
100
+ Pause the current task until it's cancelled.
101
+
102
+ This is a shortcut for ``sleep(math.inf)``.
103
+
104
+ .. versionadded:: 3.1
105
+
106
+ """
107
+ await sleep(math.inf)
108
+
109
+
110
+ async def sleep_until(deadline: float) -> None:
111
+ """
112
+ Pause the current task until the given time.
113
+
114
+ :param deadline: the absolute time to wake up at (according to the internal
115
+ monotonic clock of the event loop)
116
+
117
+ .. versionadded:: 3.1
118
+
119
+ """
120
+ now = current_time()
121
+ await sleep(max(deadline - now, 0))
122
+
123
+
124
+ def current_time() -> float:
125
+ """
126
+ Return the current value of the event loop's internal clock.
127
+
128
+ :return: the clock value (seconds)
129
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
130
+ current thread
131
+
132
+ """
133
+ return get_async_backend().current_time()
134
+
135
+
136
+ def get_all_backends() -> tuple[str, ...]:
137
+ """Return a tuple of the names of all built-in backends."""
138
+ return BACKENDS
139
+
140
+
141
+ def get_available_backends() -> tuple[str, ...]:
142
+ """
143
+ Test for the availability of built-in backends.
144
+
145
+ :return a tuple of the built-in backend names that were successfully imported
146
+
147
+ .. versionadded:: 4.12
148
+
149
+ """
150
+ available_backends: list[str] = []
151
+ for backend_name in get_all_backends():
152
+ try:
153
+ get_async_backend(backend_name)
154
+ except ImportError:
155
+ continue
156
+
157
+ available_backends.append(backend_name)
158
+
159
+ return tuple(available_backends)
160
+
161
+
162
+ def get_cancelled_exc_class() -> type[BaseException]:
163
+ """
164
+ Return the current async library's cancellation exception class.
165
+
166
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
167
+ current thread
168
+
169
+ """
170
+ return get_async_backend().cancelled_exception_class()
171
+
172
+
173
+ #
174
+ # Private API
175
+ #
176
+
177
+
178
+ @contextmanager
179
+ def claim_worker_thread(
180
+ backend_class: type[AsyncBackend], token: object
181
+ ) -> Generator[Any, None, None]:
182
+ from ..lowlevel import EventLoopToken
183
+
184
+ threadlocals.current_token = EventLoopToken(backend_class, token)
185
+ try:
186
+ yield
187
+ finally:
188
+ del threadlocals.current_token
189
+
190
+
191
+ def get_async_backend(asynclib_name: str | None = None) -> type[AsyncBackend]:
192
+ if asynclib_name is None:
193
+ asynclib_name = current_async_library()
194
+ if not asynclib_name:
195
+ raise NoEventLoopError(
196
+ f"Not currently running on any asynchronous event loop. "
197
+ f"Available async backends: {', '.join(get_all_backends())}"
198
+ )
199
+
200
+ # We use our own dict instead of sys.modules to get the already imported back-end
201
+ # class because the appropriate modules in sys.modules could potentially be only
202
+ # partially initialized
203
+ try:
204
+ return loaded_backends[asynclib_name]
205
+ except KeyError:
206
+ module = import_module(f"anyio._backends._{asynclib_name}")
207
+ loaded_backends[asynclib_name] = module.backend_class
208
+ return module.backend_class
209
+
210
+
211
+ def current_async_library() -> str | None:
212
+ if sniffio is None:
213
+ # If sniffio is not installed, we assume we're either running asyncio or nothing
214
+ import asyncio
215
+
216
+ try:
217
+ asyncio.get_running_loop()
218
+ return "asyncio"
219
+ except RuntimeError:
220
+ pass
221
+ else:
222
+ try:
223
+ return sniffio.current_async_library()
224
+ except sniffio.AsyncLibraryNotFoundError:
225
+ pass
226
+
227
+ return None
228
+
229
+
230
+ def set_current_async_library(asynclib_name: str | None) -> Token | None:
231
+ # no-op if sniffio is not installed
232
+ if sniffio is None:
233
+ return None
234
+
235
+ return sniffio.current_async_library_cvar.set(asynclib_name)
236
+
237
+
238
+ def reset_current_async_library(token: Token | None) -> None:
239
+ if token is not None:
240
+ sniffio.current_async_library_cvar.reset(token)
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_exceptions.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from collections.abc import Generator
5
+ from textwrap import dedent
6
+ from typing import Any
7
+
8
+ if sys.version_info < (3, 11):
9
+ from exceptiongroup import BaseExceptionGroup
10
+
11
+
12
+ class BrokenResourceError(Exception):
13
+ """
14
+ Raised when trying to use a resource that has been rendered unusable due to external
15
+ causes (e.g. a send stream whose peer has disconnected).
16
+ """
17
+
18
+
19
+ class BrokenWorkerProcess(Exception):
20
+ """
21
+ Raised by :meth:`~anyio.to_process.run_sync` if the worker process terminates abruptly or
22
+ otherwise misbehaves.
23
+ """
24
+
25
+
26
+ class BrokenWorkerInterpreter(Exception):
27
+ """
28
+ Raised by :meth:`~anyio.to_interpreter.run_sync` if an unexpected exception is
29
+ raised in the subinterpreter.
30
+ """
31
+
32
+ def __init__(self, excinfo: Any):
33
+ # This was adapted from concurrent.futures.interpreter.ExecutionFailed
34
+ msg = excinfo.formatted
35
+ if not msg:
36
+ if excinfo.type and excinfo.msg:
37
+ msg = f"{excinfo.type.__name__}: {excinfo.msg}"
38
+ else:
39
+ msg = excinfo.type.__name__ or excinfo.msg
40
+
41
+ super().__init__(msg)
42
+ self.excinfo = excinfo
43
+
44
+ def __str__(self) -> str:
45
+ try:
46
+ formatted = self.excinfo.errdisplay
47
+ except Exception:
48
+ return super().__str__()
49
+ else:
50
+ return dedent(
51
+ f"""
52
+ {super().__str__()}
53
+
54
+ Uncaught in the interpreter:
55
+
56
+ {formatted}
57
+ """.strip()
58
+ )
59
+
60
+
61
+ class BusyResourceError(Exception):
62
+ """
63
+ Raised when two tasks are trying to read from or write to the same resource
64
+ concurrently.
65
+ """
66
+
67
+ def __init__(self, action: str):
68
+ super().__init__(f"Another task is already {action} this resource")
69
+
70
+
71
+ class ClosedResourceError(Exception):
72
+ """Raised when trying to use a resource that has been closed."""
73
+
74
+
75
+ class ConnectionFailed(OSError):
76
+ """
77
+ Raised when a connection attempt fails.
78
+
79
+ .. note:: This class inherits from :exc:`OSError` for backwards compatibility.
80
+ """
81
+
82
+
83
+ def iterate_exceptions(
84
+ exception: BaseException,
85
+ ) -> Generator[BaseException, None, None]:
86
+ if isinstance(exception, BaseExceptionGroup):
87
+ for exc in exception.exceptions:
88
+ yield from iterate_exceptions(exc)
89
+ else:
90
+ yield exception
91
+
92
+
93
+ class DelimiterNotFound(Exception):
94
+ """
95
+ Raised during
96
+ :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the
97
+ maximum number of bytes has been read without the delimiter being found.
98
+ """
99
+
100
+ def __init__(self, max_bytes: int) -> None:
101
+ super().__init__(
102
+ f"The delimiter was not found among the first {max_bytes} bytes"
103
+ )
104
+
105
+
106
+ class EndOfStream(Exception):
107
+ """
108
+ Raised when trying to read from a stream that has been closed from the other end.
109
+ """
110
+
111
+
112
+ class IncompleteRead(Exception):
113
+ """
114
+ Raised during
115
+ :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_exactly` or
116
+ :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the
117
+ connection is closed before the requested amount of bytes has been read.
118
+ """
119
+
120
+ def __init__(self) -> None:
121
+ super().__init__(
122
+ "The stream was closed before the read operation could be completed"
123
+ )
124
+
125
+
126
+ class TypedAttributeLookupError(LookupError):
127
+ """
128
+ Raised by :meth:`~anyio.TypedAttributeProvider.extra` when the given typed attribute
129
+ is not found and no default value has been given.
130
+ """
131
+
132
+
133
+ class WouldBlock(Exception):
134
+ """Raised by ``X_nowait`` functions if ``X()`` would block."""
135
+
136
+
137
+ class NoEventLoopError(RuntimeError):
138
+ """
139
+ Raised by several functions that require an event loop to be running in the current
140
+ thread when there is no running event loop.
141
+
142
+ This is also raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync`
143
+ if not calling from an AnyIO worker thread, and no ``token`` was passed.
144
+ """
145
+
146
+
147
+ class RunFinishedError(RuntimeError):
148
+ """
149
+ Raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync` if the event
150
+ loop associated with the explicitly passed token has already finished.
151
+ """
152
+
153
+ def __init__(self) -> None:
154
+ super().__init__(
155
+ "The event loop associated with the given token has already finished"
156
+ )
157
+
158
+
159
+ class TaskFailed(Exception):
160
+ """
161
+ Raised when awaiting on, or attempting to access the return value of, a
162
+ :class:`.TaskHandle` that raised an exception.
163
+ """
164
+
165
+
166
+ class TaskCancelled(TaskFailed):
167
+ """
168
+ Raised when awaiting on, or attempting to access the return value of, a
169
+ :class:`.TaskHandle` that was cancelled.
170
+ """
171
+
172
+
173
+ class TaskNotFinished(Exception):
174
+ """
175
+ Raised when attempting to access the return value or exception of a
176
+ :class:`.TaskHandle` that is still pending completion.
177
+ """
178
+
179
+
180
+ class FutureFailed(Exception):
181
+ """
182
+ Raised when awaiting on, or attempting to access the return value of, a
183
+ :class:`.Future` that raised an exception.
184
+ """
185
+
186
+
187
+ class FutureCancelled(FutureFailed):
188
+ """
189
+ Raised when attempting to access the return value or exception of a
190
+ :class:`.Future` that was cancelled.
191
+ """
192
+
193
+
194
+ class FutureNotFinished(Exception):
195
+ """
196
+ Raised when attempting to access the return value or exception of a
197
+ :class:`.Future` that is still pending completion.
198
+ """
199
+
200
+
201
+ class FutureAlreadyFinished(Exception):
202
+ """
203
+ Raised when attempting set a result of or await a
204
+ :class:`.Future` that has already completed.
205
+ """
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_fileio.py ADDED
@@ -0,0 +1,1045 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import pathlib
5
+ import sys
6
+ from collections.abc import (
7
+ AsyncIterator,
8
+ Callable,
9
+ Iterable,
10
+ Iterator,
11
+ Sequence,
12
+ )
13
+ from dataclasses import dataclass
14
+ from functools import partial
15
+ from os import PathLike
16
+ from typing import (
17
+ IO,
18
+ TYPE_CHECKING,
19
+ Any,
20
+ AnyStr,
21
+ ClassVar,
22
+ Final,
23
+ Generic,
24
+ TypeVar,
25
+ overload,
26
+ )
27
+
28
+ from .. import to_thread
29
+ from ..abc import AsyncResource
30
+ from ._synchronization import CapacityLimiter
31
+
32
+ if sys.version_info >= (3, 11):
33
+ from typing import Self
34
+ else:
35
+ from typing_extensions import Self
36
+
37
+ if sys.version_info >= (3, 14):
38
+ from pathlib.types import PathInfo
39
+
40
+ if TYPE_CHECKING:
41
+ from types import ModuleType
42
+
43
+ from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer
44
+ else:
45
+ ReadableBuffer = OpenBinaryMode = OpenTextMode = WriteableBuffer = object
46
+
47
+
48
+ T = TypeVar("T", bound="Path")
49
+
50
+
51
+ class AsyncFile(AsyncResource, Generic[AnyStr]):
52
+ """
53
+ An asynchronous file object.
54
+
55
+ This class wraps a standard file object and provides async friendly versions of the
56
+ following blocking methods (where available on the original file object):
57
+
58
+ * read
59
+ * read1
60
+ * readline
61
+ * readlines
62
+ * readinto
63
+ * readinto1
64
+ * write
65
+ * writelines
66
+ * truncate
67
+ * seek
68
+ * tell
69
+ * flush
70
+
71
+ All other methods are directly passed through.
72
+
73
+ This class supports the asynchronous context manager protocol which closes the
74
+ underlying file at the end of the context block.
75
+
76
+ This class also supports asynchronous iteration::
77
+
78
+ async with await open_file(...) as f:
79
+ async for line in f:
80
+ print(line)
81
+ """
82
+
83
+ def __init__(
84
+ self, fp: IO[AnyStr], *, limiter: CapacityLimiter | None = None
85
+ ) -> None:
86
+ if limiter is not None and not isinstance(limiter, CapacityLimiter):
87
+ raise TypeError(
88
+ f"limiter must be a CapacityLimiter or None, not "
89
+ f"{limiter.__class__.__name__}"
90
+ )
91
+
92
+ self._fp: Any = fp
93
+ self._limiter = limiter
94
+
95
+ def __getattr__(self, name: str) -> object:
96
+ return getattr(self._fp, name)
97
+
98
+ @property
99
+ def limiter(self) -> CapacityLimiter | None:
100
+ """The capacity limiter used by this file object, if not the global limiter."""
101
+ return self._limiter
102
+
103
+ @property
104
+ def wrapped(self) -> IO[AnyStr]:
105
+ """The wrapped file object."""
106
+ return self._fp
107
+
108
+ async def __aiter__(self) -> AsyncIterator[AnyStr]:
109
+ while True:
110
+ line = await self.readline()
111
+ if line:
112
+ yield line
113
+ else:
114
+ break
115
+
116
+ async def aclose(self) -> None:
117
+ return await to_thread.run_sync(self._fp.close, limiter=self._limiter)
118
+
119
+ async def read(self, size: int = -1) -> AnyStr:
120
+ return await to_thread.run_sync(self._fp.read, size, limiter=self._limiter)
121
+
122
+ async def read1(self: AsyncFile[bytes], size: int = -1) -> bytes:
123
+ return await to_thread.run_sync(self._fp.read1, size, limiter=self._limiter)
124
+
125
+ async def readline(self) -> AnyStr:
126
+ return await to_thread.run_sync(self._fp.readline, limiter=self._limiter)
127
+
128
+ async def readlines(self) -> list[AnyStr]:
129
+ return await to_thread.run_sync(self._fp.readlines, limiter=self._limiter)
130
+
131
+ async def readinto(self: AsyncFile[bytes], b: WriteableBuffer) -> int:
132
+ return await to_thread.run_sync(self._fp.readinto, b, limiter=self._limiter)
133
+
134
+ async def readinto1(self: AsyncFile[bytes], b: WriteableBuffer) -> int:
135
+ return await to_thread.run_sync(self._fp.readinto1, b, limiter=self._limiter)
136
+
137
+ @overload
138
+ async def write(self: AsyncFile[bytes], b: ReadableBuffer) -> int: ...
139
+
140
+ @overload
141
+ async def write(self: AsyncFile[str], b: str) -> int: ...
142
+
143
+ async def write(self, b: ReadableBuffer | str) -> int:
144
+ return await to_thread.run_sync(self._fp.write, b, limiter=self._limiter)
145
+
146
+ @overload
147
+ async def writelines(
148
+ self: AsyncFile[bytes], lines: Iterable[ReadableBuffer]
149
+ ) -> None: ...
150
+
151
+ @overload
152
+ async def writelines(self: AsyncFile[str], lines: Iterable[str]) -> None: ...
153
+
154
+ async def writelines(self, lines: Iterable[ReadableBuffer] | Iterable[str]) -> None:
155
+ return await to_thread.run_sync(
156
+ self._fp.writelines, lines, limiter=self._limiter
157
+ )
158
+
159
+ async def truncate(self, size: int | None = None) -> int:
160
+ return await to_thread.run_sync(self._fp.truncate, size, limiter=self._limiter)
161
+
162
+ async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int:
163
+ return await to_thread.run_sync(
164
+ self._fp.seek, offset, whence, limiter=self._limiter
165
+ )
166
+
167
+ async def tell(self) -> int:
168
+ return await to_thread.run_sync(self._fp.tell, limiter=self._limiter)
169
+
170
+ async def flush(self) -> None:
171
+ return await to_thread.run_sync(self._fp.flush, limiter=self._limiter)
172
+
173
+
174
+ @overload
175
+ async def open_file(
176
+ file: str | PathLike[str] | int,
177
+ mode: OpenBinaryMode,
178
+ buffering: int = ...,
179
+ encoding: str | None = ...,
180
+ errors: str | None = ...,
181
+ newline: str | None = ...,
182
+ closefd: bool = ...,
183
+ opener: Callable[[str, int], int] | None = ...,
184
+ *,
185
+ limiter: CapacityLimiter | None = ...,
186
+ ) -> AsyncFile[bytes]: ...
187
+
188
+
189
+ @overload
190
+ async def open_file(
191
+ file: str | PathLike[str] | int,
192
+ mode: OpenTextMode = ...,
193
+ buffering: int = ...,
194
+ encoding: str | None = ...,
195
+ errors: str | None = ...,
196
+ newline: str | None = ...,
197
+ closefd: bool = ...,
198
+ opener: Callable[[str, int], int] | None = ...,
199
+ *,
200
+ limiter: CapacityLimiter | None = ...,
201
+ ) -> AsyncFile[str]: ...
202
+
203
+
204
+ async def open_file(
205
+ file: str | PathLike[str] | int,
206
+ mode: str = "r",
207
+ buffering: int = -1,
208
+ encoding: str | None = None,
209
+ errors: str | None = None,
210
+ newline: str | None = None,
211
+ closefd: bool = True,
212
+ opener: Callable[[str, int], int] | None = None,
213
+ *,
214
+ limiter: CapacityLimiter | None = None,
215
+ ) -> AsyncFile[Any]:
216
+ """
217
+ Open a file asynchronously.
218
+
219
+ Except for ``limiter``, the arguments are exactly the same as for the builtin :func:`open`.
220
+
221
+ :param limiter: an optional capacity limiter to use with the file
222
+ instead of the default one
223
+ :return: an asynchronous file object
224
+
225
+ .. versionchanged:: 4.14.0
226
+ Added the ``limiter`` keyword argument.
227
+
228
+ """
229
+ fp = await to_thread.run_sync(
230
+ open,
231
+ file,
232
+ mode,
233
+ buffering,
234
+ encoding,
235
+ errors,
236
+ newline,
237
+ closefd,
238
+ opener,
239
+ limiter=limiter,
240
+ )
241
+ return AsyncFile(fp, limiter=limiter)
242
+
243
+
244
+ def wrap_file(
245
+ file: IO[AnyStr], *, limiter: CapacityLimiter | None = None
246
+ ) -> AsyncFile[AnyStr]:
247
+ """
248
+ Wrap an existing file as an asynchronous file.
249
+
250
+ :param file: an existing file-like object
251
+ :param limiter: an optional capacity limiter to use with the file
252
+ instead of the default one
253
+ :return: an asynchronous file object
254
+
255
+ .. versionchanged:: 4.14.0
256
+ Added the ``limiter`` keyword argument.
257
+
258
+ """
259
+ return AsyncFile(file, limiter=limiter)
260
+
261
+
262
+ @dataclass(eq=False)
263
+ class _PathIterator(AsyncIterator[T]):
264
+ iterator: Iterator[PathLike[str]]
265
+ limiter: CapacityLimiter | None
266
+ # This was added to ensure that iterating over a subclass of Path yields instances
267
+ # of that subclass rather than the base Path class.
268
+ path_cls: type[T]
269
+
270
+ async def __anext__(self) -> T:
271
+ nextval = await to_thread.run_sync(
272
+ next, self.iterator, None, abandon_on_cancel=True, limiter=self.limiter
273
+ )
274
+ if nextval is None:
275
+ raise StopAsyncIteration from None
276
+
277
+ return self.path_cls(nextval, limiter=self.limiter)
278
+
279
+
280
+ class Path:
281
+ """
282
+ An asynchronous version of :class:`pathlib.Path`.
283
+
284
+ This class cannot be substituted for :class:`pathlib.Path` or
285
+ :class:`pathlib.PurePath`, but it is compatible with the :class:`os.PathLike`
286
+ interface.
287
+
288
+ It implements the Python 3.10 version of :class:`pathlib.Path` interface, except for
289
+ the deprecated :meth:`~pathlib.Path.link_to` method.
290
+
291
+ Some methods may be unavailable or have limited functionality, based on the Python
292
+ version:
293
+
294
+ * :meth:`~pathlib.Path.copy` (available on Python 3.14 or later)
295
+ * :meth:`~pathlib.Path.copy_into` (available on Python 3.14 or later)
296
+ * :meth:`~pathlib.Path.from_uri` (available on Python 3.13 or later)
297
+ * :meth:`~pathlib.PurePath.full_match` (available on Python 3.13 or later)
298
+ * :attr:`~pathlib.Path.info` (available on Python 3.14 or later)
299
+ * :meth:`~pathlib.Path.is_junction` (available on Python 3.12 or later)
300
+ * :meth:`~pathlib.PurePath.match` (the ``case_sensitive`` parameter is only
301
+ available on Python 3.13 or later)
302
+ * :meth:`~pathlib.Path.move` (available on Python 3.14 or later)
303
+ * :meth:`~pathlib.Path.move_into` (available on Python 3.14 or later)
304
+ * :meth:`~pathlib.PurePath.relative_to` (the ``walk_up`` parameter is only available
305
+ on Python 3.12 or later)
306
+ * :meth:`~pathlib.Path.walk` (available on Python 3.12 or later)
307
+
308
+ Any methods that do disk I/O need to be awaited on. These methods are:
309
+
310
+ * :meth:`~pathlib.Path.absolute`
311
+ * :meth:`~pathlib.Path.chmod`
312
+ * :meth:`~pathlib.Path.cwd`
313
+ * :meth:`~pathlib.Path.exists`
314
+ * :meth:`~pathlib.Path.expanduser`
315
+ * :meth:`~pathlib.Path.group`
316
+ * :meth:`~pathlib.Path.hardlink_to`
317
+ * :meth:`~pathlib.Path.home`
318
+ * :meth:`~pathlib.Path.is_block_device`
319
+ * :meth:`~pathlib.Path.is_char_device`
320
+ * :meth:`~pathlib.Path.is_dir`
321
+ * :meth:`~pathlib.Path.is_fifo`
322
+ * :meth:`~pathlib.Path.is_file`
323
+ * :meth:`~pathlib.Path.is_junction`
324
+ * :meth:`~pathlib.Path.is_mount`
325
+ * :meth:`~pathlib.Path.is_socket`
326
+ * :meth:`~pathlib.Path.is_symlink`
327
+ * :meth:`~pathlib.Path.lchmod`
328
+ * :meth:`~pathlib.Path.lstat`
329
+ * :meth:`~pathlib.Path.mkdir`
330
+ * :meth:`~pathlib.Path.open`
331
+ * :meth:`~pathlib.Path.owner`
332
+ * :meth:`~pathlib.Path.read_bytes`
333
+ * :meth:`~pathlib.Path.read_text`
334
+ * :meth:`~pathlib.Path.readlink`
335
+ * :meth:`~pathlib.Path.rename`
336
+ * :meth:`~pathlib.Path.replace`
337
+ * :meth:`~pathlib.Path.resolve`
338
+ * :meth:`~pathlib.Path.rmdir`
339
+ * :meth:`~pathlib.Path.samefile`
340
+ * :meth:`~pathlib.Path.stat`
341
+ * :meth:`~pathlib.Path.symlink_to`
342
+ * :meth:`~pathlib.Path.touch`
343
+ * :meth:`~pathlib.Path.unlink`
344
+ * :meth:`~pathlib.Path.walk`
345
+ * :meth:`~pathlib.Path.write_bytes`
346
+ * :meth:`~pathlib.Path.write_text`
347
+
348
+ Additionally, the following methods return an async iterator yielding
349
+ :class:`~.Path` objects:
350
+
351
+ * :meth:`~pathlib.Path.glob`
352
+ * :meth:`~pathlib.Path.iterdir`
353
+ * :meth:`~pathlib.Path.rglob`
354
+
355
+ .. versionchanged:: 4.14.0
356
+ Added the ``limiter`` keyword argument.
357
+ """
358
+
359
+ __slots__ = "__weakref__", "_limiter", "_path"
360
+
361
+ __weakref__: Any
362
+
363
+ def __init__(
364
+ self, *args: str | PathLike[str], limiter: CapacityLimiter | None = None
365
+ ) -> None:
366
+ if limiter is not None and not isinstance(limiter, CapacityLimiter):
367
+ raise TypeError(
368
+ f"limiter must be a CapacityLimiter or None, not "
369
+ f"{limiter.__class__.__name__}"
370
+ )
371
+
372
+ self._path: Final[pathlib.Path] = pathlib.Path(*args)
373
+ self._limiter = limiter
374
+
375
+ def __fspath__(self) -> str:
376
+ return self._path.__fspath__()
377
+
378
+ if sys.version_info >= (3, 15):
379
+
380
+ def __vfspath__(self) -> str:
381
+ return self._path.__vfspath__()
382
+
383
+ def __str__(self) -> str:
384
+ return self._path.__str__()
385
+
386
+ def __repr__(self) -> str:
387
+ return f"{self.__class__.__name__}({self.as_posix()!r})"
388
+
389
+ def __bytes__(self) -> bytes:
390
+ return self._path.__bytes__()
391
+
392
+ def __hash__(self) -> int:
393
+ return self._path.__hash__()
394
+
395
+ def __eq__(self, other: object) -> bool:
396
+ target = other._path if isinstance(other, Path) else other
397
+ return self._path.__eq__(target)
398
+
399
+ def __lt__(self, other: pathlib.PurePath | Path) -> bool:
400
+ target = other._path if isinstance(other, Path) else other
401
+ return self._path.__lt__(target)
402
+
403
+ def __le__(self, other: pathlib.PurePath | Path) -> bool:
404
+ target = other._path if isinstance(other, Path) else other
405
+ return self._path.__le__(target)
406
+
407
+ def __gt__(self, other: pathlib.PurePath | Path) -> bool:
408
+ target = other._path if isinstance(other, Path) else other
409
+ return self._path.__gt__(target)
410
+
411
+ def __ge__(self, other: pathlib.PurePath | Path) -> bool:
412
+ target = other._path if isinstance(other, Path) else other
413
+ return self._path.__ge__(target)
414
+
415
+ def __truediv__(self, other: str | PathLike[str]) -> Self:
416
+ return type(self)(self._path / other, limiter=self._limiter)
417
+
418
+ def __rtruediv__(self, other: str | PathLike[str]) -> Self:
419
+ return type(self)(other, limiter=self._limiter) / self
420
+
421
+ @property
422
+ def limiter(self) -> CapacityLimiter | None:
423
+ """The capacity limiter used by this path, if not the global limiter."""
424
+ return self._limiter
425
+
426
+ @property
427
+ def parts(self) -> tuple[str, ...]:
428
+ return self._path.parts
429
+
430
+ @property
431
+ def drive(self) -> str:
432
+ return self._path.drive
433
+
434
+ @property
435
+ def root(self) -> str:
436
+ return self._path.root
437
+
438
+ @property
439
+ def anchor(self) -> str:
440
+ return self._path.anchor
441
+
442
+ @property
443
+ def parents(self) -> Sequence[Self]:
444
+ return tuple(type(self)(p, limiter=self._limiter) for p in self._path.parents)
445
+
446
+ @property
447
+ def parent(self) -> Self:
448
+ return type(self)(self._path.parent, limiter=self._limiter)
449
+
450
+ @property
451
+ def name(self) -> str:
452
+ return self._path.name
453
+
454
+ @property
455
+ def suffix(self) -> str:
456
+ return self._path.suffix
457
+
458
+ @property
459
+ def suffixes(self) -> list[str]:
460
+ return self._path.suffixes
461
+
462
+ @property
463
+ def stem(self) -> str:
464
+ return self._path.stem
465
+
466
+ async def absolute(self) -> Self:
467
+ path = await to_thread.run_sync(self._path.absolute, limiter=self._limiter)
468
+ return type(self)(path, limiter=self._limiter)
469
+
470
+ def as_posix(self) -> str:
471
+ return self._path.as_posix()
472
+
473
+ def as_uri(self) -> str:
474
+ return self._path.as_uri()
475
+
476
+ if sys.version_info >= (3, 13):
477
+ parser: ClassVar[ModuleType] = pathlib.Path.parser
478
+
479
+ @classmethod
480
+ def from_uri(cls, uri: str, *, limiter: CapacityLimiter | None = None) -> Self:
481
+ return cls(pathlib.Path.from_uri(uri), limiter=limiter)
482
+
483
+ def full_match(
484
+ self, path_pattern: str, *, case_sensitive: bool | None = None
485
+ ) -> bool:
486
+ return self._path.full_match(path_pattern, case_sensitive=case_sensitive)
487
+
488
+ def match(
489
+ self, path_pattern: str, *, case_sensitive: bool | None = None
490
+ ) -> bool:
491
+ return self._path.match(path_pattern, case_sensitive=case_sensitive)
492
+ else:
493
+
494
+ def match(self, path_pattern: str) -> bool:
495
+ return self._path.match(path_pattern)
496
+
497
+ if sys.version_info >= (3, 14):
498
+
499
+ @property
500
+ def info(self) -> PathInfo:
501
+ return self._path.info
502
+
503
+ async def copy(
504
+ self,
505
+ target: str | os.PathLike[str],
506
+ *,
507
+ follow_symlinks: bool = True,
508
+ preserve_metadata: bool = False,
509
+ ) -> Self:
510
+ func = partial(
511
+ self._path.copy,
512
+ follow_symlinks=follow_symlinks,
513
+ preserve_metadata=preserve_metadata,
514
+ )
515
+ return type(self)(
516
+ await to_thread.run_sync(
517
+ func, pathlib.Path(target), limiter=self._limiter
518
+ ),
519
+ limiter=self._limiter,
520
+ )
521
+
522
+ async def copy_into(
523
+ self,
524
+ target_dir: str | os.PathLike[str],
525
+ *,
526
+ follow_symlinks: bool = True,
527
+ preserve_metadata: bool = False,
528
+ ) -> Self:
529
+ func = partial(
530
+ self._path.copy_into,
531
+ follow_symlinks=follow_symlinks,
532
+ preserve_metadata=preserve_metadata,
533
+ )
534
+ return type(self)(
535
+ await to_thread.run_sync(
536
+ func, pathlib.Path(target_dir), limiter=self._limiter
537
+ ),
538
+ limiter=self._limiter,
539
+ )
540
+
541
+ async def move(self, target: str | os.PathLike[str]) -> Self:
542
+ # Upstream does not handle anyio.Path properly as a PathLike
543
+ target = pathlib.Path(target)
544
+ return type(self)(
545
+ await to_thread.run_sync(
546
+ self._path.move, target, limiter=self._limiter
547
+ ),
548
+ limiter=self._limiter,
549
+ )
550
+
551
+ async def move_into(
552
+ self,
553
+ target_dir: str | os.PathLike[str],
554
+ ) -> Self:
555
+ return type(self)(
556
+ await to_thread.run_sync(
557
+ self._path.move_into, target_dir, limiter=self._limiter
558
+ ),
559
+ limiter=self._limiter,
560
+ )
561
+
562
+ def is_relative_to(self, other: str | PathLike[str]) -> bool:
563
+ try:
564
+ self.relative_to(other)
565
+ return True
566
+ except ValueError:
567
+ return False
568
+
569
+ async def chmod(self, mode: int, *, follow_symlinks: bool = True) -> None:
570
+ func = partial(os.chmod, follow_symlinks=follow_symlinks)
571
+ return await to_thread.run_sync(func, self._path, mode, limiter=self._limiter)
572
+
573
+ @classmethod
574
+ async def cwd(cls, *, limiter: CapacityLimiter | None = None) -> Self:
575
+ path = await to_thread.run_sync(pathlib.Path.cwd, limiter=limiter)
576
+ return cls(path, limiter=limiter)
577
+
578
+ if sys.version_info >= (3, 12):
579
+
580
+ async def exists(self, *, follow_symlinks: bool = True) -> bool:
581
+ return await to_thread.run_sync(
582
+ partial(self._path.exists, follow_symlinks=follow_symlinks),
583
+ abandon_on_cancel=True,
584
+ limiter=self._limiter,
585
+ )
586
+
587
+ else:
588
+
589
+ async def exists(self) -> bool:
590
+ return await to_thread.run_sync(
591
+ self._path.exists, abandon_on_cancel=True, limiter=self._limiter
592
+ )
593
+
594
+ async def expanduser(self) -> Self:
595
+ return type(self)(
596
+ await to_thread.run_sync(
597
+ self._path.expanduser, abandon_on_cancel=True, limiter=self._limiter
598
+ ),
599
+ limiter=self._limiter,
600
+ )
601
+
602
+ if sys.version_info < (3, 12):
603
+ # Python 3.11 and earlier
604
+ def glob(self, pattern: str) -> AsyncIterator[Self]:
605
+ gen = self._path.glob(pattern)
606
+ return _PathIterator(gen, self._limiter, type(self))
607
+ elif (3, 12) <= sys.version_info < (3, 13):
608
+ # changed in Python 3.12:
609
+ # - The case_sensitive parameter was added.
610
+ def glob(
611
+ self,
612
+ pattern: str,
613
+ *,
614
+ case_sensitive: bool | None = None,
615
+ ) -> AsyncIterator[Self]:
616
+ gen = self._path.glob(pattern, case_sensitive=case_sensitive)
617
+ return _PathIterator(gen, self._limiter, type(self))
618
+ elif sys.version_info >= (3, 13):
619
+ # Changed in Python 3.13:
620
+ # - The recurse_symlinks parameter was added.
621
+ # - The pattern parameter accepts a path-like object.
622
+ def glob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block
623
+ self,
624
+ pattern: str | PathLike[str],
625
+ *,
626
+ case_sensitive: bool | None = None,
627
+ recurse_symlinks: bool = False,
628
+ ) -> AsyncIterator[Self]:
629
+ gen = self._path.glob(
630
+ pattern, # type: ignore[arg-type]
631
+ case_sensitive=case_sensitive,
632
+ recurse_symlinks=recurse_symlinks,
633
+ )
634
+ return _PathIterator(gen, self._limiter, type(self))
635
+
636
+ if sys.version_info >= (3, 13):
637
+
638
+ async def group(self, *, follow_symlinks: bool = True) -> str:
639
+ return await to_thread.run_sync(
640
+ partial(self._path.group, follow_symlinks=follow_symlinks),
641
+ abandon_on_cancel=True,
642
+ limiter=self._limiter,
643
+ )
644
+
645
+ else:
646
+
647
+ async def group(self) -> str:
648
+ return await to_thread.run_sync(
649
+ self._path.group, abandon_on_cancel=True, limiter=self._limiter
650
+ )
651
+
652
+ async def hardlink_to(
653
+ self, target: str | bytes | PathLike[str] | PathLike[bytes]
654
+ ) -> None:
655
+ if isinstance(target, Path):
656
+ target = target._path
657
+
658
+ await to_thread.run_sync(os.link, target, self, limiter=self._limiter)
659
+
660
+ @classmethod
661
+ async def home(cls, *, limiter: CapacityLimiter | None = None) -> Self:
662
+ home_path = await to_thread.run_sync(pathlib.Path.home, limiter=limiter)
663
+ return cls(home_path, limiter=limiter)
664
+
665
+ def is_absolute(self) -> bool:
666
+ return self._path.is_absolute()
667
+
668
+ async def is_block_device(self) -> bool:
669
+ return await to_thread.run_sync(
670
+ self._path.is_block_device, abandon_on_cancel=True, limiter=self._limiter
671
+ )
672
+
673
+ async def is_char_device(self) -> bool:
674
+ return await to_thread.run_sync(
675
+ self._path.is_char_device, abandon_on_cancel=True, limiter=self._limiter
676
+ )
677
+
678
+ if sys.version_info >= (3, 13):
679
+
680
+ async def is_dir(self, *, follow_symlinks: bool = True) -> bool:
681
+ return await to_thread.run_sync(
682
+ partial(self._path.is_dir, follow_symlinks=follow_symlinks),
683
+ abandon_on_cancel=True,
684
+ limiter=self._limiter,
685
+ )
686
+
687
+ else:
688
+
689
+ async def is_dir(self) -> bool:
690
+ return await to_thread.run_sync(
691
+ self._path.is_dir, abandon_on_cancel=True, limiter=self._limiter
692
+ )
693
+
694
+ async def is_fifo(self) -> bool:
695
+ return await to_thread.run_sync(
696
+ self._path.is_fifo, abandon_on_cancel=True, limiter=self._limiter
697
+ )
698
+
699
+ if sys.version_info >= (3, 13):
700
+
701
+ async def is_file(self, *, follow_symlinks: bool = True) -> bool:
702
+ return await to_thread.run_sync(
703
+ partial(self._path.is_file, follow_symlinks=follow_symlinks),
704
+ abandon_on_cancel=True,
705
+ limiter=self._limiter,
706
+ )
707
+
708
+ else:
709
+
710
+ async def is_file(self) -> bool:
711
+ return await to_thread.run_sync(
712
+ self._path.is_file, abandon_on_cancel=True, limiter=self._limiter
713
+ )
714
+
715
+ if sys.version_info >= (3, 12):
716
+
717
+ async def is_junction(self) -> bool:
718
+ return await to_thread.run_sync(
719
+ self._path.is_junction, limiter=self._limiter
720
+ )
721
+
722
+ async def is_mount(self) -> bool:
723
+ return await to_thread.run_sync(
724
+ os.path.ismount, self._path, abandon_on_cancel=True, limiter=self._limiter
725
+ )
726
+
727
+ if sys.version_info < (3, 15):
728
+
729
+ def is_reserved(self) -> bool:
730
+ return self._path.is_reserved()
731
+
732
+ async def is_socket(self) -> bool:
733
+ return await to_thread.run_sync(
734
+ self._path.is_socket, abandon_on_cancel=True, limiter=self._limiter
735
+ )
736
+
737
+ async def is_symlink(self) -> bool:
738
+ return await to_thread.run_sync(
739
+ self._path.is_symlink, abandon_on_cancel=True, limiter=self._limiter
740
+ )
741
+
742
+ async def iterdir(self) -> AsyncIterator[Self]:
743
+ gen = (
744
+ self._path.iterdir()
745
+ if sys.version_info < (3, 13)
746
+ else await to_thread.run_sync(
747
+ self._path.iterdir, abandon_on_cancel=True, limiter=self._limiter
748
+ )
749
+ )
750
+ async for path in _PathIterator(gen, self._limiter, type(self)):
751
+ yield path
752
+
753
+ def joinpath(self, *args: str | PathLike[str]) -> Self:
754
+ return type(self)(self._path.joinpath(*args), limiter=self._limiter)
755
+
756
+ async def lchmod(self, mode: int) -> None:
757
+ await to_thread.run_sync(self._path.lchmod, mode, limiter=self._limiter)
758
+
759
+ async def lstat(self) -> os.stat_result:
760
+ return await to_thread.run_sync(
761
+ self._path.lstat, abandon_on_cancel=True, limiter=self._limiter
762
+ )
763
+
764
+ async def mkdir(
765
+ self, mode: int = 0o777, parents: bool = False, exist_ok: bool = False
766
+ ) -> None:
767
+ await to_thread.run_sync(
768
+ self._path.mkdir, mode, parents, exist_ok, limiter=self._limiter
769
+ )
770
+
771
+ @overload
772
+ async def open(
773
+ self,
774
+ mode: OpenBinaryMode,
775
+ buffering: int = ...,
776
+ encoding: str | None = ...,
777
+ errors: str | None = ...,
778
+ newline: str | None = ...,
779
+ ) -> AsyncFile[bytes]: ...
780
+
781
+ @overload
782
+ async def open(
783
+ self,
784
+ mode: OpenTextMode = ...,
785
+ buffering: int = ...,
786
+ encoding: str | None = ...,
787
+ errors: str | None = ...,
788
+ newline: str | None = ...,
789
+ ) -> AsyncFile[str]: ...
790
+
791
+ async def open(
792
+ self,
793
+ mode: str = "r",
794
+ buffering: int = -1,
795
+ encoding: str | None = None,
796
+ errors: str | None = None,
797
+ newline: str | None = None,
798
+ ) -> AsyncFile[Any]:
799
+ fp = await to_thread.run_sync(
800
+ self._path.open,
801
+ mode,
802
+ buffering,
803
+ encoding,
804
+ errors,
805
+ newline,
806
+ limiter=self._limiter,
807
+ )
808
+ return AsyncFile(fp, limiter=self._limiter)
809
+
810
+ if sys.version_info >= (3, 13):
811
+
812
+ async def owner(self, *, follow_symlinks: bool = True) -> str:
813
+ return await to_thread.run_sync(
814
+ partial(self._path.owner, follow_symlinks=follow_symlinks),
815
+ abandon_on_cancel=True,
816
+ limiter=self._limiter,
817
+ )
818
+
819
+ else:
820
+
821
+ async def owner(self) -> str:
822
+ return await to_thread.run_sync(
823
+ self._path.owner, abandon_on_cancel=True, limiter=self._limiter
824
+ )
825
+
826
+ async def read_bytes(self) -> bytes:
827
+ return await to_thread.run_sync(self._path.read_bytes, limiter=self._limiter)
828
+
829
+ if sys.version_info >= (3, 13):
830
+
831
+ async def read_text(
832
+ self,
833
+ encoding: str | None = None,
834
+ errors: str | None = None,
835
+ newline: str | None = None,
836
+ ) -> str:
837
+ return await to_thread.run_sync(
838
+ self._path.read_text,
839
+ encoding,
840
+ errors,
841
+ newline,
842
+ limiter=self._limiter,
843
+ )
844
+
845
+ else:
846
+
847
+ async def read_text(
848
+ self, encoding: str | None = None, errors: str | None = None
849
+ ) -> str:
850
+ return await to_thread.run_sync(
851
+ self._path.read_text, encoding, errors, limiter=self._limiter
852
+ )
853
+
854
+ if sys.version_info >= (3, 12):
855
+
856
+ def relative_to(
857
+ self, *other: str | PathLike[str], walk_up: bool = False
858
+ ) -> Self:
859
+ # relative_to() should work with any PathLike but it doesn't
860
+ others = [pathlib.Path(other) for other in other]
861
+ return type(self)(
862
+ self._path.relative_to(*others, walk_up=walk_up), limiter=self._limiter
863
+ )
864
+
865
+ else:
866
+
867
+ def relative_to(self, *other: str | PathLike[str]) -> Self:
868
+ return type(self)(self._path.relative_to(*other), limiter=self._limiter)
869
+
870
+ async def readlink(self) -> Self:
871
+ target = await to_thread.run_sync(
872
+ os.readlink, self._path, limiter=self._limiter
873
+ )
874
+ return type(self)(target, limiter=self._limiter)
875
+
876
+ async def rename(self, target: str | pathlib.PurePath | Path) -> Self:
877
+ if isinstance(target, Path):
878
+ target = target._path
879
+
880
+ await to_thread.run_sync(self._path.rename, target, limiter=self._limiter)
881
+ return type(self)(target, limiter=self._limiter)
882
+
883
+ async def replace(self, target: str | pathlib.PurePath | Path) -> Self:
884
+ if isinstance(target, Path):
885
+ target = target._path
886
+
887
+ await to_thread.run_sync(self._path.replace, target, limiter=self._limiter)
888
+ return type(self)(target, limiter=self._limiter)
889
+
890
+ async def resolve(self, strict: bool = False) -> Self:
891
+ func = partial(self._path.resolve, strict=strict)
892
+ return type(self)(
893
+ await to_thread.run_sync(
894
+ func, abandon_on_cancel=True, limiter=self._limiter
895
+ ),
896
+ limiter=self._limiter,
897
+ )
898
+
899
+ if sys.version_info < (3, 12):
900
+ # Pre Python 3.12
901
+ def rglob(self, pattern: str) -> AsyncIterator[Self]:
902
+ gen = self._path.rglob(pattern)
903
+ return _PathIterator(gen, self._limiter, type(self))
904
+ elif (3, 12) <= sys.version_info < (3, 13):
905
+ # Changed in Python 3.12:
906
+ # - The case_sensitive parameter was added.
907
+ def rglob(
908
+ self, pattern: str, *, case_sensitive: bool | None = None
909
+ ) -> AsyncIterator[Self]:
910
+ gen = self._path.rglob(pattern, case_sensitive=case_sensitive)
911
+ return _PathIterator(gen, self._limiter, type(self))
912
+ elif sys.version_info >= (3, 13):
913
+ # Changed in Python 3.13:
914
+ # - The recurse_symlinks parameter was added.
915
+ # - The pattern parameter accepts a path-like object.
916
+ def rglob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block
917
+ self,
918
+ pattern: str | PathLike[str],
919
+ *,
920
+ case_sensitive: bool | None = None,
921
+ recurse_symlinks: bool = False,
922
+ ) -> AsyncIterator[Self]:
923
+ gen = self._path.rglob(
924
+ pattern, # type: ignore[arg-type]
925
+ case_sensitive=case_sensitive,
926
+ recurse_symlinks=recurse_symlinks,
927
+ )
928
+ return _PathIterator(gen, self._limiter, type(self))
929
+
930
+ async def rmdir(self) -> None:
931
+ await to_thread.run_sync(self._path.rmdir, limiter=self._limiter)
932
+
933
+ async def samefile(self, other_path: str | PathLike[str]) -> bool:
934
+ if isinstance(other_path, Path):
935
+ other_path = other_path._path
936
+
937
+ return await to_thread.run_sync(
938
+ self._path.samefile,
939
+ other_path,
940
+ abandon_on_cancel=True,
941
+ limiter=self._limiter,
942
+ )
943
+
944
+ async def stat(self, *, follow_symlinks: bool = True) -> os.stat_result:
945
+ func = partial(os.stat, follow_symlinks=follow_symlinks)
946
+ return await to_thread.run_sync(
947
+ func, self._path, abandon_on_cancel=True, limiter=self._limiter
948
+ )
949
+
950
+ async def symlink_to(
951
+ self,
952
+ target: str | bytes | PathLike[str] | PathLike[bytes],
953
+ target_is_directory: bool = False,
954
+ ) -> None:
955
+ if isinstance(target, Path):
956
+ target = target._path
957
+
958
+ await to_thread.run_sync(
959
+ self._path.symlink_to, target, target_is_directory, limiter=self._limiter
960
+ )
961
+
962
+ async def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None:
963
+ await to_thread.run_sync(
964
+ self._path.touch, mode, exist_ok, limiter=self._limiter
965
+ )
966
+
967
+ async def unlink(self, missing_ok: bool = False) -> None:
968
+ try:
969
+ await to_thread.run_sync(self._path.unlink, limiter=self._limiter)
970
+ except FileNotFoundError:
971
+ if not missing_ok:
972
+ raise
973
+
974
+ if sys.version_info >= (3, 12):
975
+
976
+ async def walk(
977
+ self,
978
+ top_down: bool = True,
979
+ on_error: Callable[[OSError], object] | None = None,
980
+ follow_symlinks: bool = False,
981
+ ) -> AsyncIterator[tuple[Self, list[str], list[str]]]:
982
+ def get_next_value() -> tuple[pathlib.Path, list[str], list[str]] | None:
983
+ try:
984
+ return next(gen)
985
+ except StopIteration:
986
+ return None
987
+
988
+ gen = self._path.walk(top_down, on_error, follow_symlinks)
989
+ while True:
990
+ value = await to_thread.run_sync(get_next_value, limiter=self._limiter)
991
+ if value is None:
992
+ return
993
+
994
+ root, dirs, paths = value
995
+ yield type(self)(root, limiter=self._limiter), dirs, paths
996
+
997
+ def with_name(self, name: str) -> Self:
998
+ return type(self)(self._path.with_name(name), limiter=self._limiter)
999
+
1000
+ if sys.version_info < (3, 13):
1001
+ # Backport pathlib's Python>=3.13 behavior for empty stems on paths with non-empty suffixes.
1002
+ # See: https://github.com/python/cpython/pull/114612
1003
+ def with_stem(self, stem: str) -> Self:
1004
+ suffix = self._path.suffix
1005
+ if not suffix:
1006
+ return self.with_name(stem)
1007
+ elif not stem:
1008
+ # If the suffix is non-empty, we can't make the stem empty.
1009
+ raise ValueError(f"{self!r} has a non-empty suffix")
1010
+ else:
1011
+ return self.with_name(stem + suffix)
1012
+ else:
1013
+
1014
+ def with_stem(self, stem: str) -> Self:
1015
+ return type(self)(self._path.with_stem(stem), limiter=self._limiter)
1016
+
1017
+ def with_suffix(self, suffix: str) -> Self:
1018
+ return type(self)(self._path.with_suffix(suffix), limiter=self._limiter)
1019
+
1020
+ def with_segments(self, *pathsegments: str | PathLike[str]) -> Self:
1021
+ return type(self)(*pathsegments, limiter=self._limiter)
1022
+
1023
+ async def write_bytes(self, data: ReadableBuffer) -> int:
1024
+ return await to_thread.run_sync(
1025
+ self._path.write_bytes, data, limiter=self._limiter
1026
+ )
1027
+
1028
+ async def write_text(
1029
+ self,
1030
+ data: str,
1031
+ encoding: str | None = None,
1032
+ errors: str | None = None,
1033
+ newline: str | None = None,
1034
+ ) -> int:
1035
+ return await to_thread.run_sync(
1036
+ self._path.write_text,
1037
+ data,
1038
+ encoding,
1039
+ errors,
1040
+ newline,
1041
+ limiter=self._limiter,
1042
+ )
1043
+
1044
+
1045
+ PathLike.register(Path)
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_futures.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Generator
4
+ from enum import Enum, auto
5
+ from typing import Any, Generic, TypeVar
6
+
7
+ from ._exceptions import (
8
+ FutureAlreadyFinished,
9
+ FutureCancelled,
10
+ FutureFailed,
11
+ FutureNotFinished,
12
+ )
13
+ from ._synchronization import Event
14
+
15
+ T = TypeVar("T")
16
+
17
+
18
+ class Future(Generic[T]):
19
+ """
20
+ An awaitable object that works similar to a :class:`asyncio.Future` but
21
+ with similar characteristics to a :class:`.TaskHandle`.
22
+ """
23
+
24
+ class Status(Enum):
25
+ """
26
+ The status of a future handle.
27
+
28
+ .. attribute:: PENDING
29
+
30
+ The future has not finished yet.
31
+ .. attribute:: FINISHED
32
+
33
+ The future has finished with a return value.
34
+ .. attribute:: CANCELLED
35
+
36
+ The future was cancelled and has finished since.
37
+ .. attribute:: FAILED
38
+
39
+ The future raised an exception.
40
+ """
41
+
42
+ PENDING = auto()
43
+ FINISHED = auto()
44
+ CANCELLED = auto()
45
+ FAILED = auto()
46
+
47
+ __slots__ = (
48
+ "_cancelled",
49
+ "_exception",
50
+ "_finished_event",
51
+ "_name",
52
+ "_return_value",
53
+ )
54
+ _return_value: T
55
+
56
+ def __init__(self, *, name: str | None = None) -> None:
57
+ self._finished_event = Event()
58
+ self._exception: BaseException | None = None
59
+ self._cancelled: bool = False
60
+ self._name = name
61
+
62
+ def _check_pending(self) -> None:
63
+ """Shortcut for checking if a Future is pending
64
+
65
+ :raises FutureAlreadyFinished: if future was already given a result or exception.
66
+ :raises FutureCancelled: if future has been cancelled previously.
67
+ """
68
+ match self.status:
69
+ case Future.Status.PENDING:
70
+ return
71
+ case Future.Status.FINISHED:
72
+ raise FutureAlreadyFinished("future has already finished")
73
+ case Future.Status.FAILED:
74
+ raise FutureAlreadyFinished("future already failed")
75
+ case Future.Status.CANCELLED:
76
+ raise FutureCancelled("future was cancelled")
77
+
78
+ async def wait(self) -> None:
79
+ """
80
+ Waits for the future to finish.
81
+
82
+ This method will attempt to wait for a result or exception
83
+ """
84
+ await self._finished_event.wait()
85
+
86
+ def cancel(self) -> None:
87
+ """Cancels a pending `.Future` object
88
+
89
+ Does nothing if the Future was already finished.
90
+ """
91
+ if self.status is Future.Status.PENDING:
92
+ self._cancelled = True
93
+ self._finished_event.set()
94
+
95
+ @property
96
+ def exception(self) -> BaseException | None:
97
+ """
98
+ The exception value of a `.Future`
99
+
100
+ :raises FutureNotFinished: if future is still pending
101
+ :raises FutureCancelled: if future was cancelled
102
+ :returns: None if future succeeds with a result sent instead
103
+ otherwise this will be an exception
104
+ """
105
+
106
+ match self.status:
107
+ case Future.Status.PENDING:
108
+ raise FutureNotFinished("the future has not finished yet")
109
+ case Future.Status.FINISHED:
110
+ return None
111
+ case Future.Status.CANCELLED:
112
+ raise FutureCancelled("the future was cancelled")
113
+ case Future.Status.FAILED:
114
+ return self._exception
115
+
116
+ @exception.setter
117
+ def exception(self, exception: BaseException) -> None:
118
+ """Send exception for a `.Future` object
119
+
120
+ :raises FutureAlreadyFinished: if future was already given a result or exception.
121
+ :raises FutureCancelled: if future has been cancelled previously.
122
+ """
123
+ self._check_pending()
124
+ self._exception = exception
125
+ self._finished_event.set()
126
+
127
+ @property
128
+ def return_value(self) -> T:
129
+ """
130
+ The return value of the future.
131
+
132
+ :raises FutureNotFinished: if the future has not finished yet
133
+ :raises FutureCancelled: if the future was cancelled
134
+ :raises FutureFailed: if the future raised an exception
135
+
136
+ """
137
+ match self.status:
138
+ case Future.Status.PENDING:
139
+ raise FutureNotFinished("the future has not finished yet")
140
+ case Future.Status.FINISHED:
141
+ return self._return_value
142
+ case Future.Status.CANCELLED:
143
+ raise FutureCancelled("the future was cancelled")
144
+ case Future.Status.FAILED:
145
+ raise FutureFailed(
146
+ "the future raised an exception"
147
+ ) from self._exception
148
+
149
+ @return_value.setter
150
+ def return_value(self, value: T) -> None:
151
+ """
152
+ Send pending result for a `.Future` object
153
+
154
+ :raises FutureAlreadyFinished: if future was already given a result or exception.
155
+ :raises FutureCancelled: if future has been cancelled previously.
156
+ """
157
+ self._check_pending()
158
+ self._return_value = value
159
+ self._finished_event.set()
160
+
161
+ @property
162
+ def status(self) -> Future.Status:
163
+ """
164
+ The current status of a future.
165
+
166
+ Every future starts in the :attr:`~Future.Status.PENDING` state.
167
+ If a future is cancelled while in this state, it will transition to the
168
+ :attr:`Future.Status.CANCELLED` state. When the task finishes, it will
169
+ transition to one of the three final states (
170
+ :attr:`Future.Status.FINISHED`, :attr:`Future.Status.FAILED`, or
171
+ :attr:`Future.Status.CANCELLED`) depending on the exception the task
172
+ raised, if any. No other status transitions will happen.
173
+ """
174
+ if not self._finished_event.is_set():
175
+ return Future.Status.PENDING
176
+ elif self._cancelled:
177
+ return Future.Status.CANCELLED
178
+ elif self._exception is not None:
179
+ return Future.Status.FAILED
180
+ else:
181
+ return Future.Status.FINISHED
182
+
183
+ def __await__(self) -> Generator[Any, Any, T]:
184
+ yield from self.wait().__await__()
185
+ return self.return_value
186
+
187
+ def __repr__(self) -> str:
188
+ return (
189
+ f"<{self.__class__.__name__} {self.status.name.lower()} "
190
+ f"name={self._name!r}>"
191
+ )
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_resources.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ..abc import AsyncResource # noqa: TC001
4
+ from ._tasks import CancelScope
5
+
6
+
7
+ async def aclose_forcefully(resource: AsyncResource) -> None:
8
+ """
9
+ Close an asynchronous resource in a cancelled scope.
10
+
11
+ Doing this closes the resource without waiting on anything.
12
+
13
+ :param resource: the resource to close
14
+
15
+ """
16
+ with CancelScope() as scope:
17
+ scope.cancel()
18
+ await resource.aclose()
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_signals.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncIterator
4
+ from contextlib import AbstractContextManager
5
+ from signal import Signals
6
+
7
+ from ._eventloop import get_async_backend
8
+
9
+
10
+ def open_signal_receiver(
11
+ *signals: Signals,
12
+ ) -> AbstractContextManager[AsyncIterator[Signals]]:
13
+ """
14
+ Start receiving operating system signals.
15
+
16
+ :param signals: signals to receive (e.g. ``signal.SIGINT``)
17
+ :return: an asynchronous context manager for an asynchronous iterator which yields
18
+ signal numbers
19
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
20
+ current thread
21
+
22
+ .. warning:: Windows does not support signals natively so it is best to avoid
23
+ relying on this in cross-platform applications.
24
+
25
+ .. warning:: On asyncio, this permanently replaces any previous signal handler for
26
+ the given signals, as set via :meth:`~asyncio.loop.add_signal_handler`.
27
+
28
+ """
29
+ return get_async_backend().open_signal_receiver(*signals)
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_sockets.py ADDED
@@ -0,0 +1,1011 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import errno
4
+ import os
5
+ import socket
6
+ import ssl
7
+ import stat
8
+ import sys
9
+ from collections.abc import Awaitable
10
+ from dataclasses import dataclass
11
+ from ipaddress import IPv4Address, IPv6Address, ip_address
12
+ from os import PathLike, chmod
13
+ from socket import AddressFamily, SocketKind
14
+ from typing import TYPE_CHECKING, Any, Literal, cast, overload
15
+
16
+ from .. import ConnectionFailed, to_thread
17
+ from ..abc import (
18
+ ByteStreamConnectable,
19
+ ConnectedUDPSocket,
20
+ ConnectedUNIXDatagramSocket,
21
+ IPAddressType,
22
+ IPSockAddrType,
23
+ SocketListener,
24
+ SocketStream,
25
+ UDPSocket,
26
+ UNIXDatagramSocket,
27
+ UNIXSocketStream,
28
+ )
29
+ from ..streams.stapled import MultiListener
30
+ from ..streams.tls import TLSConnectable, TLSStream
31
+ from ._eventloop import get_async_backend
32
+ from ._resources import aclose_forcefully
33
+ from ._synchronization import Event
34
+ from ._tasks import create_task_group, move_on_after
35
+
36
+ if TYPE_CHECKING:
37
+ from _typeshed import FileDescriptorLike
38
+ else:
39
+ FileDescriptorLike = object
40
+
41
+ if sys.version_info < (3, 11):
42
+ from exceptiongroup import ExceptionGroup
43
+
44
+ if sys.version_info >= (3, 12):
45
+ from typing import override
46
+ else:
47
+ from typing_extensions import override
48
+
49
+ if sys.version_info < (3, 13):
50
+ from typing_extensions import deprecated
51
+ else:
52
+ from warnings import deprecated
53
+
54
+ IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) # https://bugs.python.org/issue29515
55
+
56
+ AnyIPAddressFamily = Literal[
57
+ AddressFamily.AF_UNSPEC, AddressFamily.AF_INET, AddressFamily.AF_INET6
58
+ ]
59
+ IPAddressFamily = Literal[AddressFamily.AF_INET, AddressFamily.AF_INET6]
60
+
61
+
62
+ def idna2008_resolve(host: str) -> bytes:
63
+ try:
64
+ return host.encode("ascii")
65
+ except UnicodeEncodeError:
66
+ import idna
67
+
68
+ return idna.encode(host, uts46=True)
69
+
70
+
71
+ # tls_hostname given
72
+ @overload
73
+ async def connect_tcp(
74
+ remote_host: IPAddressType,
75
+ remote_port: int,
76
+ *,
77
+ local_host: IPAddressType | None = ...,
78
+ local_port: int | None = ...,
79
+ ssl_context: ssl.SSLContext | None = ...,
80
+ tls_standard_compatible: bool = ...,
81
+ tls_hostname: str,
82
+ happy_eyeballs_delay: float = ...,
83
+ ) -> TLSStream: ...
84
+
85
+
86
+ # ssl_context given
87
+ @overload
88
+ async def connect_tcp(
89
+ remote_host: IPAddressType,
90
+ remote_port: int,
91
+ *,
92
+ local_host: IPAddressType | None = ...,
93
+ local_port: int | None = ...,
94
+ ssl_context: ssl.SSLContext,
95
+ tls_standard_compatible: bool = ...,
96
+ tls_hostname: str | None = ...,
97
+ happy_eyeballs_delay: float = ...,
98
+ ) -> TLSStream: ...
99
+
100
+
101
+ # tls=True
102
+ @overload
103
+ async def connect_tcp(
104
+ remote_host: IPAddressType,
105
+ remote_port: int,
106
+ *,
107
+ local_host: IPAddressType | None = ...,
108
+ local_port: int | None = ...,
109
+ tls: Literal[True],
110
+ ssl_context: ssl.SSLContext | None = ...,
111
+ tls_standard_compatible: bool = ...,
112
+ tls_hostname: str | None = ...,
113
+ happy_eyeballs_delay: float = ...,
114
+ ) -> TLSStream: ...
115
+
116
+
117
+ # tls=False
118
+ @overload
119
+ async def connect_tcp(
120
+ remote_host: IPAddressType,
121
+ remote_port: int,
122
+ *,
123
+ local_host: IPAddressType | None = ...,
124
+ local_port: int | None = ...,
125
+ tls: Literal[False],
126
+ ssl_context: ssl.SSLContext | None = ...,
127
+ tls_standard_compatible: bool = ...,
128
+ tls_hostname: str | None = ...,
129
+ happy_eyeballs_delay: float = ...,
130
+ ) -> SocketStream: ...
131
+
132
+
133
+ # No TLS arguments
134
+ @overload
135
+ async def connect_tcp(
136
+ remote_host: IPAddressType,
137
+ remote_port: int,
138
+ *,
139
+ local_host: IPAddressType | None = ...,
140
+ local_port: int | None = ...,
141
+ happy_eyeballs_delay: float = ...,
142
+ ) -> SocketStream: ...
143
+
144
+
145
+ async def connect_tcp(
146
+ remote_host: IPAddressType,
147
+ remote_port: int,
148
+ *,
149
+ local_host: IPAddressType | None = None,
150
+ local_port: int | None = None,
151
+ tls: bool = False,
152
+ ssl_context: ssl.SSLContext | None = None,
153
+ tls_standard_compatible: bool = True,
154
+ tls_hostname: str | None = None,
155
+ happy_eyeballs_delay: float = 0.25,
156
+ ) -> SocketStream | TLSStream:
157
+ """
158
+ Connect to a host using the TCP protocol.
159
+
160
+ This function implements the stateless version of the Happy Eyeballs algorithm (RFC
161
+ 6555). If ``remote_host`` is a host name that resolves to multiple IP addresses,
162
+ each one is tried until one connection attempt succeeds. If the first attempt does
163
+ not connected within 250 milliseconds, a second attempt is started using the next
164
+ address in the list, and so on. On IPv6 enabled systems, an IPv6 address (if
165
+ available) is tried first.
166
+
167
+ When the connection has been established, a TLS handshake will be done if either
168
+ ``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``.
169
+
170
+ :param remote_host: the IP address or host name to connect to
171
+ :param remote_port: port on the target host to connect to
172
+ :param local_host: the interface address or name to bind the socket to before
173
+ connecting
174
+ :param local_port: the local port to bind to (requires ``local_host`` to also be
175
+ set)
176
+ :param tls: ``True`` to do a TLS handshake with the connected stream and return a
177
+ :class:`~anyio.streams.tls.TLSStream` instead
178
+ :param ssl_context: the SSL context object to use (if omitted, a default context is
179
+ created)
180
+ :param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake
181
+ before closing the stream and requires that the server does this as well.
182
+ Otherwise, :exc:`~ssl.SSLEOFError` may be raised during reads from the stream.
183
+ Some protocols, such as HTTP, require this option to be ``False``.
184
+ See :meth:`~ssl.SSLContext.wrap_socket` for details.
185
+ :param tls_hostname: host name to check the server certificate against (defaults to
186
+ the value of ``remote_host``)
187
+ :param happy_eyeballs_delay: delay (in seconds) before starting the next connection
188
+ attempt
189
+ :return: a socket stream object if no TLS handshake was done, otherwise a TLS stream
190
+ :raises ConnectionFailed: if the connection fails
191
+
192
+ """
193
+ # Placed here due to https://github.com/python/mypy/issues/7057
194
+ connected_stream: SocketStream | None = None
195
+
196
+ async def try_connect(remote_host: str, event: Event) -> None:
197
+ nonlocal connected_stream
198
+ try:
199
+ stream = await asynclib.connect_tcp(remote_host, remote_port, local_address)
200
+ except OSError as exc:
201
+ oserrors.append(exc)
202
+ return
203
+ else:
204
+ if connected_stream is None:
205
+ connected_stream = stream
206
+ tg.cancel_scope.cancel()
207
+ else:
208
+ await stream.aclose()
209
+ finally:
210
+ event.set()
211
+
212
+ asynclib = get_async_backend()
213
+ local_address: IPSockAddrType | None = None
214
+ family = socket.AF_UNSPEC
215
+ if local_host:
216
+ gai_res = await getaddrinfo(str(local_host), local_port)
217
+ family, *_, local_address = gai_res[0]
218
+
219
+ target_host = str(remote_host)
220
+ try:
221
+ addr_obj = ip_address(remote_host)
222
+ except ValueError:
223
+ addr_obj = None
224
+
225
+ if addr_obj is not None:
226
+ if isinstance(addr_obj, IPv6Address):
227
+ target_addrs = [(socket.AF_INET6, addr_obj.compressed)]
228
+ else:
229
+ target_addrs = [(socket.AF_INET, addr_obj.compressed)]
230
+ else:
231
+ # getaddrinfo() will raise an exception if name resolution fails
232
+ gai_res = await getaddrinfo(
233
+ target_host, remote_port, family=family, type=socket.SOCK_STREAM
234
+ )
235
+
236
+ # Organize the list so that the first address is an IPv6 address (if available)
237
+ # and the second one is an IPv4 addresses. The rest can be in whatever order.
238
+ v6_found = v4_found = False
239
+ target_addrs = []
240
+ for af, *_, sa in gai_res:
241
+ if af == socket.AF_INET6 and not v6_found:
242
+ v6_found = True
243
+ target_addrs.insert(0, (af, sa[0]))
244
+ elif af == socket.AF_INET and not v4_found and v6_found:
245
+ v4_found = True
246
+ target_addrs.insert(1, (af, sa[0]))
247
+ else:
248
+ target_addrs.append((af, sa[0]))
249
+
250
+ oserrors: list[OSError] = []
251
+ try:
252
+ async with create_task_group() as tg:
253
+ for _af, addr in target_addrs:
254
+ event = Event()
255
+ tg.start_soon(try_connect, addr, event)
256
+ with move_on_after(happy_eyeballs_delay):
257
+ await event.wait()
258
+
259
+ if connected_stream is None:
260
+ cause = (
261
+ oserrors[0]
262
+ if len(oserrors) == 1
263
+ else ExceptionGroup("multiple connection attempts failed", oserrors)
264
+ )
265
+ raise OSError("All connection attempts failed") from cause
266
+ finally:
267
+ oserrors.clear()
268
+
269
+ if tls or tls_hostname or ssl_context:
270
+ try:
271
+ return await TLSStream.wrap(
272
+ connected_stream,
273
+ server_side=False,
274
+ hostname=tls_hostname or str(remote_host),
275
+ ssl_context=ssl_context,
276
+ standard_compatible=tls_standard_compatible,
277
+ )
278
+ except BaseException:
279
+ await aclose_forcefully(connected_stream)
280
+ raise
281
+
282
+ return connected_stream
283
+
284
+
285
+ async def connect_unix(path: str | bytes | PathLike[Any]) -> UNIXSocketStream:
286
+ """
287
+ Connect to the given UNIX socket.
288
+
289
+ Not available on Windows.
290
+
291
+ :param path: path to the socket
292
+ :return: a socket stream object
293
+ :raises ConnectionFailed: if the connection fails
294
+
295
+ """
296
+ path = os.fspath(path)
297
+ return await get_async_backend().connect_unix(path)
298
+
299
+
300
+ async def create_tcp_listener(
301
+ *,
302
+ local_host: IPAddressType | None = None,
303
+ local_port: int = 0,
304
+ family: AnyIPAddressFamily = socket.AddressFamily.AF_UNSPEC,
305
+ backlog: int = 65536,
306
+ reuse_port: bool = False,
307
+ ) -> MultiListener[SocketStream]:
308
+ """
309
+ Create a TCP socket listener.
310
+
311
+ :param local_port: port number to listen on
312
+ :param local_host: IP address of the interface to listen on. If omitted, listen on
313
+ all IPv4 and IPv6 interfaces. To listen on all interfaces on a specific address
314
+ family, use ``0.0.0.0`` for IPv4 or ``::`` for IPv6.
315
+ :param family: address family (used if ``local_host`` was omitted)
316
+ :param backlog: maximum number of queued incoming connections (up to a maximum of
317
+ 2**16, or 65536)
318
+ :param reuse_port: ``True`` to allow multiple sockets to bind to the same
319
+ address/port (not supported on Windows)
320
+ :return: a multi-listener object containing one or more socket listeners
321
+ :raises OSError: if there's an error creating a socket, or binding to one or more
322
+ interfaces failed
323
+
324
+ """
325
+ asynclib = get_async_backend()
326
+ backlog = min(backlog, 65536)
327
+ local_host = str(local_host) if local_host is not None else None
328
+
329
+ def setup_raw_socket(
330
+ fam: AddressFamily,
331
+ bind_addr: tuple[str, int] | tuple[str, int, int, int],
332
+ *,
333
+ v6only: bool = True,
334
+ ) -> socket.socket:
335
+ sock = socket.socket(fam)
336
+ try:
337
+ sock.setblocking(False)
338
+
339
+ if fam == AddressFamily.AF_INET6:
340
+ sock.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, v6only)
341
+
342
+ # For Windows, enable exclusive address use. For others, enable address
343
+ # reuse.
344
+ if sys.platform == "win32":
345
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1)
346
+ else:
347
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
348
+
349
+ if reuse_port:
350
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
351
+
352
+ # Workaround for #554
353
+ if fam == socket.AF_INET6 and "%" in bind_addr[0]:
354
+ addr, scope_id = bind_addr[0].split("%", 1)
355
+ bind_addr = (addr, bind_addr[1], 0, int(scope_id))
356
+
357
+ sock.bind(bind_addr)
358
+ sock.listen(backlog)
359
+ except BaseException:
360
+ sock.close()
361
+ raise
362
+
363
+ return sock
364
+
365
+ # We passing type=0 on non-Windows platforms as a workaround for a uvloop bug
366
+ # where we don't get the correct scope ID for IPv6 link-local addresses when passing
367
+ # type=socket.SOCK_STREAM to getaddrinfo():
368
+ # https://github.com/MagicStack/uvloop/issues/539
369
+ gai_res = await getaddrinfo(
370
+ local_host,
371
+ local_port,
372
+ family=family,
373
+ type=socket.SOCK_STREAM if sys.platform == "win32" else 0,
374
+ flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG,
375
+ )
376
+
377
+ # The set comprehension is here to work around a glibc bug:
378
+ # https://sourceware.org/bugzilla/show_bug.cgi?id=14969
379
+ sockaddrs = sorted({res for res in gai_res if res[1] == SocketKind.SOCK_STREAM})
380
+
381
+ # Special case for dual-stack binding on the "any" interface
382
+ if (
383
+ local_host is None
384
+ and family == AddressFamily.AF_UNSPEC
385
+ and socket.has_dualstack_ipv6()
386
+ and any(fam == AddressFamily.AF_INET6 for fam, *_ in gai_res)
387
+ ):
388
+ raw_socket = setup_raw_socket(
389
+ AddressFamily.AF_INET6, ("::", local_port), v6only=False
390
+ )
391
+ listener = asynclib.create_tcp_listener(raw_socket)
392
+ return MultiListener([listener])
393
+
394
+ errors: list[OSError] = []
395
+ try:
396
+ for _ in range(len(sockaddrs)):
397
+ listeners: list[SocketListener] = []
398
+ bound_ephemeral_port = local_port
399
+ try:
400
+ for fam, *_, sockaddr in sockaddrs:
401
+ sockaddr = sockaddr[0], bound_ephemeral_port, *sockaddr[2:]
402
+ raw_socket = setup_raw_socket(fam, sockaddr)
403
+
404
+ # Store the assigned port if an ephemeral port was requested, so
405
+ # we'll bind to the same port on all interfaces
406
+ if local_port == 0 and len(gai_res) > 1:
407
+ bound_ephemeral_port = raw_socket.getsockname()[1]
408
+
409
+ listeners.append(asynclib.create_tcp_listener(raw_socket))
410
+ except BaseException as exc:
411
+ for listener in listeners:
412
+ await listener.aclose()
413
+
414
+ # If an ephemeral port was requested but binding the assigned port
415
+ # failed for another interface, rotate the address list and try again
416
+ if (
417
+ isinstance(exc, OSError)
418
+ and exc.errno == errno.EADDRINUSE
419
+ and local_port == 0
420
+ and bound_ephemeral_port
421
+ ):
422
+ errors.append(exc)
423
+ sockaddrs.append(sockaddrs.pop(0))
424
+ continue
425
+
426
+ raise
427
+
428
+ return MultiListener(listeners)
429
+
430
+ raise OSError(
431
+ f"Could not create {len(sockaddrs)} listeners with a consistent port"
432
+ ) from ExceptionGroup("Several bind attempts failed", errors)
433
+ finally:
434
+ del errors # Prevent reference cycles
435
+
436
+
437
+ async def create_unix_listener(
438
+ path: str | bytes | PathLike[Any],
439
+ *,
440
+ mode: int | None = None,
441
+ backlog: int = 65536,
442
+ ) -> SocketListener:
443
+ """
444
+ Create a UNIX socket listener.
445
+
446
+ Not available on Windows.
447
+
448
+ :param path: path of the socket
449
+ :param mode: permissions to set on the socket
450
+ :param backlog: maximum number of queued incoming connections (up to a maximum of
451
+ 2**16, or 65536)
452
+ :return: a listener object
453
+
454
+ .. versionchanged:: 3.0
455
+ If a socket already exists on the file system in the given path, it will be
456
+ removed first.
457
+
458
+ """
459
+ backlog = min(backlog, 65536)
460
+ raw_socket = await setup_unix_local_socket(path, mode, socket.SOCK_STREAM)
461
+ try:
462
+ raw_socket.listen(backlog)
463
+ return get_async_backend().create_unix_listener(raw_socket)
464
+ except BaseException:
465
+ raw_socket.close()
466
+ raise
467
+
468
+
469
+ async def create_udp_socket(
470
+ family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC,
471
+ *,
472
+ local_host: IPAddressType | None = None,
473
+ local_port: int = 0,
474
+ reuse_port: bool = False,
475
+ ) -> UDPSocket:
476
+ """
477
+ Create a UDP socket.
478
+
479
+ If ``port`` has been given, the socket will be bound to this port on the local
480
+ machine, making this socket suitable for providing UDP based services.
481
+
482
+ :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically
483
+ determined from ``local_host`` if omitted
484
+ :param local_host: IP address or host name of the local interface to bind to
485
+ :param local_port: local port to bind to
486
+ :param reuse_port: ``True`` to allow multiple sockets to bind to the same
487
+ address/port (not supported on Windows)
488
+ :return: a UDP socket
489
+
490
+ """
491
+ if family is AddressFamily.AF_UNSPEC and not local_host:
492
+ raise ValueError('Either "family" or "local_host" must be given')
493
+
494
+ if local_host:
495
+ gai_res = await getaddrinfo(
496
+ str(local_host),
497
+ local_port,
498
+ family=family,
499
+ type=socket.SOCK_DGRAM,
500
+ flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG,
501
+ )
502
+ family = cast(AnyIPAddressFamily, gai_res[0][0])
503
+ local_address = gai_res[0][-1]
504
+ elif family is AddressFamily.AF_INET6:
505
+ local_address = ("::", 0)
506
+ else:
507
+ local_address = ("0.0.0.0", 0)
508
+
509
+ sock = await get_async_backend().create_udp_socket(
510
+ family, local_address, None, reuse_port
511
+ )
512
+ return cast(UDPSocket, sock)
513
+
514
+
515
+ async def create_connected_udp_socket(
516
+ remote_host: IPAddressType,
517
+ remote_port: int,
518
+ *,
519
+ family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC,
520
+ local_host: IPAddressType | None = None,
521
+ local_port: int = 0,
522
+ reuse_port: bool = False,
523
+ ) -> ConnectedUDPSocket:
524
+ """
525
+ Create a connected UDP socket.
526
+
527
+ Connected UDP sockets can only communicate with the specified remote host/port, an
528
+ any packets sent from other sources are dropped.
529
+
530
+ :param remote_host: remote host to set as the default target
531
+ :param remote_port: port on the remote host to set as the default target
532
+ :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically
533
+ determined from ``local_host`` or ``remote_host`` if omitted
534
+ :param local_host: IP address or host name of the local interface to bind to
535
+ :param local_port: local port to bind to
536
+ :param reuse_port: ``True`` to allow multiple sockets to bind to the same
537
+ address/port (not supported on Windows)
538
+ :return: a connected UDP socket
539
+
540
+ """
541
+ local_address = None
542
+ if local_host:
543
+ gai_res = await getaddrinfo(
544
+ str(local_host),
545
+ local_port,
546
+ family=family,
547
+ type=socket.SOCK_DGRAM,
548
+ flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG,
549
+ )
550
+ family = cast(AnyIPAddressFamily, gai_res[0][0])
551
+ local_address = gai_res[0][-1]
552
+
553
+ gai_res = await getaddrinfo(
554
+ str(remote_host), remote_port, family=family, type=socket.SOCK_DGRAM
555
+ )
556
+ family = cast(AnyIPAddressFamily, gai_res[0][0])
557
+ remote_address = gai_res[0][-1]
558
+
559
+ sock = await get_async_backend().create_udp_socket(
560
+ family, local_address, remote_address, reuse_port
561
+ )
562
+ return cast(ConnectedUDPSocket, sock)
563
+
564
+
565
+ async def create_unix_datagram_socket(
566
+ *,
567
+ local_path: None | str | bytes | PathLike[Any] = None,
568
+ local_mode: int | None = None,
569
+ ) -> UNIXDatagramSocket:
570
+ """
571
+ Create a UNIX datagram socket.
572
+
573
+ Not available on Windows.
574
+
575
+ If ``local_path`` has been given, the socket will be bound to this path, making this
576
+ socket suitable for receiving datagrams from other processes. Other processes can
577
+ send datagrams to this socket only if ``local_path`` is set.
578
+
579
+ If a socket already exists on the file system in the ``local_path``, it will be
580
+ removed first.
581
+
582
+ :param local_path: the path on which to bind to
583
+ :param local_mode: permissions to set on the local socket
584
+ :return: a UNIX datagram socket
585
+
586
+ """
587
+ raw_socket = await setup_unix_local_socket(
588
+ local_path, local_mode, socket.SOCK_DGRAM
589
+ )
590
+ return await get_async_backend().create_unix_datagram_socket(raw_socket, None)
591
+
592
+
593
+ async def create_connected_unix_datagram_socket(
594
+ remote_path: str | bytes | PathLike[Any],
595
+ *,
596
+ local_path: None | str | bytes | PathLike[Any] = None,
597
+ local_mode: int | None = None,
598
+ ) -> ConnectedUNIXDatagramSocket:
599
+ """
600
+ Create a connected UNIX datagram socket.
601
+
602
+ Connected datagram sockets can only communicate with the specified remote path.
603
+
604
+ If ``local_path`` has been given, the socket will be bound to this path, making
605
+ this socket suitable for receiving datagrams from other processes. Other processes
606
+ can send datagrams to this socket only if ``local_path`` is set.
607
+
608
+ If a socket already exists on the file system in the ``local_path``, it will be
609
+ removed first.
610
+
611
+ :param remote_path: the path to set as the default target
612
+ :param local_path: the path on which to bind to
613
+ :param local_mode: permissions to set on the local socket
614
+ :return: a connected UNIX datagram socket
615
+
616
+ """
617
+ remote_path = os.fspath(remote_path)
618
+ raw_socket = await setup_unix_local_socket(
619
+ local_path, local_mode, socket.SOCK_DGRAM
620
+ )
621
+ return await get_async_backend().create_unix_datagram_socket(
622
+ raw_socket, remote_path
623
+ )
624
+
625
+
626
+ async def getaddrinfo(
627
+ host: bytes | str | None,
628
+ port: str | int | None,
629
+ *,
630
+ family: int | AddressFamily = 0,
631
+ type: int | SocketKind = 0,
632
+ proto: int = 0,
633
+ flags: int = 0,
634
+ ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int]]]:
635
+ """
636
+ Look up a numeric IP address given a host name.
637
+
638
+ Internationalized domain names are translated according to the (non-transitional)
639
+ IDNA 2008 standard.
640
+
641
+ .. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of
642
+ (host, port), unlike what :func:`socket.getaddrinfo` does.
643
+
644
+ :param host: host name
645
+ :param port: port number
646
+ :param family: socket family (`'AF_INET``, ...)
647
+ :param type: socket type (``SOCK_STREAM``, ...)
648
+ :param proto: protocol number
649
+ :param flags: flags to pass to upstream ``getaddrinfo()``
650
+ :return: list of tuples containing (family, type, proto, canonname, sockaddr)
651
+
652
+ .. seealso:: :func:`socket.getaddrinfo`
653
+
654
+ """
655
+ # Handle unicode hostnames
656
+ encoded_host = idna2008_resolve(host) if isinstance(host, str) else host
657
+ gai_res = await get_async_backend().getaddrinfo(
658
+ encoded_host, port, family=family, type=type, proto=proto, flags=flags
659
+ )
660
+ return [
661
+ (family, type, proto, canonname, convert_ipv6_sockaddr(sockaddr))
662
+ for family, type, proto, canonname, sockaddr in gai_res
663
+ # filter out IPv6 results when IPv6 is disabled
664
+ if not isinstance(sockaddr[0], int)
665
+ ]
666
+
667
+
668
+ def getnameinfo(sockaddr: IPSockAddrType, flags: int = 0) -> Awaitable[tuple[str, str]]:
669
+ """
670
+ Look up the host name of an IP address.
671
+
672
+ :param sockaddr: socket address (e.g. (ipaddress, port) for IPv4)
673
+ :param flags: flags to pass to upstream ``getnameinfo()``
674
+ :return: a tuple of (host name, service name)
675
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
676
+ current thread
677
+
678
+ .. seealso:: :func:`socket.getnameinfo`
679
+
680
+ """
681
+ return get_async_backend().getnameinfo(sockaddr, flags)
682
+
683
+
684
+ @deprecated("This function is deprecated; use `wait_readable` instead")
685
+ def wait_socket_readable(sock: socket.socket) -> Awaitable[None]:
686
+ """
687
+ .. deprecated:: 4.7.0
688
+ Use :func:`wait_readable` instead.
689
+
690
+ Wait until the given socket has data to be read.
691
+
692
+ .. warning:: Only use this on raw sockets that have not been wrapped by any higher
693
+ level constructs like socket streams!
694
+
695
+ :param sock: a socket object
696
+ :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the
697
+ socket to become readable
698
+ :raises ~anyio.BusyResourceError: if another task is already waiting for the socket
699
+ to become readable
700
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
701
+ current thread
702
+
703
+ """
704
+ return get_async_backend().wait_readable(sock.fileno())
705
+
706
+
707
+ @deprecated("This function is deprecated; use `wait_writable` instead")
708
+ def wait_socket_writable(sock: socket.socket) -> Awaitable[None]:
709
+ """
710
+ .. deprecated:: 4.7.0
711
+ Use :func:`wait_writable` instead.
712
+
713
+ Wait until the given socket can be written to.
714
+
715
+ This does **NOT** work on Windows when using the asyncio backend with a proactor
716
+ event loop (default on py3.8+).
717
+
718
+ .. warning:: Only use this on raw sockets that have not been wrapped by any higher
719
+ level constructs like socket streams!
720
+
721
+ :param sock: a socket object
722
+ :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the
723
+ socket to become writable
724
+ :raises ~anyio.BusyResourceError: if another task is already waiting for the socket
725
+ to become writable
726
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
727
+ current thread
728
+
729
+ """
730
+ return get_async_backend().wait_writable(sock.fileno())
731
+
732
+
733
+ def wait_readable(obj: FileDescriptorLike) -> Awaitable[None]:
734
+ """
735
+ Wait until the given object has data to be read.
736
+
737
+ On Unix systems, ``obj`` must either be an integer file descriptor, or else an
738
+ object with a ``.fileno()`` method which returns an integer file descriptor. Any
739
+ kind of file descriptor can be passed, though the exact semantics will depend on
740
+ your kernel. For example, this probably won't do anything useful for on-disk files.
741
+
742
+ On Windows systems, ``obj`` must either be an integer ``SOCKET`` handle, or else an
743
+ object with a ``.fileno()`` method which returns an integer ``SOCKET`` handle. File
744
+ descriptors aren't supported, and neither are handles that refer to anything besides
745
+ a ``SOCKET``.
746
+
747
+ On backends where this functionality is not natively provided (asyncio
748
+ ``ProactorEventLoop`` on Windows), it is provided using a separate selector thread
749
+ which is set to shut down when the interpreter shuts down.
750
+
751
+ .. warning:: Don't use this on raw sockets that have been wrapped by any higher
752
+ level constructs like socket streams!
753
+
754
+ :param obj: an object with a ``.fileno()`` method or an integer handle
755
+ :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the
756
+ object to become readable
757
+ :raises ~anyio.BusyResourceError: if another task is already waiting for the object
758
+ to become readable
759
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
760
+ current thread
761
+
762
+ """
763
+ return get_async_backend().wait_readable(obj)
764
+
765
+
766
+ def wait_writable(obj: FileDescriptorLike) -> Awaitable[None]:
767
+ """
768
+ Wait until the given object can be written to.
769
+
770
+ :param obj: an object with a ``.fileno()`` method or an integer handle
771
+ :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the
772
+ object to become writable
773
+ :raises ~anyio.BusyResourceError: if another task is already waiting for the object
774
+ to become writable
775
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
776
+ current thread
777
+
778
+ .. seealso:: See the documentation of :func:`wait_readable` for the definition of
779
+ ``obj`` and notes on backend compatibility.
780
+
781
+ .. warning:: Don't use this on raw sockets that have been wrapped by any higher
782
+ level constructs like socket streams!
783
+
784
+ """
785
+ return get_async_backend().wait_writable(obj)
786
+
787
+
788
+ def notify_closing(obj: FileDescriptorLike) -> None:
789
+ """
790
+ Call this before closing a file descriptor (on Unix) or socket (on
791
+ Windows). This will cause any `wait_readable` or `wait_writable`
792
+ calls on the given object to immediately wake up and raise
793
+ `~anyio.ClosedResourceError`.
794
+
795
+ This doesn't actually close the object – you still have to do that
796
+ yourself afterwards. Also, you want to be careful to make sure no
797
+ new tasks start waiting on the object in between when you call this
798
+ and when it's actually closed. So to close something properly, you
799
+ usually want to do these steps in order:
800
+
801
+ 1. Explicitly mark the object as closed, so that any new attempts
802
+ to use it will abort before they start.
803
+ 2. Call `notify_closing` to wake up any already-existing users.
804
+ 3. Actually close the object.
805
+
806
+ It's also possible to do them in a different order if that's more
807
+ convenient, *but only if* you make sure not to have any checkpoints in
808
+ between the steps. This way they all happen in a single atomic
809
+ step, so other tasks won't be able to tell what order they happened
810
+ in anyway.
811
+
812
+ :param obj: an object with a ``.fileno()`` method or an integer handle
813
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
814
+ current thread
815
+
816
+ """
817
+ get_async_backend().notify_closing(obj)
818
+
819
+
820
+ #
821
+ # Private API
822
+ #
823
+
824
+
825
+ def convert_ipv6_sockaddr(
826
+ sockaddr: tuple[str, int, int, int] | tuple[str, int],
827
+ ) -> tuple[str, int]:
828
+ """
829
+ Convert a 4-tuple IPv6 socket address to a 2-tuple (address, port) format.
830
+
831
+ If the scope ID is nonzero, it is added to the address, separated with ``%``.
832
+ Otherwise the flow id and scope id are simply cut off from the tuple.
833
+ Any other kinds of socket addresses are returned as-is.
834
+
835
+ :param sockaddr: the result of :meth:`~socket.socket.getsockname`
836
+ :return: the converted socket address
837
+
838
+ """
839
+ # This is more complicated than it should be because of MyPy
840
+ if isinstance(sockaddr, tuple) and len(sockaddr) == 4:
841
+ host, port, _flowinfo, scope_id = sockaddr
842
+ if scope_id:
843
+ # PyPy (as of v7.3.11) leaves the interface name in the result, so
844
+ # we discard it and only get the scope ID from the end
845
+ # (https://foss.heptapod.net/pypy/pypy/-/issues/3938)
846
+ host = host.split("%")[0]
847
+
848
+ # Add scope_id to the address
849
+ return f"{host}%{scope_id}", port
850
+ else:
851
+ return host, port
852
+ else:
853
+ return sockaddr
854
+
855
+
856
+ async def setup_unix_local_socket(
857
+ path: None | str | bytes | PathLike[Any],
858
+ mode: int | None,
859
+ socktype: int,
860
+ ) -> socket.socket:
861
+ """
862
+ Create a UNIX local socket object, deleting the socket at the given path if it
863
+ exists.
864
+
865
+ Not available on Windows.
866
+
867
+ :param path: path of the socket
868
+ :param mode: permissions to set on the socket
869
+ :param socktype: socket.SOCK_STREAM or socket.SOCK_DGRAM
870
+
871
+ """
872
+ path_str: str | None
873
+ if path is not None:
874
+ path_str = os.fsdecode(path)
875
+
876
+ # Linux abstract namespace sockets aren't backed by a concrete file so skip stat call
877
+ if not path_str.startswith("\0"):
878
+ # Copied from pathlib...
879
+ try:
880
+ stat_result = os.stat(path)
881
+ except OSError as e:
882
+ if e.errno not in (
883
+ errno.ENOENT,
884
+ errno.ENOTDIR,
885
+ errno.EBADF,
886
+ errno.ELOOP,
887
+ ):
888
+ raise
889
+ else:
890
+ if stat.S_ISSOCK(stat_result.st_mode):
891
+ os.unlink(path)
892
+ else:
893
+ path_str = None
894
+
895
+ raw_socket = socket.socket(socket.AF_UNIX, socktype)
896
+ raw_socket.setblocking(False)
897
+
898
+ if path_str is not None:
899
+ try:
900
+ await to_thread.run_sync(raw_socket.bind, path_str, abandon_on_cancel=True)
901
+ if mode is not None:
902
+ await to_thread.run_sync(chmod, path_str, mode, abandon_on_cancel=True)
903
+ except BaseException:
904
+ raw_socket.close()
905
+ raise
906
+
907
+ return raw_socket
908
+
909
+
910
+ @dataclass
911
+ class TCPConnectable(ByteStreamConnectable):
912
+ """
913
+ Connects to a TCP server at the given host and port.
914
+
915
+ :param host: host name or IP address of the server
916
+ :param port: TCP port number of the server
917
+ """
918
+
919
+ host: str | IPv4Address | IPv6Address
920
+ port: int
921
+
922
+ def __post_init__(self) -> None:
923
+ if self.port < 1 or self.port > 65535:
924
+ raise ValueError("TCP port number out of range")
925
+
926
+ @override
927
+ async def connect(self) -> SocketStream:
928
+ try:
929
+ return await connect_tcp(self.host, self.port)
930
+ except OSError as exc:
931
+ raise ConnectionFailed(
932
+ f"error connecting to {self.host}:{self.port}: {exc}"
933
+ ) from exc
934
+
935
+
936
+ @dataclass
937
+ class UNIXConnectable(ByteStreamConnectable):
938
+ """
939
+ Connects to a UNIX domain socket at the given path.
940
+
941
+ :param path: the file system path of the socket
942
+ """
943
+
944
+ path: str | bytes | PathLike[str] | PathLike[bytes]
945
+
946
+ @override
947
+ async def connect(self) -> UNIXSocketStream:
948
+ try:
949
+ return await connect_unix(self.path)
950
+ except OSError as exc:
951
+ raise ConnectionFailed(f"error connecting to {self.path!r}: {exc}") from exc
952
+
953
+
954
+ def as_connectable(
955
+ remote: ByteStreamConnectable
956
+ | tuple[str | IPv4Address | IPv6Address, int]
957
+ | str
958
+ | bytes
959
+ | PathLike[str],
960
+ /,
961
+ *,
962
+ tls: bool = False,
963
+ ssl_context: ssl.SSLContext | None = None,
964
+ tls_hostname: str | None = None,
965
+ tls_standard_compatible: bool = True,
966
+ ) -> ByteStreamConnectable:
967
+ """
968
+ Return a byte stream connectable from the given object.
969
+
970
+ If a bytestream connectable is given, it is returned unchanged.
971
+ If a tuple of (host, port) is given, a TCP connectable is returned.
972
+ If a string or bytes path is given, a UNIX connectable is returned.
973
+
974
+ If ``tls=True``, the connectable will be wrapped in a
975
+ :class:`~.streams.tls.TLSConnectable`.
976
+
977
+ :param remote: a connectable, a tuple of (host, port) or a path to a UNIX socket
978
+ :param tls: if ``True``, wrap the plaintext connectable in a
979
+ :class:`~.streams.tls.TLSConnectable`, using the provided TLS settings)
980
+ :param ssl_context: if ``tls=True``, the SSLContext object to use (if not provided,
981
+ a secure default will be created)
982
+ :param tls_hostname: if ``tls=True``, host name of the server to use for checking
983
+ the server certificate (defaults to the host portion of the address for TCP
984
+ connectables)
985
+ :param tls_standard_compatible: if ``False`` and ``tls=True``, makes the TLS stream
986
+ skip the closing handshake when closing the connection, so it won't raise an
987
+ exception if the server does the same
988
+
989
+ """
990
+ connectable: TCPConnectable | UNIXConnectable | TLSConnectable
991
+ if isinstance(remote, ByteStreamConnectable):
992
+ return remote
993
+ elif isinstance(remote, tuple) and len(remote) == 2:
994
+ connectable = TCPConnectable(*remote)
995
+ elif isinstance(remote, (str, bytes, PathLike)):
996
+ connectable = UNIXConnectable(remote)
997
+ else:
998
+ raise TypeError(f"cannot convert {remote!r} to a connectable")
999
+
1000
+ if tls:
1001
+ if not tls_hostname and isinstance(connectable, TCPConnectable):
1002
+ tls_hostname = str(connectable.host)
1003
+
1004
+ connectable = TLSConnectable(
1005
+ connectable,
1006
+ ssl_context=ssl_context,
1007
+ hostname=tls_hostname,
1008
+ standard_compatible=tls_standard_compatible,
1009
+ )
1010
+
1011
+ return connectable
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_streams.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ from typing import TypeVar
5
+ from warnings import warn
6
+
7
+ from ..streams.memory import (
8
+ MemoryObjectReceiveStream,
9
+ MemoryObjectSendStream,
10
+ _MemoryObjectStreamState,
11
+ )
12
+
13
+ T_Item = TypeVar("T_Item")
14
+
15
+
16
+ class create_memory_object_stream(
17
+ tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]],
18
+ ):
19
+ """
20
+ Create a memory object stream.
21
+
22
+ The stream's item type can be annotated like
23
+ :func:`create_memory_object_stream[T_Item]`.
24
+
25
+ :param max_buffer_size: number of items held in the buffer until ``send()`` starts
26
+ blocking
27
+ :param item_type: old way of marking the streams with the right generic type for
28
+ static typing (does nothing on AnyIO 4)
29
+
30
+ .. deprecated:: 4.0
31
+ Use ``create_memory_object_stream[YourItemType](...)`` instead.
32
+ :return: a tuple of (send stream, receive stream)
33
+
34
+ """
35
+
36
+ def __new__( # type: ignore[misc]
37
+ cls, max_buffer_size: float = 0, item_type: object = None
38
+ ) -> tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]]:
39
+ if max_buffer_size != math.inf and not isinstance(max_buffer_size, int):
40
+ raise ValueError("max_buffer_size must be either an integer or math.inf")
41
+ if max_buffer_size < 0:
42
+ raise ValueError("max_buffer_size cannot be negative")
43
+ if item_type is not None:
44
+ warn(
45
+ "The item_type argument has been deprecated in AnyIO 4.0. "
46
+ "Use create_memory_object_stream[YourItemType](...) instead.",
47
+ DeprecationWarning,
48
+ stacklevel=2,
49
+ )
50
+
51
+ state = _MemoryObjectStreamState[T_Item](max_buffer_size)
52
+ return (MemoryObjectSendStream(state), MemoryObjectReceiveStream(state))
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_subprocesses.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncIterable, Iterable, Mapping, Sequence
4
+ from io import BytesIO
5
+ from os import PathLike
6
+ from subprocess import PIPE, CalledProcessError, CompletedProcess
7
+ from typing import IO, Any, TypeAlias, cast
8
+
9
+ from ..abc import Process # noqa: TC001
10
+ from ._eventloop import get_async_backend
11
+ from ._tasks import create_task_group
12
+
13
+ StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes]
14
+
15
+
16
+ async def run_process(
17
+ command: StrOrBytesPath | Sequence[StrOrBytesPath],
18
+ *,
19
+ input: bytes | None = None,
20
+ stdin: int | IO[Any] | None = None,
21
+ stdout: int | IO[Any] | None = PIPE,
22
+ stderr: int | IO[Any] | None = PIPE,
23
+ check: bool = True,
24
+ cwd: StrOrBytesPath | None = None,
25
+ env: Mapping[str, str] | None = None,
26
+ startupinfo: Any = None,
27
+ creationflags: int = 0,
28
+ start_new_session: bool = False,
29
+ pass_fds: Sequence[int] = (),
30
+ user: str | int | None = None,
31
+ group: str | int | None = None,
32
+ extra_groups: Iterable[str | int] | None = None,
33
+ umask: int = -1,
34
+ ) -> CompletedProcess[bytes]:
35
+ """
36
+ Run an external command in a subprocess and wait until it completes.
37
+
38
+ .. seealso:: :func:`subprocess.run`
39
+
40
+ :param command: either a string to pass to the shell, or an iterable of strings
41
+ containing the executable name or path and its arguments
42
+ :param input: bytes passed to the standard input of the subprocess
43
+ :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`,
44
+ a file-like object, or `None`; ``input`` overrides this
45
+ :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`,
46
+ a file-like object, or `None`
47
+ :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`,
48
+ :data:`subprocess.STDOUT`, a file-like object, or `None`
49
+ :param check: if ``True``, raise :exc:`~subprocess.CalledProcessError` if the
50
+ process terminates with a return code other than 0
51
+ :param cwd: If not ``None``, change the working directory to this before running the
52
+ command
53
+ :param env: if not ``None``, this mapping replaces the inherited environment
54
+ variables from the parent process
55
+ :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used
56
+ to specify process startup parameters (Windows only)
57
+ :param creationflags: flags that can be used to control the creation of the
58
+ subprocess (see :class:`subprocess.Popen` for the specifics)
59
+ :param start_new_session: if ``true`` the setsid() system call will be made in the
60
+ child process prior to the execution of the subprocess. (POSIX only)
61
+ :param pass_fds: sequence of file descriptors to keep open between the parent and
62
+ child processes. (POSIX only)
63
+ :param user: effective user to run the process as (Python >= 3.9, POSIX only)
64
+ :param group: effective group to run the process as (Python >= 3.9, POSIX only)
65
+ :param extra_groups: supplementary groups to set in the subprocess (Python >= 3.9,
66
+ POSIX only)
67
+ :param umask: if not negative, this umask is applied in the child process before
68
+ running the given command (Python >= 3.9, POSIX only)
69
+ :return: an object representing the completed process
70
+ :raises ~subprocess.CalledProcessError: if ``check`` is ``True`` and the process
71
+ exits with a nonzero return code
72
+
73
+ """
74
+
75
+ async def drain_stream(stream: AsyncIterable[bytes], index: int) -> None:
76
+ buffer = BytesIO()
77
+ async for chunk in stream:
78
+ buffer.write(chunk)
79
+
80
+ stream_contents[index] = buffer.getvalue()
81
+
82
+ if stdin is not None and input is not None:
83
+ raise ValueError("only one of stdin and input is allowed")
84
+
85
+ async with await open_process(
86
+ command,
87
+ stdin=PIPE if input else stdin,
88
+ stdout=stdout,
89
+ stderr=stderr,
90
+ cwd=cwd,
91
+ env=env,
92
+ startupinfo=startupinfo,
93
+ creationflags=creationflags,
94
+ start_new_session=start_new_session,
95
+ pass_fds=pass_fds,
96
+ user=user,
97
+ group=group,
98
+ extra_groups=extra_groups,
99
+ umask=umask,
100
+ ) as process:
101
+ stream_contents: list[bytes | None] = [None, None]
102
+ async with create_task_group() as tg:
103
+ if process.stdout:
104
+ tg.start_soon(drain_stream, process.stdout, 0)
105
+
106
+ if process.stderr:
107
+ tg.start_soon(drain_stream, process.stderr, 1)
108
+
109
+ if process.stdin and input:
110
+ await process.stdin.send(input)
111
+ await process.stdin.aclose()
112
+
113
+ await process.wait()
114
+
115
+ output, errors = stream_contents
116
+ if check and process.returncode != 0:
117
+ raise CalledProcessError(cast(int, process.returncode), command, output, errors)
118
+
119
+ return CompletedProcess(command, cast(int, process.returncode), output, errors)
120
+
121
+
122
+ async def open_process(
123
+ command: StrOrBytesPath | Sequence[StrOrBytesPath],
124
+ *,
125
+ stdin: int | IO[Any] | None = PIPE,
126
+ stdout: int | IO[Any] | None = PIPE,
127
+ stderr: int | IO[Any] | None = PIPE,
128
+ cwd: StrOrBytesPath | None = None,
129
+ env: Mapping[str, str] | None = None,
130
+ startupinfo: Any = None,
131
+ creationflags: int = 0,
132
+ start_new_session: bool = False,
133
+ pass_fds: Sequence[int] = (),
134
+ user: str | int | None = None,
135
+ group: str | int | None = None,
136
+ extra_groups: Iterable[str | int] | None = None,
137
+ umask: int = -1,
138
+ ) -> Process:
139
+ """
140
+ Start an external command in a subprocess.
141
+
142
+ .. seealso:: :class:`subprocess.Popen`
143
+
144
+ :param command: either a string to pass to the shell, or an iterable of strings
145
+ containing the executable name or path and its arguments
146
+ :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, a
147
+ file-like object, or ``None``
148
+ :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`,
149
+ a file-like object, or ``None``
150
+ :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`,
151
+ :data:`subprocess.STDOUT`, a file-like object, or ``None``
152
+ :param cwd: If not ``None``, the working directory is changed before executing
153
+ :param env: If env is not ``None``, it must be a mapping that defines the
154
+ environment variables for the new process
155
+ :param creationflags: flags that can be used to control the creation of the
156
+ subprocess (see :class:`subprocess.Popen` for the specifics)
157
+ :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used
158
+ to specify process startup parameters (Windows only)
159
+ :param start_new_session: if ``true`` the setsid() system call will be made in the
160
+ child process prior to the execution of the subprocess. (POSIX only)
161
+ :param pass_fds: sequence of file descriptors to keep open between the parent and
162
+ child processes. (POSIX only)
163
+ :param user: effective user to run the process as (POSIX only)
164
+ :param group: effective group to run the process as (POSIX only)
165
+ :param extra_groups: supplementary groups to set in the subprocess (POSIX only)
166
+ :param umask: if not negative, this umask is applied in the child process before
167
+ running the given command (POSIX only)
168
+ :return: an asynchronous process object
169
+
170
+ """
171
+ kwargs: dict[str, Any] = {}
172
+ if user is not None:
173
+ kwargs["user"] = user
174
+
175
+ if group is not None:
176
+ kwargs["group"] = group
177
+
178
+ if extra_groups is not None:
179
+ kwargs["extra_groups"] = extra_groups
180
+
181
+ if umask >= 0:
182
+ kwargs["umask"] = umask
183
+
184
+ return await get_async_backend().open_process(
185
+ command,
186
+ stdin=stdin,
187
+ stdout=stdout,
188
+ stderr=stderr,
189
+ cwd=cwd,
190
+ env=env,
191
+ startupinfo=startupinfo,
192
+ creationflags=creationflags,
193
+ start_new_session=start_new_session,
194
+ pass_fds=pass_fds,
195
+ **kwargs,
196
+ )
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_synchronization.py ADDED
@@ -0,0 +1,778 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import sys
5
+ from collections import deque
6
+ from collections.abc import Callable
7
+ from dataclasses import dataclass
8
+ from types import TracebackType
9
+ from typing import TypeVar
10
+
11
+ from ..lowlevel import checkpoint_if_cancelled
12
+ from ._eventloop import get_async_backend
13
+ from ._exceptions import BusyResourceError, NoEventLoopError
14
+ from ._tasks import CancelScope
15
+ from ._testing import TaskInfo, get_current_task
16
+
17
+ if sys.version_info >= (3, 11):
18
+ from typing import Self
19
+ else:
20
+ from typing_extensions import Self
21
+
22
+ T = TypeVar("T")
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class EventStatistics:
27
+ """
28
+ :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Event.wait`
29
+ """
30
+
31
+ tasks_waiting: int
32
+
33
+
34
+ @dataclass(frozen=True)
35
+ class CapacityLimiterStatistics:
36
+ """
37
+ :ivar int borrowed_tokens: number of tokens currently borrowed by tasks
38
+ :ivar float total_tokens: total number of available tokens
39
+ :ivar tuple borrowers: tasks or other objects currently holding tokens borrowed from
40
+ this limiter
41
+ :ivar int tasks_waiting: number of tasks waiting on
42
+ :meth:`~.CapacityLimiter.acquire` or
43
+ :meth:`~.CapacityLimiter.acquire_on_behalf_of`
44
+ """
45
+
46
+ borrowed_tokens: int
47
+ total_tokens: float
48
+ borrowers: tuple[object, ...]
49
+ tasks_waiting: int
50
+
51
+
52
+ @dataclass(frozen=True)
53
+ class LockStatistics:
54
+ """
55
+ :ivar bool locked: flag indicating if this lock is locked or not
56
+ :ivar ~anyio.TaskInfo owner: task currently holding the lock (or ``None`` if the
57
+ lock is not held by any task)
58
+ :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Lock.acquire`
59
+ """
60
+
61
+ locked: bool
62
+ owner: TaskInfo | None
63
+ tasks_waiting: int
64
+
65
+
66
+ @dataclass(frozen=True)
67
+ class ConditionStatistics:
68
+ """
69
+ :ivar int tasks_waiting: number of tasks blocked on :meth:`~.Condition.wait`
70
+ :ivar ~anyio.LockStatistics lock_statistics: statistics of the underlying
71
+ :class:`~.Lock`
72
+ """
73
+
74
+ tasks_waiting: int
75
+ lock_statistics: LockStatistics
76
+
77
+
78
+ @dataclass(frozen=True)
79
+ class SemaphoreStatistics:
80
+ """
81
+ :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Semaphore.acquire`
82
+
83
+ """
84
+
85
+ tasks_waiting: int
86
+
87
+
88
+ class Event:
89
+ __slots__ = ("__weakref__",)
90
+
91
+ def __new__(cls) -> Event:
92
+ try:
93
+ return get_async_backend().create_event()
94
+ except NoEventLoopError:
95
+ return EventAdapter()
96
+
97
+ def set(self) -> None:
98
+ """Set the flag, notifying all listeners."""
99
+ raise NotImplementedError
100
+
101
+ def is_set(self) -> bool:
102
+ """Return ``True`` if the flag is set, ``False`` if not."""
103
+ raise NotImplementedError
104
+
105
+ async def wait(self) -> None:
106
+ """
107
+ Wait until the flag has been set.
108
+
109
+ If the flag has already been set when this method is called, it returns
110
+ immediately.
111
+
112
+ """
113
+ raise NotImplementedError
114
+
115
+ def statistics(self) -> EventStatistics:
116
+ """Return statistics about the current state of this event."""
117
+ raise NotImplementedError
118
+
119
+
120
+ class EventAdapter(Event):
121
+ __slots__ = "_internal_event", "_is_set"
122
+
123
+ def __new__(cls) -> Self:
124
+ return object.__new__(cls)
125
+
126
+ def __init__(self) -> None:
127
+ self._internal_event: Event | None = None
128
+ self._is_set = False
129
+
130
+ @property
131
+ def _event(self) -> Event:
132
+ if self._internal_event is None:
133
+ self._internal_event = get_async_backend().create_event()
134
+ if self._is_set:
135
+ self._internal_event.set()
136
+
137
+ return self._internal_event
138
+
139
+ def set(self) -> None:
140
+ if self._internal_event is None:
141
+ self._is_set = True
142
+ else:
143
+ self._event.set()
144
+
145
+ def is_set(self) -> bool:
146
+ if self._internal_event is None:
147
+ return self._is_set
148
+
149
+ return self._internal_event.is_set()
150
+
151
+ async def wait(self) -> None:
152
+ await self._event.wait()
153
+
154
+ def statistics(self) -> EventStatistics:
155
+ if self._internal_event is None:
156
+ return EventStatistics(tasks_waiting=0)
157
+
158
+ return self._internal_event.statistics()
159
+
160
+
161
+ class Lock:
162
+ __slots__ = ("__weakref__",)
163
+
164
+ def __new__(cls, *, fast_acquire: bool = False) -> Lock:
165
+ try:
166
+ return get_async_backend().create_lock(fast_acquire=fast_acquire)
167
+ except NoEventLoopError:
168
+ return LockAdapter(fast_acquire=fast_acquire)
169
+
170
+ async def __aenter__(self) -> None:
171
+ await self.acquire()
172
+
173
+ async def __aexit__(
174
+ self,
175
+ exc_type: type[BaseException] | None,
176
+ exc_val: BaseException | None,
177
+ exc_tb: TracebackType | None,
178
+ ) -> None:
179
+ self.release()
180
+
181
+ async def acquire(self) -> None:
182
+ """Acquire the lock."""
183
+ raise NotImplementedError
184
+
185
+ def acquire_nowait(self) -> None:
186
+ """
187
+ Acquire the lock, without blocking.
188
+
189
+ :raises ~anyio.WouldBlock: if the operation would block
190
+
191
+ """
192
+ raise NotImplementedError
193
+
194
+ def release(self) -> None:
195
+ """Release the lock."""
196
+ raise NotImplementedError
197
+
198
+ def locked(self) -> bool:
199
+ """Return True if the lock is currently held."""
200
+ raise NotImplementedError
201
+
202
+ def statistics(self) -> LockStatistics:
203
+ """
204
+ Return statistics about the current state of this lock.
205
+
206
+ .. versionadded:: 3.0
207
+ """
208
+ raise NotImplementedError
209
+
210
+
211
+ class LockAdapter(Lock):
212
+ __slots__ = "_fast_acquire", "_internal_lock"
213
+
214
+ def __new__(cls, *, fast_acquire: bool = False) -> Self:
215
+ return object.__new__(cls)
216
+
217
+ def __init__(self, *, fast_acquire: bool = False):
218
+ self._internal_lock: Lock | None = None
219
+ self._fast_acquire = fast_acquire
220
+
221
+ @property
222
+ def _lock(self) -> Lock:
223
+ if self._internal_lock is None:
224
+ self._internal_lock = get_async_backend().create_lock(
225
+ fast_acquire=self._fast_acquire
226
+ )
227
+
228
+ return self._internal_lock
229
+
230
+ async def __aenter__(self) -> None:
231
+ await self._lock.acquire()
232
+
233
+ async def __aexit__(
234
+ self,
235
+ exc_type: type[BaseException] | None,
236
+ exc_val: BaseException | None,
237
+ exc_tb: TracebackType | None,
238
+ ) -> None:
239
+ if self._internal_lock is not None:
240
+ self._internal_lock.release()
241
+
242
+ async def acquire(self) -> None:
243
+ """Acquire the lock."""
244
+ await self._lock.acquire()
245
+
246
+ def acquire_nowait(self) -> None:
247
+ """
248
+ Acquire the lock, without blocking.
249
+
250
+ :raises ~anyio.WouldBlock: if the operation would block
251
+
252
+ """
253
+ self._lock.acquire_nowait()
254
+
255
+ def release(self) -> None:
256
+ """Release the lock."""
257
+ self._lock.release()
258
+
259
+ def locked(self) -> bool:
260
+ """Return True if the lock is currently held."""
261
+ return self._lock.locked()
262
+
263
+ def statistics(self) -> LockStatistics:
264
+ """
265
+ Return statistics about the current state of this lock.
266
+
267
+ .. versionadded:: 3.0
268
+
269
+ """
270
+ if self._internal_lock is None:
271
+ return LockStatistics(False, None, 0)
272
+
273
+ return self._internal_lock.statistics()
274
+
275
+
276
+ class Condition:
277
+ __slots__ = "__weakref__", "_lock", "_owner_task", "_waiters"
278
+
279
+ def __init__(self, lock: Lock | None = None):
280
+ self._owner_task: TaskInfo | None = None
281
+ self._lock = lock or Lock()
282
+ self._waiters: deque[Event] = deque()
283
+
284
+ async def __aenter__(self) -> None:
285
+ await self.acquire()
286
+
287
+ async def __aexit__(
288
+ self,
289
+ exc_type: type[BaseException] | None,
290
+ exc_val: BaseException | None,
291
+ exc_tb: TracebackType | None,
292
+ ) -> None:
293
+ self.release()
294
+
295
+ def _check_acquired(self) -> None:
296
+ if self._owner_task != get_current_task():
297
+ raise RuntimeError("The current task is not holding the underlying lock")
298
+
299
+ async def acquire(self) -> None:
300
+ """Acquire the underlying lock."""
301
+ await self._lock.acquire()
302
+ self._owner_task = get_current_task()
303
+
304
+ def acquire_nowait(self) -> None:
305
+ """
306
+ Acquire the underlying lock, without blocking.
307
+
308
+ :raises ~anyio.WouldBlock: if the operation would block
309
+
310
+ """
311
+ self._lock.acquire_nowait()
312
+ self._owner_task = get_current_task()
313
+
314
+ def release(self) -> None:
315
+ """Release the underlying lock."""
316
+ self._lock.release()
317
+
318
+ def locked(self) -> bool:
319
+ """Return True if the lock is set."""
320
+ return self._lock.locked()
321
+
322
+ def notify(self, n: int = 1) -> None:
323
+ """Notify exactly n listeners."""
324
+ self._check_acquired()
325
+ for _ in range(n):
326
+ try:
327
+ event = self._waiters.popleft()
328
+ except IndexError:
329
+ break
330
+
331
+ event.set()
332
+
333
+ def notify_all(self) -> None:
334
+ """Notify all the listeners."""
335
+ self._check_acquired()
336
+ for event in self._waiters:
337
+ event.set()
338
+
339
+ self._waiters.clear()
340
+
341
+ async def wait(self) -> None:
342
+ """Wait for a notification."""
343
+ await checkpoint_if_cancelled()
344
+ self._check_acquired()
345
+ event = Event()
346
+ self._waiters.append(event)
347
+ self.release()
348
+ try:
349
+ await event.wait()
350
+ except BaseException:
351
+ if not event.is_set():
352
+ self._waiters.remove(event)
353
+ elif self._waiters:
354
+ # This task was notified by could not act on it, so pass
355
+ # it on to the next task
356
+ self._waiters.popleft().set()
357
+
358
+ raise
359
+ finally:
360
+ with CancelScope(shield=True):
361
+ await self.acquire()
362
+
363
+ async def wait_for(self, predicate: Callable[[], T]) -> T:
364
+ """
365
+ Wait until a predicate becomes true.
366
+
367
+ :param predicate: a callable that returns a truthy value when the condition is
368
+ met
369
+ :return: the result of the predicate
370
+
371
+ .. versionadded:: 4.11.0
372
+
373
+ """
374
+ while not (result := predicate()):
375
+ await self.wait()
376
+
377
+ return result
378
+
379
+ def statistics(self) -> ConditionStatistics:
380
+ """
381
+ Return statistics about the current state of this condition.
382
+
383
+ .. versionadded:: 3.0
384
+ """
385
+ return ConditionStatistics(len(self._waiters), self._lock.statistics())
386
+
387
+
388
+ class Semaphore:
389
+ __slots__ = "__weakref__", "_fast_acquire"
390
+
391
+ def __new__(
392
+ cls,
393
+ initial_value: int,
394
+ *,
395
+ max_value: int | None = None,
396
+ fast_acquire: bool = False,
397
+ ) -> Semaphore:
398
+ try:
399
+ return get_async_backend().create_semaphore(
400
+ initial_value, max_value=max_value, fast_acquire=fast_acquire
401
+ )
402
+ except NoEventLoopError:
403
+ return SemaphoreAdapter(initial_value, max_value=max_value)
404
+
405
+ def __init__(
406
+ self,
407
+ initial_value: int,
408
+ *,
409
+ max_value: int | None = None,
410
+ fast_acquire: bool = False,
411
+ ):
412
+ if not isinstance(initial_value, int):
413
+ raise TypeError("initial_value must be an integer")
414
+ if initial_value < 0:
415
+ raise ValueError("initial_value must be >= 0")
416
+ if max_value is not None:
417
+ if not isinstance(max_value, int):
418
+ raise TypeError("max_value must be an integer or None")
419
+ if max_value < initial_value:
420
+ raise ValueError(
421
+ "max_value must be equal to or higher than initial_value"
422
+ )
423
+
424
+ self._fast_acquire = fast_acquire
425
+
426
+ async def __aenter__(self) -> Self:
427
+ await self.acquire()
428
+ return self
429
+
430
+ async def __aexit__(
431
+ self,
432
+ exc_type: type[BaseException] | None,
433
+ exc_val: BaseException | None,
434
+ exc_tb: TracebackType | None,
435
+ ) -> None:
436
+ self.release()
437
+
438
+ async def acquire(self) -> None:
439
+ """Decrement the semaphore value, blocking if necessary."""
440
+ raise NotImplementedError
441
+
442
+ def acquire_nowait(self) -> None:
443
+ """
444
+ Acquire the underlying lock, without blocking.
445
+
446
+ :raises ~anyio.WouldBlock: if the operation would block
447
+
448
+ """
449
+ raise NotImplementedError
450
+
451
+ def release(self) -> None:
452
+ """Increment the semaphore value."""
453
+ raise NotImplementedError
454
+
455
+ @property
456
+ def value(self) -> int:
457
+ """The current value of the semaphore."""
458
+ raise NotImplementedError
459
+
460
+ @property
461
+ def max_value(self) -> int | None:
462
+ """The maximum value of the semaphore."""
463
+ raise NotImplementedError
464
+
465
+ def statistics(self) -> SemaphoreStatistics:
466
+ """
467
+ Return statistics about the current state of this semaphore.
468
+
469
+ .. versionadded:: 3.0
470
+ """
471
+ raise NotImplementedError
472
+
473
+
474
+ class SemaphoreAdapter(Semaphore):
475
+ __slots__ = "_initial_value", "_internal_semaphore", "_max_value"
476
+
477
+ def __new__(
478
+ cls,
479
+ initial_value: int,
480
+ *,
481
+ max_value: int | None = None,
482
+ fast_acquire: bool = False,
483
+ ) -> Self:
484
+ return object.__new__(cls)
485
+
486
+ def __init__(
487
+ self,
488
+ initial_value: int,
489
+ *,
490
+ max_value: int | None = None,
491
+ fast_acquire: bool = False,
492
+ ) -> None:
493
+ super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire)
494
+ self._internal_semaphore: Semaphore | None = None
495
+ self._initial_value = initial_value
496
+ self._max_value = max_value
497
+
498
+ @property
499
+ def _semaphore(self) -> Semaphore:
500
+ if self._internal_semaphore is None:
501
+ self._internal_semaphore = get_async_backend().create_semaphore(
502
+ self._initial_value, max_value=self._max_value
503
+ )
504
+
505
+ return self._internal_semaphore
506
+
507
+ async def acquire(self) -> None:
508
+ await self._semaphore.acquire()
509
+
510
+ def acquire_nowait(self) -> None:
511
+ self._semaphore.acquire_nowait()
512
+
513
+ def release(self) -> None:
514
+ self._semaphore.release()
515
+
516
+ @property
517
+ def value(self) -> int:
518
+ if self._internal_semaphore is None:
519
+ return self._initial_value
520
+
521
+ return self._semaphore.value
522
+
523
+ @property
524
+ def max_value(self) -> int | None:
525
+ return self._max_value
526
+
527
+ def statistics(self) -> SemaphoreStatistics:
528
+ if self._internal_semaphore is None:
529
+ return SemaphoreStatistics(tasks_waiting=0)
530
+
531
+ return self._semaphore.statistics()
532
+
533
+
534
+ class CapacityLimiter:
535
+ __slots__ = ("__weakref__",)
536
+
537
+ def __new__(cls, total_tokens: float) -> CapacityLimiter:
538
+ try:
539
+ return get_async_backend().create_capacity_limiter(total_tokens)
540
+ except NoEventLoopError:
541
+ return CapacityLimiterAdapter(total_tokens)
542
+
543
+ async def __aenter__(self) -> None:
544
+ raise NotImplementedError
545
+
546
+ async def __aexit__(
547
+ self,
548
+ exc_type: type[BaseException] | None,
549
+ exc_val: BaseException | None,
550
+ exc_tb: TracebackType | None,
551
+ ) -> None:
552
+ raise NotImplementedError
553
+
554
+ @property
555
+ def total_tokens(self) -> float:
556
+ """
557
+ The total number of tokens available for borrowing.
558
+
559
+ This is a read-write property. If the total number of tokens is increased, the
560
+ proportionate number of tasks waiting on this limiter will be granted their
561
+ tokens.
562
+
563
+ .. versionchanged:: 3.0
564
+ The property is now writable.
565
+ .. versionchanged:: 4.12
566
+ The value can now be set to 0.
567
+
568
+ """
569
+ raise NotImplementedError
570
+
571
+ @total_tokens.setter
572
+ def total_tokens(self, value: float) -> None:
573
+ raise NotImplementedError
574
+
575
+ @property
576
+ def borrowed_tokens(self) -> int:
577
+ """The number of tokens that have currently been borrowed."""
578
+ raise NotImplementedError
579
+
580
+ @property
581
+ def available_tokens(self) -> float:
582
+ """The number of tokens currently available to be borrowed"""
583
+ raise NotImplementedError
584
+
585
+ def acquire_nowait(self) -> None:
586
+ """
587
+ Acquire a token for the current task without waiting for one to become
588
+ available.
589
+
590
+ :raises ~anyio.WouldBlock: if there are no tokens available for borrowing
591
+
592
+ """
593
+ raise NotImplementedError
594
+
595
+ def acquire_on_behalf_of_nowait(self, borrower: object) -> None:
596
+ """
597
+ Acquire a token without waiting for one to become available.
598
+
599
+ :param borrower: the entity borrowing a token
600
+ :raises ~anyio.WouldBlock: if there are no tokens available for borrowing
601
+
602
+ """
603
+ raise NotImplementedError
604
+
605
+ async def acquire(self) -> None:
606
+ """
607
+ Acquire a token for the current task, waiting if necessary for one to become
608
+ available.
609
+
610
+ """
611
+ raise NotImplementedError
612
+
613
+ async def acquire_on_behalf_of(self, borrower: object) -> None:
614
+ """
615
+ Acquire a token, waiting if necessary for one to become available.
616
+
617
+ :param borrower: the entity borrowing a token
618
+
619
+ """
620
+ raise NotImplementedError
621
+
622
+ def release(self) -> None:
623
+ """
624
+ Release the token held by the current task.
625
+
626
+ :raises RuntimeError: if the current task has not borrowed a token from this
627
+ limiter.
628
+
629
+ """
630
+ raise NotImplementedError
631
+
632
+ def release_on_behalf_of(self, borrower: object) -> None:
633
+ """
634
+ Release the token held by the given borrower.
635
+
636
+ :raises RuntimeError: if the borrower has not borrowed a token from this
637
+ limiter.
638
+
639
+ """
640
+ raise NotImplementedError
641
+
642
+ def statistics(self) -> CapacityLimiterStatistics:
643
+ """
644
+ Return statistics about the current state of this limiter.
645
+
646
+ .. versionadded:: 3.0
647
+
648
+ """
649
+ raise NotImplementedError
650
+
651
+
652
+ class CapacityLimiterAdapter(CapacityLimiter):
653
+ __slots__ = "_internal_limiter", "_total_tokens"
654
+
655
+ def __new__(cls, total_tokens: float) -> Self:
656
+ return object.__new__(cls)
657
+
658
+ def __init__(self, total_tokens: float) -> None:
659
+ self._internal_limiter: CapacityLimiter | None = None
660
+ self.total_tokens = total_tokens
661
+
662
+ @property
663
+ def _limiter(self) -> CapacityLimiter:
664
+ if self._internal_limiter is None:
665
+ self._internal_limiter = get_async_backend().create_capacity_limiter(
666
+ self._total_tokens
667
+ )
668
+
669
+ return self._internal_limiter
670
+
671
+ async def __aenter__(self) -> None:
672
+ await self._limiter.__aenter__()
673
+
674
+ async def __aexit__(
675
+ self,
676
+ exc_type: type[BaseException] | None,
677
+ exc_val: BaseException | None,
678
+ exc_tb: TracebackType | None,
679
+ ) -> None:
680
+ return await self._limiter.__aexit__(exc_type, exc_val, exc_tb)
681
+
682
+ @property
683
+ def total_tokens(self) -> float:
684
+ if self._internal_limiter is None:
685
+ return self._total_tokens
686
+
687
+ return self._internal_limiter.total_tokens
688
+
689
+ @total_tokens.setter
690
+ def total_tokens(self, value: float) -> None:
691
+ if not isinstance(value, int) and not math.isinf(value):
692
+ raise TypeError("total_tokens must be an int or math.inf")
693
+ elif value < 0:
694
+ raise ValueError("total_tokens must be >= 0")
695
+
696
+ if self._internal_limiter is None:
697
+ self._total_tokens = value
698
+ return
699
+
700
+ self._limiter.total_tokens = value
701
+
702
+ @property
703
+ def borrowed_tokens(self) -> int:
704
+ if self._internal_limiter is None:
705
+ return 0
706
+
707
+ return self._internal_limiter.borrowed_tokens
708
+
709
+ @property
710
+ def available_tokens(self) -> float:
711
+ if self._internal_limiter is None:
712
+ return self._total_tokens
713
+
714
+ return self._internal_limiter.available_tokens
715
+
716
+ def acquire_nowait(self) -> None:
717
+ self._limiter.acquire_nowait()
718
+
719
+ def acquire_on_behalf_of_nowait(self, borrower: object) -> None:
720
+ self._limiter.acquire_on_behalf_of_nowait(borrower)
721
+
722
+ async def acquire(self) -> None:
723
+ await self._limiter.acquire()
724
+
725
+ async def acquire_on_behalf_of(self, borrower: object) -> None:
726
+ await self._limiter.acquire_on_behalf_of(borrower)
727
+
728
+ def release(self) -> None:
729
+ self._limiter.release()
730
+
731
+ def release_on_behalf_of(self, borrower: object) -> None:
732
+ self._limiter.release_on_behalf_of(borrower)
733
+
734
+ def statistics(self) -> CapacityLimiterStatistics:
735
+ if self._internal_limiter is None:
736
+ return CapacityLimiterStatistics(
737
+ borrowed_tokens=0,
738
+ total_tokens=self.total_tokens,
739
+ borrowers=(),
740
+ tasks_waiting=0,
741
+ )
742
+
743
+ return self._internal_limiter.statistics()
744
+
745
+
746
+ class ResourceGuard:
747
+ """
748
+ A context manager for ensuring that a resource is only used by a single task at a
749
+ time.
750
+
751
+ Entering this context manager while the previous has not exited it yet will trigger
752
+ :exc:`BusyResourceError`.
753
+
754
+ :param action: the action to guard against (visible in the :exc:`BusyResourceError`
755
+ when triggered, e.g. "Another task is already {action} this resource")
756
+
757
+ .. versionadded:: 4.1
758
+ """
759
+
760
+ __slots__ = "__weakref__", "_guarded", "action"
761
+
762
+ def __init__(self, action: str = "using"):
763
+ self.action: str = action
764
+ self._guarded = False
765
+
766
+ def __enter__(self) -> None:
767
+ if self._guarded:
768
+ raise BusyResourceError(self.action)
769
+
770
+ self._guarded = True
771
+
772
+ def __exit__(
773
+ self,
774
+ exc_type: type[BaseException] | None,
775
+ exc_val: BaseException | None,
776
+ exc_tb: TracebackType | None,
777
+ ) -> None:
778
+ self._guarded = False
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_tasks.py ADDED
@@ -0,0 +1,464 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import sys
5
+ from collections.abc import (
6
+ Coroutine,
7
+ Generator,
8
+ )
9
+ from contextlib import contextmanager
10
+ from enum import Enum, auto
11
+ from inspect import iscoroutine
12
+ from types import TracebackType
13
+ from typing import Any, Generic, final
14
+
15
+ from ..abc import TaskGroup, TaskStatus
16
+ from ._eventloop import get_async_backend, get_cancelled_exc_class
17
+ from ._exceptions import TaskCancelled, TaskFailed, TaskNotFinished
18
+
19
+ if sys.version_info >= (3, 13):
20
+ from typing import TypeVar
21
+ else:
22
+ from typing_extensions import TypeVar
23
+
24
+ if sys.version_info >= (3, 11):
25
+ from typing import Never, Self, TypeVarTuple
26
+ else:
27
+ from typing_extensions import Never, Self, TypeVarTuple
28
+
29
+ T = TypeVar("T")
30
+ T_co = TypeVar("T_co", covariant=True)
31
+ T_startval_co = TypeVar("T_startval_co", covariant=True, default=Never)
32
+ PosArgsT = TypeVarTuple("PosArgsT")
33
+
34
+
35
+ class _IgnoredTaskStatus(TaskStatus[object]):
36
+ def started(self, value: object = None) -> None:
37
+ pass
38
+
39
+
40
+ TASK_STATUS_IGNORED = _IgnoredTaskStatus()
41
+
42
+
43
+ class CancelScope:
44
+ """
45
+ Wraps a unit of work that can be made separately cancellable.
46
+
47
+ :param deadline: The time (clock value) when this scope is cancelled automatically
48
+ :param shield: ``True`` to shield the cancel scope from external cancellation
49
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
50
+ current thread
51
+ """
52
+
53
+ __slots__ = ("__weakref__",)
54
+
55
+ def __new__(
56
+ cls, *, deadline: float = math.inf, shield: bool = False
57
+ ) -> CancelScope:
58
+ return get_async_backend().create_cancel_scope(shield=shield, deadline=deadline)
59
+
60
+ def cancel(self, reason: str | None = None) -> None:
61
+ """
62
+ Cancel this scope immediately.
63
+
64
+ :param reason: a message describing the reason for the cancellation
65
+
66
+ """
67
+ raise NotImplementedError
68
+
69
+ @property
70
+ def deadline(self) -> float:
71
+ """
72
+ The time (clock value) when this scope is cancelled automatically.
73
+
74
+ Will be ``float('inf')`` if no timeout has been set.
75
+
76
+ """
77
+ raise NotImplementedError
78
+
79
+ @deadline.setter
80
+ def deadline(self, value: float) -> None:
81
+ raise NotImplementedError
82
+
83
+ @property
84
+ def cancel_called(self) -> bool:
85
+ """``True`` if :meth:`cancel` has been called."""
86
+ raise NotImplementedError
87
+
88
+ @property
89
+ def cancelled_caught(self) -> bool:
90
+ """
91
+ ``True`` if this scope suppressed a cancellation exception it itself raised.
92
+
93
+ This is typically used to check if any work was interrupted, or to see if the
94
+ scope was cancelled due to its deadline being reached. The value will, however,
95
+ only be ``True`` if the cancellation was triggered by the scope itself (and not
96
+ an outer scope).
97
+
98
+ """
99
+ raise NotImplementedError
100
+
101
+ @property
102
+ def shield(self) -> bool:
103
+ """
104
+ ``True`` if this scope is shielded from external cancellation.
105
+
106
+ While a scope is shielded, it will not receive cancellations from outside.
107
+
108
+ """
109
+ raise NotImplementedError
110
+
111
+ @shield.setter
112
+ def shield(self, value: bool) -> None:
113
+ raise NotImplementedError
114
+
115
+ def __enter__(self) -> Self:
116
+ raise NotImplementedError
117
+
118
+ def __exit__(
119
+ self,
120
+ exc_type: type[BaseException] | None,
121
+ exc_val: BaseException | None,
122
+ exc_tb: TracebackType | None,
123
+ ) -> bool:
124
+ raise NotImplementedError
125
+
126
+
127
+ @contextmanager
128
+ def fail_at(
129
+ deadline: float | None, shield: bool = False, reason: str | None = None
130
+ ) -> Generator[CancelScope, None, None]:
131
+ """
132
+ Create a context manager which raises a :class:`TimeoutError` if the code in the
133
+ enclosing context does not finish by the given deadline.
134
+
135
+ :param deadline: the deadline before raising the exception, or
136
+ ``None`` to disable the timeout
137
+ :param shield: ``True`` to shield the cancel scope from external cancellation
138
+ :param reason: explanation for timeout to add to the message of a raised `TimeoutError`
139
+ :return: a context manager that yields a cancel scope
140
+ :rtype: :class:`~typing.ContextManager`\\[:class:`~anyio.CancelScope`\\]
141
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
142
+ current thread
143
+
144
+ .. versionadded:: 4.15.0
145
+
146
+ """
147
+ current_time = get_async_backend().current_time
148
+ effective_deadline = math.inf if deadline is None else deadline
149
+ with get_async_backend().create_cancel_scope(
150
+ deadline=effective_deadline, shield=shield
151
+ ) as cancel_scope:
152
+ yield cancel_scope
153
+
154
+ if cancel_scope.cancelled_caught and current_time() >= cancel_scope.deadline:
155
+ raise TimeoutError(reason) if reason else TimeoutError
156
+
157
+
158
+ @contextmanager
159
+ def fail_after(
160
+ delay: float | None, shield: bool = False, reason: str | None = None
161
+ ) -> Generator[CancelScope, None, None]:
162
+ """
163
+ Create a context manager which raises a :class:`TimeoutError` if the code in the
164
+ enclosing context block does not finish in time.
165
+
166
+ :param delay: maximum allowed time (in seconds) before raising the exception, or
167
+ ``None`` to disable the timeout
168
+ :param shield: ``True`` to shield the cancel scope from external cancellation
169
+ :param reason: explanation for timeout to add to the message of a raised `TimeoutError`
170
+ :return: a context manager that yields a cancel scope
171
+ :rtype: :class:`~typing.ContextManager`\\[:class:`~anyio.CancelScope`\\]
172
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
173
+ current thread
174
+
175
+ """
176
+ current_time = get_async_backend().current_time
177
+ deadline = (current_time() + delay) if delay is not None else math.inf
178
+ with fail_at(deadline, shield=shield, reason=reason) as scope:
179
+ yield scope
180
+
181
+
182
+ def move_on_at(deadline: float | None, shield: bool = False) -> CancelScope:
183
+ """
184
+ Create a cancel scope with a deadline that expires after the given delay.
185
+
186
+ :param deadline: the deadline before exiting the context block, or
187
+ ``None`` to disable the timeout
188
+ :param shield: ``True`` to shield the cancel scope from external cancellation
189
+ :return: a cancel scope
190
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
191
+ current thread
192
+
193
+ .. versionadded:: 4.15.0
194
+
195
+ """
196
+ return get_async_backend().create_cancel_scope(
197
+ deadline=deadline if deadline is not None else math.inf, shield=shield
198
+ )
199
+
200
+
201
+ def move_on_after(delay: float | None, shield: bool = False) -> CancelScope:
202
+ """
203
+ Create a cancel scope with a deadline that expires after the given delay.
204
+
205
+ :param delay: maximum allowed time (in seconds) before exiting the context block, or
206
+ ``None`` to disable the timeout
207
+ :param shield: ``True`` to shield the cancel scope from external cancellation
208
+ :return: a cancel scope
209
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
210
+ current thread
211
+
212
+ .. note:: Unlike with :func:`fail_after`, the timer starts when this function is
213
+ called, not when the context manager is entered. This will be changed in v5.0.
214
+
215
+ """
216
+ deadline = (
217
+ (get_async_backend().current_time() + delay) if delay is not None else math.inf
218
+ )
219
+ return get_async_backend().create_cancel_scope(deadline=deadline, shield=shield)
220
+
221
+
222
+ def current_effective_deadline() -> float:
223
+ """
224
+ Return the nearest deadline among all the cancel scopes effective for the current
225
+ task.
226
+
227
+ :return: a clock value from the event loop's internal clock (or ``float('inf')`` if
228
+ there is no deadline in effect, or ``float('-inf')`` if the current scope has
229
+ been cancelled)
230
+ :rtype: float
231
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
232
+ current thread
233
+
234
+ """
235
+ return get_async_backend().current_effective_deadline()
236
+
237
+
238
+ def create_task_group() -> TaskGroup:
239
+ """
240
+ Create a task group.
241
+
242
+ :return: a task group
243
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
244
+ current thread
245
+
246
+ """
247
+ return get_async_backend().create_task_group()
248
+
249
+
250
+ @final
251
+ class TaskHandle(Generic[T_co, T_startval_co]):
252
+ """
253
+ Returned from the task-spawning methods of :class:`TaskGroup`. Can be awaited on to
254
+ get the return value of the task (or the raised exception). If the task was
255
+ terminated by a :exc:`BaseException`, :exc:`TaskFailed` will be raised (or its
256
+ subclass :exc:`TaskCancelled` if the task was cancelled).
257
+
258
+ .. versionadded:: 4.14.0
259
+ """
260
+
261
+ class Status(Enum):
262
+ """
263
+ The status of a task handle.
264
+
265
+ .. attribute:: PENDING
266
+
267
+ The task has not finished yet.
268
+ .. attribute:: FINISHED
269
+
270
+ The task has finished with a return value.
271
+ .. attribute:: CANCELLING
272
+
273
+ The task has been cancelled but has not finished yet.
274
+ .. attribute:: CANCELLED
275
+
276
+ The task was cancelled and has finished since.
277
+ .. attribute:: FAILED
278
+
279
+ The task raised an exception.
280
+ """
281
+
282
+ PENDING = auto()
283
+ FINISHED = auto()
284
+ CANCELLING = auto()
285
+ CANCELLED = auto()
286
+ FAILED = auto()
287
+
288
+ __slots__ = (
289
+ "__weakref__",
290
+ "_cancel_scope",
291
+ "_coro",
292
+ "_exception",
293
+ "_finished_event",
294
+ "_name",
295
+ "_return_value",
296
+ "_start_value",
297
+ )
298
+
299
+ _return_value: T_co
300
+ _start_value: T_startval_co
301
+
302
+ def __init__(
303
+ self,
304
+ coro: Coroutine[Any, Any, T_co],
305
+ name: object,
306
+ cancel_scope: CancelScope | None = None,
307
+ ) -> None:
308
+ from ._synchronization import Event
309
+
310
+ self._coro = coro
311
+ self._cancel_scope = cancel_scope if cancel_scope is not None else CancelScope()
312
+ self._finished_event = Event()
313
+ self._exception: BaseException | None = None
314
+
315
+ if name is not None:
316
+ self._name = str(name)
317
+ elif iscoroutine(coro):
318
+ self._name = coro.__qualname__
319
+ else:
320
+ self._name = str(coro) # coroutine-like object (e.g. asend() objects)
321
+
322
+ async def _run_coro(self) -> None:
323
+ __tracebackhide__ = True
324
+
325
+ with self._cancel_scope:
326
+ try:
327
+ retval = await self._coro
328
+ except BaseException as exc:
329
+ self._exception = exc
330
+ raise
331
+ else:
332
+ self._return_value = retval
333
+ finally:
334
+ self._finished_event.set()
335
+ del self # Break the reference cycle
336
+
337
+ def cancel(self) -> None:
338
+ """
339
+ Set the task to a cancelled state.
340
+
341
+ This will interrupt any interruptible asynchronous operation, and will cause
342
+ any further awaits on this task to get immediately cancelled, unless done in
343
+ a shielded cancel scope.
344
+
345
+ If the task has already finished, this method has no effect.
346
+ """
347
+ if not self._finished_event.is_set():
348
+ self._cancel_scope.cancel()
349
+
350
+ @property
351
+ def coro(self) -> Coroutine[Any, Any, T_co]:
352
+ """
353
+ The coroutine object that was passed to one of the task-spawning methods in
354
+ :class:`TaskGroup`.
355
+ """
356
+ return self._coro
357
+
358
+ @property
359
+ def status(self) -> TaskHandle.Status:
360
+ """
361
+ The current status of the task.
362
+
363
+ Every task starts in the :attr:`~TaskHandle.Status.PENDING` state.
364
+ If a task is cancelled while in this state, it will transition to the
365
+ :attr:`~TaskHandle.Status.CANCELLING` state. When the task finishes, it will
366
+ transition to one of the three final states (
367
+ :attr:`~TaskHandle.Status.FINISHED`, :attr:`~TaskHandle.Status.FAILED`, or
368
+ :attr:`~TaskHandle.Status.CANCELLING`) depending on the exception the task
369
+ raised, if any. No other status transitions will happen.
370
+ """
371
+ if not self._finished_event.is_set():
372
+ if self._cancel_scope.cancel_called:
373
+ return TaskHandle.Status.CANCELLING
374
+ else:
375
+ return TaskHandle.Status.PENDING
376
+ elif self._exception is not None:
377
+ if isinstance(self._exception, get_cancelled_exc_class()):
378
+ return TaskHandle.Status.CANCELLED
379
+ else:
380
+ return TaskHandle.Status.FAILED
381
+ else:
382
+ return TaskHandle.Status.FINISHED
383
+
384
+ @property
385
+ def name(self) -> str:
386
+ """The name of the task."""
387
+ return self._name
388
+
389
+ @property
390
+ def exception(self) -> BaseException | None:
391
+ """
392
+ The exception raised by the task, or ``None`` if it finished without raising.
393
+
394
+ :raises TaskNotFinished: if the task has not finished yet
395
+ :raises TaskCancelled: if the task was cancelled
396
+
397
+ """
398
+ match self.status:
399
+ case TaskHandle.Status.PENDING:
400
+ raise TaskNotFinished("the task has not finished yet")
401
+ case TaskHandle.Status.FINISHED:
402
+ return None
403
+ case TaskHandle.Status.CANCELLING:
404
+ raise TaskCancelled("the task was cancelled")
405
+ case TaskHandle.Status.CANCELLED:
406
+ raise TaskCancelled("the task was cancelled") from self._exception
407
+ case TaskHandle.Status.FAILED:
408
+ return self._exception
409
+
410
+ @property
411
+ def return_value(self) -> T_co:
412
+ """
413
+ The return value of the task.
414
+
415
+ :raises TaskNotFinished: if the task has not finished yet
416
+ :raises TaskCancelled: if the task was cancelled
417
+ :raises TaskFailed: if the task raised an exception
418
+
419
+ """
420
+ match self.status:
421
+ case TaskHandle.Status.PENDING:
422
+ raise TaskNotFinished("the task has not finished yet")
423
+ case TaskHandle.Status.FINISHED:
424
+ return self._return_value
425
+ case TaskHandle.Status.CANCELLING:
426
+ raise TaskCancelled("the task was cancelled")
427
+ case TaskHandle.Status.CANCELLED:
428
+ raise TaskCancelled("the task was cancelled") from self._exception
429
+ case TaskHandle.Status.FAILED:
430
+ raise TaskFailed("the task raised an exception") from self._exception
431
+
432
+ @property
433
+ def start_value(self) -> T_startval_co:
434
+ """
435
+ The value passed to :meth:`task_status.started() <.abc.TaskStatus.started>`,
436
+
437
+ :raises RuntimeError: if the task was not started with :meth:`TaskGroup.start()
438
+ <.abc.TaskGroup.start>`
439
+ """
440
+ try:
441
+ return self._start_value
442
+ except AttributeError:
443
+ raise RuntimeError(
444
+ "the task was not started with TaskGroup.start()"
445
+ ) from None
446
+
447
+ async def wait(self) -> None:
448
+ """
449
+ Wait for the task to finish.
450
+
451
+ This method will return as soon as the task has finished, no matter how it
452
+ happened.
453
+ """
454
+ await self._finished_event.wait()
455
+
456
+ def __await__(self) -> Generator[Any, Any, T_co]:
457
+ yield from self._finished_event.wait().__await__()
458
+ return self.return_value
459
+
460
+ def __repr__(self) -> str:
461
+ return (
462
+ f"<{self.__class__.__name__} {self.status.name.lower()} "
463
+ f"name={self._name!r} coro={self._coro!r}>"
464
+ )
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_tempfile.py ADDED
@@ -0,0 +1,615 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import sys
5
+ import tempfile
6
+ from collections.abc import Iterable
7
+ from io import BytesIO, TextIOWrapper
8
+ from types import TracebackType
9
+ from typing import (
10
+ TYPE_CHECKING,
11
+ Any,
12
+ AnyStr,
13
+ Generic,
14
+ overload,
15
+ )
16
+
17
+ from .. import to_thread
18
+ from .._core._fileio import AsyncFile
19
+ from ..lowlevel import checkpoint_if_cancelled
20
+ from ._tasks import CancelScope
21
+
22
+ if TYPE_CHECKING:
23
+ from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer
24
+
25
+
26
+ class TemporaryFile(Generic[AnyStr]):
27
+ """
28
+ An asynchronous temporary file that is automatically created and cleaned up.
29
+
30
+ This class provides an asynchronous context manager interface to a temporary file.
31
+ The file is created using Python's standard `tempfile.TemporaryFile` function in a
32
+ background thread, and is wrapped as an asynchronous file using `AsyncFile`.
33
+
34
+ :param mode: The mode in which the file is opened. Defaults to "w+b".
35
+ :param buffering: The buffering policy (-1 means the default buffering).
36
+ :param encoding: The encoding used to decode or encode the file. Only applicable in
37
+ text mode.
38
+ :param newline: Controls how universal newlines mode works (only applicable in text
39
+ mode).
40
+ :param suffix: The suffix for the temporary file name.
41
+ :param prefix: The prefix for the temporary file name.
42
+ :param dir: The directory in which the temporary file is created.
43
+ :param errors: The error handling scheme used for encoding/decoding errors.
44
+ """
45
+
46
+ _async_file: AsyncFile[AnyStr]
47
+
48
+ @overload
49
+ def __init__(
50
+ self: TemporaryFile[bytes],
51
+ mode: OpenBinaryMode = ...,
52
+ buffering: int = ...,
53
+ encoding: str | None = ...,
54
+ newline: str | None = ...,
55
+ suffix: str | None = ...,
56
+ prefix: str | None = ...,
57
+ dir: str | None = ...,
58
+ *,
59
+ errors: str | None = ...,
60
+ ): ...
61
+ @overload
62
+ def __init__(
63
+ self: TemporaryFile[str],
64
+ mode: OpenTextMode,
65
+ buffering: int = ...,
66
+ encoding: str | None = ...,
67
+ newline: str | None = ...,
68
+ suffix: str | None = ...,
69
+ prefix: str | None = ...,
70
+ dir: str | None = ...,
71
+ *,
72
+ errors: str | None = ...,
73
+ ): ...
74
+
75
+ def __init__(
76
+ self,
77
+ mode: OpenTextMode | OpenBinaryMode = "w+b",
78
+ buffering: int = -1,
79
+ encoding: str | None = None,
80
+ newline: str | None = None,
81
+ suffix: str | None = None,
82
+ prefix: str | None = None,
83
+ dir: str | None = None,
84
+ *,
85
+ errors: str | None = None,
86
+ ) -> None:
87
+ self.mode = mode
88
+ self.buffering = buffering
89
+ self.encoding = encoding
90
+ self.newline = newline
91
+ self.suffix: str | None = suffix
92
+ self.prefix: str | None = prefix
93
+ self.dir: str | None = dir
94
+ self.errors = errors
95
+
96
+ async def __aenter__(self) -> AsyncFile[AnyStr]:
97
+ fp = await to_thread.run_sync(
98
+ lambda: tempfile.TemporaryFile(
99
+ self.mode,
100
+ self.buffering,
101
+ self.encoding,
102
+ self.newline,
103
+ self.suffix,
104
+ self.prefix,
105
+ self.dir,
106
+ errors=self.errors,
107
+ )
108
+ )
109
+ self._async_file = AsyncFile(fp)
110
+ return self._async_file
111
+
112
+ async def __aexit__(
113
+ self,
114
+ exc_type: type[BaseException] | None,
115
+ exc_value: BaseException | None,
116
+ traceback: TracebackType | None,
117
+ ) -> None:
118
+ await self._async_file.aclose()
119
+
120
+
121
+ class NamedTemporaryFile(Generic[AnyStr]):
122
+ """
123
+ An asynchronous named temporary file that is automatically created and cleaned up.
124
+
125
+ This class provides an asynchronous context manager for a temporary file with a
126
+ visible name in the file system. It uses Python's standard
127
+ :func:`~tempfile.NamedTemporaryFile` function and wraps the file object with
128
+ :class:`AsyncFile` for asynchronous operations.
129
+
130
+ :param mode: The mode in which the file is opened. Defaults to "w+b".
131
+ :param buffering: The buffering policy (-1 means the default buffering).
132
+ :param encoding: The encoding used to decode or encode the file. Only applicable in
133
+ text mode.
134
+ :param newline: Controls how universal newlines mode works (only applicable in text
135
+ mode).
136
+ :param suffix: The suffix for the temporary file name.
137
+ :param prefix: The prefix for the temporary file name.
138
+ :param dir: The directory in which the temporary file is created.
139
+ :param delete: Whether to delete the file when it is closed.
140
+ :param errors: The error handling scheme used for encoding/decoding errors.
141
+ :param delete_on_close: (Python 3.12+) Whether to delete the file on close.
142
+ """
143
+
144
+ _async_file: AsyncFile[AnyStr]
145
+
146
+ @overload
147
+ def __init__(
148
+ self: NamedTemporaryFile[bytes],
149
+ mode: OpenBinaryMode = ...,
150
+ buffering: int = ...,
151
+ encoding: str | None = ...,
152
+ newline: str | None = ...,
153
+ suffix: str | None = ...,
154
+ prefix: str | None = ...,
155
+ dir: str | None = ...,
156
+ delete: bool = ...,
157
+ *,
158
+ errors: str | None = ...,
159
+ delete_on_close: bool = ...,
160
+ ): ...
161
+ @overload
162
+ def __init__(
163
+ self: NamedTemporaryFile[str],
164
+ mode: OpenTextMode,
165
+ buffering: int = ...,
166
+ encoding: str | None = ...,
167
+ newline: str | None = ...,
168
+ suffix: str | None = ...,
169
+ prefix: str | None = ...,
170
+ dir: str | None = ...,
171
+ delete: bool = ...,
172
+ *,
173
+ errors: str | None = ...,
174
+ delete_on_close: bool = ...,
175
+ ): ...
176
+
177
+ def __init__(
178
+ self,
179
+ mode: OpenBinaryMode | OpenTextMode = "w+b",
180
+ buffering: int = -1,
181
+ encoding: str | None = None,
182
+ newline: str | None = None,
183
+ suffix: str | None = None,
184
+ prefix: str | None = None,
185
+ dir: str | None = None,
186
+ delete: bool = True,
187
+ *,
188
+ errors: str | None = None,
189
+ delete_on_close: bool = True,
190
+ ) -> None:
191
+ self._params: dict[str, Any] = {
192
+ "mode": mode,
193
+ "buffering": buffering,
194
+ "encoding": encoding,
195
+ "newline": newline,
196
+ "suffix": suffix,
197
+ "prefix": prefix,
198
+ "dir": dir,
199
+ "delete": delete,
200
+ "errors": errors,
201
+ }
202
+ if sys.version_info >= (3, 12):
203
+ self._params["delete_on_close"] = delete_on_close
204
+
205
+ async def __aenter__(self) -> AsyncFile[AnyStr]:
206
+ fp = await to_thread.run_sync(
207
+ lambda: tempfile.NamedTemporaryFile(**self._params)
208
+ )
209
+ self._async_file = AsyncFile(fp)
210
+ return self._async_file
211
+
212
+ async def __aexit__(
213
+ self,
214
+ exc_type: type[BaseException] | None,
215
+ exc_value: BaseException | None,
216
+ traceback: TracebackType | None,
217
+ ) -> None:
218
+ await self._async_file.aclose()
219
+
220
+
221
+ class SpooledTemporaryFile(AsyncFile[AnyStr]):
222
+ """
223
+ An asynchronous spooled temporary file that starts in memory and is spooled to disk.
224
+
225
+ This class provides an asynchronous interface to a spooled temporary file, much like
226
+ Python's standard :class:`~tempfile.SpooledTemporaryFile`. It supports asynchronous
227
+ write operations and provides a method to force a rollover to disk.
228
+
229
+ :param max_size: Maximum size in bytes before the file is rolled over to disk.
230
+ :param mode: The mode in which the file is opened. Defaults to "w+b".
231
+ :param buffering: The buffering policy (-1 means the default buffering).
232
+ :param encoding: The encoding used to decode or encode the file (text mode only).
233
+ :param newline: Controls how universal newlines mode works (text mode only).
234
+ :param suffix: The suffix for the temporary file name.
235
+ :param prefix: The prefix for the temporary file name.
236
+ :param dir: The directory in which the temporary file is created.
237
+ :param errors: The error handling scheme used for encoding/decoding errors.
238
+ """
239
+
240
+ _rolled: bool = False
241
+
242
+ @overload
243
+ def __init__(
244
+ self: SpooledTemporaryFile[bytes],
245
+ max_size: int = ...,
246
+ mode: OpenBinaryMode = ...,
247
+ buffering: int = ...,
248
+ encoding: str | None = ...,
249
+ newline: str | None = ...,
250
+ suffix: str | None = ...,
251
+ prefix: str | None = ...,
252
+ dir: str | None = ...,
253
+ *,
254
+ errors: str | None = ...,
255
+ ): ...
256
+ @overload
257
+ def __init__(
258
+ self: SpooledTemporaryFile[str],
259
+ max_size: int = ...,
260
+ mode: OpenTextMode = ...,
261
+ buffering: int = ...,
262
+ encoding: str | None = ...,
263
+ newline: str | None = ...,
264
+ suffix: str | None = ...,
265
+ prefix: str | None = ...,
266
+ dir: str | None = ...,
267
+ *,
268
+ errors: str | None = ...,
269
+ ): ...
270
+
271
+ def __init__(
272
+ self,
273
+ max_size: int = 0,
274
+ mode: OpenBinaryMode | OpenTextMode = "w+b",
275
+ buffering: int = -1,
276
+ encoding: str | None = None,
277
+ newline: str | None = None,
278
+ suffix: str | None = None,
279
+ prefix: str | None = None,
280
+ dir: str | None = None,
281
+ *,
282
+ errors: str | None = None,
283
+ ) -> None:
284
+ self._tempfile_params: dict[str, Any] = {
285
+ "mode": mode,
286
+ "buffering": buffering,
287
+ "encoding": encoding,
288
+ "newline": newline,
289
+ "suffix": suffix,
290
+ "prefix": prefix,
291
+ "dir": dir,
292
+ "errors": errors,
293
+ }
294
+ self._max_size = max_size
295
+ if "b" in mode:
296
+ super().__init__(BytesIO()) # type: ignore[arg-type]
297
+ else:
298
+ super().__init__(
299
+ TextIOWrapper( # type: ignore[arg-type]
300
+ BytesIO(),
301
+ encoding=encoding,
302
+ errors=errors,
303
+ newline=newline,
304
+ write_through=True,
305
+ )
306
+ )
307
+
308
+ async def aclose(self) -> None:
309
+ if not self._rolled:
310
+ self._fp.close()
311
+ return
312
+
313
+ await super().aclose()
314
+
315
+ async def _check(self) -> None:
316
+ if self._rolled or self._fp.tell() <= self._max_size:
317
+ return
318
+
319
+ await self.rollover()
320
+
321
+ async def rollover(self) -> None:
322
+ if self._rolled:
323
+ return
324
+
325
+ self._rolled = True
326
+ buffer = self._fp
327
+ buffer.seek(0)
328
+ self._fp = await to_thread.run_sync(
329
+ lambda: tempfile.TemporaryFile(**self._tempfile_params)
330
+ )
331
+ await self.write(buffer.read())
332
+ buffer.close()
333
+
334
+ @property
335
+ def closed(self) -> bool:
336
+ return self._fp.closed
337
+
338
+ async def read(self, size: int = -1) -> AnyStr:
339
+ if not self._rolled:
340
+ await checkpoint_if_cancelled()
341
+ return self._fp.read(size)
342
+
343
+ return await super().read(size) # type: ignore[return-value]
344
+
345
+ async def read1(self: SpooledTemporaryFile[bytes], size: int = -1) -> bytes:
346
+ if not self._rolled:
347
+ await checkpoint_if_cancelled()
348
+ return self._fp.read1(size)
349
+
350
+ return await super().read1(size)
351
+
352
+ async def readline(self) -> AnyStr:
353
+ if not self._rolled:
354
+ await checkpoint_if_cancelled()
355
+ return self._fp.readline()
356
+
357
+ return await super().readline() # type: ignore[return-value]
358
+
359
+ async def readlines(self) -> list[AnyStr]:
360
+ if not self._rolled:
361
+ await checkpoint_if_cancelled()
362
+ return self._fp.readlines()
363
+
364
+ return await super().readlines() # type: ignore[return-value]
365
+
366
+ async def readinto(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int:
367
+ if not self._rolled:
368
+ await checkpoint_if_cancelled()
369
+ return self._fp.readinto(b)
370
+
371
+ return await super().readinto(b)
372
+
373
+ async def readinto1(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int:
374
+ if not self._rolled:
375
+ await checkpoint_if_cancelled()
376
+ return self._fp.readinto1(b)
377
+
378
+ return await super().readinto1(b)
379
+
380
+ async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int:
381
+ if not self._rolled:
382
+ await checkpoint_if_cancelled()
383
+ return self._fp.seek(offset, whence)
384
+
385
+ return await super().seek(offset, whence)
386
+
387
+ async def tell(self) -> int:
388
+ if not self._rolled:
389
+ await checkpoint_if_cancelled()
390
+ return self._fp.tell()
391
+
392
+ return await super().tell()
393
+
394
+ async def truncate(self, size: int | None = None) -> int:
395
+ if not self._rolled:
396
+ await checkpoint_if_cancelled()
397
+ return self._fp.truncate(size)
398
+
399
+ return await super().truncate(size)
400
+
401
+ @overload
402
+ async def write(self: SpooledTemporaryFile[bytes], b: ReadableBuffer) -> int: ...
403
+ @overload
404
+ async def write(self: SpooledTemporaryFile[str], b: str) -> int: ...
405
+
406
+ async def write(self, b: ReadableBuffer | str) -> int:
407
+ """
408
+ Asynchronously write data to the spooled temporary file.
409
+
410
+ If the file has not yet been rolled over, the data is written synchronously,
411
+ and a rollover is triggered if the size exceeds the maximum size.
412
+
413
+ :param s: The data to write.
414
+ :return: The number of bytes written.
415
+ :raises RuntimeError: If the underlying file is not initialized.
416
+
417
+ """
418
+ if not self._rolled:
419
+ await checkpoint_if_cancelled()
420
+ result = self._fp.write(b)
421
+ await self._check()
422
+ return result
423
+
424
+ return await super().write(b) # type: ignore[misc]
425
+
426
+ @overload
427
+ async def writelines(
428
+ self: SpooledTemporaryFile[bytes], lines: Iterable[ReadableBuffer]
429
+ ) -> None: ...
430
+ @overload
431
+ async def writelines(
432
+ self: SpooledTemporaryFile[str], lines: Iterable[str]
433
+ ) -> None: ...
434
+
435
+ async def writelines(self, lines: Iterable[str] | Iterable[ReadableBuffer]) -> None:
436
+ """
437
+ Asynchronously write a list of lines to the spooled temporary file.
438
+
439
+ If the file has not yet been rolled over, the lines are written synchronously,
440
+ and a rollover is triggered if the size exceeds the maximum size.
441
+
442
+ :param lines: An iterable of lines to write.
443
+ :raises RuntimeError: If the underlying file is not initialized.
444
+
445
+ """
446
+ if not self._rolled:
447
+ await checkpoint_if_cancelled()
448
+ result = self._fp.writelines(lines)
449
+ await self._check()
450
+ return result
451
+
452
+ return await super().writelines(lines) # type: ignore[misc]
453
+
454
+
455
+ class TemporaryDirectory(Generic[AnyStr]):
456
+ """
457
+ An asynchronous temporary directory that is created and cleaned up automatically.
458
+
459
+ This class provides an asynchronous context manager for creating a temporary
460
+ directory. It wraps Python's standard :class:`~tempfile.TemporaryDirectory` to
461
+ perform directory creation and cleanup operations in a background thread.
462
+
463
+ :param suffix: Suffix to be added to the temporary directory name.
464
+ :param prefix: Prefix to be added to the temporary directory name.
465
+ :param dir: The parent directory where the temporary directory is created.
466
+ :param ignore_cleanup_errors: Whether to ignore errors during cleanup
467
+ :param delete: Whether to delete the directory upon closing (Python 3.12+).
468
+ """
469
+
470
+ def __init__(
471
+ self,
472
+ suffix: AnyStr | None = None,
473
+ prefix: AnyStr | None = None,
474
+ dir: AnyStr | None = None,
475
+ *,
476
+ ignore_cleanup_errors: bool = False,
477
+ delete: bool = True,
478
+ ) -> None:
479
+ self.suffix: AnyStr | None = suffix
480
+ self.prefix: AnyStr | None = prefix
481
+ self.dir: AnyStr | None = dir
482
+ self.ignore_cleanup_errors = ignore_cleanup_errors
483
+ self.delete = delete
484
+
485
+ self._tempdir: tempfile.TemporaryDirectory | None = None
486
+
487
+ async def __aenter__(self) -> str:
488
+ params: dict[str, Any] = {
489
+ "suffix": self.suffix,
490
+ "prefix": self.prefix,
491
+ "dir": self.dir,
492
+ "ignore_cleanup_errors": self.ignore_cleanup_errors,
493
+ }
494
+ if sys.version_info >= (3, 12):
495
+ params["delete"] = self.delete
496
+
497
+ self._tempdir = await to_thread.run_sync(
498
+ lambda: tempfile.TemporaryDirectory(**params)
499
+ )
500
+ return await to_thread.run_sync(self._tempdir.__enter__)
501
+
502
+ async def __aexit__(
503
+ self,
504
+ exc_type: type[BaseException] | None,
505
+ exc_value: BaseException | None,
506
+ traceback: TracebackType | None,
507
+ ) -> None:
508
+ if self._tempdir is not None:
509
+ with CancelScope(shield=True):
510
+ await to_thread.run_sync(
511
+ self._tempdir.__exit__, exc_type, exc_value, traceback
512
+ )
513
+
514
+ async def cleanup(self) -> None:
515
+ if self._tempdir is not None:
516
+ await to_thread.run_sync(self._tempdir.cleanup)
517
+
518
+
519
+ @overload
520
+ async def mkstemp(
521
+ suffix: str | None = None,
522
+ prefix: str | None = None,
523
+ dir: str | None = None,
524
+ text: bool = False,
525
+ ) -> tuple[int, str]: ...
526
+
527
+
528
+ @overload
529
+ async def mkstemp(
530
+ suffix: bytes | None = None,
531
+ prefix: bytes | None = None,
532
+ dir: bytes | None = None,
533
+ text: bool = False,
534
+ ) -> tuple[int, bytes]: ...
535
+
536
+
537
+ async def mkstemp(
538
+ suffix: AnyStr | None = None,
539
+ prefix: AnyStr | None = None,
540
+ dir: AnyStr | None = None,
541
+ text: bool = False,
542
+ ) -> tuple[int, str | bytes]:
543
+ """
544
+ Asynchronously create a temporary file and return an OS-level handle and the file
545
+ name.
546
+
547
+ This function wraps `tempfile.mkstemp` and executes it in a background thread.
548
+
549
+ :param suffix: Suffix to be added to the file name.
550
+ :param prefix: Prefix to be added to the file name.
551
+ :param dir: Directory in which the temporary file is created.
552
+ :param text: Whether the file is opened in text mode.
553
+ :return: A tuple containing the file descriptor and the file name.
554
+
555
+ """
556
+ return await to_thread.run_sync(tempfile.mkstemp, suffix, prefix, dir, text)
557
+
558
+
559
+ @overload
560
+ async def mkdtemp(
561
+ suffix: str | None = None,
562
+ prefix: str | None = None,
563
+ dir: str | None = None,
564
+ ) -> str: ...
565
+
566
+
567
+ @overload
568
+ async def mkdtemp(
569
+ suffix: bytes | None = None,
570
+ prefix: bytes | None = None,
571
+ dir: bytes | None = None,
572
+ ) -> bytes: ...
573
+
574
+
575
+ async def mkdtemp(
576
+ suffix: AnyStr | None = None,
577
+ prefix: AnyStr | None = None,
578
+ dir: AnyStr | None = None,
579
+ ) -> str | bytes:
580
+ """
581
+ Asynchronously create a temporary directory and return its path.
582
+
583
+ This function wraps `tempfile.mkdtemp` and executes it in a background thread.
584
+
585
+ :param suffix: Suffix to be added to the directory name.
586
+ :param prefix: Prefix to be added to the directory name.
587
+ :param dir: Parent directory where the temporary directory is created.
588
+ :return: The path of the created temporary directory.
589
+
590
+ """
591
+ return await to_thread.run_sync(tempfile.mkdtemp, suffix, prefix, dir)
592
+
593
+
594
+ async def gettempdir() -> str:
595
+ """
596
+ Asynchronously return the name of the directory used for temporary files.
597
+
598
+ This function wraps `tempfile.gettempdir` and executes it in a background thread.
599
+
600
+ :return: The path of the temporary directory as a string.
601
+
602
+ """
603
+ return await to_thread.run_sync(tempfile.gettempdir)
604
+
605
+
606
+ async def gettempdirb() -> bytes:
607
+ """
608
+ Asynchronously return the name of the directory used for temporary files in bytes.
609
+
610
+ This function wraps `tempfile.gettempdirb` and executes it in a background thread.
611
+
612
+ :return: The path of the temporary directory as bytes.
613
+
614
+ """
615
+ return await to_thread.run_sync(tempfile.gettempdirb)
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_testing.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Awaitable, Generator
4
+ from typing import Any, cast
5
+
6
+ from ._eventloop import get_async_backend
7
+
8
+
9
+ class TaskInfo:
10
+ """
11
+ Represents an asynchronous task.
12
+
13
+ :ivar int id: the unique identifier of the task
14
+ :ivar parent_id: the identifier of the parent task, if any
15
+ :vartype parent_id: Optional[int]
16
+ :ivar str name: the description of the task (if any)
17
+ :ivar ~collections.abc.Coroutine coro: the coroutine object of the task
18
+ """
19
+
20
+ __slots__ = "_name", "coro", "id", "name", "parent_id"
21
+
22
+ def __init__(
23
+ self,
24
+ id: int,
25
+ parent_id: int | None,
26
+ name: str | None,
27
+ coro: Generator[Any, Any, Any] | Awaitable[Any],
28
+ ):
29
+ func = get_current_task
30
+ self._name = f"{func.__module__}.{func.__qualname__}"
31
+ self.id: int = id
32
+ self.parent_id: int | None = parent_id
33
+ self.name: str | None = name
34
+ self.coro: Generator[Any, Any, Any] | Awaitable[Any] = coro
35
+
36
+ def __eq__(self, other: object) -> bool:
37
+ if isinstance(other, TaskInfo):
38
+ return self.id == other.id
39
+
40
+ return NotImplemented
41
+
42
+ def __hash__(self) -> int:
43
+ return hash(self.id)
44
+
45
+ def __repr__(self) -> str:
46
+ return f"{self.__class__.__name__}(id={self.id!r}, name={self.name!r})"
47
+
48
+ def has_pending_cancellation(self) -> bool:
49
+ """
50
+ Return ``True`` if the task has a cancellation pending, ``False`` otherwise.
51
+
52
+ """
53
+ return False
54
+
55
+
56
+ def get_current_task() -> TaskInfo:
57
+ """
58
+ Return the current task.
59
+
60
+ :return: a representation of the current task
61
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
62
+ current thread
63
+
64
+ """
65
+ return get_async_backend().get_current_task()
66
+
67
+
68
+ def get_running_tasks() -> list[TaskInfo]:
69
+ """
70
+ Return a list of running tasks in the current event loop.
71
+
72
+ :return: a list of task info objects
73
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
74
+ current thread
75
+
76
+ """
77
+ return cast("list[TaskInfo]", get_async_backend().get_running_tasks())
78
+
79
+
80
+ async def wait_all_tasks_blocked() -> None:
81
+ """Wait until all other tasks are waiting for something."""
82
+ await get_async_backend().wait_all_tasks_blocked()
.venvs/kimodo/lib/python3.10/site-packages/anyio/_core/_typedattr.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from collections.abc import Callable, Mapping
5
+ from typing import Any, TypeVar, final, overload
6
+
7
+ from ._exceptions import TypedAttributeLookupError
8
+
9
+ if sys.version_info < (3, 15):
10
+ from typing_extensions import sentinel
11
+
12
+ T_Attr = TypeVar("T_Attr")
13
+ T_Default = TypeVar("T_Default")
14
+ undefined = sentinel("undefined")
15
+
16
+
17
+ def typed_attribute() -> Any:
18
+ """Return a unique object, used to mark typed attributes."""
19
+ return object()
20
+
21
+
22
+ class TypedAttributeSet:
23
+ """
24
+ Superclass for typed attribute collections.
25
+
26
+ Checks that every public attribute of every subclass has a type annotation.
27
+ """
28
+
29
+ def __init_subclass__(cls) -> None:
30
+ annotations: dict[str, Any] = getattr(cls, "__annotations__", {})
31
+ for attrname in dir(cls):
32
+ if not attrname.startswith("_") and attrname not in annotations:
33
+ raise TypeError(
34
+ f"Attribute {attrname!r} is missing its type annotation"
35
+ )
36
+
37
+ super().__init_subclass__()
38
+
39
+
40
+ class TypedAttributeProvider:
41
+ """Base class for classes that wish to provide typed extra attributes."""
42
+
43
+ @property
44
+ def extra_attributes(self) -> Mapping[T_Attr, Callable[[], T_Attr]]:
45
+ """
46
+ A mapping of the extra attributes to callables that return the corresponding
47
+ values.
48
+
49
+ If the provider wraps another provider, the attributes from that wrapper should
50
+ also be included in the returned mapping (but the wrapper may override the
51
+ callables from the wrapped instance).
52
+
53
+ """
54
+ return {}
55
+
56
+ @overload
57
+ def extra(self, attribute: T_Attr) -> T_Attr: ...
58
+
59
+ @overload
60
+ def extra(self, attribute: T_Attr, default: T_Default) -> T_Attr | T_Default: ...
61
+
62
+ @final
63
+ def extra(self, attribute: Any, default: object = undefined) -> object:
64
+ """
65
+ extra(attribute, default=undefined)
66
+
67
+ Return the value of the given typed extra attribute.
68
+
69
+ :param attribute: the attribute (member of a :class:`~TypedAttributeSet`) to
70
+ look for
71
+ :param default: the value that should be returned if no value is found for the
72
+ attribute
73
+ :raises ~anyio.TypedAttributeLookupError: if the search failed and no default
74
+ value was given
75
+
76
+ """
77
+ try:
78
+ getter = self.extra_attributes[attribute]
79
+ except KeyError:
80
+ if default is undefined:
81
+ raise TypedAttributeLookupError("Attribute not found") from None
82
+ else:
83
+ return default
84
+
85
+ return getter()
.venvs/kimodo/lib/python3.10/site-packages/anyio/_lazyimport.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ __all__ = (
4
+ "fix_package_names",
5
+ "install_lazy_importer",
6
+ "set_deprecated_aliases",
7
+ )
8
+
9
+ import ast
10
+ import inspect
11
+ import sys
12
+ import warnings
13
+ from importlib import import_module
14
+ from types import ModuleType
15
+ from typing import Any
16
+
17
+
18
+ def install_lazy_importer() -> bool:
19
+ module_globals = sys._getframe(1).f_globals
20
+ module_name = module_globals["__name__"]
21
+ module_prefix = module_name + "."
22
+ module = sys.modules[module_name]
23
+ lazy_map, deprecated_aliases, submodule_names = _build_lazy_map(module)
24
+ names = sorted(lazy_map)
25
+
26
+ # Delete symbols that are not part of the API
27
+ del module_globals["TYPE_CHECKING"]
28
+ del module_globals["install_lazy_importer"]
29
+
30
+ if not lazy_map and not deprecated_aliases:
31
+ return False
32
+
33
+ def __getattr__(name: str) -> Any:
34
+ if new_name := deprecated_aliases.get(name):
35
+ emit_deprecation_warning(module_name, name, new_name)
36
+ target_mod, target_attr = new_name.rsplit(".", 1)
37
+ elif name in submodule_names:
38
+ target_mod, target_attr = "." + name, ""
39
+ else:
40
+ try:
41
+ target_mod, target_attr = lazy_map[name]
42
+ except KeyError:
43
+ raise AttributeError(
44
+ f"module {module_name!r} has no attribute {name!r}"
45
+ ) from None
46
+
47
+ imported = import_module(target_mod, module_name)
48
+ value = getattr(imported, target_attr) if target_attr else imported
49
+
50
+ # patch the module name to match
51
+ if (
52
+ getattr(value, "__module__", "").startswith(module_prefix)
53
+ and name not in deprecated_aliases
54
+ ):
55
+ value.__module__ = module_name
56
+
57
+ module_globals[name] = value
58
+ return value
59
+
60
+ def __dir__() -> list[str]:
61
+ return names
62
+
63
+ module_globals["__dir__"] = __dir__
64
+ module_globals["__getattr__"] = __getattr__
65
+ module_globals.pop("fix_package_names", None)
66
+ module_globals.pop("set_deprecated_aliases", None)
67
+ return True
68
+
69
+
70
+ def fix_package_names() -> None:
71
+ module_globals = sys._getframe(1).f_globals
72
+ module_prefix = module_globals["__name__"] + "."
73
+ del module_globals[fix_package_names.__name__]
74
+ for value in module_globals.values():
75
+ if modname := getattr(value, "__module__", ""):
76
+ if modname.startswith(module_prefix):
77
+ parts = modname.split(".")
78
+ value.__module__ = ".".join(
79
+ part for part in parts if not part.startswith("_")
80
+ )
81
+
82
+
83
+ def emit_deprecation_warning(module_name: str, name: str, target: str) -> None:
84
+ warnings.warn(
85
+ f"The {module_name}.{name} alias is deprecated, use {target} instead.",
86
+ DeprecationWarning,
87
+ stacklevel=3,
88
+ )
89
+
90
+
91
+ def set_deprecated_aliases(aliases: dict[str, str]) -> None:
92
+ module_globals = sys._getframe(1).f_globals
93
+ module_name = module_globals["__name__"]
94
+ del module_globals[set_deprecated_aliases.__name__]
95
+
96
+ def __getattr__(name: str) -> Any:
97
+ try:
98
+ target = aliases[name]
99
+ except KeyError:
100
+ raise AttributeError(
101
+ f"module {module_name!r} has no attribute {name!r}"
102
+ ) from None
103
+
104
+ emit_deprecation_warning(module_name, name, target)
105
+ target_modname, attrname = target.rsplit(".", 1)
106
+ module = import_module(target_modname)
107
+ return getattr(module, attrname)
108
+
109
+ sys.modules[module_name].__dict__["__getattr__"] = __getattr__
110
+
111
+
112
+ def _build_lazy_map(
113
+ module: ModuleType,
114
+ ) -> tuple[dict[str, tuple[str, str]], dict[str, str], list[str]]:
115
+ try:
116
+ source = inspect.getsource(module)
117
+ except OSError:
118
+ return {}, {}, []
119
+
120
+ tree = compile(source, module.__file__ or "", "exec", ast.PyCF_ONLY_AST)
121
+ assert isinstance(tree, ast.Module)
122
+ out: dict[str, tuple[str, str]] = {}
123
+ deprecated_aliases: dict[str, str] = {}
124
+ submodule_names: list[str] = []
125
+
126
+ for node in tree.body:
127
+ if not isinstance(node, ast.If) or not _is_type_checking_block(node.test):
128
+ continue
129
+
130
+ for stmt in node.body:
131
+ match stmt:
132
+ case ast.ImportFrom():
133
+ if stmt.module is None:
134
+ submodule_names.extend(alias.name for alias in stmt.names)
135
+ else:
136
+ base = "." * stmt.level + (stmt.module or "")
137
+ for alias in stmt.names:
138
+ if alias.name == "*":
139
+ raise RuntimeError("star imports not supported")
140
+
141
+ exported = alias.asname or alias.name
142
+ out[exported] = (base, alias.name)
143
+ case ast.Expr() if isinstance(stmt.value, ast.Call):
144
+ call = stmt.value
145
+ if (
146
+ isinstance(call.func, ast.Name)
147
+ and call.func.id == "set_deprecated_aliases"
148
+ ):
149
+ arg0 = call.args[0]
150
+ assert isinstance(arg0, ast.Dict)
151
+ for key, value in zip(arg0.keys, arg0.values, strict=True):
152
+ assert isinstance(key, ast.Constant)
153
+ assert isinstance(key.value, str)
154
+ assert isinstance(value, ast.Constant)
155
+ assert isinstance(value.value, str)
156
+ deprecated_aliases[key.value] = value.value
157
+
158
+ return out, deprecated_aliases, submodule_names
159
+
160
+
161
+ def _is_type_checking_block(test: ast.AST) -> bool:
162
+ if not isinstance(test, ast.BoolOp):
163
+ return False
164
+
165
+ subtest = test.values[0]
166
+ match subtest:
167
+ case ast.Name():
168
+ return subtest.id == "TYPE_CHECKING"
169
+ case ast.Attribute():
170
+ return (
171
+ isinstance(subtest.value, ast.Name)
172
+ and subtest.value.id == "typing"
173
+ and subtest.attr == "TYPE_CHECKING"
174
+ )
175
+ case _:
176
+ return False
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/__init__.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from .._lazyimport import (
6
+ fix_package_names,
7
+ install_lazy_importer,
8
+ set_deprecated_aliases,
9
+ )
10
+
11
+ if TYPE_CHECKING or not install_lazy_importer():
12
+ from ._eventloop import AsyncBackend as AsyncBackend
13
+ from ._resources import AsyncResource as AsyncResource
14
+ from ._sockets import ConnectedUDPSocket as ConnectedUDPSocket
15
+ from ._sockets import ConnectedUNIXDatagramSocket as ConnectedUNIXDatagramSocket
16
+ from ._sockets import IPAddressType as IPAddressType
17
+ from ._sockets import IPSockAddrType as IPSockAddrType
18
+ from ._sockets import SocketAttribute as SocketAttribute
19
+ from ._sockets import SocketListener as SocketListener
20
+ from ._sockets import SocketStream as SocketStream
21
+ from ._sockets import UDPPacketType as UDPPacketType
22
+ from ._sockets import UDPSocket as UDPSocket
23
+ from ._sockets import UNIXDatagramPacketType as UNIXDatagramPacketType
24
+ from ._sockets import UNIXDatagramSocket as UNIXDatagramSocket
25
+ from ._sockets import UNIXSocketStream as UNIXSocketStream
26
+ from ._streams import AnyByteReceiveStream as AnyByteReceiveStream
27
+ from ._streams import AnyByteSendStream as AnyByteSendStream
28
+ from ._streams import AnyByteStream as AnyByteStream
29
+ from ._streams import AnyByteStreamConnectable as AnyByteStreamConnectable
30
+ from ._streams import (
31
+ AnyUnreliableByteReceiveStream as AnyUnreliableByteReceiveStream,
32
+ )
33
+ from ._streams import AnyUnreliableByteSendStream as AnyUnreliableByteSendStream
34
+ from ._streams import AnyUnreliableByteStream as AnyUnreliableByteStream
35
+ from ._streams import ByteReceiveStream as ByteReceiveStream
36
+ from ._streams import ByteSendStream as ByteSendStream
37
+ from ._streams import ByteStream as ByteStream
38
+ from ._streams import ByteStreamConnectable as ByteStreamConnectable
39
+ from ._streams import Listener as Listener
40
+ from ._streams import ObjectReceiveStream as ObjectReceiveStream
41
+ from ._streams import ObjectSendStream as ObjectSendStream
42
+ from ._streams import ObjectStream as ObjectStream
43
+ from ._streams import ObjectStreamConnectable as ObjectStreamConnectable
44
+ from ._streams import UnreliableObjectReceiveStream as UnreliableObjectReceiveStream
45
+ from ._streams import UnreliableObjectSendStream as UnreliableObjectSendStream
46
+ from ._streams import UnreliableObjectStream as UnreliableObjectStream
47
+ from ._subprocesses import Process as Process
48
+ from ._tasks import TaskGroup as TaskGroup
49
+ from ._tasks import TaskStatus as TaskStatus
50
+ from ._testing import TestRunner as TestRunner
51
+
52
+ fix_package_names()
53
+ set_deprecated_aliases(
54
+ {
55
+ "CapacityLimiter": "anyio.CapacityLimiter",
56
+ "Condition": "anyio.Condition",
57
+ "Event": "anyio.Event",
58
+ "Lock": "anyio.Lock",
59
+ "Semaphore": "anyio.Semaphore",
60
+ "CancelScope": "anyio.CancelScope",
61
+ "BlockingPortal": "anyio.from_thread.BlockingPortal",
62
+ }
63
+ )
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_eventloop.py ADDED
@@ -0,0 +1,428 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import sys
5
+ from abc import ABCMeta, abstractmethod
6
+ from collections.abc import (
7
+ AsyncIterator,
8
+ Awaitable,
9
+ Callable,
10
+ Coroutine,
11
+ Iterable,
12
+ Mapping,
13
+ Sequence,
14
+ )
15
+ from contextlib import AbstractContextManager
16
+ from os import PathLike
17
+ from signal import Signals
18
+ from socket import AddressFamily, SocketKind, socket
19
+ from typing import (
20
+ IO,
21
+ TYPE_CHECKING,
22
+ Any,
23
+ TypeAlias,
24
+ TypeVar,
25
+ overload,
26
+ )
27
+
28
+ if sys.version_info >= (3, 11):
29
+ from typing import TypeVarTuple, Unpack
30
+ else:
31
+ from typing_extensions import TypeVarTuple, Unpack
32
+
33
+ if TYPE_CHECKING:
34
+ from _typeshed import FileDescriptorLike
35
+
36
+ from .._core._synchronization import CapacityLimiter, Event, Lock, Semaphore
37
+ from .._core._tasks import CancelScope
38
+ from .._core._testing import TaskInfo
39
+ from ._sockets import (
40
+ ConnectedUDPSocket,
41
+ ConnectedUNIXDatagramSocket,
42
+ IPSockAddrType,
43
+ SocketListener,
44
+ SocketStream,
45
+ UDPSocket,
46
+ UNIXDatagramSocket,
47
+ UNIXSocketStream,
48
+ )
49
+ from ._subprocesses import Process
50
+ from ._tasks import TaskGroup
51
+ from ._testing import TestRunner
52
+
53
+ T_Retval = TypeVar("T_Retval")
54
+ T_co = TypeVar("T_co", covariant=True)
55
+ PosArgsT = TypeVarTuple("PosArgsT")
56
+ StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes]
57
+
58
+
59
+ class AsyncBackend(metaclass=ABCMeta):
60
+ @classmethod
61
+ @abstractmethod
62
+ def run(
63
+ cls,
64
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
65
+ args: tuple[Unpack[PosArgsT]],
66
+ kwargs: dict[str, Any],
67
+ options: dict[str, Any],
68
+ ) -> T_Retval:
69
+ """
70
+ Run the given coroutine function in an asynchronous event loop.
71
+
72
+ The current thread must not be already running an event loop.
73
+
74
+ :param func: a coroutine function
75
+ :param args: positional arguments to ``func``
76
+ :param kwargs: positional arguments to ``func``
77
+ :param options: keyword arguments to call the backend ``run()`` implementation
78
+ with
79
+ :return: the return value of the coroutine function
80
+ """
81
+
82
+ @classmethod
83
+ @abstractmethod
84
+ def current_token(cls) -> object:
85
+ """
86
+ Return an object that allows other threads to run code inside the event loop.
87
+
88
+ :return: a token object, specific to the event loop running in the current
89
+ thread
90
+ """
91
+
92
+ @classmethod
93
+ @abstractmethod
94
+ def current_time(cls) -> float:
95
+ """
96
+ Return the current value of the event loop's internal clock.
97
+
98
+ :return: the clock value (seconds)
99
+ """
100
+
101
+ @classmethod
102
+ @abstractmethod
103
+ def cancelled_exception_class(cls) -> type[BaseException]:
104
+ """Return the exception class that is raised in a task if it's cancelled."""
105
+
106
+ @classmethod
107
+ @abstractmethod
108
+ async def checkpoint(cls) -> None:
109
+ """
110
+ Check if the task has been cancelled, and allow rescheduling of other tasks.
111
+
112
+ This is effectively the same as running :meth:`checkpoint_if_cancelled` and then
113
+ :meth:`cancel_shielded_checkpoint`.
114
+ """
115
+
116
+ @classmethod
117
+ async def checkpoint_if_cancelled(cls) -> None:
118
+ """
119
+ Check if the current task group has been cancelled.
120
+
121
+ This will check if the task has been cancelled, but will not allow other tasks
122
+ to be scheduled if not.
123
+
124
+ """
125
+ if cls.current_effective_deadline() == -math.inf:
126
+ await cls.checkpoint()
127
+
128
+ @classmethod
129
+ async def cancel_shielded_checkpoint(cls) -> None:
130
+ """
131
+ Allow the rescheduling of other tasks.
132
+
133
+ This will give other tasks the opportunity to run, but without checking if the
134
+ current task group has been cancelled, unlike with :meth:`checkpoint`.
135
+
136
+ """
137
+ with cls.create_cancel_scope(shield=True):
138
+ await cls.sleep(0)
139
+
140
+ @classmethod
141
+ @abstractmethod
142
+ async def sleep(cls, delay: float) -> None:
143
+ """
144
+ Pause the current task for the specified duration.
145
+
146
+ :param delay: the duration, in seconds
147
+ """
148
+
149
+ @classmethod
150
+ @abstractmethod
151
+ def create_cancel_scope(
152
+ cls, *, deadline: float = math.inf, shield: bool = False
153
+ ) -> CancelScope:
154
+ pass
155
+
156
+ @classmethod
157
+ @abstractmethod
158
+ def current_effective_deadline(cls) -> float:
159
+ """
160
+ Return the nearest deadline among all the cancel scopes effective for the
161
+ current task.
162
+
163
+ :return:
164
+ - a clock value from the event loop's internal clock
165
+ - ``inf`` if there is no deadline in effect
166
+ - ``-inf`` if the current scope has been cancelled
167
+ :rtype: float
168
+ """
169
+
170
+ @classmethod
171
+ @abstractmethod
172
+ def create_task_group(cls) -> TaskGroup:
173
+ pass
174
+
175
+ @classmethod
176
+ @abstractmethod
177
+ def create_event(cls) -> Event:
178
+ pass
179
+
180
+ @classmethod
181
+ @abstractmethod
182
+ def create_lock(cls, *, fast_acquire: bool) -> Lock:
183
+ pass
184
+
185
+ @classmethod
186
+ @abstractmethod
187
+ def create_semaphore(
188
+ cls,
189
+ initial_value: int,
190
+ *,
191
+ max_value: int | None = None,
192
+ fast_acquire: bool = False,
193
+ ) -> Semaphore:
194
+ pass
195
+
196
+ @classmethod
197
+ @abstractmethod
198
+ def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter:
199
+ pass
200
+
201
+ @classmethod
202
+ @abstractmethod
203
+ async def run_sync_in_worker_thread(
204
+ cls,
205
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
206
+ args: tuple[Unpack[PosArgsT]],
207
+ abandon_on_cancel: bool = False,
208
+ limiter: CapacityLimiter | None = None,
209
+ ) -> T_Retval:
210
+ pass
211
+
212
+ @classmethod
213
+ @abstractmethod
214
+ def check_cancelled(cls) -> None:
215
+ pass
216
+
217
+ @classmethod
218
+ @abstractmethod
219
+ def run_async_from_thread(
220
+ cls,
221
+ func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]],
222
+ args: tuple[Unpack[PosArgsT]],
223
+ token: object,
224
+ ) -> T_co:
225
+ pass
226
+
227
+ @classmethod
228
+ @abstractmethod
229
+ def run_sync_from_thread(
230
+ cls,
231
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
232
+ args: tuple[Unpack[PosArgsT]],
233
+ token: object,
234
+ ) -> T_Retval:
235
+ pass
236
+
237
+ @classmethod
238
+ @abstractmethod
239
+ async def open_process(
240
+ cls,
241
+ command: StrOrBytesPath | Sequence[StrOrBytesPath],
242
+ *,
243
+ stdin: int | IO[Any] | None,
244
+ stdout: int | IO[Any] | None,
245
+ stderr: int | IO[Any] | None,
246
+ cwd: StrOrBytesPath | None = None,
247
+ env: Mapping[str, str] | None = None,
248
+ startupinfo: Any = None,
249
+ creationflags: int = 0,
250
+ start_new_session: bool = False,
251
+ pass_fds: Sequence[int] = (),
252
+ user: str | int | None = None,
253
+ group: str | int | None = None,
254
+ extra_groups: Iterable[str | int] | None = None,
255
+ umask: int = -1,
256
+ **kwargs: Any,
257
+ ) -> Process:
258
+ pass
259
+
260
+ @classmethod
261
+ @abstractmethod
262
+ def setup_process_pool_exit_at_shutdown(cls, workers: set[Process]) -> None:
263
+ pass
264
+
265
+ @classmethod
266
+ @abstractmethod
267
+ async def connect_tcp(
268
+ cls, host: str, port: int, local_address: IPSockAddrType | None = None
269
+ ) -> SocketStream:
270
+ pass
271
+
272
+ @classmethod
273
+ @abstractmethod
274
+ async def connect_unix(cls, path: str | bytes) -> UNIXSocketStream:
275
+ pass
276
+
277
+ @classmethod
278
+ @abstractmethod
279
+ def create_tcp_listener(cls, sock: socket) -> SocketListener:
280
+ pass
281
+
282
+ @classmethod
283
+ @abstractmethod
284
+ def create_unix_listener(cls, sock: socket) -> SocketListener:
285
+ pass
286
+
287
+ @classmethod
288
+ @abstractmethod
289
+ async def create_udp_socket(
290
+ cls,
291
+ family: AddressFamily,
292
+ local_address: IPSockAddrType | None,
293
+ remote_address: IPSockAddrType | None,
294
+ reuse_port: bool,
295
+ ) -> UDPSocket | ConnectedUDPSocket:
296
+ pass
297
+
298
+ @classmethod
299
+ @overload
300
+ async def create_unix_datagram_socket(
301
+ cls, raw_socket: socket, remote_path: None
302
+ ) -> UNIXDatagramSocket: ...
303
+
304
+ @classmethod
305
+ @overload
306
+ async def create_unix_datagram_socket(
307
+ cls, raw_socket: socket, remote_path: str | bytes
308
+ ) -> ConnectedUNIXDatagramSocket: ...
309
+
310
+ @classmethod
311
+ @abstractmethod
312
+ async def create_unix_datagram_socket(
313
+ cls, raw_socket: socket, remote_path: str | bytes | None
314
+ ) -> UNIXDatagramSocket | ConnectedUNIXDatagramSocket:
315
+ pass
316
+
317
+ @classmethod
318
+ @abstractmethod
319
+ async def getaddrinfo(
320
+ cls,
321
+ host: bytes | str | None,
322
+ port: str | int | None,
323
+ *,
324
+ family: int | AddressFamily = 0,
325
+ type: int | SocketKind = 0,
326
+ proto: int = 0,
327
+ flags: int = 0,
328
+ ) -> Sequence[
329
+ tuple[
330
+ AddressFamily,
331
+ SocketKind,
332
+ int,
333
+ str,
334
+ tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
335
+ ]
336
+ ]:
337
+ pass
338
+
339
+ @classmethod
340
+ @abstractmethod
341
+ async def getnameinfo(
342
+ cls, sockaddr: IPSockAddrType, flags: int = 0
343
+ ) -> tuple[str, str]:
344
+ pass
345
+
346
+ @classmethod
347
+ @abstractmethod
348
+ async def wait_readable(cls, obj: FileDescriptorLike) -> None:
349
+ pass
350
+
351
+ @classmethod
352
+ @abstractmethod
353
+ async def wait_writable(cls, obj: FileDescriptorLike) -> None:
354
+ pass
355
+
356
+ @classmethod
357
+ @abstractmethod
358
+ def notify_closing(cls, obj: FileDescriptorLike) -> None:
359
+ pass
360
+
361
+ @classmethod
362
+ @abstractmethod
363
+ async def wrap_listener_socket(cls, sock: socket) -> SocketListener:
364
+ pass
365
+
366
+ @classmethod
367
+ @abstractmethod
368
+ async def wrap_stream_socket(cls, sock: socket) -> SocketStream:
369
+ pass
370
+
371
+ @classmethod
372
+ @abstractmethod
373
+ async def wrap_unix_stream_socket(cls, sock: socket) -> UNIXSocketStream:
374
+ pass
375
+
376
+ @classmethod
377
+ @abstractmethod
378
+ async def wrap_udp_socket(cls, sock: socket) -> UDPSocket:
379
+ pass
380
+
381
+ @classmethod
382
+ @abstractmethod
383
+ async def wrap_connected_udp_socket(cls, sock: socket) -> ConnectedUDPSocket:
384
+ pass
385
+
386
+ @classmethod
387
+ @abstractmethod
388
+ async def wrap_unix_datagram_socket(cls, sock: socket) -> UNIXDatagramSocket:
389
+ pass
390
+
391
+ @classmethod
392
+ @abstractmethod
393
+ async def wrap_connected_unix_datagram_socket(
394
+ cls, sock: socket
395
+ ) -> ConnectedUNIXDatagramSocket:
396
+ pass
397
+
398
+ @classmethod
399
+ @abstractmethod
400
+ def current_default_thread_limiter(cls) -> CapacityLimiter:
401
+ pass
402
+
403
+ @classmethod
404
+ @abstractmethod
405
+ def open_signal_receiver(
406
+ cls, *signals: Signals
407
+ ) -> AbstractContextManager[AsyncIterator[Signals]]:
408
+ pass
409
+
410
+ @classmethod
411
+ @abstractmethod
412
+ def get_current_task(cls) -> TaskInfo:
413
+ pass
414
+
415
+ @classmethod
416
+ @abstractmethod
417
+ def get_running_tasks(cls) -> Sequence[TaskInfo]:
418
+ pass
419
+
420
+ @classmethod
421
+ @abstractmethod
422
+ async def wait_all_tasks_blocked(cls) -> None:
423
+ pass
424
+
425
+ @classmethod
426
+ @abstractmethod
427
+ def create_test_runner(cls, options: dict[str, Any]) -> TestRunner:
428
+ pass
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_resources.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from abc import ABCMeta, abstractmethod
5
+ from types import TracebackType
6
+ from typing import TypeVar
7
+
8
+ if sys.version_info >= (3, 11):
9
+ from typing import Self
10
+ else:
11
+ from typing_extensions import Self
12
+
13
+ T = TypeVar("T")
14
+
15
+
16
+ class AsyncResource(metaclass=ABCMeta):
17
+ """
18
+ Abstract base class for all closeable asynchronous resources.
19
+
20
+ Works as an asynchronous context manager which returns the instance itself on enter,
21
+ and calls :meth:`aclose` on exit.
22
+ """
23
+
24
+ __slots__ = ()
25
+
26
+ async def __aenter__(self) -> Self:
27
+ return self
28
+
29
+ async def __aexit__(
30
+ self,
31
+ exc_type: type[BaseException] | None,
32
+ exc_val: BaseException | None,
33
+ exc_tb: TracebackType | None,
34
+ ) -> None:
35
+ await self.aclose()
36
+
37
+ @abstractmethod
38
+ async def aclose(self) -> None:
39
+ """Close the resource."""
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_sockets.py ADDED
@@ -0,0 +1,401 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import errno
4
+ import socket
5
+ from abc import abstractmethod
6
+ from collections.abc import Callable, Collection, Mapping
7
+ from contextlib import AsyncExitStack
8
+ from io import IOBase
9
+ from ipaddress import IPv4Address, IPv6Address
10
+ from socket import AddressFamily
11
+ from typing import TYPE_CHECKING, Any, TypeAlias, TypeVar
12
+
13
+ from .._core._eventloop import get_async_backend
14
+ from .._core._typedattr import (
15
+ TypedAttributeProvider,
16
+ TypedAttributeSet,
17
+ typed_attribute,
18
+ )
19
+ from ._streams import ByteStream, Listener, UnreliableObjectStream
20
+
21
+ if TYPE_CHECKING:
22
+ from ._tasks import TaskGroup
23
+
24
+ IPAddressType: TypeAlias = str | IPv4Address | IPv6Address
25
+ IPSockAddrType: TypeAlias = tuple[str, int]
26
+ SockAddrType: TypeAlias = IPSockAddrType | str
27
+ UDPPacketType: TypeAlias = tuple[bytes, IPSockAddrType]
28
+ UNIXDatagramPacketType: TypeAlias = tuple[bytes, str]
29
+ T_Retval = TypeVar("T_Retval")
30
+
31
+
32
+ def _validate_socket(
33
+ sock_or_fd: socket.socket | int,
34
+ sock_type: socket.SocketKind,
35
+ addr_family: socket.AddressFamily = socket.AF_UNSPEC,
36
+ *,
37
+ require_connected: bool = False,
38
+ require_bound: bool = False,
39
+ ) -> socket.socket:
40
+ if isinstance(sock_or_fd, int):
41
+ try:
42
+ sock = socket.socket(fileno=sock_or_fd)
43
+ except OSError as exc:
44
+ if exc.errno == errno.ENOTSOCK:
45
+ raise ValueError(
46
+ "the file descriptor does not refer to a socket"
47
+ ) from exc
48
+ elif require_connected:
49
+ raise ValueError("the socket must be connected") from exc
50
+ elif require_bound:
51
+ raise ValueError("the socket must be bound to a local address") from exc
52
+ else:
53
+ raise
54
+ elif isinstance(sock_or_fd, socket.socket):
55
+ sock = sock_or_fd
56
+ else:
57
+ raise TypeError(
58
+ f"expected an int or socket, got {type(sock_or_fd).__qualname__} instead"
59
+ )
60
+
61
+ try:
62
+ if require_connected:
63
+ try:
64
+ sock.getpeername()
65
+ except OSError as exc:
66
+ raise ValueError("the socket must be connected") from exc
67
+
68
+ if require_bound:
69
+ try:
70
+ if sock.family in (socket.AF_INET, socket.AF_INET6):
71
+ bound_addr = sock.getsockname()[1]
72
+ else:
73
+ bound_addr = sock.getsockname()
74
+ except OSError:
75
+ bound_addr = None
76
+
77
+ if not bound_addr:
78
+ raise ValueError("the socket must be bound to a local address")
79
+
80
+ if addr_family != socket.AF_UNSPEC and sock.family != addr_family:
81
+ raise ValueError(
82
+ f"address family mismatch: expected {addr_family.name}, got "
83
+ f"{sock.family.name}"
84
+ )
85
+
86
+ if sock.type != sock_type:
87
+ raise ValueError(
88
+ f"socket type mismatch: expected {sock_type.name}, got {sock.type.name}"
89
+ )
90
+ except BaseException:
91
+ # Avoid ResourceWarning from the locally constructed socket object
92
+ if isinstance(sock_or_fd, int):
93
+ sock.detach()
94
+
95
+ raise
96
+
97
+ sock.setblocking(False)
98
+ return sock
99
+
100
+
101
+ class SocketAttribute(TypedAttributeSet):
102
+ """
103
+ .. attribute:: family
104
+ :type: socket.AddressFamily
105
+
106
+ the address family of the underlying socket
107
+
108
+ .. attribute:: local_address
109
+ :type: tuple[str, int] | str
110
+
111
+ the local address the underlying socket is connected to
112
+
113
+ .. attribute:: local_port
114
+ :type: int
115
+
116
+ for IP based sockets, the local port the underlying socket is bound to
117
+
118
+ .. attribute:: raw_socket
119
+ :type: socket.socket
120
+
121
+ the underlying stdlib socket object
122
+
123
+ .. attribute:: remote_address
124
+ :type: tuple[str, int] | str
125
+
126
+ the remote address the underlying socket is connected to
127
+
128
+ .. attribute:: remote_port
129
+ :type: int
130
+
131
+ for IP based sockets, the remote port the underlying socket is connected to
132
+ """
133
+
134
+ family: AddressFamily = typed_attribute()
135
+ local_address: SockAddrType = typed_attribute()
136
+ local_port: int = typed_attribute()
137
+ raw_socket: socket.socket = typed_attribute()
138
+ remote_address: SockAddrType = typed_attribute()
139
+ remote_port: int = typed_attribute()
140
+
141
+
142
+ class _SocketProvider(TypedAttributeProvider):
143
+ @property
144
+ def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]:
145
+ from .._core._sockets import convert_ipv6_sockaddr as convert
146
+
147
+ attributes: dict[Any, Callable[[], Any]] = {
148
+ SocketAttribute.family: lambda: self._raw_socket.family,
149
+ SocketAttribute.local_address: lambda: convert(
150
+ self._raw_socket.getsockname()
151
+ ),
152
+ SocketAttribute.raw_socket: lambda: self._raw_socket,
153
+ }
154
+ try:
155
+ peername: tuple[str, int] | None = convert(self._raw_socket.getpeername())
156
+ except OSError:
157
+ peername = None
158
+
159
+ # Provide the remote address for connected sockets
160
+ if peername is not None:
161
+ attributes[SocketAttribute.remote_address] = lambda: peername
162
+
163
+ # Provide local and remote ports for IP based sockets
164
+ if self._raw_socket.family in (AddressFamily.AF_INET, AddressFamily.AF_INET6):
165
+ attributes[SocketAttribute.local_port] = lambda: (
166
+ self._raw_socket.getsockname()[1]
167
+ )
168
+ if peername is not None:
169
+ remote_port = peername[1]
170
+ attributes[SocketAttribute.remote_port] = lambda: remote_port
171
+
172
+ return attributes
173
+
174
+ @property
175
+ @abstractmethod
176
+ def _raw_socket(self) -> socket.socket:
177
+ pass
178
+
179
+
180
+ class SocketStream(ByteStream, _SocketProvider):
181
+ """
182
+ Transports bytes over a socket.
183
+
184
+ Supports all relevant extra attributes from :class:`~SocketAttribute`.
185
+ """
186
+
187
+ @classmethod
188
+ async def from_socket(cls, sock_or_fd: socket.socket | int) -> SocketStream:
189
+ """
190
+ Wrap an existing socket object or file descriptor as a socket stream.
191
+
192
+ The newly created socket wrapper takes ownership of the socket being passed in.
193
+ The existing socket must already be connected.
194
+
195
+ :param sock_or_fd: a socket object or file descriptor
196
+ :return: a socket stream
197
+
198
+ """
199
+ sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_connected=True)
200
+ return await get_async_backend().wrap_stream_socket(sock)
201
+
202
+
203
+ class UNIXSocketStream(SocketStream):
204
+ @classmethod
205
+ async def from_socket(cls, sock_or_fd: socket.socket | int) -> UNIXSocketStream:
206
+ """
207
+ Wrap an existing socket object or file descriptor as a UNIX socket stream.
208
+
209
+ The newly created socket wrapper takes ownership of the socket being passed in.
210
+ The existing socket must already be connected.
211
+
212
+ :param sock_or_fd: a socket object or file descriptor
213
+ :return: a UNIX socket stream
214
+
215
+ """
216
+ sock = _validate_socket(
217
+ sock_or_fd, socket.SOCK_STREAM, socket.AF_UNIX, require_connected=True
218
+ )
219
+ return await get_async_backend().wrap_unix_stream_socket(sock)
220
+
221
+ @abstractmethod
222
+ async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None:
223
+ """
224
+ Send file descriptors along with a message to the peer.
225
+
226
+ :param message: a non-empty bytestring
227
+ :param fds: a collection of files (either numeric file descriptors or open file
228
+ or socket objects)
229
+ """
230
+
231
+ @abstractmethod
232
+ async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]:
233
+ """
234
+ Receive file descriptors along with a message from the peer.
235
+
236
+ :param msglen: length of the message to expect from the peer
237
+ :param maxfds: maximum number of file descriptors to expect from the peer
238
+ :return: a tuple of (message, file descriptors)
239
+ """
240
+
241
+
242
+ class SocketListener(Listener[SocketStream], _SocketProvider):
243
+ """
244
+ Listens to incoming socket connections.
245
+
246
+ Supports all relevant extra attributes from :class:`~SocketAttribute`.
247
+ """
248
+
249
+ @classmethod
250
+ async def from_socket(
251
+ cls,
252
+ sock_or_fd: socket.socket | int,
253
+ ) -> SocketListener:
254
+ """
255
+ Wrap an existing socket object or file descriptor as a socket listener.
256
+
257
+ The newly created listener takes ownership of the socket being passed in.
258
+
259
+ :param sock_or_fd: a socket object or file descriptor
260
+ :return: a socket listener
261
+
262
+ """
263
+ sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_bound=True)
264
+ return await get_async_backend().wrap_listener_socket(sock)
265
+
266
+ @abstractmethod
267
+ async def accept(self) -> SocketStream:
268
+ """Accept an incoming connection."""
269
+
270
+ async def serve(
271
+ self,
272
+ handler: Callable[[SocketStream], Any],
273
+ task_group: TaskGroup | None = None,
274
+ ) -> None:
275
+ from .. import create_task_group
276
+
277
+ async with AsyncExitStack() as stack:
278
+ if task_group is None:
279
+ task_group = await stack.enter_async_context(create_task_group())
280
+
281
+ while True:
282
+ stream = await self.accept()
283
+ task_group.start_soon(handler, stream)
284
+
285
+
286
+ class UDPSocket(UnreliableObjectStream[UDPPacketType], _SocketProvider):
287
+ """
288
+ Represents an unconnected UDP socket.
289
+
290
+ Supports all relevant extra attributes from :class:`~SocketAttribute`.
291
+ """
292
+
293
+ @classmethod
294
+ async def from_socket(cls, sock_or_fd: socket.socket | int) -> UDPSocket:
295
+ """
296
+ Wrap an existing socket object or file descriptor as a UDP socket.
297
+
298
+ The newly created socket wrapper takes ownership of the socket being passed in.
299
+ The existing socket must be bound to a local address.
300
+
301
+ :param sock_or_fd: a socket object or file descriptor
302
+ :return: a UDP socket
303
+
304
+ """
305
+ sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, require_bound=True)
306
+ return await get_async_backend().wrap_udp_socket(sock)
307
+
308
+ async def sendto(self, data: bytes, host: str, port: int) -> None:
309
+ """
310
+ Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, (host, port))).
311
+
312
+ """
313
+ return await self.send((data, (host, port)))
314
+
315
+
316
+ class ConnectedUDPSocket(UnreliableObjectStream[bytes], _SocketProvider):
317
+ """
318
+ Represents an connected UDP socket.
319
+
320
+ Supports all relevant extra attributes from :class:`~SocketAttribute`.
321
+ """
322
+
323
+ @classmethod
324
+ async def from_socket(cls, sock_or_fd: socket.socket | int) -> ConnectedUDPSocket:
325
+ """
326
+ Wrap an existing socket object or file descriptor as a connected UDP socket.
327
+
328
+ The newly created socket wrapper takes ownership of the socket being passed in.
329
+ The existing socket must already be connected.
330
+
331
+ :param sock_or_fd: a socket object or file descriptor
332
+ :return: a connected UDP socket
333
+
334
+ """
335
+ sock = _validate_socket(
336
+ sock_or_fd,
337
+ socket.SOCK_DGRAM,
338
+ require_connected=True,
339
+ )
340
+ return await get_async_backend().wrap_connected_udp_socket(sock)
341
+
342
+
343
+ class UNIXDatagramSocket(
344
+ UnreliableObjectStream[UNIXDatagramPacketType], _SocketProvider
345
+ ):
346
+ """
347
+ Represents an unconnected Unix datagram socket.
348
+
349
+ Supports all relevant extra attributes from :class:`~SocketAttribute`.
350
+ """
351
+
352
+ @classmethod
353
+ async def from_socket(
354
+ cls,
355
+ sock_or_fd: socket.socket | int,
356
+ ) -> UNIXDatagramSocket:
357
+ """
358
+ Wrap an existing socket object or file descriptor as a UNIX datagram
359
+ socket.
360
+
361
+ The newly created socket wrapper takes ownership of the socket being passed in.
362
+
363
+ :param sock_or_fd: a socket object or file descriptor
364
+ :return: a UNIX datagram socket
365
+
366
+ """
367
+ sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX)
368
+ return await get_async_backend().wrap_unix_datagram_socket(sock)
369
+
370
+ async def sendto(self, data: bytes, path: str) -> None:
371
+ """Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, path))."""
372
+ return await self.send((data, path))
373
+
374
+
375
+ class ConnectedUNIXDatagramSocket(UnreliableObjectStream[bytes], _SocketProvider):
376
+ """
377
+ Represents a connected Unix datagram socket.
378
+
379
+ Supports all relevant extra attributes from :class:`~SocketAttribute`.
380
+ """
381
+
382
+ @classmethod
383
+ async def from_socket(
384
+ cls,
385
+ sock_or_fd: socket.socket | int,
386
+ ) -> ConnectedUNIXDatagramSocket:
387
+ """
388
+ Wrap an existing socket object or file descriptor as a connected UNIX datagram
389
+ socket.
390
+
391
+ The newly created socket wrapper takes ownership of the socket being passed in.
392
+ The existing socket must already be connected.
393
+
394
+ :param sock_or_fd: a socket object or file descriptor
395
+ :return: a connected UNIX datagram socket
396
+
397
+ """
398
+ sock = _validate_socket(
399
+ sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX, require_connected=True
400
+ )
401
+ return await get_async_backend().wrap_connected_unix_datagram_socket(sock)
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_streams.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from collections.abc import Callable
5
+ from typing import TYPE_CHECKING, Any, Generic, TypeAlias, TypeVar
6
+
7
+ from .._core._exceptions import EndOfStream
8
+ from .._core._typedattr import TypedAttributeProvider
9
+ from ._resources import AsyncResource
10
+
11
+ if TYPE_CHECKING:
12
+ from ._tasks import TaskGroup
13
+
14
+ T_Item = TypeVar("T_Item")
15
+ T_co = TypeVar("T_co", covariant=True)
16
+ T_contra = TypeVar("T_contra", contravariant=True)
17
+
18
+
19
+ class UnreliableObjectReceiveStream(
20
+ AsyncResource, TypedAttributeProvider, Generic[T_co]
21
+ ):
22
+ """
23
+ An interface for receiving objects.
24
+
25
+ This interface makes no guarantees that the received messages arrive in the order in
26
+ which they were sent, or that no messages are missed.
27
+
28
+ Asynchronously iterating over objects of this type will yield objects matching the
29
+ given type parameter.
30
+ """
31
+
32
+ def __aiter__(self) -> UnreliableObjectReceiveStream[T_co]:
33
+ return self
34
+
35
+ async def __anext__(self) -> T_co:
36
+ try:
37
+ return await self.receive()
38
+ except EndOfStream:
39
+ raise StopAsyncIteration from None
40
+
41
+ @abstractmethod
42
+ async def receive(self) -> T_co:
43
+ """
44
+ Receive the next item.
45
+
46
+ :raises ~anyio.ClosedResourceError: if the receive stream has been explicitly
47
+ closed
48
+ :raises ~anyio.EndOfStream: if this stream has been closed from the other end
49
+ :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable
50
+ due to external causes
51
+ """
52
+
53
+
54
+ class UnreliableObjectSendStream(
55
+ AsyncResource, TypedAttributeProvider, Generic[T_contra]
56
+ ):
57
+ """
58
+ An interface for sending objects.
59
+
60
+ This interface makes no guarantees that the messages sent will reach the
61
+ recipient(s) in the same order in which they were sent, or at all.
62
+ """
63
+
64
+ @abstractmethod
65
+ async def send(self, item: T_contra) -> None:
66
+ """
67
+ Send an item to the peer(s).
68
+
69
+ :param item: the item to send
70
+ :raises ~anyio.ClosedResourceError: if the send stream has been explicitly
71
+ closed
72
+ :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable
73
+ due to external causes
74
+ """
75
+
76
+
77
+ class UnreliableObjectStream(
78
+ UnreliableObjectReceiveStream[T_Item], UnreliableObjectSendStream[T_Item]
79
+ ):
80
+ """
81
+ A bidirectional message stream which does not guarantee the order or reliability of
82
+ message delivery.
83
+ """
84
+
85
+
86
+ class ObjectReceiveStream(UnreliableObjectReceiveStream[T_co]):
87
+ """
88
+ A receive message stream which guarantees that messages are received in the same
89
+ order in which they were sent, and that no messages are missed.
90
+ """
91
+
92
+
93
+ class ObjectSendStream(UnreliableObjectSendStream[T_contra]):
94
+ """
95
+ A send message stream which guarantees that messages are delivered in the same order
96
+ in which they were sent, without missing any messages in the middle.
97
+ """
98
+
99
+
100
+ class ObjectStream(
101
+ ObjectReceiveStream[T_Item],
102
+ ObjectSendStream[T_Item],
103
+ UnreliableObjectStream[T_Item],
104
+ ):
105
+ """
106
+ A bidirectional message stream which guarantees the order and reliability of message
107
+ delivery.
108
+ """
109
+
110
+ @abstractmethod
111
+ async def send_eof(self) -> None:
112
+ """
113
+ Send an end-of-file indication to the peer.
114
+
115
+ You should not try to send any further data to this stream after calling this
116
+ method. This method is idempotent (does nothing on successive calls).
117
+ """
118
+
119
+
120
+ class ByteReceiveStream(AsyncResource, TypedAttributeProvider):
121
+ """
122
+ An interface for receiving bytes from a single peer.
123
+
124
+ Iterating this byte stream will yield a byte string of arbitrary length, but no more
125
+ than 65536 bytes.
126
+ """
127
+
128
+ def __aiter__(self) -> ByteReceiveStream:
129
+ return self
130
+
131
+ async def __anext__(self) -> bytes:
132
+ try:
133
+ return await self.receive()
134
+ except EndOfStream:
135
+ raise StopAsyncIteration from None
136
+
137
+ @abstractmethod
138
+ async def receive(self, max_bytes: int = 65536) -> bytes:
139
+ """
140
+ Receive at most ``max_bytes`` bytes from the peer.
141
+
142
+ .. note:: Implementers of this interface should not return an empty
143
+ :class:`bytes` object, and users should ignore them.
144
+
145
+ :param max_bytes: maximum number of bytes to receive (must be a positive
146
+ integer)
147
+ :return: the received bytes
148
+ :raises ValueError: if ``max_bytes`` is less than 1
149
+ :raises ~anyio.EndOfStream: if this stream has been closed from the other end
150
+ """
151
+
152
+
153
+ class ByteSendStream(AsyncResource, TypedAttributeProvider):
154
+ """An interface for sending bytes to a single peer."""
155
+
156
+ @abstractmethod
157
+ async def send(self, item: bytes) -> None:
158
+ """
159
+ Send the given bytes to the peer.
160
+
161
+ :param item: the bytes to send
162
+ """
163
+
164
+
165
+ class ByteStream(ByteReceiveStream, ByteSendStream):
166
+ """A bidirectional byte stream."""
167
+
168
+ @abstractmethod
169
+ async def send_eof(self) -> None:
170
+ """
171
+ Send an end-of-file indication to the peer.
172
+
173
+ You should not try to send any further data to this stream after calling this
174
+ method. This method is idempotent (does nothing on successive calls).
175
+ """
176
+
177
+
178
+ #: Type alias for all unreliable bytes-oriented receive streams.
179
+ AnyUnreliableByteReceiveStream: TypeAlias = (
180
+ UnreliableObjectReceiveStream[bytes] | ByteReceiveStream
181
+ )
182
+ #: Type alias for all unreliable bytes-oriented send streams.
183
+ AnyUnreliableByteSendStream: TypeAlias = (
184
+ UnreliableObjectSendStream[bytes] | ByteSendStream
185
+ )
186
+ #: Type alias for all unreliable bytes-oriented streams.
187
+ AnyUnreliableByteStream: TypeAlias = UnreliableObjectStream[bytes] | ByteStream
188
+ #: Type alias for all bytes-oriented receive streams.
189
+ AnyByteReceiveStream: TypeAlias = ObjectReceiveStream[bytes] | ByteReceiveStream
190
+ #: Type alias for all bytes-oriented send streams.
191
+ AnyByteSendStream: TypeAlias = ObjectSendStream[bytes] | ByteSendStream
192
+ #: Type alias for all bytes-oriented streams.
193
+ AnyByteStream: TypeAlias = ObjectStream[bytes] | ByteStream
194
+
195
+
196
+ class Listener(AsyncResource, TypedAttributeProvider, Generic[T_co]):
197
+ """An interface for objects that let you accept incoming connections."""
198
+
199
+ @abstractmethod
200
+ async def serve(
201
+ self, handler: Callable[[T_co], Any], task_group: TaskGroup | None = None
202
+ ) -> None:
203
+ """
204
+ Accept incoming connections as they come in and start tasks to handle them.
205
+
206
+ :param handler: a callable that will be used to handle each accepted connection
207
+ :param task_group: the task group that will be used to start tasks for handling
208
+ each accepted connection (if omitted, an ad-hoc task group will be created)
209
+ """
210
+
211
+
212
+ class ObjectStreamConnectable(Generic[T_co], metaclass=ABCMeta):
213
+ @abstractmethod
214
+ async def connect(self) -> ObjectStream[T_co]:
215
+ """
216
+ Connect to the remote endpoint.
217
+
218
+ :return: an object stream connected to the remote end
219
+ :raises ConnectionFailed: if the connection fails
220
+ """
221
+
222
+
223
+ class ByteStreamConnectable(metaclass=ABCMeta):
224
+ @abstractmethod
225
+ async def connect(self) -> ByteStream:
226
+ """
227
+ Connect to the remote endpoint.
228
+
229
+ :return: a bytestream connected to the remote end
230
+ :raises ConnectionFailed: if the connection fails
231
+ """
232
+
233
+
234
+ #: Type alias for all connectables returning bytestreams or bytes-oriented object streams
235
+ AnyByteStreamConnectable: TypeAlias = (
236
+ ObjectStreamConnectable[bytes] | ByteStreamConnectable
237
+ )
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_subprocesses.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from abc import abstractmethod
4
+ from signal import Signals
5
+ from typing import TYPE_CHECKING
6
+
7
+ from ._resources import AsyncResource
8
+
9
+ if TYPE_CHECKING:
10
+ from ._streams import ByteReceiveStream, ByteSendStream
11
+
12
+
13
+ class Process(AsyncResource):
14
+ """An asynchronous version of :class:`subprocess.Popen`."""
15
+
16
+ @abstractmethod
17
+ async def wait(self) -> int:
18
+ """
19
+ Wait until the process exits.
20
+
21
+ :return: the exit code of the process
22
+ """
23
+
24
+ @abstractmethod
25
+ def terminate(self) -> None:
26
+ """
27
+ Terminates the process, gracefully if possible.
28
+
29
+ On Windows, this calls ``TerminateProcess()``.
30
+ On POSIX systems, this sends ``SIGTERM`` to the process.
31
+
32
+ .. seealso:: :meth:`subprocess.Popen.terminate`
33
+ """
34
+
35
+ @abstractmethod
36
+ def kill(self) -> None:
37
+ """
38
+ Kills the process.
39
+
40
+ On Windows, this calls ``TerminateProcess()``.
41
+ On POSIX systems, this sends ``SIGKILL`` to the process.
42
+
43
+ .. seealso:: :meth:`subprocess.Popen.kill`
44
+ """
45
+
46
+ @abstractmethod
47
+ def send_signal(self, signal: Signals) -> None:
48
+ """
49
+ Send a signal to the subprocess.
50
+
51
+ .. seealso:: :meth:`subprocess.Popen.send_signal`
52
+
53
+ :param signal: the signal number (e.g. :data:`signal.SIGHUP`)
54
+ """
55
+
56
+ @property
57
+ @abstractmethod
58
+ def pid(self) -> int:
59
+ """The process ID of the process."""
60
+
61
+ @property
62
+ @abstractmethod
63
+ def returncode(self) -> int | None:
64
+ """
65
+ The return code of the process. If the process has not yet terminated, this will
66
+ be ``None``.
67
+ """
68
+
69
+ @property
70
+ @abstractmethod
71
+ def stdin(self) -> ByteSendStream | None:
72
+ """The stream for the standard input of the process."""
73
+
74
+ @property
75
+ @abstractmethod
76
+ def stdout(self) -> ByteReceiveStream | None:
77
+ """The stream for the standard output of the process."""
78
+
79
+ @property
80
+ @abstractmethod
81
+ def stderr(self) -> ByteReceiveStream | None:
82
+ """The stream for the standard error output of the process."""
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_tasks.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from abc import ABCMeta, abstractmethod
5
+ from collections.abc import Callable, Coroutine
6
+ from contextvars import Context
7
+ from types import TracebackType
8
+ from typing import TYPE_CHECKING, Any, Literal, Protocol, final, overload
9
+
10
+ if sys.version_info >= (3, 13):
11
+ from typing import TypeVar
12
+ else:
13
+ from typing_extensions import TypeVar
14
+
15
+ if sys.version_info >= (3, 11):
16
+ from typing import TypeVarTuple, Unpack
17
+ else:
18
+ from typing_extensions import TypeVarTuple, Unpack
19
+
20
+ if TYPE_CHECKING:
21
+ from .._core._tasks import CancelScope, TaskHandle
22
+
23
+ T_co = TypeVar("T_co", covariant=True)
24
+ T_contra = TypeVar("T_contra", contravariant=True, default=None)
25
+ PosArgsT = TypeVarTuple("PosArgsT")
26
+
27
+
28
+ def get_coro_name(coro: Coroutine[Any, Any, object], override: object = None) -> str:
29
+ if override is not None:
30
+ return str(override)
31
+
32
+ try:
33
+ cr_frame = coro.cr_frame # type: ignore[attr-defined]
34
+ module = cr_frame.f_globals["__name__"]
35
+ except (AttributeError, KeyError):
36
+ module = None
37
+
38
+ qualname = getattr(coro, "__qualname__", None)
39
+ return ".".join([x for x in (module, qualname) if x])
40
+
41
+
42
+ def get_callable_name(func: Callable, override: object = None) -> str:
43
+ if override is not None:
44
+ return str(override)
45
+
46
+ module = getattr(func, "__module__", None)
47
+ qualname = getattr(func, "__qualname__", None)
48
+ return ".".join([x for x in (module, qualname) if x])
49
+
50
+
51
+ def call_for_coroutine(
52
+ func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]],
53
+ args: tuple[Unpack[PosArgsT]],
54
+ **kwargs: Any,
55
+ ) -> Coroutine[Any, Any, T_co]:
56
+ """
57
+ Call the given function with the given positional and keyword arguments.
58
+
59
+ :return: the resulting coroutine
60
+ :raises TypeError: if the return value was not a coroutine object
61
+
62
+ """
63
+ coro = func(*args, **kwargs)
64
+ if not isinstance(coro, Coroutine):
65
+ prefix = f"{func.__module__}." if hasattr(func, "__module__") else ""
66
+ raise TypeError(
67
+ f"Expected {prefix}{func.__qualname__}() to return a coroutine, but "
68
+ f"the return value ({coro!r}) is not a coroutine object"
69
+ )
70
+
71
+ return coro
72
+
73
+
74
+ class TaskStatus(Protocol[T_contra]):
75
+ @overload
76
+ def started(self: TaskStatus[None]) -> None: ...
77
+
78
+ @overload
79
+ def started(self, value: T_contra) -> None: ...
80
+
81
+ def started(self, value: T_contra | None = None) -> None:
82
+ """
83
+ Signal that the task has started.
84
+
85
+ :param value: object passed back to the starter of the task
86
+ """
87
+
88
+
89
+ class TaskGroup(metaclass=ABCMeta):
90
+ """
91
+ Groups several asynchronous tasks together.
92
+
93
+ :ivar cancel_scope: the cancel scope inherited by all child tasks
94
+ :vartype cancel_scope: CancelScope
95
+
96
+ .. note:: On asyncio, support for eager task factories is considered to be
97
+ **experimental**. In particular, they don't follow the usual semantics of new
98
+ tasks being scheduled on the next iteration of the event loop, and may thus
99
+ cause unexpected behavior in code that wasn't written with such semantics in
100
+ mind.
101
+ """
102
+
103
+ cancel_scope: CancelScope
104
+
105
+ def cancel(self, reason: str | None = None) -> None:
106
+ """
107
+ Cancel this task group's cancel scope immediately.
108
+
109
+ This is a shortcut for calling ``.cancel_scope.cancel()`` on the task group.
110
+
111
+ :param reason: a message describing the reason for the cancellation
112
+
113
+ .. versionadded:: 4.14.0
114
+
115
+ """
116
+ self.cancel_scope.cancel(reason)
117
+
118
+ @abstractmethod
119
+ def create_task(
120
+ self,
121
+ coro: Coroutine[Any, Any, T_co],
122
+ *,
123
+ name: object = None,
124
+ context: Context | None = None,
125
+ ) -> TaskHandle[T_co]:
126
+ """
127
+ Create a new task from a coroutine object and schedule it to run.
128
+
129
+ :param coro: a coroutine object
130
+ :param name: optional name to give the task
131
+ :param context: optional context to run the task in
132
+ :return: a task handle
133
+
134
+ .. versionadded:: 4.14.0
135
+ """
136
+
137
+ @final
138
+ def start_soon(
139
+ self,
140
+ func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]],
141
+ *args: Unpack[PosArgsT],
142
+ name: object = None,
143
+ ) -> TaskHandle[T_co]:
144
+ """
145
+ Start a new task in this task group.
146
+
147
+ :param func: a coroutine function
148
+ :param args: positional arguments to call the function with
149
+ :param name: name of the task, for the purposes of introspection and debugging
150
+ :return: a task handle
151
+
152
+ .. versionadded:: 3.0
153
+ .. versionchanged:: 4.14.0
154
+ This method now returns a task handle.
155
+
156
+ """
157
+ final_name = get_callable_name(func, name)
158
+ return self.create_task(call_for_coroutine(func, args), name=final_name)
159
+
160
+ @overload
161
+ async def start(
162
+ self,
163
+ func: Callable[..., Coroutine[Any, Any, T_co]],
164
+ *args: object,
165
+ name: object = None,
166
+ return_handle: Literal[False] = ...,
167
+ ) -> Any: ...
168
+
169
+ @overload
170
+ async def start(
171
+ self,
172
+ func: Callable[..., Coroutine[Any, Any, T_co]],
173
+ *args: object,
174
+ name: object = None,
175
+ return_handle: Literal[True],
176
+ ) -> TaskHandle[T_co, Any]: ...
177
+
178
+ @abstractmethod
179
+ async def start(
180
+ self,
181
+ func: Callable[..., Coroutine[Any, Any, T_co]],
182
+ *args: object,
183
+ name: object = None,
184
+ return_handle: Literal[False, True] = False,
185
+ ) -> Any:
186
+ """
187
+ Start a new task and wait until it signals for readiness.
188
+
189
+ The target callable must accept a keyword argument ``task_status`` (of type
190
+ :class:`TaskStatus`). Awaiting on this method will return whatever was passed to
191
+ ``task_status.started()`` (``None`` by default).
192
+
193
+ .. note:: The :class:`TaskStatus` class is generic, and the type argument should
194
+ indicate the type of the value that will be passed to
195
+ ``task_status.started()``.
196
+
197
+ :param func: a coroutine function that accepts the ``task_status`` keyword
198
+ argument
199
+ :param args: positional arguments to call the function with
200
+ :param name: an optional name for the task, for introspection and debugging
201
+ :param return_handle: if ``True``, return a :class:`TaskHandle` which also
202
+ contains the start value in ``start_value``
203
+ :return: the value passed to ``task_status.started()``
204
+ :raises RuntimeError: if the task finishes without calling
205
+ ``task_status.started()``
206
+
207
+ .. seealso:: :ref:`start_initialize`
208
+
209
+ .. versionadded:: 3.0
210
+ """
211
+
212
+ @abstractmethod
213
+ async def __aenter__(self) -> TaskGroup:
214
+ """Enter the task group context and allow starting new tasks."""
215
+
216
+ @abstractmethod
217
+ async def __aexit__(
218
+ self,
219
+ exc_type: type[BaseException] | None,
220
+ exc_val: BaseException | None,
221
+ exc_tb: TracebackType | None,
222
+ ) -> bool:
223
+ """Exit the task group context waiting for all tasks to finish."""
.venvs/kimodo/lib/python3.10/site-packages/anyio/abc/_testing.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ import types
5
+ from abc import ABCMeta, abstractmethod
6
+ from collections.abc import AsyncGenerator, Callable, Coroutine, Iterable
7
+ from typing import Any, TypeVar
8
+
9
+ if sys.version_info >= (3, 11):
10
+ from typing import Self
11
+ else:
12
+ from typing_extensions import Self
13
+
14
+ _T = TypeVar("_T")
15
+
16
+
17
+ class TestRunner(metaclass=ABCMeta):
18
+ """
19
+ Encapsulates a running event loop. Every call made through this object will use the
20
+ same event loop.
21
+ """
22
+
23
+ def __enter__(self) -> Self:
24
+ return self
25
+
26
+ @abstractmethod
27
+ def __exit__(
28
+ self,
29
+ exc_type: type[BaseException] | None,
30
+ exc_val: BaseException | None,
31
+ exc_tb: types.TracebackType | None,
32
+ ) -> bool | None: ...
33
+
34
+ @abstractmethod
35
+ def run_asyncgen_fixture(
36
+ self,
37
+ fixture_func: Callable[..., AsyncGenerator[_T, Any]],
38
+ kwargs: dict[str, Any],
39
+ ) -> Iterable[_T]:
40
+ """
41
+ Run an async generator fixture.
42
+
43
+ :param fixture_func: the fixture function
44
+ :param kwargs: keyword arguments to call the fixture function with
45
+ :return: an iterator yielding the value yielded from the async generator
46
+ """
47
+
48
+ @abstractmethod
49
+ def run_fixture(
50
+ self,
51
+ fixture_func: Callable[..., Coroutine[Any, Any, _T]],
52
+ kwargs: dict[str, Any],
53
+ ) -> _T:
54
+ """
55
+ Run an async fixture.
56
+
57
+ :param fixture_func: the fixture function
58
+ :param kwargs: keyword arguments to call the fixture function with
59
+ :return: the return value of the fixture function
60
+ """
61
+
62
+ @abstractmethod
63
+ def run_test(
64
+ self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any]
65
+ ) -> None:
66
+ """
67
+ Run an async test function.
68
+
69
+ :param test_func: the test function
70
+ :param kwargs: keyword arguments to call the test function with
71
+ """
72
+
73
+ @abstractmethod
74
+ def is_running(self) -> bool:
75
+ """
76
+ Check if the test runner is running.
77
+
78
+ :return: ``True`` if the coroutine is currently being run, ``False`` otherwise.
79
+ """
.venvs/kimodo/lib/python3.10/site-packages/anyio/from_thread.py ADDED
@@ -0,0 +1,588 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ __all__ = (
4
+ "BlockingPortal",
5
+ "BlockingPortalProvider",
6
+ "check_cancelled",
7
+ "run",
8
+ "run_sync",
9
+ "start_blocking_portal",
10
+ )
11
+
12
+ import sys
13
+ from collections.abc import Awaitable, Callable, Coroutine, Generator
14
+ from concurrent.futures import Future
15
+ from contextlib import (
16
+ AbstractAsyncContextManager,
17
+ AbstractContextManager,
18
+ contextmanager,
19
+ )
20
+ from contextvars import Context
21
+ from dataclasses import dataclass, field
22
+ from functools import partial
23
+ from inspect import isawaitable
24
+ from threading import Lock, Thread, current_thread, get_ident
25
+ from types import TracebackType
26
+ from typing import (
27
+ Any,
28
+ Generic,
29
+ TypeVar,
30
+ cast,
31
+ overload,
32
+ )
33
+
34
+ from ._core._eventloop import (
35
+ get_cancelled_exc_class,
36
+ threadlocals,
37
+ )
38
+ from ._core._eventloop import run as run_eventloop
39
+ from ._core._exceptions import NoEventLoopError
40
+ from ._core._synchronization import Event
41
+ from ._core._tasks import CancelScope, create_task_group
42
+ from .abc._tasks import TaskStatus
43
+ from .lowlevel import EventLoopToken, current_token
44
+
45
+ if sys.version_info >= (3, 11):
46
+ from typing import Self, TypeVarTuple, Unpack
47
+ else:
48
+ from typing_extensions import Self, TypeVarTuple, Unpack
49
+
50
+ T_Retval = TypeVar("T_Retval")
51
+ T_co = TypeVar("T_co", covariant=True)
52
+ PosArgsT = TypeVarTuple("PosArgsT")
53
+
54
+
55
+ def _token_or_error(token: EventLoopToken | None) -> EventLoopToken:
56
+ if token is not None:
57
+ return token
58
+
59
+ try:
60
+ return threadlocals.current_token
61
+ except AttributeError:
62
+ raise NoEventLoopError(
63
+ "Not running inside an AnyIO worker thread, and no event loop token was "
64
+ "provided"
65
+ ) from None
66
+
67
+
68
+ def run(
69
+ func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]],
70
+ *args: Unpack[PosArgsT],
71
+ token: EventLoopToken | None = None,
72
+ ) -> T_co:
73
+ """
74
+ Call a coroutine function from a worker thread.
75
+
76
+ :param func: a coroutine function
77
+ :param args: positional arguments for the callable
78
+ :param token: an event loop token to use to get back to the event loop thread
79
+ (required if calling this function from outside an AnyIO worker thread)
80
+ :return: the return value of the coroutine function
81
+ :raises MissingTokenError: if no token was provided and called from outside an
82
+ AnyIO worker thread
83
+ :raises RunFinishedError: if the event loop tied to ``token`` is no longer running
84
+
85
+ .. versionchanged:: 4.11.0
86
+ Added the ``token`` parameter.
87
+
88
+ """
89
+ explicit_token = token is not None
90
+ token = _token_or_error(token)
91
+ return token.backend_class.run_async_from_thread(
92
+ func, args, token=token.native_token if explicit_token else None
93
+ )
94
+
95
+
96
+ def run_sync(
97
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
98
+ *args: Unpack[PosArgsT],
99
+ token: EventLoopToken | None = None,
100
+ ) -> T_Retval:
101
+ """
102
+ Call a function in the event loop thread from a worker thread.
103
+
104
+ :param func: a callable
105
+ :param args: positional arguments for the callable
106
+ :param token: an event loop token to use to get back to the event loop thread
107
+ (required if calling this function from outside an AnyIO worker thread)
108
+ :return: the return value of the callable
109
+ :raises MissingTokenError: if no token was provided and called from outside an
110
+ AnyIO worker thread
111
+ :raises RunFinishedError: if the event loop tied to ``token`` is no longer running
112
+
113
+ .. versionchanged:: 4.11.0
114
+ Added the ``token`` parameter.
115
+
116
+ """
117
+ explicit_token = token is not None
118
+ token = _token_or_error(token)
119
+ return token.backend_class.run_sync_from_thread(
120
+ func, args, token=token.native_token if explicit_token else None
121
+ )
122
+
123
+
124
+ class _BlockingAsyncContextManager(AbstractContextManager, Generic[T_co]):
125
+ _enter_future: Future[T_co]
126
+ _exit_future: Future[bool | None]
127
+ _exit_event: Event
128
+ _exit_exc_info: tuple[
129
+ type[BaseException] | None, BaseException | None, TracebackType | None
130
+ ] = (None, None, None)
131
+
132
+ def __init__(
133
+ self, async_cm: AbstractAsyncContextManager[T_co], portal: BlockingPortal
134
+ ):
135
+ self._async_cm = async_cm
136
+ self._portal = portal
137
+
138
+ async def run_async_cm(self) -> bool | None:
139
+ try:
140
+ self._exit_event = Event()
141
+ value = await self._async_cm.__aenter__()
142
+ except BaseException as exc:
143
+ self._enter_future.set_exception(exc)
144
+ raise
145
+ else:
146
+ self._enter_future.set_result(value)
147
+
148
+ try:
149
+ # Wait for the sync context manager to exit.
150
+ # This next statement can raise `get_cancelled_exc_class()` if
151
+ # something went wrong in a task group in this async context
152
+ # manager.
153
+ await self._exit_event.wait()
154
+ finally:
155
+ # In case of cancellation, it could be that we end up here before
156
+ # `_BlockingAsyncContextManager.__exit__` is called, and an
157
+ # `_exit_exc_info` has been set.
158
+ result = await self._async_cm.__aexit__(*self._exit_exc_info)
159
+
160
+ return result
161
+
162
+ def __enter__(self) -> T_co:
163
+ self._enter_future = Future()
164
+ self._exit_future = self._portal.start_task_soon(self.run_async_cm)
165
+ return self._enter_future.result()
166
+
167
+ def __exit__(
168
+ self,
169
+ exc_type: type[BaseException] | None,
170
+ exc_value: BaseException | None,
171
+ traceback: TracebackType | None,
172
+ /,
173
+ ) -> bool | None:
174
+ self._exit_exc_info = exc_type, exc_value, traceback
175
+ self._portal.call(self._exit_event.set)
176
+ return self._exit_future.result()
177
+
178
+
179
+ class _BlockingPortalTaskStatus(TaskStatus):
180
+ def __init__(self, future: Future):
181
+ self._future = future
182
+
183
+ def started(self, value: object = None) -> None:
184
+ self._future.set_result(value)
185
+
186
+
187
+ class BlockingPortal:
188
+ """
189
+ An object that lets external threads run code in an asynchronous event loop.
190
+
191
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
192
+ current thread
193
+ """
194
+
195
+ def __init__(self) -> None:
196
+ self._token = current_token()
197
+ self._event_loop_thread_id: int | None = get_ident()
198
+ self._stop_event = Event()
199
+ self._task_group = create_task_group()
200
+
201
+ async def __aenter__(self) -> Self:
202
+ await self._task_group.__aenter__()
203
+ return self
204
+
205
+ async def __aexit__(
206
+ self,
207
+ exc_type: type[BaseException] | None,
208
+ exc_val: BaseException | None,
209
+ exc_tb: TracebackType | None,
210
+ ) -> bool:
211
+ await self.stop()
212
+ return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
213
+
214
+ def _check_running(self) -> None:
215
+ if self._event_loop_thread_id is None:
216
+ raise RuntimeError("This portal is not running")
217
+ if self._event_loop_thread_id == get_ident():
218
+ raise RuntimeError(
219
+ "This method cannot be called from the event loop thread"
220
+ )
221
+
222
+ async def sleep_until_stopped(self) -> None:
223
+ """Sleep until :meth:`stop` is called."""
224
+ await self._stop_event.wait()
225
+
226
+ async def stop(self, cancel_remaining: bool = False) -> None:
227
+ """
228
+ Signal the portal to shut down.
229
+
230
+ This marks the portal as no longer accepting new calls and exits from
231
+ :meth:`sleep_until_stopped`.
232
+
233
+ :param cancel_remaining: ``True`` to cancel all the remaining tasks, ``False``
234
+ to let them finish before returning
235
+
236
+ """
237
+ self._event_loop_thread_id = None
238
+ self._stop_event.set()
239
+ if cancel_remaining:
240
+ self._task_group.cancel_scope.cancel("the blocking portal is shutting down")
241
+
242
+ async def _call_func(
243
+ self,
244
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
245
+ args: tuple[Unpack[PosArgsT]],
246
+ kwargs: dict[str, Any],
247
+ future: Future[T_Retval],
248
+ ) -> None:
249
+ event_loop_thread_id = self._event_loop_thread_id
250
+
251
+ def callback(f: Future[T_Retval]) -> None:
252
+ if f.cancelled():
253
+ if event_loop_thread_id == get_ident():
254
+ scope.cancel("the future was cancelled")
255
+ elif event_loop_thread_id is not None:
256
+ run_sync(
257
+ scope.cancel, "the future was cancelled", token=self._token
258
+ )
259
+
260
+ try:
261
+ retval_or_awaitable = func(*args, **kwargs)
262
+ if isawaitable(retval_or_awaitable):
263
+ with CancelScope() as scope:
264
+ future.add_done_callback(callback)
265
+ retval = await retval_or_awaitable
266
+ else:
267
+ retval = retval_or_awaitable
268
+ except get_cancelled_exc_class():
269
+ future.cancel()
270
+ future.set_running_or_notify_cancel()
271
+ except BaseException as exc:
272
+ if not future.cancelled():
273
+ future.set_exception(exc)
274
+
275
+ # Let base exceptions fall through
276
+ if not isinstance(exc, Exception):
277
+ raise
278
+ else:
279
+ if not future.cancelled():
280
+ future.set_result(retval)
281
+ finally:
282
+ scope = None # type: ignore[assignment]
283
+
284
+ def _spawn_task_from_thread(
285
+ self,
286
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
287
+ args: tuple[Unpack[PosArgsT]],
288
+ kwargs: dict[str, Any],
289
+ name: object,
290
+ future: Future[T_Retval],
291
+ ) -> None:
292
+ """
293
+ Spawn a new task using the given callable.
294
+
295
+ :param func: a callable
296
+ :param args: positional arguments to be passed to the callable
297
+ :param kwargs: keyword arguments to be passed to the callable
298
+ :param name: name of the task (will be coerced to a string if not ``None``)
299
+ :param future: a future that will resolve to the return value of the callable,
300
+ or the exception raised during its execution
301
+
302
+ """
303
+ run_sync(
304
+ partial(self._task_group.start_soon, name=name),
305
+ self._call_func,
306
+ func,
307
+ args,
308
+ kwargs,
309
+ future,
310
+ token=self._token,
311
+ )
312
+
313
+ @overload
314
+ def call(
315
+ self,
316
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
317
+ *args: Unpack[PosArgsT],
318
+ ) -> T_Retval: ...
319
+
320
+ @overload
321
+ def call(
322
+ self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT]
323
+ ) -> T_Retval: ...
324
+
325
+ def call(
326
+ self,
327
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
328
+ *args: Unpack[PosArgsT],
329
+ ) -> T_Retval:
330
+ """
331
+ Call the given function in the event loop thread.
332
+
333
+ If the callable returns a coroutine object, it is awaited on.
334
+
335
+ :param func: any callable
336
+ :raises RuntimeError: if the portal is not running or if this method is called
337
+ from within the event loop thread
338
+
339
+ """
340
+ return cast(T_Retval, self.start_task_soon(func, *args).result())
341
+
342
+ @overload
343
+ def start_task_soon(
344
+ self,
345
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
346
+ *args: Unpack[PosArgsT],
347
+ name: object = None,
348
+ ) -> Future[T_Retval]: ...
349
+
350
+ @overload
351
+ def start_task_soon(
352
+ self,
353
+ func: Callable[[Unpack[PosArgsT]], T_Retval],
354
+ *args: Unpack[PosArgsT],
355
+ name: object = None,
356
+ ) -> Future[T_Retval]: ...
357
+
358
+ def start_task_soon(
359
+ self,
360
+ func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval],
361
+ *args: Unpack[PosArgsT],
362
+ name: object = None,
363
+ ) -> Future[T_Retval]:
364
+ """
365
+ Start a task in the portal's task group.
366
+
367
+ The task will be run inside a cancel scope which can be cancelled by cancelling
368
+ the returned future.
369
+
370
+ :param func: the target function
371
+ :param args: positional arguments passed to ``func``
372
+ :param name: name of the task (will be coerced to a string if not ``None``)
373
+ :return: a future that resolves with the return value of the callable if the
374
+ task completes successfully, or with the exception raised in the task
375
+ :raises RuntimeError: if the portal is not running or if this method is called
376
+ from within the event loop thread
377
+ :rtype: concurrent.futures.Future[T_Retval]
378
+
379
+ .. versionadded:: 3.0
380
+
381
+ """
382
+ self._check_running()
383
+ f: Future[T_Retval] = Future()
384
+ self._spawn_task_from_thread(func, args, {}, name, f)
385
+ return f
386
+
387
+ def start_task(
388
+ self,
389
+ func: Callable[..., Awaitable[T_Retval]],
390
+ *args: object,
391
+ name: object = None,
392
+ ) -> tuple[Future[T_Retval], Any]:
393
+ """
394
+ Start a task in the portal's task group and wait until it signals for readiness.
395
+
396
+ This method works the same way as :meth:`.abc.TaskGroup.start`.
397
+
398
+ :param func: the target function
399
+ :param args: positional arguments passed to ``func``
400
+ :param name: name of the task (will be coerced to a string if not ``None``)
401
+ :return: a tuple of (future, task_status_value) where the ``task_status_value``
402
+ is the value passed to ``task_status.started()`` from within the target
403
+ function
404
+ :rtype: tuple[concurrent.futures.Future[T_Retval], Any]
405
+
406
+ .. versionadded:: 3.0
407
+
408
+ """
409
+
410
+ def task_done(future: Future[T_Retval]) -> None:
411
+ if not task_status_future.done():
412
+ if future.cancelled():
413
+ task_status_future.cancel()
414
+ elif future.exception():
415
+ task_status_future.set_exception(future.exception())
416
+ else:
417
+ exc = RuntimeError(
418
+ "Task exited without calling task_status.started()"
419
+ )
420
+ task_status_future.set_exception(exc)
421
+
422
+ self._check_running()
423
+ task_status_future: Future = Future()
424
+ task_status = _BlockingPortalTaskStatus(task_status_future)
425
+ f: Future = Future()
426
+ f.add_done_callback(task_done)
427
+ self._spawn_task_from_thread(func, args, {"task_status": task_status}, name, f)
428
+ return f, task_status_future.result()
429
+
430
+ def wrap_async_context_manager(
431
+ self, cm: AbstractAsyncContextManager[T_co]
432
+ ) -> AbstractContextManager[T_co]:
433
+ """
434
+ Wrap an async context manager as a synchronous context manager via this portal.
435
+
436
+ Spawns a task that will call both ``__aenter__()`` and ``__aexit__()``, stopping
437
+ in the middle until the synchronous context manager exits.
438
+
439
+ :param cm: an asynchronous context manager
440
+ :return: a synchronous context manager
441
+
442
+ .. versionadded:: 2.1
443
+
444
+ """
445
+ return _BlockingAsyncContextManager(cm, self)
446
+
447
+
448
+ @dataclass
449
+ class BlockingPortalProvider:
450
+ """
451
+ A manager for a blocking portal. Used as a context manager. The first thread to
452
+ enter this context manager causes a blocking portal to be started with the specific
453
+ parameters, and the last thread to exit causes the portal to be shut down. Thus,
454
+ there will be exactly one blocking portal running in this context as long as at
455
+ least one thread has entered this context manager.
456
+
457
+ The parameters are the same as for :func:`~anyio.run`.
458
+
459
+ :param backend: name of the backend
460
+ :param backend_options: backend options
461
+
462
+ .. versionadded:: 4.4
463
+ """
464
+
465
+ backend: str = "asyncio"
466
+ backend_options: dict[str, Any] | None = None
467
+ _lock: Lock = field(init=False, default_factory=Lock)
468
+ _leases: int = field(init=False, default=0)
469
+ _portal: BlockingPortal = field(init=False)
470
+ _portal_cm: AbstractContextManager[BlockingPortal] | None = field(
471
+ init=False, default=None
472
+ )
473
+
474
+ def __enter__(self) -> BlockingPortal:
475
+ with self._lock:
476
+ if self._portal_cm is None:
477
+ self._portal_cm = start_blocking_portal(
478
+ self.backend, self.backend_options
479
+ )
480
+ self._portal = self._portal_cm.__enter__()
481
+
482
+ self._leases += 1
483
+ return self._portal
484
+
485
+ def __exit__(
486
+ self,
487
+ exc_type: type[BaseException] | None,
488
+ exc_val: BaseException | None,
489
+ exc_tb: TracebackType | None,
490
+ ) -> None:
491
+ portal_cm: AbstractContextManager[BlockingPortal] | None = None
492
+ with self._lock:
493
+ assert self._portal_cm
494
+ assert self._leases > 0
495
+ self._leases -= 1
496
+ if not self._leases:
497
+ portal_cm = self._portal_cm
498
+ self._portal_cm = None
499
+ del self._portal
500
+
501
+ if portal_cm:
502
+ portal_cm.__exit__(None, None, None)
503
+
504
+
505
+ @contextmanager
506
+ def start_blocking_portal(
507
+ backend: str = "asyncio",
508
+ backend_options: dict[str, Any] | None = None,
509
+ *,
510
+ name: str | None = None,
511
+ ) -> Generator[BlockingPortal, Any, None]:
512
+ """
513
+ Start a new event loop in a new thread and run a blocking portal in its main task.
514
+
515
+ The parameters are the same as for :func:`~anyio.run`.
516
+
517
+ :param backend: name of the backend
518
+ :param backend_options: backend options
519
+ :param name: name of the thread
520
+ :return: a context manager that yields a blocking portal
521
+
522
+ .. versionchanged:: 3.0
523
+ Usage as a context manager is now required.
524
+
525
+ """
526
+
527
+ async def run_portal() -> None:
528
+ async with BlockingPortal() as portal_:
529
+ if name is None:
530
+ current_thread().name = f"{backend}-portal-{id(portal_):x}"
531
+
532
+ future.set_result(portal_)
533
+ await portal_.sleep_until_stopped()
534
+
535
+ def run_blocking_portal() -> None:
536
+ if future.set_running_or_notify_cancel():
537
+ try:
538
+ run_eventloop(
539
+ run_portal, backend=backend, backend_options=backend_options
540
+ )
541
+ except BaseException as exc:
542
+ if not future.done():
543
+ future.set_exception(exc)
544
+
545
+ future: Future[BlockingPortal] = Future()
546
+ kwargs: dict[str, Any] = {}
547
+ if sys.version_info >= (3, 14):
548
+ kwargs["context"] = Context()
549
+
550
+ thread = Thread(target=run_blocking_portal, daemon=True, name=name, **kwargs)
551
+ thread.start()
552
+ try:
553
+ cancel_remaining_tasks = False
554
+ portal = future.result()
555
+ try:
556
+ yield portal
557
+ except BaseException:
558
+ cancel_remaining_tasks = True
559
+ raise
560
+ finally:
561
+ try:
562
+ portal.call(portal.stop, cancel_remaining_tasks)
563
+ except RuntimeError:
564
+ pass
565
+ finally:
566
+ thread.join()
567
+
568
+
569
+ def check_cancelled() -> None:
570
+ """
571
+ Check if the cancel scope of the host task's running the current worker thread has
572
+ been cancelled.
573
+
574
+ If the host task's current cancel scope has indeed been cancelled, the
575
+ backend-specific cancellation exception will be raised.
576
+
577
+ :raises RuntimeError: if the current thread was not spawned by
578
+ :func:`.to_thread.run_sync`
579
+
580
+ """
581
+ try:
582
+ token: EventLoopToken = threadlocals.current_token
583
+ except AttributeError:
584
+ raise NoEventLoopError(
585
+ "This function can only be called inside an AnyIO worker thread"
586
+ ) from None
587
+
588
+ token.backend_class.check_cancelled()
.venvs/kimodo/lib/python3.10/site-packages/anyio/functools.py ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ __all__ = (
4
+ "AsyncCacheInfo",
5
+ "AsyncCacheParameters",
6
+ "AsyncLRUCacheWrapper",
7
+ "cache",
8
+ "lru_cache",
9
+ "reduce",
10
+ )
11
+
12
+ import functools
13
+ from collections import OrderedDict
14
+ from collections.abc import (
15
+ AsyncIterable,
16
+ Awaitable,
17
+ Callable,
18
+ Coroutine,
19
+ Hashable,
20
+ Iterable,
21
+ )
22
+ from functools import update_wrapper
23
+ from inspect import iscoroutinefunction
24
+ from typing import (
25
+ Any,
26
+ Generic,
27
+ NamedTuple,
28
+ ParamSpec,
29
+ TypedDict,
30
+ TypeVar,
31
+ cast,
32
+ final,
33
+ overload,
34
+ )
35
+ from weakref import WeakKeyDictionary
36
+
37
+ from ._core._eventloop import current_time
38
+ from ._core._synchronization import Lock
39
+ from .lowlevel import RunVar, checkpoint
40
+
41
+ T = TypeVar("T")
42
+ S = TypeVar("S")
43
+ P = ParamSpec("P")
44
+ lru_cache_items: RunVar[
45
+ WeakKeyDictionary[
46
+ AsyncLRUCacheWrapper[Any, Any],
47
+ OrderedDict[
48
+ Hashable,
49
+ tuple[_InitialMissingType, Lock, float | None]
50
+ | tuple[Any, None, float | None],
51
+ ],
52
+ ]
53
+ ] = RunVar("lru_cache_items")
54
+
55
+
56
+ class _InitialMissingType:
57
+ pass
58
+
59
+
60
+ initial_missing: _InitialMissingType = _InitialMissingType()
61
+
62
+
63
+ class AsyncCacheInfo(NamedTuple):
64
+ hits: int
65
+ misses: int
66
+ maxsize: int | None
67
+ currsize: int
68
+ ttl: int | None
69
+
70
+
71
+ class AsyncCacheParameters(TypedDict):
72
+ maxsize: int | None
73
+ typed: bool
74
+ always_checkpoint: bool
75
+ ttl: int | None
76
+
77
+
78
+ class _LRUMethodWrapper(Generic[T]):
79
+ def __init__(self, wrapper: AsyncLRUCacheWrapper[..., T], instance: object):
80
+ self.__wrapper = wrapper
81
+ self.__instance = instance
82
+
83
+ def cache_info(self) -> AsyncCacheInfo:
84
+ return self.__wrapper.cache_info()
85
+
86
+ def cache_parameters(self) -> AsyncCacheParameters:
87
+ return self.__wrapper.cache_parameters()
88
+
89
+ def cache_clear(self) -> None:
90
+ self.__wrapper.cache_clear()
91
+
92
+ async def __call__(self, *args: Any, **kwargs: Any) -> T:
93
+ if self.__instance is None:
94
+ return await self.__wrapper(*args, **kwargs)
95
+
96
+ return await self.__wrapper(self.__instance, *args, **kwargs)
97
+
98
+
99
+ @final
100
+ class AsyncLRUCacheWrapper(Generic[P, T]):
101
+ def __init__(
102
+ self,
103
+ func: Callable[P, Awaitable[T]],
104
+ maxsize: int | None,
105
+ typed: bool,
106
+ always_checkpoint: bool,
107
+ ttl: int | None,
108
+ ):
109
+ self.__wrapped__ = func
110
+ self._hits: int = 0
111
+ self._misses: int = 0
112
+ self._maxsize = max(maxsize, 0) if maxsize is not None else None
113
+ self._currsize: int = 0
114
+ self._typed = typed
115
+ self._always_checkpoint = always_checkpoint
116
+ self._ttl = ttl
117
+ update_wrapper(self, func)
118
+
119
+ def cache_info(self) -> AsyncCacheInfo:
120
+ return AsyncCacheInfo(
121
+ self._hits, self._misses, self._maxsize, self._currsize, self._ttl
122
+ )
123
+
124
+ def cache_parameters(self) -> AsyncCacheParameters:
125
+ return {
126
+ "maxsize": self._maxsize,
127
+ "typed": self._typed,
128
+ "always_checkpoint": self._always_checkpoint,
129
+ "ttl": self._ttl,
130
+ }
131
+
132
+ def cache_clear(self) -> None:
133
+ if cache := lru_cache_items.get(None):
134
+ cache.pop(self, None)
135
+ self._hits = self._misses = self._currsize = 0
136
+
137
+ async def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T:
138
+ # Easy case first: if maxsize == 0, no caching is done
139
+ if self._maxsize == 0:
140
+ value = await self.__wrapped__(*args, **kwargs)
141
+ self._misses += 1
142
+ return value
143
+
144
+ # The key is constructed as a flat tuple to avoid memory overhead
145
+ key: tuple[Any, ...] = args
146
+ if kwargs:
147
+ # initial_missing is used as a separator
148
+ key += (initial_missing,) + sum(kwargs.items(), ())
149
+
150
+ if self._typed:
151
+ key += tuple(type(arg) for arg in args)
152
+ if kwargs:
153
+ key += (initial_missing,) + tuple(type(val) for val in kwargs.values())
154
+
155
+ try:
156
+ cache = lru_cache_items.get()
157
+ except LookupError:
158
+ cache = WeakKeyDictionary()
159
+ lru_cache_items.set(cache)
160
+
161
+ try:
162
+ cache_entry = cache[self]
163
+ except KeyError:
164
+ cache_entry = cache[self] = OrderedDict()
165
+
166
+ cached_value: T | _InitialMissingType
167
+ try:
168
+ cached_value, lock, expires_at = cache_entry[key]
169
+ except KeyError:
170
+ # We're the first task to call this function
171
+ cached_value, lock, expires_at = (
172
+ initial_missing,
173
+ Lock(fast_acquire=not self._always_checkpoint),
174
+ None,
175
+ )
176
+ cache_entry[key] = cached_value, lock, expires_at
177
+
178
+ if lock is None:
179
+ if expires_at is not None and current_time() >= expires_at:
180
+ self._currsize -= 1
181
+ cached_value, lock, expires_at = (
182
+ initial_missing,
183
+ Lock(fast_acquire=not self._always_checkpoint),
184
+ None,
185
+ )
186
+ cache_entry[key] = cached_value, lock, expires_at
187
+ else:
188
+ # The value was already cached
189
+ self._hits += 1
190
+ cache_entry.move_to_end(key)
191
+ if self._always_checkpoint:
192
+ await checkpoint()
193
+
194
+ return cast(T, cached_value)
195
+
196
+ async with lock:
197
+ # Check if another task filled the cache while we acquired the lock
198
+ if (cached_value := cache_entry[key][0]) is initial_missing:
199
+ self._misses += 1
200
+ if self._maxsize is not None and self._currsize >= self._maxsize:
201
+ cache_entry.popitem(last=False)
202
+ else:
203
+ self._currsize += 1
204
+
205
+ value = await self.__wrapped__(*args, **kwargs)
206
+ expires_at = (
207
+ current_time() + self._ttl if self._ttl is not None else None
208
+ )
209
+ cache_entry[key] = value, None, expires_at
210
+ else:
211
+ # Another task filled the cache while we were waiting for the lock
212
+ self._hits += 1
213
+ cache_entry.move_to_end(key)
214
+ value = cast(T, cached_value)
215
+
216
+ return value
217
+
218
+ def __get__(
219
+ self, instance: object, owner: type | None = None
220
+ ) -> _LRUMethodWrapper[T]:
221
+ wrapper = _LRUMethodWrapper(self, instance)
222
+ update_wrapper(wrapper, self.__wrapped__)
223
+ return wrapper
224
+
225
+
226
+ class _LRUCacheWrapper:
227
+ def __init__(
228
+ self, maxsize: int | None, typed: bool, always_checkpoint: bool, ttl: int | None
229
+ ):
230
+ self._maxsize = maxsize
231
+ self._typed = typed
232
+ self._always_checkpoint = always_checkpoint
233
+ self._ttl = ttl
234
+
235
+ @overload
236
+ def __call__( # type: ignore[overload-overlap]
237
+ self, func: Callable[P, Coroutine[Any, Any, T]], /
238
+ ) -> AsyncLRUCacheWrapper[P, T]: ...
239
+
240
+ @overload
241
+ def __call__(
242
+ self, func: Callable[..., T], /
243
+ ) -> functools._lru_cache_wrapper[T]: ...
244
+
245
+ def __call__(
246
+ self, f: Callable[P, Coroutine[Any, Any, T]] | Callable[..., T], /
247
+ ) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]:
248
+ if iscoroutinefunction(f):
249
+ return AsyncLRUCacheWrapper(
250
+ f, self._maxsize, self._typed, self._always_checkpoint, self._ttl
251
+ )
252
+
253
+ return functools.lru_cache(maxsize=self._maxsize, typed=self._typed)(f) # type: ignore[arg-type]
254
+
255
+
256
+ @overload
257
+ def cache( # type: ignore[overload-overlap]
258
+ func: Callable[P, Coroutine[Any, Any, T]], /
259
+ ) -> AsyncLRUCacheWrapper[P, T]: ...
260
+
261
+
262
+ @overload
263
+ def cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ...
264
+
265
+
266
+ def cache(func: Callable[..., Any] | Callable[P, Coroutine[Any, Any, Any]], /) -> Any:
267
+ """
268
+ A convenient shortcut for :func:`lru_cache` with ``maxsize=None``.
269
+
270
+ This is the asynchronous equivalent to :func:`functools.cache`.
271
+
272
+ """
273
+ return lru_cache(maxsize=None)(func)
274
+
275
+
276
+ @overload
277
+ def lru_cache(
278
+ *,
279
+ maxsize: int | None = ...,
280
+ typed: bool = ...,
281
+ always_checkpoint: bool = ...,
282
+ ttl: int | None = ...,
283
+ ) -> _LRUCacheWrapper: ...
284
+
285
+
286
+ @overload
287
+ def lru_cache( # type: ignore[overload-overlap]
288
+ func: Callable[P, Coroutine[Any, Any, T]], /
289
+ ) -> AsyncLRUCacheWrapper[P, T]: ...
290
+
291
+
292
+ @overload
293
+ def lru_cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ...
294
+
295
+
296
+ def lru_cache(
297
+ func: Callable[..., Coroutine[Any, Any, Any]] | Callable[..., Any] | None = None,
298
+ /,
299
+ *,
300
+ maxsize: int | None = 128,
301
+ typed: bool = False,
302
+ always_checkpoint: bool = False,
303
+ ttl: int | None = None,
304
+ ) -> Any:
305
+ """
306
+ An asynchronous version of :func:`functools.lru_cache`.
307
+
308
+ If a synchronous function is passed, the standard library
309
+ :func:`functools.lru_cache` is applied instead.
310
+
311
+ :param always_checkpoint: if ``True``, every call to the cached function will be
312
+ guaranteed to yield control to the event loop at least once
313
+ :param ttl: time in seconds after which to invalidate cache entries
314
+
315
+ .. note:: Caches and locks are managed on a per-event loop basis.
316
+
317
+ """
318
+ if func is None:
319
+ return _LRUCacheWrapper(maxsize, typed, always_checkpoint, ttl)
320
+
321
+ if not callable(func):
322
+ raise TypeError("the first argument must be callable")
323
+
324
+ return _LRUCacheWrapper(maxsize, typed, always_checkpoint, ttl)(func)
325
+
326
+
327
+ @overload
328
+ async def reduce(
329
+ function: Callable[[T, S], Awaitable[T]],
330
+ iterable: Iterable[S] | AsyncIterable[S],
331
+ /,
332
+ initial: T,
333
+ ) -> T: ...
334
+
335
+
336
+ @overload
337
+ async def reduce(
338
+ function: Callable[[T, T], Awaitable[T]],
339
+ iterable: Iterable[T] | AsyncIterable[T],
340
+ /,
341
+ ) -> T: ...
342
+
343
+
344
+ async def reduce( # type: ignore[misc]
345
+ function: Callable[[T, T], Awaitable[T]] | Callable[[T, S], Awaitable[T]],
346
+ iterable: Iterable[T] | Iterable[S] | AsyncIterable[T] | AsyncIterable[S],
347
+ /,
348
+ initial: T | _InitialMissingType = initial_missing,
349
+ ) -> T:
350
+ """
351
+ Asynchronous version of :func:`functools.reduce`.
352
+
353
+ :param function: a coroutine function that takes two arguments: the accumulated
354
+ value and the next element from the iterable
355
+ :param iterable: an iterable or async iterable
356
+ :param initial: the initial value (if missing, the first element of the iterable is
357
+ used as the initial value)
358
+
359
+ """
360
+ element: Any
361
+ function_called = False
362
+ if isinstance(iterable, AsyncIterable):
363
+ async_it = iterable.__aiter__()
364
+ if initial is initial_missing:
365
+ try:
366
+ value = cast(T, await async_it.__anext__())
367
+ except StopAsyncIteration:
368
+ raise TypeError(
369
+ "reduce() of empty sequence with no initial value"
370
+ ) from None
371
+ else:
372
+ value = cast(T, initial)
373
+
374
+ async for element in async_it:
375
+ value = await function(value, element)
376
+ function_called = True
377
+ elif isinstance(iterable, Iterable):
378
+ it = iter(iterable)
379
+ if initial is initial_missing:
380
+ try:
381
+ value = cast(T, next(it))
382
+ except StopIteration:
383
+ raise TypeError(
384
+ "reduce() of empty sequence with no initial value"
385
+ ) from None
386
+ else:
387
+ value = cast(T, initial)
388
+
389
+ for element in it:
390
+ value = await function(value, element)
391
+ function_called = True
392
+ else:
393
+ raise TypeError("reduce() argument 2 must be an iterable or async iterable")
394
+
395
+ # Make sure there is at least one checkpoint, even if an empty iterable and an
396
+ # initial value were given
397
+ if not function_called:
398
+ await checkpoint()
399
+
400
+ return value
.venvs/kimodo/lib/python3.10/site-packages/anyio/itertools.py ADDED
@@ -0,0 +1,629 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ __all__ = (
4
+ "Chain",
5
+ "accumulate",
6
+ "batched",
7
+ "combinations",
8
+ "combinations_with_replacement",
9
+ "compress",
10
+ "count",
11
+ "cycle",
12
+ "dropwhile",
13
+ "filterfalse",
14
+ "groupby",
15
+ "islice",
16
+ "pairwise",
17
+ "permutations",
18
+ "product",
19
+ "repeat",
20
+ "starmap",
21
+ "takewhile",
22
+ "tee",
23
+ "zip_longest",
24
+ )
25
+
26
+ import itertools
27
+ import operator
28
+ import sys
29
+ from collections.abc import (
30
+ AsyncGenerator,
31
+ AsyncIterable,
32
+ AsyncIterator,
33
+ Awaitable,
34
+ Callable,
35
+ Iterable,
36
+ Iterator,
37
+ )
38
+ from dataclasses import dataclass, field
39
+ from typing import Any, Generic, TypeVar, cast, overload
40
+
41
+ from ._core._synchronization import Lock
42
+ from ._core._tasks import CancelScope
43
+ from .lowlevel import cancel_shielded_checkpoint, checkpoint, checkpoint_if_cancelled
44
+
45
+ if sys.version_info < (3, 15):
46
+ from typing_extensions import sentinel
47
+
48
+ T = TypeVar("T")
49
+ R = TypeVar("R")
50
+ _tee_end = sentinel("_tee_end")
51
+
52
+
53
+ @dataclass(eq=False)
54
+ class _IterableAsyncIterator(AsyncIterator[T]):
55
+ iterator: Iterator[T]
56
+
57
+ async def __anext__(self) -> T:
58
+ await checkpoint_if_cancelled()
59
+ try:
60
+ result = next(self.iterator)
61
+ except StopIteration:
62
+ await cancel_shielded_checkpoint()
63
+ raise StopAsyncIteration from None
64
+
65
+ await cancel_shielded_checkpoint()
66
+ return result
67
+
68
+
69
+ def _iterate(iterable: Iterable[T] | AsyncIterable[T]) -> AsyncIterator[T]:
70
+ if isinstance(iterable, AsyncIterator):
71
+ return iterable
72
+
73
+ if isinstance(iterable, AsyncIterable):
74
+ return iterable.__aiter__()
75
+
76
+ return _IterableAsyncIterator(iter(iterable))
77
+
78
+
79
+ @dataclass(eq=False)
80
+ class _TeeLink(Generic[T]):
81
+ value: object | None = None
82
+ next: _TeeLink[T] | None = None
83
+ filled: bool = False
84
+
85
+
86
+ @dataclass(eq=False)
87
+ class _TeeState(Generic[T]):
88
+ iterator: AsyncIterator[T]
89
+ lock: Lock = field(default_factory=Lock)
90
+
91
+ async def fill(self, link: _TeeLink[T]) -> bool:
92
+ if link.filled:
93
+ return False
94
+
95
+ async with self.lock:
96
+ if link.filled:
97
+ return True
98
+
99
+ link.value = await anext(self.iterator, _tee_end)
100
+ if link.value is not _tee_end:
101
+ link.next = _TeeLink()
102
+
103
+ link.filled = True
104
+ return True
105
+
106
+
107
+ class _TeeAsyncIterator(AsyncIterator[T]):
108
+ _state: _TeeState[T]
109
+ _link: _TeeLink[T]
110
+ _element_yielded: bool
111
+
112
+ def __init__(
113
+ self, iterable: Iterable[T] | AsyncIterable[T] | _TeeAsyncIterator[T]
114
+ ) -> None:
115
+ if isinstance(iterable, _TeeAsyncIterator):
116
+ self._state = iterable._state
117
+ self._link = iterable._link
118
+ else:
119
+ self._state = _TeeState(_iterate(iterable))
120
+ self._link = _TeeLink()
121
+
122
+ self._element_yielded = False
123
+
124
+ async def __anext__(self) -> T:
125
+ had_yieldpoint = await self._state.fill(self._link)
126
+ if self._link.value is _tee_end:
127
+ if not self._element_yielded:
128
+ await checkpoint()
129
+
130
+ raise StopAsyncIteration
131
+
132
+ if not had_yieldpoint:
133
+ await checkpoint_if_cancelled()
134
+
135
+ self._element_yielded = True
136
+ value = cast(T, self._link.value)
137
+ next_link = self._link.next
138
+ assert next_link is not None
139
+ self._link = next_link
140
+ if not had_yieldpoint:
141
+ await cancel_shielded_checkpoint()
142
+
143
+ return value
144
+
145
+
146
+ async def _operator_add(x: T, y: T) -> T:
147
+ return operator.add(x, y)
148
+
149
+
150
+ async def accumulate(
151
+ iterable: Iterable[T] | AsyncIterable[T],
152
+ function: Callable[[T, T], Awaitable[T]] = _operator_add,
153
+ *,
154
+ initial: T | None = None,
155
+ ) -> AsyncGenerator[T, None]:
156
+ iterator = _iterate(iterable)
157
+ if initial is None:
158
+ try:
159
+ total = await anext(iterator)
160
+ except StopAsyncIteration:
161
+ await checkpoint()
162
+ return
163
+ else:
164
+ await checkpoint_if_cancelled()
165
+ total = initial
166
+ await cancel_shielded_checkpoint()
167
+
168
+ yield total
169
+
170
+ async for element in iterator:
171
+ total = await function(total, element)
172
+ yield total
173
+
174
+
175
+ async def batched(
176
+ iterable: Iterable[T] | AsyncIterable[T], n: int, *, strict: bool = False
177
+ ) -> AsyncGenerator[tuple[T, ...], None]:
178
+ if n < 1:
179
+ raise ValueError("n must be at least one")
180
+
181
+ iterator = _iterate(iterable)
182
+
183
+ while True:
184
+ batch: list[T] = []
185
+ for _ in range(n):
186
+ try:
187
+ batch.append(await anext(iterator))
188
+ except StopAsyncIteration:
189
+ if not batch:
190
+ await checkpoint()
191
+ return
192
+ if strict:
193
+ raise ValueError("batched(): incomplete batch") from None
194
+
195
+ yield tuple(batch)
196
+ return
197
+
198
+ yield tuple(batch)
199
+
200
+
201
+ class Chain:
202
+ def __call__(
203
+ self, *iterables: Iterable[T] | AsyncIterable[T]
204
+ ) -> AsyncGenerator[T, None]:
205
+ return self.from_iterable(iterables)
206
+
207
+ async def from_iterable(
208
+ self,
209
+ iterables: (
210
+ Iterable[Iterable[T] | AsyncIterable[T]]
211
+ | AsyncIterable[Iterable[T] | AsyncIterable[T]]
212
+ ),
213
+ ) -> AsyncGenerator[T, None]:
214
+ element_yielded = False
215
+ outer_iter = _iterate(iterables)
216
+
217
+ try:
218
+ async for iterable in outer_iter:
219
+ async for element in _iterate(iterable):
220
+ element_yielded = True
221
+ yield element
222
+ finally:
223
+ aclose = getattr(outer_iter, "aclose", None)
224
+ if aclose is not None:
225
+ with CancelScope(shield=True):
226
+ await aclose()
227
+
228
+ if not element_yielded:
229
+ await checkpoint()
230
+
231
+
232
+ chain: Chain = Chain()
233
+
234
+
235
+ async def combinations(
236
+ iterable: Iterable[T] | AsyncIterable[T], r: int
237
+ ) -> AsyncGenerator[tuple[T, ...], None]:
238
+ pool: list[T] = [element async for element in _iterate(iterable)]
239
+ async for combination in _iterate(itertools.combinations(pool, r)):
240
+ yield combination
241
+
242
+
243
+ async def combinations_with_replacement(
244
+ iterable: Iterable[T] | AsyncIterable[T], r: int
245
+ ) -> AsyncGenerator[tuple[T, ...], None]:
246
+ pool: list[T] = [element async for element in _iterate(iterable)]
247
+ async for combination in _iterate(itertools.combinations_with_replacement(pool, r)):
248
+ yield combination
249
+
250
+
251
+ async def compress(
252
+ data: Iterable[T] | AsyncIterable[T],
253
+ selectors: Iterable[object] | AsyncIterable[object],
254
+ ) -> AsyncGenerator[T, None]:
255
+ data_iterator = _iterate(data)
256
+ selector_iterator = _iterate(selectors)
257
+ element_yielded = False
258
+
259
+ while True:
260
+ try:
261
+ datum = await anext(data_iterator)
262
+ selector = await anext(selector_iterator)
263
+ except StopAsyncIteration:
264
+ if not element_yielded:
265
+ await checkpoint()
266
+
267
+ return
268
+
269
+ if selector:
270
+ element_yielded = True
271
+ yield datum
272
+
273
+
274
+ async def count(start: int = 0, step: int = 1) -> AsyncGenerator[int, None]:
275
+ n = start
276
+ while True:
277
+ await checkpoint_if_cancelled()
278
+ value = n
279
+ n += step
280
+ await cancel_shielded_checkpoint()
281
+ yield value
282
+
283
+
284
+ async def cycle(
285
+ iterable: Iterable[T] | AsyncIterable[T],
286
+ ) -> AsyncGenerator[T, None]:
287
+ saved: list[T] = []
288
+ async for element in _iterate(iterable):
289
+ saved.append(element)
290
+ yield element
291
+
292
+ if not saved:
293
+ await checkpoint()
294
+ return
295
+
296
+ while True:
297
+ for element in saved:
298
+ await checkpoint()
299
+ yield element
300
+
301
+
302
+ async def dropwhile(
303
+ predicate: Callable[[T], Awaitable[object]],
304
+ iterable: Iterable[T] | AsyncIterable[T],
305
+ ) -> AsyncGenerator[T, None]:
306
+ element_yielded = False
307
+ dropping = True
308
+
309
+ async for element in _iterate(iterable):
310
+ if dropping and await predicate(element):
311
+ continue
312
+
313
+ dropping = False
314
+ element_yielded = True
315
+ yield element
316
+
317
+ if not element_yielded:
318
+ await checkpoint()
319
+
320
+
321
+ async def filterfalse(
322
+ predicate: Callable[[T], Awaitable[object]],
323
+ iterable: Iterable[T] | AsyncIterable[T],
324
+ ) -> AsyncGenerator[T, None]:
325
+ element_yielded = False
326
+
327
+ async for element in _iterate(iterable):
328
+ if not await predicate(element):
329
+ element_yielded = True
330
+ yield element
331
+
332
+ if not element_yielded:
333
+ await checkpoint()
334
+
335
+
336
+ @overload
337
+ def groupby(
338
+ iterable: Iterable[T] | AsyncIterable[T],
339
+ ) -> AsyncGenerator[tuple[T, list[T]], None]: ...
340
+
341
+
342
+ @overload
343
+ def groupby(
344
+ iterable: Iterable[T] | AsyncIterable[T],
345
+ key: Callable[[T], Awaitable[R]],
346
+ ) -> AsyncGenerator[tuple[R, list[T]], None]: ...
347
+
348
+
349
+ async def groupby(
350
+ iterable: Iterable[T] | AsyncIterable[T],
351
+ key: Callable[[T], Awaitable[object]] | None = None,
352
+ ) -> AsyncGenerator[tuple[object, list[T]], None]:
353
+ iterator = _iterate(iterable)
354
+ try:
355
+ element = await anext(iterator)
356
+ except StopAsyncIteration:
357
+ await checkpoint()
358
+ return
359
+
360
+ group_key = element if key is None else await key(element)
361
+ values = [element]
362
+
363
+ async for element in iterator:
364
+ next_key = element if key is None else await key(element)
365
+ if next_key != group_key:
366
+ completed_group = group_key, values
367
+ group_key = next_key
368
+ values = [element]
369
+ yield completed_group
370
+ else:
371
+ values.append(element)
372
+
373
+ yield group_key, values
374
+
375
+
376
+ @overload
377
+ def islice(
378
+ iterable: Iterable[T] | AsyncIterable[T],
379
+ stop: int | None,
380
+ /,
381
+ ) -> AsyncGenerator[T, None]: ...
382
+
383
+
384
+ @overload
385
+ def islice(
386
+ iterable: Iterable[T] | AsyncIterable[T],
387
+ start: int | None,
388
+ stop: int | None,
389
+ step: int | None = 1,
390
+ /,
391
+ ) -> AsyncGenerator[T, None]: ...
392
+
393
+
394
+ async def islice(
395
+ iterable: Iterable[T] | AsyncIterable[T],
396
+ *args: int | None,
397
+ ) -> AsyncGenerator[T, None]:
398
+ if not args:
399
+ raise TypeError("islice expected at least 2 arguments, got 1")
400
+ if len(args) > 3:
401
+ raise TypeError(f"islice expected at most 4 arguments, got {len(args) + 1}")
402
+
403
+ slice_args = slice(*args)
404
+
405
+ start_message = (
406
+ "Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize."
407
+ )
408
+ stop_message = (
409
+ "Stop argument for islice() must be None or an integer: 0 <= x <= sys.maxsize."
410
+ )
411
+ step_message = "Step for islice() must be a positive integer or None."
412
+
413
+ def normalize_index(value: object, message: str) -> int:
414
+ try:
415
+ index = operator.index(cast(Any, value))
416
+ except TypeError:
417
+ raise ValueError(message) from None
418
+
419
+ if index < 0 or index > sys.maxsize:
420
+ raise ValueError(message)
421
+
422
+ return index
423
+
424
+ start = (
425
+ 0
426
+ if slice_args.start is None
427
+ else normalize_index(slice_args.start, start_message)
428
+ )
429
+ stop = (
430
+ None
431
+ if slice_args.stop is None
432
+ else normalize_index(slice_args.stop, stop_message)
433
+ )
434
+ step = (
435
+ 1 if slice_args.step is None else normalize_index(slice_args.step, step_message)
436
+ )
437
+
438
+ if step <= 0:
439
+ raise ValueError(step_message)
440
+
441
+ if stop == 0 or start == stop:
442
+ await checkpoint()
443
+ return
444
+
445
+ iterator = _iterate(iterable)
446
+ index = 0
447
+ element_yielded = False
448
+
449
+ while stop is None or index < stop:
450
+ try:
451
+ element = await anext(iterator)
452
+ except StopAsyncIteration:
453
+ if not element_yielded:
454
+ await checkpoint()
455
+
456
+ return
457
+
458
+ if index >= start and (index - start) % step == 0:
459
+ index += 1
460
+ element_yielded = True
461
+ yield element
462
+ else:
463
+ index += 1
464
+
465
+ if not element_yielded:
466
+ await checkpoint()
467
+
468
+
469
+ async def pairwise(
470
+ iterable: Iterable[T] | AsyncIterable[T],
471
+ ) -> AsyncGenerator[tuple[T, T], None]:
472
+ iterator = _iterate(iterable)
473
+ try:
474
+ previous = await anext(iterator)
475
+ except StopAsyncIteration:
476
+ await checkpoint()
477
+ return
478
+
479
+ element_yielded = False
480
+ async for element in iterator:
481
+ element_yielded = True
482
+ pair = (previous, element)
483
+ previous = element
484
+ yield pair
485
+
486
+ if not element_yielded:
487
+ await checkpoint()
488
+
489
+
490
+ async def permutations(
491
+ iterable: Iterable[T] | AsyncIterable[T], r: int | None = None
492
+ ) -> AsyncGenerator[tuple[T, ...], None]:
493
+ pool: list[T] = [element async for element in _iterate(iterable)]
494
+ n = len(pool)
495
+ if r is None:
496
+ r = n
497
+ elif not isinstance(r, int):
498
+ raise TypeError("Expected int as r")
499
+ elif r < 0:
500
+ raise ValueError("r must be non-negative")
501
+
502
+ async for permutation in _iterate(itertools.permutations(pool, r)):
503
+ yield permutation
504
+
505
+
506
+ async def product(
507
+ *iterables: Iterable[T] | AsyncIterable[T], repeat: int = 1
508
+ ) -> AsyncGenerator[tuple[T, ...], None]:
509
+ repeat = operator.index(repeat)
510
+ if repeat < 0:
511
+ raise ValueError("repeat argument cannot be negative")
512
+
513
+ pools: list[tuple[T, ...]] = []
514
+ for iterable in iterables:
515
+ pool: list[T] = [element async for element in _iterate(iterable)]
516
+ pools.append(tuple(pool))
517
+
518
+ async for value in _iterate(itertools.product(*pools, repeat=repeat)):
519
+ yield value
520
+
521
+
522
+ async def repeat(element: T, times: int | None = None) -> AsyncGenerator[T, None]:
523
+ if times is None:
524
+ while True:
525
+ await checkpoint()
526
+ yield element
527
+
528
+ remaining = operator.index(cast(Any, times))
529
+ if remaining <= 0:
530
+ await checkpoint()
531
+ return
532
+
533
+ while remaining > 0:
534
+ await checkpoint_if_cancelled()
535
+ remaining -= 1
536
+ await cancel_shielded_checkpoint()
537
+ yield element
538
+
539
+
540
+ async def starmap(
541
+ function: Callable[..., Awaitable[R]],
542
+ iterable: (
543
+ Iterable[Iterable[object] | AsyncIterable[object]]
544
+ | AsyncIterable[Iterable[object] | AsyncIterable[object]]
545
+ ),
546
+ ) -> AsyncGenerator[R, None]:
547
+ result_yielded = False
548
+
549
+ async for args_iterable in _iterate(iterable):
550
+ args = [element async for element in _iterate(args_iterable)]
551
+ result_yielded = True
552
+ yield await function(*args)
553
+
554
+ if not result_yielded:
555
+ await checkpoint()
556
+
557
+
558
+ def tee(
559
+ iterable: Iterable[T] | AsyncIterable[T], n: int = 2
560
+ ) -> tuple[AsyncIterator[T], ...]:
561
+ n = operator.index(cast(Any, n))
562
+ if n < 0:
563
+ raise ValueError("n must be >= 0")
564
+ if n == 0:
565
+ return ()
566
+
567
+ iterator = _TeeAsyncIterator(iterable)
568
+ iterators: list[AsyncIterator[T]] = [iterator]
569
+ iterators.extend(_TeeAsyncIterator(iterator) for _ in range(n - 1))
570
+ return tuple(iterators)
571
+
572
+
573
+ async def takewhile(
574
+ predicate: Callable[[T], Awaitable[object]],
575
+ iterable: Iterable[T] | AsyncIterable[T],
576
+ ) -> AsyncGenerator[T, None]:
577
+ element_yielded = False
578
+
579
+ async for element in _iterate(iterable):
580
+ if not await predicate(element):
581
+ if not element_yielded:
582
+ await checkpoint()
583
+
584
+ return
585
+
586
+ element_yielded = True
587
+ yield element
588
+
589
+ if not element_yielded:
590
+ await checkpoint()
591
+
592
+
593
+ async def zip_longest(
594
+ *iterables: Iterable[object] | AsyncIterable[object],
595
+ fillvalue: object = None,
596
+ ) -> AsyncGenerator[tuple[object, ...], None]:
597
+ iterators = [_iterate(iterable) for iterable in iterables]
598
+ num_active = len(iterators)
599
+ if not num_active:
600
+ await checkpoint()
601
+ return
602
+
603
+ active = [True] * num_active
604
+ tuple_yielded = False
605
+
606
+ while True:
607
+ values: list[object] = []
608
+ for index, iterator in enumerate(iterators):
609
+ if not active[index]:
610
+ values.append(fillvalue)
611
+ continue
612
+
613
+ try:
614
+ value = await anext(iterator)
615
+ except StopAsyncIteration:
616
+ active[index] = False
617
+ num_active -= 1
618
+ if not num_active:
619
+ if not tuple_yielded:
620
+ await checkpoint()
621
+
622
+ return
623
+
624
+ value = fillvalue
625
+
626
+ values.append(value)
627
+
628
+ tuple_yielded = True
629
+ yield tuple(values)
.venvs/kimodo/lib/python3.10/site-packages/anyio/lowlevel.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ __all__ = (
4
+ "EventLoopToken",
5
+ "RunVar",
6
+ "RunvarToken",
7
+ "cancel_shielded_checkpoint",
8
+ "checkpoint",
9
+ "checkpoint_if_cancelled",
10
+ "current_token",
11
+ )
12
+
13
+ import enum
14
+ from dataclasses import dataclass
15
+ from types import TracebackType
16
+ from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar, final, overload
17
+ from weakref import WeakKeyDictionary
18
+
19
+ from ._core._eventloop import get_async_backend
20
+
21
+ if TYPE_CHECKING:
22
+ from .abc import AsyncBackend
23
+
24
+ T = TypeVar("T")
25
+ D = TypeVar("D")
26
+
27
+
28
+ async def checkpoint() -> None:
29
+ """
30
+ Check for cancellation and allow the scheduler to switch to another task.
31
+
32
+ Equivalent to (but more efficient than)::
33
+
34
+ await checkpoint_if_cancelled()
35
+ await cancel_shielded_checkpoint()
36
+
37
+ .. versionadded:: 3.0
38
+
39
+ """
40
+ await get_async_backend().checkpoint()
41
+
42
+
43
+ async def checkpoint_if_cancelled() -> None:
44
+ """
45
+ Enter a checkpoint if the enclosing cancel scope has been cancelled.
46
+
47
+ This does not allow the scheduler to switch to a different task.
48
+
49
+ .. versionadded:: 3.0
50
+
51
+ """
52
+ await get_async_backend().checkpoint_if_cancelled()
53
+
54
+
55
+ async def cancel_shielded_checkpoint() -> None:
56
+ """
57
+ Allow the scheduler to switch to another task but without checking for cancellation.
58
+
59
+ Equivalent to (but potentially more efficient than)::
60
+
61
+ with CancelScope(shield=True):
62
+ await checkpoint()
63
+
64
+ .. versionadded:: 3.0
65
+
66
+ """
67
+ await get_async_backend().cancel_shielded_checkpoint()
68
+
69
+
70
+ @final
71
+ @dataclass(frozen=True, repr=False)
72
+ class EventLoopToken:
73
+ """
74
+ An opaque object that holds a reference to an event loop.
75
+
76
+ .. versionadded:: 4.11.0
77
+ """
78
+
79
+ backend_class: type[AsyncBackend]
80
+ native_token: object
81
+
82
+
83
+ def current_token() -> EventLoopToken:
84
+ """
85
+ Return a token object that can be used to call code in the current event loop from
86
+ another thread.
87
+
88
+ :raises NoEventLoopError: if no supported asynchronous event loop is running in the
89
+ current thread
90
+
91
+ .. versionadded:: 4.11.0
92
+
93
+ """
94
+ backend_class = get_async_backend()
95
+ raw_token = backend_class.current_token()
96
+ return EventLoopToken(backend_class, raw_token)
97
+
98
+
99
+ _run_vars: WeakKeyDictionary[object, dict[RunVar[Any], Any]] = WeakKeyDictionary()
100
+
101
+
102
+ class _NoValueSet(enum.Enum):
103
+ NO_VALUE_SET = enum.auto()
104
+
105
+
106
+ class RunvarToken(Generic[T]):
107
+ """
108
+ A token that can be used to restore a :class:`RunVar` to its previous value.
109
+
110
+ Returned by :meth:`RunVar.set`. Can be used as a context manager to automatically
111
+ reset the variable on exit, or passed directly to :meth:`RunVar.reset`.
112
+ """
113
+
114
+ __slots__ = "_redeemed", "_value", "_var"
115
+
116
+ def __init__(self, var: RunVar[T], value: T | Literal[_NoValueSet.NO_VALUE_SET]):
117
+ self._var = var
118
+ self._value: T | Literal[_NoValueSet.NO_VALUE_SET] = value
119
+ self._redeemed = False
120
+
121
+ def __enter__(self) -> RunvarToken[T]:
122
+ return self
123
+
124
+ def __exit__(
125
+ self,
126
+ exc_type: type[BaseException] | None,
127
+ exc_val: BaseException | None,
128
+ exc_tb: TracebackType | None,
129
+ ) -> None:
130
+ self._var.reset(self)
131
+
132
+
133
+ class RunVar(Generic[T]):
134
+ """
135
+ Like a :class:`~contextvars.ContextVar`, except scoped to the running event loop.
136
+
137
+ Can be used as a context manager, Just like :class:`~contextvars.ContextVar`, that
138
+ will reset the variable to its previous value when the context block is exited.
139
+ """
140
+
141
+ __slots__ = "_default", "_name"
142
+
143
+ NO_VALUE_SET: Literal[_NoValueSet.NO_VALUE_SET] = _NoValueSet.NO_VALUE_SET
144
+
145
+ def __init__(
146
+ self, name: str, default: T | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET
147
+ ):
148
+ self._name = name
149
+ self._default = default
150
+
151
+ @property
152
+ def _current_vars(self) -> dict[RunVar[T], T]:
153
+ native_token = current_token().native_token
154
+ try:
155
+ return _run_vars[native_token]
156
+ except KeyError:
157
+ run_vars = _run_vars[native_token] = {}
158
+ return run_vars
159
+
160
+ @overload
161
+ def get(self, default: D) -> T | D: ...
162
+
163
+ @overload
164
+ def get(self) -> T: ...
165
+
166
+ def get(
167
+ self, default: D | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET
168
+ ) -> T | D:
169
+ """
170
+ Return the current value of this run variable.
171
+
172
+ :param default: a fallback value to return if no value has been set
173
+ :return: the current value, the provided default, or the variable's own default
174
+ :raises LookupError: if no value is set and no default is available
175
+
176
+ """
177
+ try:
178
+ return self._current_vars[self]
179
+ except KeyError:
180
+ if default is not RunVar.NO_VALUE_SET:
181
+ return default
182
+ elif self._default is not RunVar.NO_VALUE_SET:
183
+ return self._default
184
+
185
+ raise LookupError(
186
+ f'Run variable "{self._name}" has no value and no default set'
187
+ )
188
+
189
+ def set(self, value: T) -> RunvarToken[T]:
190
+ """
191
+ Set the value of this run variable for the current event loop.
192
+
193
+ :param value: the new value
194
+ :return: a token that can be used to restore the previous value
195
+
196
+ """
197
+ current_vars = self._current_vars
198
+ token = RunvarToken(self, current_vars.get(self, RunVar.NO_VALUE_SET))
199
+ current_vars[self] = value
200
+ return token
201
+
202
+ def reset(self, token: RunvarToken[T]) -> None:
203
+ """
204
+ Restore this run variable to the value it held before the matching :meth:`set`.
205
+
206
+ :param token: the token returned by :meth:`set`
207
+ :raises ValueError: if the token belongs to a different :class:`RunVar` or the token
208
+ has already been used
209
+
210
+ """
211
+ if token._var is not self:
212
+ raise ValueError("This token does not belong to this RunVar")
213
+
214
+ if token._redeemed:
215
+ raise ValueError("This token has already been used")
216
+
217
+ if token._value is _NoValueSet.NO_VALUE_SET:
218
+ try:
219
+ del self._current_vars[self]
220
+ except KeyError:
221
+ pass
222
+ else:
223
+ self._current_vars[self] = token._value
224
+
225
+ token._redeemed = True
226
+
227
+ def __repr__(self) -> str:
228
+ return f"<RunVar name={self._name!r}>"
.venvs/kimodo/lib/python3.10/site-packages/anyio/py.typed ADDED
File without changes
.venvs/kimodo/lib/python3.10/site-packages/anyio/pytest_plugin.py ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import socket
5
+ import sys
6
+ from collections.abc import Callable, Generator, Iterator
7
+ from contextlib import ExitStack, contextmanager
8
+ from inspect import isasyncgenfunction, iscoroutinefunction, ismethod
9
+ from typing import TYPE_CHECKING, Any, cast
10
+
11
+ import pytest
12
+ from _pytest.fixtures import FuncFixtureInfo, SubRequest
13
+ from _pytest.outcomes import Exit
14
+ from _pytest.scope import Scope
15
+
16
+ from . import get_available_backends
17
+ from ._core._eventloop import (
18
+ current_async_library,
19
+ get_async_backend,
20
+ reset_current_async_library,
21
+ set_current_async_library,
22
+ )
23
+ from ._core._exceptions import iterate_exceptions
24
+
25
+ if TYPE_CHECKING:
26
+ from .abc import TestRunner
27
+
28
+ if sys.version_info < (3, 11):
29
+ from exceptiongroup import ExceptionGroup
30
+
31
+ if TYPE_CHECKING:
32
+ # pytest >= 9.2 keeps CallSpec2 as a TYPE_CHECKING-only alias of CallSpec
33
+ from _pytest.python import CallSpec2 as CallSpec
34
+ else:
35
+ try:
36
+ # c.f. https://github.com/pytest-dev/pytest/pull/14742
37
+ # pytest >= 9.2
38
+ from _pytest.python import CallSpec
39
+ except ImportError:
40
+ from _pytest.python import CallSpec2 as CallSpec
41
+
42
+ _current_runner: TestRunner | None = None
43
+ _runner_stack: ExitStack | None = None
44
+ _runner_leases = 0
45
+
46
+
47
+ def extract_backend_and_options(backend: object) -> tuple[str, dict[str, Any]]:
48
+ if isinstance(backend, str):
49
+ return backend, {}
50
+ elif isinstance(backend, tuple) and len(backend) == 2:
51
+ if isinstance(backend[0], str) and isinstance(backend[1], dict):
52
+ return cast(tuple[str, dict[str, Any]], backend)
53
+
54
+ raise TypeError("anyio_backend must be either a string or tuple of (string, dict)")
55
+
56
+
57
+ @contextmanager
58
+ def get_runner(
59
+ backend_name: str, backend_options: dict[str, Any]
60
+ ) -> Iterator[TestRunner]:
61
+ global _current_runner, _runner_leases, _runner_stack
62
+ if _current_runner is None:
63
+ asynclib = get_async_backend(backend_name)
64
+ _runner_stack = ExitStack()
65
+ if current_async_library() is None:
66
+ # Since we're in control of the event loop, we can cache the name of the
67
+ # async library
68
+ token = set_current_async_library(backend_name)
69
+ _runner_stack.callback(reset_current_async_library, token)
70
+
71
+ backend_options = backend_options or {}
72
+ _current_runner = _runner_stack.enter_context(
73
+ asynclib.create_test_runner(backend_options)
74
+ )
75
+
76
+ _runner_leases += 1
77
+ try:
78
+ yield _current_runner
79
+ finally:
80
+ _runner_leases -= 1
81
+ if not _runner_leases:
82
+ assert _runner_stack is not None
83
+ _runner_stack.close()
84
+ _runner_stack = _current_runner = None
85
+
86
+
87
+ def pytest_addoption(parser: pytest.Parser) -> None:
88
+ group = parser.getgroup("anyio")
89
+ parser.addini(
90
+ "anyio_mode",
91
+ default="strict",
92
+ help='AnyIO plugin mode (either "strict" or "auto")',
93
+ )
94
+ group.addoption(
95
+ "--anyio-mode",
96
+ default=None,
97
+ dest="anyio_mode",
98
+ help="""
99
+ 'auto' - All async test functions will be handled by AnyIO pytest plugin
100
+ 'strict' - Disabling autoprocessing(useful when anyio tests
101
+ need to coexist with other async test plugins)
102
+ """,
103
+ )
104
+
105
+
106
+ def _is_auto_mode(config: pytest.Config, mode: str) -> bool:
107
+ return (
108
+ config.getoption(mode, default=None) == "auto" or config.getini(mode) == "auto"
109
+ )
110
+
111
+
112
+ def pytest_configure(config: pytest.Config) -> None:
113
+ config.addinivalue_line(
114
+ "markers",
115
+ "anyio: mark the (coroutine function) test to be run asynchronously via anyio.",
116
+ )
117
+ if (
118
+ _is_auto_mode(config, "anyio_mode")
119
+ and config.pluginmanager.has_plugin("asyncio")
120
+ and _is_auto_mode(config, "asyncio_mode")
121
+ ):
122
+ config.issue_config_time_warning(
123
+ pytest.PytestConfigWarning(
124
+ "AnyIO auto mode has been enabled together with pytest-asyncio auto "
125
+ "mode. This may cause unexpected behavior."
126
+ ),
127
+ 1,
128
+ )
129
+
130
+
131
+ @pytest.hookimpl(hookwrapper=True)
132
+ def pytest_fixture_setup(fixturedef: Any, request: Any) -> Generator[Any]:
133
+ def wrapper(anyio_backend: Any, request: SubRequest, **kwargs: Any) -> Any:
134
+ # Rebind any fixture methods to the request instance
135
+ if (
136
+ request.instance
137
+ and ismethod(func)
138
+ and type(func.__self__) is type(request.instance)
139
+ ):
140
+ local_func = func.__func__.__get__(request.instance)
141
+ else:
142
+ local_func = func
143
+
144
+ backend_name, backend_options = extract_backend_and_options(anyio_backend)
145
+ if has_backend_arg:
146
+ kwargs["anyio_backend"] = anyio_backend
147
+
148
+ if has_request_arg:
149
+ kwargs["request"] = request
150
+
151
+ with get_runner(backend_name, backend_options) as runner:
152
+ # re-entrant call into the test runner detected. this happens when an async fixture
153
+ # is dynamically requested via request.getfixturevalue() from inside a running async
154
+ # test or fixture. on asyncio this raises RuntimeError: This event loop is already
155
+ # running, on trio the runner deadlocks - the host loop blocks waiting for the
156
+ # coroutine to return, but the coroutine is waiting for the host loop. raising here
157
+ # prevents the hang and gives a consistent error across backends.
158
+ if runner.is_running():
159
+ raise RuntimeError(
160
+ "Cannot schedule a coroutine in the test runner while another is already running; "
161
+ "likely caused by request.getfixturevalue() on an async fixture."
162
+ )
163
+
164
+ if isasyncgenfunction(local_func):
165
+ yield from runner.run_asyncgen_fixture(local_func, kwargs)
166
+ else:
167
+ yield runner.run_fixture(local_func, kwargs)
168
+
169
+ # Only apply this to coroutine functions and async generator functions in requests
170
+ # that involve the anyio_backend fixture
171
+ func = fixturedef.func
172
+ if isasyncgenfunction(func) or iscoroutinefunction(func):
173
+ if "anyio_backend" in request.fixturenames:
174
+ fixturedef.func = wrapper
175
+ original_argname = fixturedef.argnames
176
+
177
+ if not (has_backend_arg := "anyio_backend" in fixturedef.argnames):
178
+ fixturedef.argnames += ("anyio_backend",)
179
+
180
+ if not (has_request_arg := "request" in fixturedef.argnames):
181
+ fixturedef.argnames += ("request",)
182
+
183
+ try:
184
+ return (yield)
185
+ finally:
186
+ fixturedef.func = func
187
+ fixturedef.argnames = original_argname
188
+
189
+ return (yield)
190
+
191
+
192
+ @pytest.hookimpl(tryfirst=True)
193
+ def pytest_pycollect_makeitem(
194
+ collector: pytest.Module | pytest.Class, name: str, obj: object
195
+ ) -> None:
196
+ if collector.istestfunction(obj, name):
197
+ inner_func = obj.hypothesis.inner_test if hasattr(obj, "hypothesis") else obj
198
+ if iscoroutinefunction(inner_func):
199
+ anyio_auto_mode = _is_auto_mode(collector.config, "anyio_mode")
200
+ marker = collector.get_closest_marker("anyio")
201
+ own_markers = getattr(obj, "pytestmark", ())
202
+ if (
203
+ anyio_auto_mode
204
+ or marker
205
+ or any(marker.name == "anyio" for marker in own_markers)
206
+ ):
207
+ pytest.mark.usefixtures("anyio_backend")(obj)
208
+
209
+
210
+ def pytest_collection_finish(session: pytest.Session) -> None:
211
+ for i, item in reversed(list(enumerate(session.items))):
212
+ if (
213
+ isinstance(item, pytest.Function)
214
+ and iscoroutinefunction(item.function)
215
+ and item.get_closest_marker("anyio") is not None
216
+ and "anyio_backend" not in item.fixturenames
217
+ ):
218
+ new_items = []
219
+ try:
220
+ cs_fields = {f.name for f in dataclasses.fields(CallSpec)}
221
+ except TypeError:
222
+ cs_fields = set()
223
+
224
+ for param_index, backend in enumerate(get_available_backends()):
225
+ if "_arg2scope" in cs_fields: # pytest >= 8
226
+ callspec = CallSpec(
227
+ params={"anyio_backend": backend},
228
+ indices={"anyio_backend": param_index},
229
+ _arg2scope={"anyio_backend": Scope.Module},
230
+ _idlist=[backend],
231
+ marks=[],
232
+ )
233
+ else: # pytest 7.x
234
+ callspec = CallSpec( # type: ignore[call-arg]
235
+ funcargs={},
236
+ params={"anyio_backend": backend},
237
+ indices={"anyio_backend": param_index},
238
+ arg2scope={"anyio_backend": Scope.Module},
239
+ idlist=[backend],
240
+ marks=[],
241
+ )
242
+
243
+ fi = item._fixtureinfo
244
+ new_names_closure = list(fi.names_closure)
245
+ if "anyio_backend" not in new_names_closure:
246
+ new_names_closure.append("anyio_backend")
247
+
248
+ new_fixtureinfo = FuncFixtureInfo(
249
+ argnames=fi.argnames,
250
+ initialnames=fi.initialnames,
251
+ names_closure=new_names_closure,
252
+ name2fixturedefs=fi.name2fixturedefs,
253
+ )
254
+ new_item = pytest.Function.from_parent(
255
+ item.parent,
256
+ name=f"{item.originalname}[{backend}]",
257
+ callspec=callspec,
258
+ callobj=item.obj,
259
+ fixtureinfo=new_fixtureinfo,
260
+ keywords=item.keywords,
261
+ originalname=item.originalname,
262
+ )
263
+ new_items.append(new_item)
264
+
265
+ session.items[i : i + 1] = new_items
266
+
267
+
268
+ @pytest.hookimpl(tryfirst=True)
269
+ def pytest_pyfunc_call(pyfuncitem: Any) -> bool | None:
270
+ def run_with_hypothesis(**kwargs: Any) -> None:
271
+ with get_runner(backend_name, backend_options) as runner:
272
+ runner.run_test(original_func, kwargs)
273
+
274
+ backend = pyfuncitem.funcargs.get("anyio_backend")
275
+ if backend:
276
+ backend_name, backend_options = extract_backend_and_options(backend)
277
+
278
+ if hasattr(pyfuncitem.obj, "hypothesis"):
279
+ # Wrap the inner test function unless it's already wrapped
280
+ original_func = pyfuncitem.obj.hypothesis.inner_test
281
+ if original_func.__qualname__ != run_with_hypothesis.__qualname__:
282
+ if iscoroutinefunction(original_func):
283
+ pyfuncitem.obj.hypothesis.inner_test = run_with_hypothesis
284
+
285
+ return None
286
+
287
+ if iscoroutinefunction(pyfuncitem.obj):
288
+ funcargs = pyfuncitem.funcargs
289
+ testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames}
290
+ with get_runner(backend_name, backend_options) as runner:
291
+ try:
292
+ runner.run_test(pyfuncitem.obj, testargs)
293
+ except ExceptionGroup as excgrp:
294
+ for exc in iterate_exceptions(excgrp):
295
+ if isinstance(exc, (Exit, KeyboardInterrupt, SystemExit)):
296
+ raise exc from excgrp
297
+
298
+ raise
299
+
300
+ return True
301
+
302
+ return None
303
+
304
+
305
+ @pytest.fixture(scope="module", params=get_available_backends())
306
+ def anyio_backend(request: Any) -> Any:
307
+ return request.param
308
+
309
+
310
+ @pytest.fixture
311
+ def anyio_backend_name(anyio_backend: Any) -> str:
312
+ if isinstance(anyio_backend, str):
313
+ return anyio_backend
314
+ else:
315
+ return anyio_backend[0]
316
+
317
+
318
+ @pytest.fixture
319
+ def anyio_backend_options(anyio_backend: Any) -> dict[str, Any]:
320
+ if isinstance(anyio_backend, str):
321
+ return {}
322
+ else:
323
+ return anyio_backend[1]
324
+
325
+
326
+ class FreePortFactory:
327
+ """
328
+ Manages port generation based on specified socket kind, ensuring no duplicate
329
+ ports are generated.
330
+
331
+ This class provides functionality for generating available free ports on the
332
+ system. It is initialized with a specific socket kind and can generate ports
333
+ for given address families while avoiding reuse of previously generated ports.
334
+
335
+ Users should not instantiate this class directly, but use the
336
+ ``free_tcp_port_factory`` and ``free_udp_port_factory`` fixtures instead. For simple
337
+ uses cases, ``free_tcp_port`` and ``free_udp_port`` can be used instead.
338
+ """
339
+
340
+ def __init__(self, kind: socket.SocketKind) -> None:
341
+ self._kind = kind
342
+ self._generated = set[int]()
343
+
344
+ @property
345
+ def kind(self) -> socket.SocketKind:
346
+ """
347
+ The type of socket connection (e.g., :data:`~socket.SOCK_STREAM` or
348
+ :data:`~socket.SOCK_DGRAM`) used to bind for checking port availability
349
+
350
+ """
351
+ return self._kind
352
+
353
+ def __call__(self, family: socket.AddressFamily | None = None) -> int:
354
+ """
355
+ Return an unbound port for the given address family.
356
+
357
+ :param family: if omitted, both IPv4 and IPv6 addresses will be tried
358
+ :return: a port number
359
+
360
+ """
361
+ if family is not None:
362
+ families = [family]
363
+ else:
364
+ families = [socket.AF_INET]
365
+ if socket.has_ipv6:
366
+ families.append(socket.AF_INET6)
367
+
368
+ while True:
369
+ port = 0
370
+ with ExitStack() as stack:
371
+ for fam in families:
372
+ sock = stack.enter_context(socket.socket(fam, self._kind))
373
+ addr = "::1" if fam == socket.AF_INET6 else "127.0.0.1"
374
+ try:
375
+ sock.bind((addr, port))
376
+ except OSError:
377
+ break
378
+
379
+ if not port:
380
+ port = sock.getsockname()[1]
381
+ else:
382
+ if port not in self._generated:
383
+ self._generated.add(port)
384
+ return port
385
+
386
+
387
+ @pytest.fixture(scope="session")
388
+ def free_tcp_port_factory() -> FreePortFactory:
389
+ return FreePortFactory(socket.SOCK_STREAM)
390
+
391
+
392
+ @pytest.fixture(scope="session")
393
+ def free_udp_port_factory() -> FreePortFactory:
394
+ return FreePortFactory(socket.SOCK_DGRAM)
395
+
396
+
397
+ @pytest.fixture
398
+ def free_tcp_port(free_tcp_port_factory: Callable[[], int]) -> int:
399
+ return free_tcp_port_factory()
400
+
401
+
402
+ @pytest.fixture
403
+ def free_udp_port(free_udp_port_factory: Callable[[], int]) -> int:
404
+ return free_udp_port_factory()