shellsim 0.1.13__tar.gz → 0.1.14__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.
- {shellsim-0.1.13 → shellsim-0.1.14}/Cargo.lock +1 -1
- {shellsim-0.1.13 → shellsim-0.1.14}/Cargo.toml +1 -1
- {shellsim-0.1.13 → shellsim-0.1.14}/PKG-INFO +1 -1
- {shellsim-0.1.13 → shellsim-0.1.14}/python/native/Cargo.lock +2 -2
- {shellsim-0.1.13 → shellsim-0.1.14}/python/native/Cargo.toml +1 -1
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/protocol.rs +63 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/asyncio.py +190 -28
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/calls.rs +14 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/LICENSE +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/README.md +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/pyproject.toml +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/python/native/src/lib.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/python/shellsim/__init__.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/python/shellsim/__main__.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/python/shellsim/_api.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/python/shellsim/_cli.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/python/shellsim/py.typed +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/python/shellsim/python.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/rust-toolchain.toml +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/bin/shellsim-python.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/clock.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/archives.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/awk/ast.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/awk/eval.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/awk/lexer.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/awk/parser.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/awk.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/builtins.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/dd.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/echo.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/find.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/fs.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/apply.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/commit.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/compare.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/config.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/conflict.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/diff.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/ignore.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/import.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/log.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/merge.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/mod.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/plumbing.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/rebase.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/refs.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/repo.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/stash.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/switch.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/git/worktree.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/hashing.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/makecmd.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/mod.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/net.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/options.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/patch.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/pkg.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/printf.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/proc.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/regex_compat.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/rgcmd.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/sed.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/sort.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/system.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/tarcmd.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/text.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/unavailable.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/util.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/commands/zipcmd.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/descriptors.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/exec.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/expand.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/harness.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/harness_manager.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/hashes.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/host_ingest.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/interp.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/jqcmd.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/lib.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/main.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/mcp.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/net.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/netcmd.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/process.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/pseudo_fs.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/ast.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/bytecode.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/compiler.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/filesystem.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/heap.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/http.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/lexer.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/mapping.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/mod.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/native.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/number.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/object_model.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/parser.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/process.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/slice.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/source.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/argparse.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/asyncio.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/base64.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/bisect.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/collections.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/core.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/dataclasses.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/enum.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/frozen.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/functools.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/hashlib.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/heapq.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/http.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/importlib.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/itertools.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/json.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/math.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/mod.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/numpy.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/os.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/pytest.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/re.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/abc.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/base64.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/cmath.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/codecs.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/collections.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/complex.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/copy.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/csv.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/datetime.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/glob.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/hashlib.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/http.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/http_client.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/importlib.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/io.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/json.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/logging.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/numpy_random.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/os.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/pathlib.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/pytest.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/random.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/shutil.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/statistics.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/struct.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/subprocess.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/tempfile.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/textwrap.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/urllib.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/urllib_error.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/urllib_request.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/uuid.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/zipfile.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/source/zlib.py +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/string.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/struct.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/subprocess.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/sys.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/time.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/typing.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/unittest.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/vfs.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/stdlib/zlib.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/string.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/token.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/dispatch.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/host.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/iteration.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/namespace.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/native_runtime.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/objects.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm/operations.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/python/vm.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/resources.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/sandbox.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/scenario.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/scheduler.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/shell.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/telemetry.rs +0 -0
- {shellsim-0.1.13 → shellsim-0.1.14}/src/vfs.rs +0 -0
|
@@ -406,7 +406,7 @@ dependencies = [
|
|
|
406
406
|
|
|
407
407
|
[[package]]
|
|
408
408
|
name = "shellsim"
|
|
409
|
-
version = "0.1.
|
|
409
|
+
version = "0.1.14"
|
|
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.
|
|
430
|
+
version = "0.1.14"
|
|
431
431
|
dependencies = [
|
|
432
432
|
"pyo3",
|
|
433
433
|
"serde",
|
|
@@ -20,6 +20,25 @@ pub fn display(heap: &Heap, value: &Value) -> Result<String, String> {
|
|
|
20
20
|
if let Some((kind, message)) = exception_parts(heap, value)? {
|
|
21
21
|
return Ok(if message.is_empty() { kind } else { message });
|
|
22
22
|
}
|
|
23
|
+
if let Some((_, args)) = user_exception_parts(heap, value)? {
|
|
24
|
+
return match args.as_slice() {
|
|
25
|
+
[] => Ok(String::new()),
|
|
26
|
+
[only] => {
|
|
27
|
+
if let Some(value) = string_value(heap, only)? {
|
|
28
|
+
Ok(value)
|
|
29
|
+
} else {
|
|
30
|
+
repr(heap, only)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
_ => {
|
|
34
|
+
let values = args
|
|
35
|
+
.iter()
|
|
36
|
+
.map(|value| repr(heap, value))
|
|
37
|
+
.collect::<Result<Vec<_>, _>>()?;
|
|
38
|
+
Ok(format!("({})", values.join(", ")))
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
23
42
|
repr(heap, value)
|
|
24
43
|
}
|
|
25
44
|
|
|
@@ -100,6 +119,41 @@ pub fn exception_parts(heap: &Heap, value: &Value) -> Result<Option<(String, Str
|
|
|
100
119
|
})
|
|
101
120
|
}
|
|
102
121
|
|
|
122
|
+
fn user_exception_parts(
|
|
123
|
+
heap: &Heap,
|
|
124
|
+
value: &Value,
|
|
125
|
+
) -> Result<Option<(String, Vec<Value>)>, String> {
|
|
126
|
+
let Some(id) = value.object_id() else {
|
|
127
|
+
return Ok(None);
|
|
128
|
+
};
|
|
129
|
+
let Object::Instance { class, .. } = heap.get(id)? else {
|
|
130
|
+
return Ok(None);
|
|
131
|
+
};
|
|
132
|
+
let Object::Class {
|
|
133
|
+
name,
|
|
134
|
+
exception_base,
|
|
135
|
+
..
|
|
136
|
+
} = heap.get(*class)?
|
|
137
|
+
else {
|
|
138
|
+
return Ok(None);
|
|
139
|
+
};
|
|
140
|
+
if exception_base.is_none() {
|
|
141
|
+
return Ok(None);
|
|
142
|
+
}
|
|
143
|
+
let args = if let Some(symbol) = heap.symbol_id("args") {
|
|
144
|
+
heap.attribute_by_symbol(id, symbol)?
|
|
145
|
+
.and_then(|value| value.object_id())
|
|
146
|
+
.and_then(|args| match heap.get(args).ok()? {
|
|
147
|
+
Object::Tuple(values) => Some(values.clone()),
|
|
148
|
+
_ => None,
|
|
149
|
+
})
|
|
150
|
+
.unwrap_or_default()
|
|
151
|
+
} else {
|
|
152
|
+
Vec::new()
|
|
153
|
+
};
|
|
154
|
+
Ok(Some((name.clone(), args)))
|
|
155
|
+
}
|
|
156
|
+
|
|
103
157
|
fn bigint_value<'a>(heap: &'a Heap, value: &Value) -> Option<&'a BigInt> {
|
|
104
158
|
let id = value.object_id()?;
|
|
105
159
|
match heap.get(id).ok()? {
|
|
@@ -244,6 +298,15 @@ fn render(heap: &Heap, value: &Value, active: &mut BTreeSet<ObjectId>) -> Result
|
|
|
244
298
|
Object::Instance { class, payload, .. } => match payload {
|
|
245
299
|
InstancePayload::Int(value) => value.to_string(),
|
|
246
300
|
InstancePayload::Object => match heap.get(*class)? {
|
|
301
|
+
Object::Class {
|
|
302
|
+
name,
|
|
303
|
+
exception_base: Some(_),
|
|
304
|
+
..
|
|
305
|
+
} => {
|
|
306
|
+
let (_, args) = user_exception_parts(heap, value)?
|
|
307
|
+
.ok_or("exception instance lost its native base")?;
|
|
308
|
+
format!("{name}({})", render_values(heap, &args, active)?.join(", "))
|
|
309
|
+
}
|
|
247
310
|
Object::Class { name, .. } => format!("<{name} object>"),
|
|
248
311
|
_ => return Err("instance has an invalid class".into()),
|
|
249
312
|
},
|
|
@@ -33,6 +33,40 @@ class QueueFull(Exception):
|
|
|
33
33
|
pass
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
class InvalidStateError(Exception):
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Handle:
|
|
41
|
+
def __init__(self, callback, args):
|
|
42
|
+
self._callback = callback
|
|
43
|
+
self._args = args
|
|
44
|
+
self._cancelled = False
|
|
45
|
+
|
|
46
|
+
def cancel(self):
|
|
47
|
+
self._cancelled = True
|
|
48
|
+
|
|
49
|
+
def cancelled(self):
|
|
50
|
+
return self._cancelled
|
|
51
|
+
|
|
52
|
+
def _run(self):
|
|
53
|
+
if self._cancelled:
|
|
54
|
+
return
|
|
55
|
+
try:
|
|
56
|
+
self._callback(*self._args)
|
|
57
|
+
except Exception:
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TimerHandle(Handle):
|
|
62
|
+
def __init__(self, when, callback, args):
|
|
63
|
+
Handle.__init__(self, callback, args)
|
|
64
|
+
self._when = when
|
|
65
|
+
|
|
66
|
+
def when(self):
|
|
67
|
+
return self._when
|
|
68
|
+
|
|
69
|
+
|
|
36
70
|
class _Sleep:
|
|
37
71
|
def __init__(self, delay):
|
|
38
72
|
self.delay = delay
|
|
@@ -87,6 +121,82 @@ class _TimeoutWait:
|
|
|
87
121
|
self.timed_out = False
|
|
88
122
|
|
|
89
123
|
|
|
124
|
+
class Future:
|
|
125
|
+
def __init__(self, *, loop=None):
|
|
126
|
+
if loop is None:
|
|
127
|
+
loop = get_running_loop()
|
|
128
|
+
self._loop = loop
|
|
129
|
+
self._done = False
|
|
130
|
+
self._cancelled = False
|
|
131
|
+
self._result = None
|
|
132
|
+
self._exception = None
|
|
133
|
+
self._waiters = []
|
|
134
|
+
self._callbacks = []
|
|
135
|
+
|
|
136
|
+
def get_loop(self):
|
|
137
|
+
return self._loop
|
|
138
|
+
|
|
139
|
+
def done(self):
|
|
140
|
+
return self._done
|
|
141
|
+
|
|
142
|
+
def cancelled(self):
|
|
143
|
+
return self._cancelled
|
|
144
|
+
|
|
145
|
+
def result(self):
|
|
146
|
+
if not self._done:
|
|
147
|
+
raise InvalidStateError("Result is not ready")
|
|
148
|
+
if self._cancelled:
|
|
149
|
+
raise CancelledError()
|
|
150
|
+
if self._exception is not None:
|
|
151
|
+
raise self._exception
|
|
152
|
+
return self._result
|
|
153
|
+
|
|
154
|
+
def exception(self):
|
|
155
|
+
if not self._done:
|
|
156
|
+
raise InvalidStateError("Exception is not set")
|
|
157
|
+
if self._cancelled:
|
|
158
|
+
raise CancelledError()
|
|
159
|
+
return self._exception
|
|
160
|
+
|
|
161
|
+
def add_done_callback(self, callback, *, context=None):
|
|
162
|
+
if self._done:
|
|
163
|
+
self._loop.call_soon(callback, self)
|
|
164
|
+
else:
|
|
165
|
+
self._callbacks.append(callback)
|
|
166
|
+
|
|
167
|
+
def remove_done_callback(self, callback):
|
|
168
|
+
previous = len(self._callbacks)
|
|
169
|
+
self._callbacks = [item for item in self._callbacks if item is not callback]
|
|
170
|
+
return previous - len(self._callbacks)
|
|
171
|
+
|
|
172
|
+
def cancel(self, msg=None):
|
|
173
|
+
if self._done:
|
|
174
|
+
return False
|
|
175
|
+
self._done = True
|
|
176
|
+
self._cancelled = True
|
|
177
|
+
self._loop._run_done_callbacks(self)
|
|
178
|
+
self._loop._wake_waiters(self)
|
|
179
|
+
return True
|
|
180
|
+
|
|
181
|
+
def set_result(self, result):
|
|
182
|
+
if self._done:
|
|
183
|
+
raise InvalidStateError("invalid state")
|
|
184
|
+
self._done = True
|
|
185
|
+
self._result = result
|
|
186
|
+
self._loop._run_done_callbacks(self)
|
|
187
|
+
self._loop._wake_waiters(self)
|
|
188
|
+
|
|
189
|
+
def set_exception(self, exception):
|
|
190
|
+
if self._done:
|
|
191
|
+
raise InvalidStateError("invalid state")
|
|
192
|
+
if not isinstance(exception, BaseException):
|
|
193
|
+
raise TypeError("invalid exception object")
|
|
194
|
+
self._done = True
|
|
195
|
+
self._exception = exception
|
|
196
|
+
self._loop._run_done_callbacks(self)
|
|
197
|
+
self._loop._wake_waiters(self)
|
|
198
|
+
|
|
199
|
+
|
|
90
200
|
class Task:
|
|
91
201
|
def __init__(self, coroutine, loop, name=None):
|
|
92
202
|
if not _is_coroutine(coroutine):
|
|
@@ -145,7 +255,7 @@ class Task:
|
|
|
145
255
|
|
|
146
256
|
def add_done_callback(self, callback, context=None):
|
|
147
257
|
if self._done:
|
|
148
|
-
callback
|
|
258
|
+
self._loop.call_soon(callback, self)
|
|
149
259
|
else:
|
|
150
260
|
self._callbacks.append(callback)
|
|
151
261
|
|
|
@@ -583,6 +693,9 @@ class _Loop:
|
|
|
583
693
|
self._ready.append(task)
|
|
584
694
|
return task
|
|
585
695
|
|
|
696
|
+
def create_future(self):
|
|
697
|
+
return Future(loop=self)
|
|
698
|
+
|
|
586
699
|
def _create_awaited_task(self, coroutine, parent):
|
|
587
700
|
task = self.create_task(coroutine)
|
|
588
701
|
task._logical_task = parent._logical_task
|
|
@@ -591,6 +704,22 @@ class _Loop:
|
|
|
591
704
|
def time(self):
|
|
592
705
|
return _monotonic_ns() / 1000000000
|
|
593
706
|
|
|
707
|
+
def call_soon(self, callback, *args, context=None):
|
|
708
|
+
handle = Handle(callback, args)
|
|
709
|
+
self._ready.append(handle)
|
|
710
|
+
return handle
|
|
711
|
+
|
|
712
|
+
def call_soon_threadsafe(self, callback, *args, context=None):
|
|
713
|
+
return self.call_soon(callback, *args, context=context)
|
|
714
|
+
|
|
715
|
+
def call_at(self, when, callback, *args, context=None):
|
|
716
|
+
handle = TimerHandle(when, callback, args)
|
|
717
|
+
self._timers.append((int(when * 1000000000), handle))
|
|
718
|
+
return handle
|
|
719
|
+
|
|
720
|
+
def call_later(self, delay, callback, *args, context=None):
|
|
721
|
+
return self.call_at(self.time() + delay, callback, *args, context=context)
|
|
722
|
+
|
|
594
723
|
def _schedule(self, task, value):
|
|
595
724
|
if not task._done:
|
|
596
725
|
self._resource_waiters = [
|
|
@@ -608,6 +737,8 @@ class _Loop:
|
|
|
608
737
|
self._ready.append(task)
|
|
609
738
|
|
|
610
739
|
def _cancel(self, task):
|
|
740
|
+
if isinstance(task._waiting_on, Future) and task._waiting_on.cancel():
|
|
741
|
+
return
|
|
611
742
|
if not task._started:
|
|
612
743
|
task._done = True
|
|
613
744
|
task._cancelled = True
|
|
@@ -627,11 +758,15 @@ class _Loop:
|
|
|
627
758
|
now = _monotonic_ns()
|
|
628
759
|
pending = []
|
|
629
760
|
for timer_deadline, timer in self._timers:
|
|
761
|
+
if isinstance(timer, TimerHandle) and timer.cancelled():
|
|
762
|
+
continue
|
|
630
763
|
if timer_deadline <= now:
|
|
631
764
|
if isinstance(timer, _TimeoutWait):
|
|
632
765
|
if timer.parent._waiting_on is timer:
|
|
633
766
|
timer.timed_out = True
|
|
634
767
|
timer.child.cancel()
|
|
768
|
+
elif isinstance(timer, TimerHandle):
|
|
769
|
+
self._ready.append(timer)
|
|
635
770
|
else:
|
|
636
771
|
self._schedule(timer, None)
|
|
637
772
|
else:
|
|
@@ -639,10 +774,15 @@ class _Loop:
|
|
|
639
774
|
self._timers = pending
|
|
640
775
|
|
|
641
776
|
def _next_timer_token(self):
|
|
642
|
-
|
|
777
|
+
active = [
|
|
778
|
+
item
|
|
779
|
+
for item in self._timers
|
|
780
|
+
if not isinstance(item[1], TimerHandle) or not item[1].cancelled()
|
|
781
|
+
]
|
|
782
|
+
if not active:
|
|
643
783
|
return None
|
|
644
|
-
deadline =
|
|
645
|
-
for timer_deadline, timer in
|
|
784
|
+
deadline = active[0][0]
|
|
785
|
+
for timer_deadline, timer in active:
|
|
646
786
|
if timer_deadline < deadline:
|
|
647
787
|
deadline = timer_deadline
|
|
648
788
|
return ("timer", deadline)
|
|
@@ -661,31 +801,38 @@ class _Loop:
|
|
|
661
801
|
for task, token in waiters:
|
|
662
802
|
self._schedule(task, None)
|
|
663
803
|
|
|
664
|
-
def _wake_waiters(self,
|
|
665
|
-
waiters =
|
|
666
|
-
|
|
804
|
+
def _wake_waiters(self, future):
|
|
805
|
+
waiters = future._waiters
|
|
806
|
+
future._waiters = []
|
|
667
807
|
for waiter in waiters:
|
|
668
808
|
if isinstance(waiter, _TimeoutWait):
|
|
669
809
|
waiter.parent._waiting_on = None
|
|
670
810
|
if waiter.timed_out:
|
|
671
811
|
self._schedule_failure(waiter.parent, TimeoutError())
|
|
672
|
-
elif
|
|
673
|
-
self._schedule_failure(waiter.parent,
|
|
812
|
+
elif future._cancelled:
|
|
813
|
+
self._schedule_failure(waiter.parent, CancelledError())
|
|
814
|
+
elif future._exception is not None:
|
|
815
|
+
self._schedule_failure(waiter.parent, future._exception)
|
|
674
816
|
else:
|
|
675
|
-
self._schedule(waiter.parent,
|
|
676
|
-
elif
|
|
677
|
-
|
|
817
|
+
self._schedule(waiter.parent, future._result)
|
|
818
|
+
elif future._cancelled:
|
|
819
|
+
if waiter._waiting_on is future:
|
|
820
|
+
waiter._waiting_on = None
|
|
821
|
+
self._schedule_failure(waiter, CancelledError())
|
|
822
|
+
elif future._exception is not None:
|
|
823
|
+
if waiter._waiting_on is future:
|
|
824
|
+
waiter._waiting_on = None
|
|
825
|
+
self._schedule_failure(waiter, future._exception)
|
|
678
826
|
else:
|
|
679
|
-
|
|
827
|
+
if waiter._waiting_on is future:
|
|
828
|
+
waiter._waiting_on = None
|
|
829
|
+
self._schedule(waiter, future._result)
|
|
680
830
|
|
|
681
|
-
def _run_done_callbacks(self,
|
|
682
|
-
callbacks =
|
|
683
|
-
|
|
831
|
+
def _run_done_callbacks(self, future):
|
|
832
|
+
callbacks = future._callbacks
|
|
833
|
+
future._callbacks = []
|
|
684
834
|
for callback in callbacks:
|
|
685
|
-
|
|
686
|
-
callback(task)
|
|
687
|
-
except Exception:
|
|
688
|
-
pass
|
|
835
|
+
self.call_soon(callback, future)
|
|
689
836
|
|
|
690
837
|
def _finish(self, task, result):
|
|
691
838
|
task._done = True
|
|
@@ -700,18 +847,22 @@ class _Loop:
|
|
|
700
847
|
self._wake_waiters(task)
|
|
701
848
|
self._run_done_callbacks(task)
|
|
702
849
|
|
|
703
|
-
def
|
|
850
|
+
def _block_on_future(self, task, awaited):
|
|
704
851
|
if awaited._done:
|
|
705
|
-
if awaited.
|
|
852
|
+
if awaited._cancelled:
|
|
853
|
+
self._schedule_failure(task, CancelledError())
|
|
854
|
+
elif awaited._exception is not None:
|
|
706
855
|
self._schedule_failure(task, awaited._exception)
|
|
707
856
|
else:
|
|
708
857
|
self._schedule(task, awaited._result)
|
|
709
858
|
else:
|
|
859
|
+
if isinstance(awaited, Future):
|
|
860
|
+
task._waiting_on = awaited
|
|
710
861
|
awaited._waiters.append(task)
|
|
711
862
|
|
|
712
863
|
def _dispatch_yield(self, task, awaited):
|
|
713
|
-
if isinstance(awaited, Task):
|
|
714
|
-
self.
|
|
864
|
+
if isinstance(awaited, (Task, Future)):
|
|
865
|
+
self._block_on_future(task, awaited)
|
|
715
866
|
elif isinstance(awaited, _Sleep):
|
|
716
867
|
self._sleep(task, awaited.delay)
|
|
717
868
|
elif isinstance(awaited, _EventWait):
|
|
@@ -738,7 +889,7 @@ class _Loop:
|
|
|
738
889
|
awaited.condition._waiters.append(task)
|
|
739
890
|
elif isinstance(awaited, _WaitFor):
|
|
740
891
|
if awaited.task._done:
|
|
741
|
-
self.
|
|
892
|
+
self._block_on_future(task, awaited.task)
|
|
742
893
|
else:
|
|
743
894
|
timeout = _TimeoutWait(task, awaited.task)
|
|
744
895
|
task._waiting_on = timeout
|
|
@@ -749,7 +900,7 @@ class _Loop:
|
|
|
749
900
|
elif isinstance(awaited, _ResourceWait):
|
|
750
901
|
self._resource_waiters.append((task, awaited.token))
|
|
751
902
|
elif _is_coroutine(awaited):
|
|
752
|
-
self.
|
|
903
|
+
self._block_on_future(task, self._create_awaited_task(awaited, task))
|
|
753
904
|
else:
|
|
754
905
|
raise TypeError("object cannot be used in 'await' expression")
|
|
755
906
|
|
|
@@ -761,6 +912,9 @@ class _Loop:
|
|
|
761
912
|
if not self._ready:
|
|
762
913
|
self._wait_for_resources()
|
|
763
914
|
task = self._ready.pop(0)
|
|
915
|
+
if isinstance(task, Handle):
|
|
916
|
+
task._run()
|
|
917
|
+
continue
|
|
764
918
|
if task._done:
|
|
765
919
|
continue
|
|
766
920
|
task._started = True
|
|
@@ -783,6 +937,10 @@ def get_running_loop():
|
|
|
783
937
|
return _running_loop
|
|
784
938
|
|
|
785
939
|
|
|
940
|
+
def get_event_loop():
|
|
941
|
+
return get_running_loop()
|
|
942
|
+
|
|
943
|
+
|
|
786
944
|
def create_task(coroutine, name=None, context=None):
|
|
787
945
|
return get_running_loop().create_task(coroutine, name)
|
|
788
946
|
|
|
@@ -791,6 +949,10 @@ def ensure_future(awaitable):
|
|
|
791
949
|
return _ensure_task(awaitable)
|
|
792
950
|
|
|
793
951
|
|
|
952
|
+
def isfuture(value):
|
|
953
|
+
return isinstance(value, (Future, Task))
|
|
954
|
+
|
|
955
|
+
|
|
794
956
|
def current_task(loop=None):
|
|
795
957
|
if loop is None:
|
|
796
958
|
loop = get_running_loop()
|
|
@@ -806,7 +968,7 @@ def all_tasks(loop=None):
|
|
|
806
968
|
|
|
807
969
|
|
|
808
970
|
def _ensure_task(awaitable):
|
|
809
|
-
if isinstance(awaitable, Task):
|
|
971
|
+
if isinstance(awaitable, (Task, Future)):
|
|
810
972
|
return awaitable
|
|
811
973
|
return create_task(awaitable)
|
|
812
974
|
|
|
@@ -923,7 +1085,7 @@ async def wait(awaitables, timeout=None, return_when=ALL_COMPLETED):
|
|
|
923
1085
|
if not tasks:
|
|
924
1086
|
raise ValueError("Set of Tasks/Futures is empty")
|
|
925
1087
|
for task in tasks:
|
|
926
|
-
if not isinstance(task, Task):
|
|
1088
|
+
if not isinstance(task, (Task, Future)):
|
|
927
1089
|
raise TypeError("Passing coroutines is forbidden, use tasks explicitly")
|
|
928
1090
|
changed = Event()
|
|
929
1091
|
|
|
@@ -200,6 +200,7 @@ impl Vm<'_> {
|
|
|
200
200
|
name,
|
|
201
201
|
metaclass,
|
|
202
202
|
layout,
|
|
203
|
+
exception_base,
|
|
203
204
|
is_dataclass,
|
|
204
205
|
dataclass_fields,
|
|
205
206
|
enum_members,
|
|
@@ -339,6 +340,16 @@ impl Vm<'_> {
|
|
|
339
340
|
payload,
|
|
340
341
|
attributes: InstanceAttributes::default(),
|
|
341
342
|
})?;
|
|
343
|
+
if exception_base.is_some() {
|
|
344
|
+
let exception_args =
|
|
345
|
+
self.allocate_object(Object::Tuple(arguments.clone()))?;
|
|
346
|
+
self.state.heap.insert_attribute(
|
|
347
|
+
instance.object_id().expect("instances are heap objects"),
|
|
348
|
+
"args".into(),
|
|
349
|
+
exception_args,
|
|
350
|
+
&mut self.interp.resources,
|
|
351
|
+
)?;
|
|
352
|
+
}
|
|
342
353
|
if is_dataclass {
|
|
343
354
|
let mut values = Vec::new();
|
|
344
355
|
for (index, (field, default)) in dataclass_fields.iter().enumerate() {
|
|
@@ -428,7 +439,10 @@ impl Vm<'_> {
|
|
|
428
439
|
unreachable!("immediate initializer cannot suspend")
|
|
429
440
|
}
|
|
430
441
|
}
|
|
442
|
+
} else if exception_base.is_some() && !keyword_arguments.is_empty() {
|
|
443
|
+
return Err(format!("{name}() does not accept keyword arguments"));
|
|
431
444
|
} else if layout == ClassLayout::Object
|
|
445
|
+
&& exception_base.is_none()
|
|
432
446
|
&& (!arguments.is_empty() || !keyword_arguments.is_empty())
|
|
433
447
|
{
|
|
434
448
|
return Err(format!("{name}() takes no arguments"));
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|