shellsim 0.1.14__tar.gz → 0.1.16__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.
Files changed (183) hide show
  1. {shellsim-0.1.14 → shellsim-0.1.16}/Cargo.lock +1 -1
  2. {shellsim-0.1.14 → shellsim-0.1.16}/Cargo.toml +1 -1
  3. {shellsim-0.1.14 → shellsim-0.1.16}/PKG-INFO +1 -1
  4. {shellsim-0.1.14 → shellsim-0.1.16}/python/native/Cargo.lock +2 -2
  5. {shellsim-0.1.14 → shellsim-0.1.16}/python/native/Cargo.toml +1 -1
  6. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/compiler.rs +0 -2
  7. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/heap.rs +6 -1
  8. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/asyncio.py +182 -38
  9. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/calls.rs +1 -0
  10. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/iteration.rs +43 -22
  11. {shellsim-0.1.14 → shellsim-0.1.16}/LICENSE +0 -0
  12. {shellsim-0.1.14 → shellsim-0.1.16}/README.md +0 -0
  13. {shellsim-0.1.14 → shellsim-0.1.16}/pyproject.toml +0 -0
  14. {shellsim-0.1.14 → shellsim-0.1.16}/python/native/src/lib.rs +0 -0
  15. {shellsim-0.1.14 → shellsim-0.1.16}/python/shellsim/__init__.py +0 -0
  16. {shellsim-0.1.14 → shellsim-0.1.16}/python/shellsim/__main__.py +0 -0
  17. {shellsim-0.1.14 → shellsim-0.1.16}/python/shellsim/_api.py +0 -0
  18. {shellsim-0.1.14 → shellsim-0.1.16}/python/shellsim/_cli.py +0 -0
  19. {shellsim-0.1.14 → shellsim-0.1.16}/python/shellsim/py.typed +0 -0
  20. {shellsim-0.1.14 → shellsim-0.1.16}/python/shellsim/python.py +0 -0
  21. {shellsim-0.1.14 → shellsim-0.1.16}/rust-toolchain.toml +0 -0
  22. {shellsim-0.1.14 → shellsim-0.1.16}/src/bin/shellsim-python.rs +0 -0
  23. {shellsim-0.1.14 → shellsim-0.1.16}/src/clock.rs +0 -0
  24. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/archives.rs +0 -0
  25. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/awk/ast.rs +0 -0
  26. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/awk/eval.rs +0 -0
  27. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/awk/lexer.rs +0 -0
  28. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/awk/parser.rs +0 -0
  29. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/awk.rs +0 -0
  30. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/builtins.rs +0 -0
  31. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/dd.rs +0 -0
  32. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/echo.rs +0 -0
  33. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/find.rs +0 -0
  34. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/fs.rs +0 -0
  35. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/apply.rs +0 -0
  36. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/commit.rs +0 -0
  37. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/compare.rs +0 -0
  38. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/config.rs +0 -0
  39. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/conflict.rs +0 -0
  40. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/diff.rs +0 -0
  41. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/ignore.rs +0 -0
  42. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/import.rs +0 -0
  43. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/log.rs +0 -0
  44. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/merge.rs +0 -0
  45. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/mod.rs +0 -0
  46. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/plumbing.rs +0 -0
  47. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/rebase.rs +0 -0
  48. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/refs.rs +0 -0
  49. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/repo.rs +0 -0
  50. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/stash.rs +0 -0
  51. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/switch.rs +0 -0
  52. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/git/worktree.rs +0 -0
  53. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/hashing.rs +0 -0
  54. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/makecmd.rs +0 -0
  55. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/mod.rs +0 -0
  56. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/net.rs +0 -0
  57. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/options.rs +0 -0
  58. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/patch.rs +0 -0
  59. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/pkg.rs +0 -0
  60. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/printf.rs +0 -0
  61. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/proc.rs +0 -0
  62. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/regex_compat.rs +0 -0
  63. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/rgcmd.rs +0 -0
  64. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/sed.rs +0 -0
  65. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/sort.rs +0 -0
  66. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/system.rs +0 -0
  67. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/tarcmd.rs +0 -0
  68. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/text.rs +0 -0
  69. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/unavailable.rs +0 -0
  70. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/util.rs +0 -0
  71. {shellsim-0.1.14 → shellsim-0.1.16}/src/commands/zipcmd.rs +0 -0
  72. {shellsim-0.1.14 → shellsim-0.1.16}/src/descriptors.rs +0 -0
  73. {shellsim-0.1.14 → shellsim-0.1.16}/src/exec.rs +0 -0
  74. {shellsim-0.1.14 → shellsim-0.1.16}/src/expand.rs +0 -0
  75. {shellsim-0.1.14 → shellsim-0.1.16}/src/harness.rs +0 -0
  76. {shellsim-0.1.14 → shellsim-0.1.16}/src/harness_manager.rs +0 -0
  77. {shellsim-0.1.14 → shellsim-0.1.16}/src/hashes.rs +0 -0
  78. {shellsim-0.1.14 → shellsim-0.1.16}/src/host_ingest.rs +0 -0
  79. {shellsim-0.1.14 → shellsim-0.1.16}/src/interp.rs +0 -0
  80. {shellsim-0.1.14 → shellsim-0.1.16}/src/jqcmd.rs +0 -0
  81. {shellsim-0.1.14 → shellsim-0.1.16}/src/lib.rs +0 -0
  82. {shellsim-0.1.14 → shellsim-0.1.16}/src/main.rs +0 -0
  83. {shellsim-0.1.14 → shellsim-0.1.16}/src/mcp.rs +0 -0
  84. {shellsim-0.1.14 → shellsim-0.1.16}/src/net.rs +0 -0
  85. {shellsim-0.1.14 → shellsim-0.1.16}/src/netcmd.rs +0 -0
  86. {shellsim-0.1.14 → shellsim-0.1.16}/src/process.rs +0 -0
  87. {shellsim-0.1.14 → shellsim-0.1.16}/src/pseudo_fs.rs +0 -0
  88. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/ast.rs +0 -0
  89. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/bytecode.rs +0 -0
  90. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/filesystem.rs +0 -0
  91. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/http.rs +0 -0
  92. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/lexer.rs +0 -0
  93. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/mapping.rs +0 -0
  94. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/mod.rs +0 -0
  95. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/native.rs +0 -0
  96. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/number.rs +0 -0
  97. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/object_model.rs +0 -0
  98. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/parser.rs +0 -0
  99. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/process.rs +0 -0
  100. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/protocol.rs +0 -0
  101. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/slice.rs +0 -0
  102. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/source.rs +0 -0
  103. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/argparse.rs +0 -0
  104. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/asyncio.rs +0 -0
  105. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/base64.rs +0 -0
  106. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/bisect.rs +0 -0
  107. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/collections.rs +0 -0
  108. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/core.rs +0 -0
  109. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/dataclasses.rs +0 -0
  110. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/enum.rs +0 -0
  111. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/frozen.rs +0 -0
  112. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/functools.rs +0 -0
  113. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/hashlib.rs +0 -0
  114. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/heapq.rs +0 -0
  115. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/http.rs +0 -0
  116. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/importlib.rs +0 -0
  117. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/itertools.rs +0 -0
  118. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/json.rs +0 -0
  119. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/math.rs +0 -0
  120. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/mod.rs +0 -0
  121. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/numpy.rs +0 -0
  122. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/os.rs +0 -0
  123. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/pytest.rs +0 -0
  124. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/re.rs +0 -0
  125. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/abc.py +0 -0
  126. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/base64.py +0 -0
  127. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/cmath.py +0 -0
  128. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/codecs.py +0 -0
  129. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/collections.py +0 -0
  130. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/complex.py +0 -0
  131. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/copy.py +0 -0
  132. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/csv.py +0 -0
  133. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/datetime.py +0 -0
  134. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/glob.py +0 -0
  135. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/hashlib.py +0 -0
  136. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/http.py +0 -0
  137. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/http_client.py +0 -0
  138. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/importlib.py +0 -0
  139. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/io.py +0 -0
  140. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/json.py +0 -0
  141. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/logging.py +0 -0
  142. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/numpy_random.py +0 -0
  143. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/os.py +0 -0
  144. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/pathlib.py +0 -0
  145. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/pytest.py +0 -0
  146. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/random.py +0 -0
  147. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/shutil.py +0 -0
  148. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/statistics.py +0 -0
  149. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/struct.py +0 -0
  150. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/subprocess.py +0 -0
  151. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/tempfile.py +0 -0
  152. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/textwrap.py +0 -0
  153. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/urllib.py +0 -0
  154. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/urllib_error.py +0 -0
  155. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/urllib_request.py +0 -0
  156. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/uuid.py +0 -0
  157. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/zipfile.py +0 -0
  158. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/source/zlib.py +0 -0
  159. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/string.rs +0 -0
  160. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/struct.rs +0 -0
  161. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/subprocess.rs +0 -0
  162. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/sys.rs +0 -0
  163. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/time.rs +0 -0
  164. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/typing.rs +0 -0
  165. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/unittest.rs +0 -0
  166. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/vfs.rs +0 -0
  167. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/stdlib/zlib.rs +0 -0
  168. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/string.rs +0 -0
  169. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/token.rs +0 -0
  170. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/dispatch.rs +0 -0
  171. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/host.rs +0 -0
  172. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/namespace.rs +0 -0
  173. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/native_runtime.rs +0 -0
  174. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/objects.rs +0 -0
  175. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm/operations.rs +0 -0
  176. {shellsim-0.1.14 → shellsim-0.1.16}/src/python/vm.rs +0 -0
  177. {shellsim-0.1.14 → shellsim-0.1.16}/src/resources.rs +0 -0
  178. {shellsim-0.1.14 → shellsim-0.1.16}/src/sandbox.rs +0 -0
  179. {shellsim-0.1.14 → shellsim-0.1.16}/src/scenario.rs +0 -0
  180. {shellsim-0.1.14 → shellsim-0.1.16}/src/scheduler.rs +0 -0
  181. {shellsim-0.1.14 → shellsim-0.1.16}/src/shell.rs +0 -0
  182. {shellsim-0.1.14 → shellsim-0.1.16}/src/telemetry.rs +0 -0
  183. {shellsim-0.1.14 → shellsim-0.1.16}/src/vfs.rs +0 -0
@@ -330,7 +330,7 @@ dependencies = [
330
330
 
331
331
  [[package]]
332
332
  name = "shellsim"
333
- version = "0.1.14"
333
+ version = "0.1.16"
334
334
  dependencies = [
335
335
  "base64",
336
336
  "crc32fast",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "shellsim"
3
- version = "0.1.14"
3
+ version = "0.1.16"
4
4
  edition = "2021"
5
5
  description = "In-process BusyBox-like environment for RL rollouts and agent tests"
6
6
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shellsim
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: License :: OSI Approved :: Apache Software License
6
6
  Classifier: Operating System :: MacOS :: MacOS X
@@ -406,7 +406,7 @@ dependencies = [
406
406
 
407
407
  [[package]]
408
408
  name = "shellsim"
409
- version = "0.1.14"
409
+ version = "0.1.16"
410
410
  dependencies = [
411
411
  "base64",
412
412
  "crc32fast",
@@ -427,7 +427,7 @@ dependencies = [
427
427
 
428
428
  [[package]]
429
429
  name = "shellsim-python-bindings"
430
- version = "0.1.14"
430
+ version = "0.1.16"
431
431
  dependencies = [
432
432
  "pyo3",
433
433
  "serde",
@@ -2,7 +2,7 @@
2
2
 
3
3
  [package]
4
4
  name = "shellsim-python-bindings"
5
- version = "0.1.14"
5
+ version = "0.1.16"
6
6
  edition = "2021"
7
7
  description = "Python bindings for shellsim"
8
8
  license = "Apache-2.0"
@@ -659,8 +659,6 @@ impl Compiler {
659
659
  self.protected_regions.pop();
660
660
  if let Some(handler_body_try) = handler_body_try {
661
661
  self.emit(Operation::TryEnd, span);
662
- self.emit(Operation::ClearException, span);
663
- self.statements(finalbody.clone());
664
662
  let handler_body_done = self.emit(Operation::Jump(usize::MAX), span);
665
663
  let handler_body_cleanup = self.instructions.len();
666
664
  self.patch_try_begin(handler_body_try, handler_body_cleanup);
@@ -202,13 +202,14 @@ pub enum Object {
202
202
  exhausted: bool,
203
203
  },
204
204
  /// A suspended Python generator frame. The bytecode is immutable; the instruction pointer,
205
- /// exception-handler stack, and lexical scope are the complete resumable state.
205
+ /// exception state, and lexical scope are the complete resumable state.
206
206
  Generator {
207
207
  name: String,
208
208
  code: CodeRef,
209
209
  scope: ScopeId,
210
210
  instruction_pointer: usize,
211
211
  handlers: Vec<(usize, usize)>,
212
+ exceptions: Vec<(String, Value)>,
212
213
  stack: Vec<Value>,
213
214
  exhausted: bool,
214
215
  running: bool,
@@ -1433,11 +1434,13 @@ fn trace_object(
1433
1434
  }
1434
1435
  Object::Generator {
1435
1436
  scope,
1437
+ exceptions,
1436
1438
  stack,
1437
1439
  return_value,
1438
1440
  ..
1439
1441
  } => {
1440
1442
  scope_work.push(*scope);
1443
+ trace_values(exceptions.iter().map(|(_, value)| *value), object_work);
1441
1444
  trace_values(stack.iter().copied(), object_work);
1442
1445
  trace_value(*return_value, object_work);
1443
1446
  }
@@ -1566,12 +1569,14 @@ fn modeled_size(object: &Object) -> Result<u64, String> {
1566
1569
  name,
1567
1570
  code,
1568
1571
  handlers,
1572
+ exceptions,
1569
1573
  stack,
1570
1574
  ..
1571
1575
  } => name
1572
1576
  .len()
1573
1577
  .checked_add(code.instructions.len())
1574
1578
  .and_then(|size| size.checked_add(handlers.len()))
1579
+ .and_then(|size| size.checked_add(exceptions.len()))
1575
1580
  .and_then(|size| size.checked_add(stack.len()))
1576
1581
  .ok_or("modeled object size overflow")?,
1577
1582
  Object::Module { name, .. } => name.len(),
@@ -197,6 +197,24 @@ class Future:
197
197
  self._loop._wake_waiters(self)
198
198
 
199
199
 
200
+ class _GatheringFuture(Future):
201
+ def __init__(self, children, *, loop):
202
+ Future.__init__(self, loop=loop)
203
+ self._children = children
204
+ self._cancel_requested = False
205
+
206
+ def cancel(self, msg=None):
207
+ if self._done:
208
+ return False
209
+ cancelled = False
210
+ for child in self._children:
211
+ if child.cancel(msg=msg):
212
+ cancelled = True
213
+ if cancelled:
214
+ self._cancel_requested = True
215
+ return cancelled
216
+
217
+
200
218
  class Task:
201
219
  def __init__(self, coroutine, loop, name=None):
202
220
  if not _is_coroutine(coroutine):
@@ -214,6 +232,7 @@ class Task:
214
232
  self._name = name
215
233
  self._callbacks = []
216
234
  self._cancel_requests = 0
235
+ self._must_cancel = False
217
236
  self._logical_task = self
218
237
 
219
238
  def done(self):
@@ -251,6 +270,8 @@ class Task:
251
270
  def uncancel(self):
252
271
  if self._cancel_requests:
253
272
  self._cancel_requests -= 1
273
+ if not self._cancel_requests:
274
+ self._must_cancel = False
254
275
  return self._cancel_requests
255
276
 
256
277
  def add_done_callback(self, callback, context=None):
@@ -686,8 +707,12 @@ class _Loop:
686
707
  self._resource_waiters = []
687
708
  self._tasks = []
688
709
  self._current = None
710
+ self._running = False
711
+ self._closed = False
689
712
 
690
713
  def create_task(self, coroutine, name=None):
714
+ if self._closed:
715
+ raise RuntimeError("Event loop is closed")
691
716
  task = Task(coroutine, self, name)
692
717
  self._tasks.append(task)
693
718
  self._ready.append(task)
@@ -705,6 +730,8 @@ class _Loop:
705
730
  return _monotonic_ns() / 1000000000
706
731
 
707
732
  def call_soon(self, callback, *args, context=None):
733
+ if self._closed:
734
+ raise RuntimeError("Event loop is closed")
708
735
  handle = Handle(callback, args)
709
736
  self._ready.append(handle)
710
737
  return handle
@@ -713,6 +740,8 @@ class _Loop:
713
740
  return self.call_soon(callback, *args, context=context)
714
741
 
715
742
  def call_at(self, when, callback, *args, context=None):
743
+ if self._closed:
744
+ raise RuntimeError("Event loop is closed")
716
745
  handle = TimerHandle(when, callback, args)
717
746
  self._timers.append((int(when * 1000000000), handle))
718
747
  return handle
@@ -726,7 +755,8 @@ class _Loop:
726
755
  waiter for waiter in self._resource_waiters if waiter[0] is not task
727
756
  ]
728
757
  task._send_value = (True, value)
729
- self._ready.append(task)
758
+ if task not in self._ready:
759
+ self._ready.append(task)
730
760
 
731
761
  def _schedule_failure(self, task, error):
732
762
  if not task._done:
@@ -734,10 +764,17 @@ class _Loop:
734
764
  waiter for waiter in self._resource_waiters if waiter[0] is not task
735
765
  ]
736
766
  task._send_value = (False, error)
737
- self._ready.append(task)
767
+ if task not in self._ready:
768
+ self._ready.append(task)
738
769
 
739
770
  def _cancel(self, task):
740
- if isinstance(task._waiting_on, Future) and task._waiting_on.cancel():
771
+ if self._current is task:
772
+ task._must_cancel = True
773
+ return
774
+ dependency = task._waiting_on
775
+ if isinstance(dependency, (Task, Future)) and dependency.cancel():
776
+ return
777
+ if isinstance(dependency, _TimeoutWait) and dependency.child.cancel():
741
778
  return
742
779
  if not task._started:
743
780
  task._done = True
@@ -856,8 +893,7 @@ class _Loop:
856
893
  else:
857
894
  self._schedule(task, awaited._result)
858
895
  else:
859
- if isinstance(awaited, Future):
860
- task._waiting_on = awaited
896
+ task._waiting_on = awaited
861
897
  awaited._waiters.append(task)
862
898
 
863
899
  def _dispatch_yield(self, task, awaited):
@@ -905,30 +941,83 @@ class _Loop:
905
941
  raise TypeError("object cannot be used in 'await' expression")
906
942
 
907
943
  def run(self, coroutine):
944
+ if self._closed:
945
+ raise RuntimeError("Event loop is closed")
946
+ if self._running:
947
+ raise RuntimeError("This event loop is already running")
908
948
  root = self.create_task(coroutine)
909
- while not root.done():
910
- if not self._ready:
911
- self._wake_due_timers()
912
- if not self._ready:
913
- self._wait_for_resources()
914
- task = self._ready.pop(0)
915
- if isinstance(task, Handle):
916
- task._run()
917
- continue
918
- if task._done:
919
- continue
920
- task._started = True
921
- self._current = task
922
- status, value = _step(task._coroutine, task._send_value)
949
+ self._running = True
950
+ try:
951
+ while not root.done():
952
+ if not self._ready:
953
+ self._wake_due_timers()
954
+ if not self._ready:
955
+ self._wait_for_resources()
956
+ task = self._ready.pop(0)
957
+ if isinstance(task, Handle):
958
+ task._run()
959
+ continue
960
+ if task._done:
961
+ continue
962
+ task._started = True
963
+ self._current = task
964
+ status, value = _step(task._coroutine, task._send_value)
965
+ self._current = None
966
+ task._send_value = None
967
+ if status == 1:
968
+ self._finish(task, value)
969
+ elif status == 2:
970
+ self._fail(task, value)
971
+ elif task._must_cancel:
972
+ task._must_cancel = False
973
+ self._schedule_failure(task, CancelledError())
974
+ else:
975
+ self._dispatch_yield(task, value)
976
+ return root.result()
977
+ finally:
923
978
  self._current = None
924
- task._send_value = None
925
- if status == 1:
926
- self._finish(task, value)
927
- elif status == 2:
928
- self._fail(task, value)
929
- else:
930
- self._dispatch_yield(task, value)
931
- return root.result()
979
+ self._running = False
980
+
981
+ def run_until_complete(self, awaitable):
982
+ async def wait_for_awaitable():
983
+ return await awaitable
984
+
985
+ return self.run(wait_for_awaitable())
986
+
987
+ def is_running(self):
988
+ return self._running
989
+
990
+ def is_closed(self):
991
+ return self._closed
992
+
993
+ async def shutdown_asyncgens(self):
994
+ return None
995
+
996
+ async def shutdown_default_executor(self, timeout=None):
997
+ return None
998
+
999
+ def _shutdown(self):
1000
+ pending = [task for task in self._tasks if not task.done()]
1001
+ if not pending:
1002
+ return
1003
+ for task in pending:
1004
+ task.cancel()
1005
+
1006
+ async def wait_for_pending():
1007
+ await gather(*pending, return_exceptions=True)
1008
+
1009
+ self.run(wait_for_pending())
1010
+
1011
+ def close(self):
1012
+ if self._running:
1013
+ raise RuntimeError("Cannot close a running event loop")
1014
+ if self._closed:
1015
+ return
1016
+ self._closed = True
1017
+ self._ready = []
1018
+ self._timers = []
1019
+ self._resource_waiters = []
1020
+ self._tasks = []
932
1021
 
933
1022
 
934
1023
  def get_running_loop():
@@ -978,17 +1067,50 @@ async def sleep(delay, result=None):
978
1067
  return result
979
1068
 
980
1069
 
981
- async def gather(*coroutines, return_exceptions=False):
1070
+ def gather(*coroutines, return_exceptions=False):
982
1071
  tasks = [_ensure_task(coroutine) for coroutine in coroutines]
983
- results = []
1072
+ observed = []
984
1073
  for task in tasks:
985
- try:
986
- results.append(await task)
987
- except Exception as error:
1074
+ if task not in observed:
1075
+ observed.append(task)
1076
+ loop = get_running_loop()
1077
+ outer = _GatheringFuture(observed, loop=loop)
1078
+ if not tasks:
1079
+ outer.set_result([])
1080
+ return outer
1081
+
1082
+ results = [None for task in tasks]
1083
+ completed = [False for task in tasks]
1084
+
1085
+ def child_completed(child):
1086
+ if outer.done():
1087
+ return
1088
+ if outer._cancel_requested:
1089
+ if all(task.done() for task in observed):
1090
+ outer.set_exception(CancelledError())
1091
+ return
1092
+ if child.cancelled():
1093
+ if not return_exceptions:
1094
+ outer.set_exception(CancelledError())
1095
+ return
1096
+ result = CancelledError()
1097
+ elif child.exception() is not None:
988
1098
  if not return_exceptions:
989
- raise
990
- results.append(error)
991
- return results
1099
+ outer.set_exception(child.exception())
1100
+ return
1101
+ result = child.exception()
1102
+ else:
1103
+ result = child.result()
1104
+ for index in range(len(tasks)):
1105
+ if tasks[index] is child:
1106
+ completed[index] = True
1107
+ results[index] = result
1108
+ if all(completed):
1109
+ outer.set_result(results)
1110
+
1111
+ for task in observed:
1112
+ task.add_done_callback(child_completed)
1113
+ return outer
992
1114
 
993
1115
 
994
1116
  async def wait_for(awaitable, timeout):
@@ -1147,8 +1269,24 @@ def as_completed(awaitables, timeout=None):
1147
1269
  yield next_result()
1148
1270
 
1149
1271
 
1150
- async def shield(awaitable):
1151
- return await _ensure_task(awaitable)
1272
+ def shield(awaitable):
1273
+ inner = _ensure_task(awaitable)
1274
+ if inner.done():
1275
+ return inner
1276
+ outer = get_running_loop().create_future()
1277
+
1278
+ def inner_completed(completed):
1279
+ if outer.done():
1280
+ return
1281
+ if completed.cancelled():
1282
+ outer.cancel()
1283
+ elif completed.exception() is not None:
1284
+ outer.set_exception(completed.exception())
1285
+ else:
1286
+ outer.set_result(completed.result())
1287
+
1288
+ inner.add_done_callback(inner_completed)
1289
+ return outer
1152
1290
 
1153
1291
 
1154
1292
  async def create_subprocess_exec(program, *args, stdin=None, stdout=None, stderr=None,
@@ -1193,4 +1331,10 @@ def run(coroutine):
1193
1331
  try:
1194
1332
  return loop.run(coroutine)
1195
1333
  finally:
1196
- _running_loop = None
1334
+ try:
1335
+ loop._shutdown()
1336
+ loop.run(loop.shutdown_asyncgens())
1337
+ loop.run(loop.shutdown_default_executor())
1338
+ finally:
1339
+ loop.close()
1340
+ _running_loop = None
@@ -1179,6 +1179,7 @@ impl Vm<'_> {
1179
1179
  scope,
1180
1180
  instruction_pointer: 0,
1181
1181
  handlers: Vec::new(),
1182
+ exceptions: Vec::new(),
1182
1183
  stack: Vec::new(),
1183
1184
  exhausted: false,
1184
1185
  running: false,
@@ -274,28 +274,38 @@ impl Vm<'_> {
274
274
  if self.call_depth >= MAX_GENERATOR_DEPTH {
275
275
  return Err("maximum recursion depth exceeded".into());
276
276
  }
277
- let (code, scope, instruction_pointer, mut handlers, frame_stack, exhausted, running) =
278
- match self.state.heap.get(id)?.clone() {
279
- Object::Generator {
280
- code,
281
- scope,
282
- instruction_pointer,
283
- handlers,
284
- stack,
285
- exhausted,
286
- running,
287
- ..
288
- } => (
289
- code,
290
- scope,
291
- instruction_pointer,
292
- handlers,
293
- stack,
294
- exhausted,
295
- running,
296
- ),
297
- _ => return Err("object is not a generator".into()),
298
- };
277
+ let (
278
+ code,
279
+ scope,
280
+ instruction_pointer,
281
+ mut handlers,
282
+ exceptions,
283
+ frame_stack,
284
+ exhausted,
285
+ running,
286
+ ) = match self.state.heap.get(id)?.clone() {
287
+ Object::Generator {
288
+ code,
289
+ scope,
290
+ instruction_pointer,
291
+ handlers,
292
+ exceptions,
293
+ stack,
294
+ exhausted,
295
+ running,
296
+ ..
297
+ } => (
298
+ code,
299
+ scope,
300
+ instruction_pointer,
301
+ handlers,
302
+ exceptions,
303
+ stack,
304
+ exhausted,
305
+ running,
306
+ ),
307
+ _ => return Err("object is not a generator".into()),
308
+ };
299
309
  if exhausted {
300
310
  return Ok(None);
301
311
  }
@@ -313,11 +323,20 @@ impl Vm<'_> {
313
323
  if instruction_pointer != 0 {
314
324
  self.stack.push(sent);
315
325
  }
326
+ let generator_exceptions = exceptions
327
+ .into_iter()
328
+ .map(|(kind, value)| super::RaisedException { kind, value })
329
+ .collect();
330
+ let outer_exceptions = std::mem::replace(&mut self.exception_stack, generator_exceptions);
316
331
  self.local_scopes.push(scope);
317
332
  self.call_depth += 1;
318
333
  let result = self.execute_code_from(&code, instruction_pointer, &mut handlers, 0);
319
334
  self.call_depth -= 1;
320
335
  self.local_scopes.pop();
336
+ let generator_exceptions = std::mem::replace(&mut self.exception_stack, outer_exceptions)
337
+ .into_iter()
338
+ .map(|exception| (exception.kind, exception.value))
339
+ .collect();
321
340
  let frame_result_stack = std::mem::take(&mut self.stack);
322
341
  self.stack = outer_stack;
323
342
 
@@ -328,6 +347,7 @@ impl Vm<'_> {
328
347
  if let Object::Generator {
329
348
  instruction_pointer,
330
349
  handlers: saved_handlers,
350
+ exceptions: saved_exceptions,
331
351
  stack: saved_stack,
332
352
  running,
333
353
  ..
@@ -335,6 +355,7 @@ impl Vm<'_> {
335
355
  {
336
356
  *instruction_pointer = next_instruction;
337
357
  *saved_handlers = handlers;
358
+ *saved_exceptions = generator_exceptions;
338
359
  *saved_stack = frame_result_stack;
339
360
  *running = false;
340
361
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes