ez-a-sync 0.24.34__tar.gz → 0.24.35__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ez-a-sync might be problematic. Click here for more details.

Files changed (171) hide show
  1. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/PKG-INFO +1 -1
  2. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/executor.py +65 -18
  3. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_debug.c +475 -377
  4. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_debug.pxd +2 -1
  5. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_debug.pyx +20 -12
  6. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/counter.c +9 -10
  7. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/event.c +188 -176
  8. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/prio_semaphore.c +211 -201
  9. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/semaphore.c +34 -35
  10. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/ez_a_sync.egg-info/PKG-INFO +1 -1
  11. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.coverage +0 -0
  12. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.github/workflows/black.yaml +0 -0
  13. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.github/workflows/codeql.yaml +0 -0
  14. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.github/workflows/docs.yaml +0 -0
  15. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.github/workflows/mypy.yaml +0 -0
  16. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.github/workflows/pytest.yaml +0 -0
  17. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.github/workflows/release.yaml +0 -0
  18. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.gitignore +0 -0
  19. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/.sourcery.yaml +0 -0
  20. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/LICENSE.txt +0 -0
  21. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/MANIFEST.in +0 -0
  22. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/Makefile +0 -0
  23. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/README.md +0 -0
  24. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/TODO +0 -0
  25. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/ENVIRONMENT_VARIABLES.py +0 -0
  26. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/__init__.pxd +0 -0
  27. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/__init__.py +0 -0
  28. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/_smart.c +0 -0
  29. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/_smart.pyx +0 -0
  30. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/_typing.py +0 -0
  31. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/__init__.py +0 -0
  32. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_descriptor.py +0 -0
  33. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_flags.c +0 -0
  34. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_flags.pxd +0 -0
  35. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_flags.pyx +0 -0
  36. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_helpers.c +0 -0
  37. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_helpers.pxd +0 -0
  38. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_helpers.pyi +0 -0
  39. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_helpers.pyx +0 -0
  40. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_kwargs.c +0 -0
  41. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_kwargs.pxd +0 -0
  42. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_kwargs.pyx +0 -0
  43. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/_meta.py +0 -0
  44. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/abstract.c +0 -0
  45. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/abstract.pyi +0 -0
  46. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/abstract.pyx +0 -0
  47. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/base.c +0 -0
  48. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/base.pyi +0 -0
  49. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/base.pyx +0 -0
  50. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/config.py +0 -0
  51. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/decorator.py +0 -0
  52. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/flags.py +0 -0
  53. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/function.c +0 -0
  54. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/function.pyi +0 -0
  55. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/function.pyx +0 -0
  56. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/method.c +0 -0
  57. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/method.pxd +0 -0
  58. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/method.pyi +0 -0
  59. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/method.pyx +0 -0
  60. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/__init__.py +0 -0
  61. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/cache/__init__.py +0 -0
  62. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/cache/memory.py +0 -0
  63. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/limiter.py +0 -0
  64. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/manager.c +0 -0
  65. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/manager.pyi +0 -0
  66. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/manager.pyx +0 -0
  67. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/modifiers/semaphores.py +0 -0
  68. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/property.c +0 -0
  69. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/property.pyi +0 -0
  70. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/property.pyx +0 -0
  71. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/a_sync/singleton.py +0 -0
  72. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/aliases.py +0 -0
  73. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/__init__.py +0 -0
  74. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/as_completed.c +0 -0
  75. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/as_completed.pxd +0 -0
  76. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/as_completed.pyi +0 -0
  77. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/as_completed.pyx +0 -0
  78. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/create_task.c +0 -0
  79. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/create_task.pxd +0 -0
  80. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/create_task.pyi +0 -0
  81. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/create_task.pyx +0 -0
  82. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/gather.c +0 -0
  83. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/gather.pyi +0 -0
  84. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/asyncio/gather.pyx +0 -0
  85. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/exceptions.py +0 -0
  86. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/future.py +0 -0
  87. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/iter.c +0 -0
  88. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/iter.pyi +0 -0
  89. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/iter.pyx +0 -0
  90. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/__init__.pxd +0 -0
  91. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/__init__.py +0 -0
  92. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_debug.pyi +0 -0
  93. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_loggable.c +0 -0
  94. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_loggable.pxd +0 -0
  95. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_loggable.pyi +0 -0
  96. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/_loggable.pyx +0 -0
  97. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/__init__.pxd +0 -0
  98. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/__init__.py +0 -0
  99. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/counter.pxd +0 -0
  100. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/counter.pyi +0 -0
  101. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/counter.pyx +0 -0
  102. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/event.pxd +0 -0
  103. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/event.pyi +0 -0
  104. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/event.pyx +0 -0
  105. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/prio_semaphore.pxd +0 -0
  106. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/prio_semaphore.pyi +0 -0
  107. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/prio_semaphore.pyx +0 -0
  108. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/semaphore.pxd +0 -0
  109. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/semaphore.pyi +0 -0
  110. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/locks/semaphore.pyx +0 -0
  111. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/primitives/queue.py +0 -0
  112. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/py.typed +0 -0
  113. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/sphinx/__init__.py +0 -0
  114. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/sphinx/ext.py +0 -0
  115. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/task.py +0 -0
  116. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/utils/__init__.py +0 -0
  117. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/a_sync/utils/iterators.py +0 -0
  118. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/Makefile +0 -0
  119. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/alabaster.css +0 -0
  120. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/basic.css +0 -0
  121. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/custom.css +0 -0
  122. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/doctools.js +0 -0
  123. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/documentation_options.js +0 -0
  124. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/file.png +0 -0
  125. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/language_data.js +0 -0
  126. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/minus.png +0 -0
  127. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/plus.png +0 -0
  128. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/pygments.css +0 -0
  129. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/searchtools.js +0 -0
  130. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/_build/html/_static/sphinx_highlight.js +0 -0
  131. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/conf.py +0 -0
  132. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/index.rst +0 -0
  133. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/docs/make.bat +0 -0
  134. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/ez_a_sync.egg-info/SOURCES.txt +0 -0
  135. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/ez_a_sync.egg-info/dependency_links.txt +0 -0
  136. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/ez_a_sync.egg-info/not-zip-safe +0 -0
  137. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/ez_a_sync.egg-info/requires.txt +0 -0
  138. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/ez_a_sync.egg-info/top_level.txt +0 -0
  139. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/pyproject.toml +0 -0
  140. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/requirements-dev.txt +0 -0
  141. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/requirements.txt +0 -0
  142. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/setup.cfg +0 -0
  143. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/setup.py +0 -0
  144. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/__init__.py +0 -0
  145. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/modifiers/test_apply_semaphore.py +0 -0
  146. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_abstract.py +0 -0
  147. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_base.py +0 -0
  148. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_cache.py +0 -0
  149. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_decorator.py +0 -0
  150. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_limiter.py +0 -0
  151. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_meta.py +0 -0
  152. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_modified.py +0 -0
  153. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/a_sync/test_singleton.py +0 -0
  154. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/asyncio/test_as_completed.py +0 -0
  155. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/asyncio/test_create_task.py +0 -0
  156. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/asyncio/test_gather.py +0 -0
  157. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/conftest.py +0 -0
  158. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/executor.py +0 -0
  159. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/fixtures.py +0 -0
  160. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/primitives/test_counter.py +0 -0
  161. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/primitives/test_event.py +0 -0
  162. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/primitives/test_prio_semaphore.py +0 -0
  163. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/primitives/test_queue.py +0 -0
  164. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/primitives/test_semaphore.py +0 -0
  165. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/task/test_task.py +0 -0
  166. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/task/test_task_mapping_views.py +0 -0
  167. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/test_executor.py +0 -0
  168. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/test_future.py +0 -0
  169. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/test_helpers.py +0 -0
  170. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/test_iter.py +0 -0
  171. {ez_a_sync-0.24.34 → ez_a_sync-0.24.35}/tests/test_smart.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ez-a-sync
3
- Version: 0.24.34
3
+ Version: 0.24.35
4
4
  Summary: A library that makes it easy to define objects that can be used for both sync and async use cases.
5
5
  Home-page: https://github.com/BobTheBuidler/a-sync
6
6
  Author: BobTheBuidler
@@ -20,6 +20,8 @@ import multiprocessing.context
20
20
  import queue
21
21
  import threading
22
22
  import weakref
23
+ from asyncio import sleep
24
+ from asyncio.futures import wrap_future, _convert_future_exc
23
25
  from concurrent.futures import _base, thread
24
26
  from functools import cached_property
25
27
 
@@ -32,6 +34,21 @@ TEN_MINUTES = 60 * 10
32
34
  Initializer = Callable[..., object]
33
35
 
34
36
 
37
+ def _copy_future_state(cf_fut: concurrent.futures.Future, fut: asyncio.Future):
38
+ """Internal helper to copy state from another Future.
39
+
40
+ The other Future may be a concurrent.futures.Future.
41
+ """
42
+ # check this again in case it was cancelled since the last check
43
+ if fut.cancelled():
44
+ return
45
+ exception = cf_fut.exception()
46
+ if exception is None:
47
+ fut.set_result(cf_fut.result())
48
+ else:
49
+ fut.set_exception(_convert_future_exc(exception))
50
+
51
+
35
52
  class _AsyncExecutorMixin(concurrent.futures.Executor, _DebugDaemonMixin):
36
53
  """
37
54
  A mixin for Executors to provide asynchronous run and submit methods.
@@ -49,6 +66,15 @@ class _AsyncExecutorMixin(concurrent.futures.Executor, _DebugDaemonMixin):
49
66
  - :meth:`submit` for submitting functions to the executor.
50
67
  """
51
68
 
69
+ sync_mode: bool
70
+ """
71
+ Indicates if the executor is in synchronous mode (max_workers == 0).
72
+
73
+ Examples:
74
+ >>> if executor.sync_mode:
75
+ >>> print("Executor is in synchronous mode.")
76
+ """
77
+
52
78
  _max_workers: int
53
79
 
54
80
  _workers: str
@@ -96,15 +122,35 @@ class _AsyncExecutorMixin(concurrent.futures.Executor, _DebugDaemonMixin):
96
122
  See Also:
97
123
  - :meth:`run` for running functions with the executor.
98
124
  """
125
+ fut = self._create_future()
99
126
  if self.sync_mode:
100
- fut = self._get_loop().create_future()
101
127
  try:
102
128
  fut.set_result(fn(*args, **kwargs))
103
129
  except Exception as e:
104
130
  fut.set_exception(e)
105
131
  else:
106
- fut = asyncio.futures.wrap_future(super().submit(fn, *args, **kwargs)) # type: ignore [assignment]
107
- self._start_debug_daemon(fut, fn, *args, **kwargs)
132
+ self._ensure_debug_daemon(fut, fn, *args, **kwargs)
133
+
134
+ cf_fut = self._super_submit(fn, *args, **kwargs)
135
+
136
+ # TODO: implement logic to actually cancel the job, not just the future which is useless for our use case
137
+ # def _call_check_cancel(destination: asyncio.Future):
138
+ # if destination.cancelled():
139
+ # cf_fut.cancel()
140
+ #
141
+ # fut.add_done_callback(_call_check_cancel)
142
+
143
+ def _call_copy_future_state(cf_fut: "concurrent.futures.Future"):
144
+ if fut.cancelled():
145
+ return
146
+ self._call_soon_threadsafe(
147
+ _copy_future_state,
148
+ cf_fut,
149
+ fut,
150
+ )
151
+
152
+ cf_fut.add_done_callback(_call_copy_future_state)
153
+
108
154
  return fut
109
155
 
110
156
  def __repr__(self) -> str:
@@ -114,17 +160,6 @@ class _AsyncExecutorMixin(concurrent.futures.Executor, _DebugDaemonMixin):
114
160
  # NOTE: should this be queue length instead? probably
115
161
  return self.worker_count_current
116
162
 
117
- @cached_property
118
- def sync_mode(self) -> bool:
119
- """
120
- Indicates if the executor is in synchronous mode (max_workers == 0).
121
-
122
- Examples:
123
- >>> if executor.sync_mode:
124
- >>> print("Executor is in synchronous mode.")
125
- """
126
- return self._max_workers == 0
127
-
128
163
  @property
129
164
  def worker_count_current(self) -> int:
130
165
  """
@@ -135,6 +170,13 @@ class _AsyncExecutorMixin(concurrent.futures.Executor, _DebugDaemonMixin):
135
170
  """
136
171
  return len(getattr(self, f"_{self._workers}"))
137
172
 
173
+ def __init_mixin__(self):
174
+ self.sync_mode = self._max_workers == 0
175
+ loop = self._get_loop()
176
+ self._create_future = loop.create_future
177
+ self._super_submit = super().submit
178
+ self._call_soon_threadsafe = loop.call_soon_threadsafe
179
+
138
180
  async def _debug_daemon(self, fut: asyncio.Future, fn, *args, **kwargs) -> None:
139
181
  """
140
182
  Runs until manually cancelled by the finished work item.
@@ -162,10 +204,13 @@ class _AsyncExecutorMixin(concurrent.futures.Executor, _DebugDaemonMixin):
162
204
  else:
163
205
  msg = f"{msg[:-2]})"
164
206
 
165
- while not fut.done():
166
- await asyncio.sleep(15)
167
- if not fut.done():
168
- self.logger.debug(msg, self, fnid)
207
+ done = fut.done
208
+ log_debug = self.logger.debug
209
+
210
+ while not done():
211
+ await sleep(15)
212
+ if not done():
213
+ log_debug(msg, self, fnid)
169
214
 
170
215
 
171
216
  # Process
@@ -224,6 +269,7 @@ class AsyncProcessPoolExecutor(_AsyncExecutorMixin, concurrent.futures.ProcessPo
224
269
  self._max_workers = 0
225
270
  else:
226
271
  super().__init__(max_workers, mp_context, initializer, initargs)
272
+ self.__init_mixin__()
227
273
 
228
274
 
229
275
  # Thread
@@ -277,6 +323,7 @@ class AsyncThreadPoolExecutor(_AsyncExecutorMixin, concurrent.futures.ThreadPool
277
323
  self._max_workers = 0
278
324
  else:
279
325
  super().__init__(max_workers, thread_name_prefix, initializer, initargs)
326
+ self.__init_mixin__()
280
327
 
281
328
 
282
329
  # For backward-compatibility