shellsim 0.1.27__tar.gz → 0.1.29__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.27 → shellsim-0.1.29}/Cargo.lock +1 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/Cargo.toml +1 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/PKG-INFO +2 -2
- {shellsim-0.1.27 → shellsim-0.1.29}/pyproject.toml +1 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/python/native/Cargo.lock +2 -2
- {shellsim-0.1.27 → shellsim-0.1.29}/python/native/Cargo.toml +1 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/builtins.rs +211 -107
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/find.rs +33 -15
- shellsim-0.1.29/src/commands/git/archive.rs +135 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/compare.rs +22 -4
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/mod.rs +3 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/worktree.rs +29 -4
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/mod.rs +1 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/pkg.rs +29 -2
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/proc.rs +55 -15
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/sort.rs +16 -6
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/streams.rs +30 -6
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/tarcmd.rs +6 -6
- {shellsim-0.1.27 → shellsim-0.1.29}/src/exec.rs +119 -22
- {shellsim-0.1.27 → shellsim-0.1.29}/src/interp.rs +33 -2
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/find.rs +43 -39
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/attributes.rs +103 -108
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/bytecode.rs +58 -3
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/compiler.rs +25 -7
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/exception_types.rs +50 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/heap/gc.rs +28 -63
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/heap/mod.rs +149 -221
- shellsim-0.1.29/src/python/heap/native_object.rs +56 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/heap/snapshot.rs +17 -105
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/heap/stack.rs +13 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/mod.rs +56 -37
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/native.rs +39 -6
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/number.rs +68 -10
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/object_model.rs +825 -554
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/protocol.rs +43 -438
- shellsim-0.1.29/src/python/pytest_options.rs +198 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/scopes.rs +3 -2
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/argparse.rs +191 -4
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/core.rs +90 -27
- shellsim-0.1.29/src/python/stdlib/enum.rs +106 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/json.rs +0 -3
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/convert.rs +9 -16
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/mod.rs +1 -0
- shellsim-0.1.29/src/python/stdlib/numpy/storage.rs +116 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/pytest.rs +21 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/re.rs +104 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/unittest.rs +28 -0
- shellsim-0.1.29/src/python/string.rs +392 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/calls.rs +350 -254
- shellsim-0.1.29/src/python/vm/compare.rs +367 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/dispatch.rs +215 -61
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/equality.rs +35 -117
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/handles.rs +20 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/hashing.rs +43 -73
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/host.rs +4 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/iteration.rs +55 -44
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/mappings.rs +1 -1
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/namespace.rs +79 -72
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/native_runtime.rs +222 -196
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/objects.rs +446 -577
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/operations.rs +35 -183
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm.rs +197 -62
- shellsim-0.1.27/src/python/stdlib/enum.rs +0 -16
- shellsim-0.1.27/src/python/string.rs +0 -175
- {shellsim-0.1.27 → shellsim-0.1.29}/LICENSE +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/README.md +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/native/src/lib.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/__init__.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/__main__.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/_api.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/_cli.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/display_host.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/package.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/py.typed +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/python/shellsim/python.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/rust-toolchain.toml +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/arith.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/bin/shellsim-python.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/clock.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/archives.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/arcmd.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/awk/ast.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/awk/eval.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/awk/lexer.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/awk/parser.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/awk.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/bc.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/dd.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/diff.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/echo.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/expr.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/format.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/fs.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/apply.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/commit.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/config.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/conflict.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/diff.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/ignore.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/import.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/log.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/merge.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/plumbing.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/rebase.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/refs.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/repo.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/stash.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/git/switch.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/grep.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/hashing.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/makecmd.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/net.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/options.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/patch.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/printf.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/regex_compat.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/rgcmd.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/sed.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/system.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/text.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/unavailable.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/util.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/wasm.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/xargs.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/commands/zipcmd.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/corpus.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/descriptors.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/display.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/expand.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/harness.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/harness_manager.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/hashes.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/host_ingest.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/jqcmd.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/lib.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/main.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/mcp.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/net.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/netcmd.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/process.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/profile.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/cat.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/env.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/head.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/make.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/nice.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/nohup.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/sleep.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/tee.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/timeout.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program/xargs.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/program.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/pseudo_fs.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/ast.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/complex.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/cpython_names.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/definitions.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/filesystem.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/float_text.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/hash.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/heap/mapping.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/heap/tests.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/heap/value.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/http.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/lexer.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/parser.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/process.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/slice.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/sort.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/source.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/asyncio.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/base64.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/collections.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/dataclasses.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/frozen.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/functools.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/hashlib.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/heapq.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/http.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/importlib.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/introspect.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/itertools.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/mapping_views.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/math.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/mod.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/args.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/array.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/construct.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/dtype.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/dtype_object.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/element.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/errstate.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/format.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/index.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/io.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/layout.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/linalg/dense.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/linalg.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/math.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/ndarray.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/ops.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/products.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/random/bitgen.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/random/discrete.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/random/gamma.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/random/integers.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/random/normal.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/random/sequence.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/random.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/reduce.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/scalar.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/select.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/shape/broadcast.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/shape/diagonal.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/shape/join.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/shape/repeat.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/shape.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/sort/bincount.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/sort/search.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/sort.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/ufunc/masked.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/ufunc.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/numpy/underflow.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/operator.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/os.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/mod.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/special/erf.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/special/gamma.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/special/ibeta.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/special/igam.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/special/meter.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/special/mod.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/scipy/special/zeta.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/_exceptions.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/_io.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/_iteration.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/abc.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/asyncio.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/base64.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/bisect.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/cmath.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/codecs.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/collections.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/collections_abc.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/contextlib.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/copy.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/csv.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/datetime.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/errno.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/fnmatch.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/fractions.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/functools.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/glob.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/hashlib.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/heapq.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/http.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/http_client.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/importlib.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/inspect.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/io.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/itertools.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/json.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/keyword.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/logging.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/__init__.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_creation.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_errors.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_io.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_math.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_printing.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_products.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_sets.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_shapes.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/_stats.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/exceptions.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/fft.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/linalg.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/random.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/numpy/testing.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/operator.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/os.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/pathlib.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/posixpath.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/pytest.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/random.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/re.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/__init__.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/integrate.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/interpolate.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/linalg.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/optimize.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/spatial/__init__.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/spatial/distance.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/special.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/stats/__init__.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/stats/_describe.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/stats/_distributions.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/scipy/stats/_tests.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/shutil.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/signal.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/stat.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/statistics.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/string.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/struct.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/subprocess.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/sys.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/tempfile.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/textwrap.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/time.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/types.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/urllib.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/urllib_error.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/urllib_parse.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/urllib_request.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/uuid.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/warnings.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/zipfile.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/source/zlib.py +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/string.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/struct.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/subprocess.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/sys.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/time.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/typing.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/vfs.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/warnings.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/stdlib/zlib.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/symbols.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/token.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/unicode/tables.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/unicode.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/format.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/python/vm/summation.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/realtime.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/resources.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/sandbox.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/scenario.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/scheduler.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/shell.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/stack.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/syscalls.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/telemetry.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/variables.rs +0 -0
- {shellsim-0.1.27 → shellsim-0.1.29}/src/vfs.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shellsim
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.29
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
6
6
|
Classifier: Operating System :: Microsoft :: Windows
|
|
@@ -10,7 +10,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
10
10
|
Classifier: Programming Language :: Rust
|
|
11
11
|
Classifier: Topic :: Software Development :: Testing
|
|
12
12
|
Classifier: Typing :: Typed
|
|
13
|
-
Requires-Dist: shellsim-c-toolchain==0.1.
|
|
13
|
+
Requires-Dist: shellsim-c-toolchain==0.1.29 ; extra == 'c'
|
|
14
14
|
Provides-Extra: c
|
|
15
15
|
License-File: LICENSE
|
|
16
16
|
Summary: In-process BusyBox-like environment for RL rollouts and agent tests
|
|
@@ -25,7 +25,7 @@ classifiers = [
|
|
|
25
25
|
keywords = ["agents", "containers", "reinforcement-learning", "sandbox", "simulation", "testing"]
|
|
26
26
|
|
|
27
27
|
[project.optional-dependencies]
|
|
28
|
-
c = ["shellsim-c-toolchain==0.1.
|
|
28
|
+
c = ["shellsim-c-toolchain==0.1.29"]
|
|
29
29
|
|
|
30
30
|
[project.urls]
|
|
31
31
|
Homepage = "https://github.com/rjpower/shellsim"
|
|
@@ -953,7 +953,7 @@ dependencies = [
|
|
|
953
953
|
|
|
954
954
|
[[package]]
|
|
955
955
|
name = "shellsim"
|
|
956
|
-
version = "0.1.
|
|
956
|
+
version = "0.1.29"
|
|
957
957
|
dependencies = [
|
|
958
958
|
"base64",
|
|
959
959
|
"crc32fast",
|
|
@@ -978,7 +978,7 @@ dependencies = [
|
|
|
978
978
|
|
|
979
979
|
[[package]]
|
|
980
980
|
name = "shellsim-python-bindings"
|
|
981
|
-
version = "0.1.
|
|
981
|
+
version = "0.1.29"
|
|
982
982
|
dependencies = [
|
|
983
983
|
"base64",
|
|
984
984
|
"pyo3",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
use std::collections::HashMap;
|
|
6
6
|
|
|
7
|
-
use crate::commands::util::{ewln,
|
|
7
|
+
use crate::commands::util::{ewln, wln};
|
|
8
8
|
use crate::commands::{CommandContext, CommandPoll, CommandResume, CommandSpec, Io, Trust};
|
|
9
9
|
use crate::interp::Interp;
|
|
10
10
|
use crate::syscalls::System;
|
|
@@ -357,7 +357,7 @@ fn cmd_flock(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i
|
|
|
357
357
|
|
|
358
358
|
fn cmd_trap(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32 {
|
|
359
359
|
if args.is_empty() {
|
|
360
|
-
print_traps(interp, &[], true, io);
|
|
360
|
+
print_traps(interp, &[], true, true, true, io);
|
|
361
361
|
return 0;
|
|
362
362
|
}
|
|
363
363
|
if args[0] == "-l" {
|
|
@@ -368,14 +368,21 @@ fn cmd_trap(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i3
|
|
|
368
368
|
return list_signal(None, io);
|
|
369
369
|
}
|
|
370
370
|
if args[0] == "-p" {
|
|
371
|
-
let (include_exit, signals) = match parse_trap_targets(&args[1..]) {
|
|
371
|
+
let (include_exit, include_err, signals) = match parse_trap_targets(&args[1..]) {
|
|
372
372
|
Ok(targets) => targets,
|
|
373
373
|
Err(error) => {
|
|
374
374
|
ewln(io.err, &format!("trap: {error}"));
|
|
375
375
|
return 2;
|
|
376
376
|
}
|
|
377
377
|
};
|
|
378
|
-
print_traps(
|
|
378
|
+
print_traps(
|
|
379
|
+
interp,
|
|
380
|
+
&signals,
|
|
381
|
+
include_exit,
|
|
382
|
+
include_err,
|
|
383
|
+
args.len() == 1,
|
|
384
|
+
io,
|
|
385
|
+
);
|
|
379
386
|
return 0;
|
|
380
387
|
}
|
|
381
388
|
|
|
@@ -389,7 +396,7 @@ fn cmd_trap(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i3
|
|
|
389
396
|
ewln(io.err, "trap: missing signal operand");
|
|
390
397
|
return 2;
|
|
391
398
|
}
|
|
392
|
-
let (has_exit, signals) = match parse_trap_targets(signal_args) {
|
|
399
|
+
let (has_exit, has_err, signals) = match parse_trap_targets(signal_args) {
|
|
393
400
|
Ok(targets) => targets,
|
|
394
401
|
Err(error) => {
|
|
395
402
|
ewln(io.err, &format!("trap: {error}"));
|
|
@@ -439,6 +446,11 @@ fn cmd_trap(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i3
|
|
|
439
446
|
if has_exit {
|
|
440
447
|
updated_exit = disposition.clone();
|
|
441
448
|
}
|
|
449
|
+
let updated_err = if has_err {
|
|
450
|
+
disposition.clone()
|
|
451
|
+
} else {
|
|
452
|
+
interp.err_disposition.clone()
|
|
453
|
+
};
|
|
442
454
|
let state_bytes = updated
|
|
443
455
|
.values()
|
|
444
456
|
.fold(0_u64, |total, disposition| {
|
|
@@ -450,61 +462,81 @@ fn cmd_trap(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i3
|
|
|
450
462
|
.saturating_add(32),
|
|
451
463
|
})
|
|
452
464
|
})
|
|
453
|
-
.saturating_add(updated_exit.
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
465
|
+
.saturating_add(updated_exit.iter().chain(updated_err.iter()).fold(
|
|
466
|
+
0_u64,
|
|
467
|
+
|total, disposition| {
|
|
468
|
+
total.saturating_add(match disposition {
|
|
469
|
+
crate::interp::ShellSignalDisposition::Ignore => 16,
|
|
470
|
+
crate::interp::ShellSignalDisposition::Handler { source, body } => {
|
|
471
|
+
(source.len() as u64)
|
|
472
|
+
.saturating_add(body.estimated_bytes())
|
|
473
|
+
.saturating_add(32)
|
|
474
|
+
}
|
|
475
|
+
})
|
|
476
|
+
},
|
|
477
|
+
));
|
|
462
478
|
if state_bytes > MAX_TRAP_STATE_BYTES {
|
|
463
479
|
ewln(io.err, "trap: signal handler state exceeds the 1 MiB limit");
|
|
464
480
|
return 2;
|
|
465
481
|
}
|
|
466
482
|
interp.signal_dispositions = updated;
|
|
467
483
|
interp.exit_disposition = updated_exit;
|
|
484
|
+
interp.err_disposition = updated_err;
|
|
485
|
+
if has_err {
|
|
486
|
+
interp.err_trap_active = true;
|
|
487
|
+
}
|
|
468
488
|
0
|
|
469
489
|
}
|
|
470
490
|
|
|
471
|
-
fn parse_trap_targets(
|
|
491
|
+
fn parse_trap_targets(
|
|
492
|
+
values: &[String],
|
|
493
|
+
) -> Result<(bool, bool, Vec<crate::process::Signal>), String> {
|
|
472
494
|
let mut has_exit = values.is_empty();
|
|
495
|
+
let mut has_err = values.is_empty();
|
|
473
496
|
let mut signals = Vec::with_capacity(values.len());
|
|
474
497
|
for value in values {
|
|
475
498
|
if value == "0" || value.eq_ignore_ascii_case("EXIT") {
|
|
476
499
|
has_exit = true;
|
|
477
500
|
continue;
|
|
478
501
|
}
|
|
502
|
+
if value.eq_ignore_ascii_case("ERR") {
|
|
503
|
+
has_err = true;
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
479
506
|
let signal = crate::process::Signal::parse(value)
|
|
480
507
|
.ok_or_else(|| format!("invalid signal: {value}"))?;
|
|
481
508
|
if !signals.contains(&signal) {
|
|
482
509
|
signals.push(signal);
|
|
483
510
|
}
|
|
484
511
|
}
|
|
485
|
-
Ok((has_exit, signals))
|
|
512
|
+
Ok((has_exit, has_err, signals))
|
|
486
513
|
}
|
|
487
514
|
|
|
488
515
|
fn print_traps(
|
|
489
516
|
interp: &CommandContext<'_>,
|
|
490
517
|
selected: &[crate::process::Signal],
|
|
491
518
|
include_exit: bool,
|
|
519
|
+
include_err: bool,
|
|
520
|
+
all: bool,
|
|
492
521
|
io: &mut Io,
|
|
493
522
|
) {
|
|
494
|
-
|
|
495
|
-
|
|
523
|
+
for (include, name, disposition) in [
|
|
524
|
+
(include_exit, "EXIT", &interp.exit_disposition),
|
|
525
|
+
(include_err, "ERR", &interp.err_disposition),
|
|
526
|
+
] {
|
|
527
|
+
if let Some(disposition) = disposition.as_ref().filter(|_| include) {
|
|
496
528
|
let action = match disposition {
|
|
497
529
|
crate::interp::ShellSignalDisposition::Ignore => String::new(),
|
|
498
530
|
crate::interp::ShellSignalDisposition::Handler { source, .. } => source.clone(),
|
|
499
531
|
};
|
|
500
532
|
wln(
|
|
501
533
|
io.out,
|
|
502
|
-
&format!("trap -- '{}'
|
|
534
|
+
&format!("trap -- '{}' {name}", action.replace('\'', "'\\''")),
|
|
503
535
|
);
|
|
504
536
|
}
|
|
505
537
|
}
|
|
506
538
|
for (signal, disposition) in &interp.signal_dispositions {
|
|
507
|
-
if !
|
|
539
|
+
if !all && !selected.contains(signal) {
|
|
508
540
|
continue;
|
|
509
541
|
}
|
|
510
542
|
let action = match disposition {
|
|
@@ -1091,6 +1123,8 @@ fn cmd_set(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32
|
|
|
1091
1123
|
match a.as_str() {
|
|
1092
1124
|
"-e" => interp.opt_errexit = true,
|
|
1093
1125
|
"+e" => interp.opt_errexit = false,
|
|
1126
|
+
"-E" => interp.opt_errtrace = true,
|
|
1127
|
+
"+E" => interp.opt_errtrace = false,
|
|
1094
1128
|
"-u" => interp.opt_nounset = true,
|
|
1095
1129
|
"+u" => interp.opt_nounset = false,
|
|
1096
1130
|
"-x" | "+x" => {
|
|
@@ -1102,6 +1136,7 @@ fn cmd_set(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32
|
|
|
1102
1136
|
match opt.as_str() {
|
|
1103
1137
|
"pipefail" => interp.opt_pipefail = true,
|
|
1104
1138
|
"errexit" => interp.opt_errexit = true,
|
|
1139
|
+
"errtrace" => interp.opt_errtrace = true,
|
|
1105
1140
|
"nounset" => interp.opt_nounset = true,
|
|
1106
1141
|
_ => {
|
|
1107
1142
|
ewln(io.err, &format!("set: unimplemented option '{opt}'"));
|
|
@@ -1116,6 +1151,7 @@ fn cmd_set(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32
|
|
|
1116
1151
|
match opt.as_str() {
|
|
1117
1152
|
"pipefail" => interp.opt_pipefail = false,
|
|
1118
1153
|
"errexit" => interp.opt_errexit = false,
|
|
1154
|
+
"errtrace" => interp.opt_errtrace = false,
|
|
1119
1155
|
"nounset" => interp.opt_nounset = false,
|
|
1120
1156
|
_ => {
|
|
1121
1157
|
ewln(io.err, &format!("set: unimplemented option '{opt}'"));
|
|
@@ -1129,17 +1165,19 @@ fn cmd_set(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32
|
|
|
1129
1165
|
interp.positional = args[i + 1..].to_vec().into();
|
|
1130
1166
|
break;
|
|
1131
1167
|
}
|
|
1132
|
-
s if s.starts_with('-') && s.len() > 1 => {
|
|
1168
|
+
s if (s.starts_with('-') || s.starts_with('+')) && s.len() > 1 => {
|
|
1169
|
+
let enable = s.starts_with('-');
|
|
1133
1170
|
for option in s[1..].chars() {
|
|
1134
1171
|
match option {
|
|
1135
|
-
'e' => interp.opt_errexit =
|
|
1136
|
-
'
|
|
1172
|
+
'e' => interp.opt_errexit = enable,
|
|
1173
|
+
'E' => interp.opt_errtrace = enable,
|
|
1174
|
+
'u' => interp.opt_nounset = enable,
|
|
1137
1175
|
'x' => {
|
|
1138
1176
|
ewln(io.err, "set: xtrace is unimplemented");
|
|
1139
1177
|
return 2;
|
|
1140
1178
|
}
|
|
1141
1179
|
'o' if args.get(i + 1).map(String::as_str) == Some("pipefail") => {
|
|
1142
|
-
interp.opt_pipefail =
|
|
1180
|
+
interp.opt_pipefail = enable;
|
|
1143
1181
|
i += 1;
|
|
1144
1182
|
}
|
|
1145
1183
|
'o' => {
|
|
@@ -1750,42 +1788,129 @@ fn num(s: &str) -> i64 {
|
|
|
1750
1788
|
s.trim().parse().unwrap_or(0)
|
|
1751
1789
|
}
|
|
1752
1790
|
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1791
|
+
/// Parsed record framing and assignment options for the shell `read` builtin.
|
|
1792
|
+
struct ReadOptions<'a> {
|
|
1793
|
+
raw: bool,
|
|
1794
|
+
delimiter: u8,
|
|
1795
|
+
array: Option<&'a str>,
|
|
1796
|
+
names: Vec<&'a str>,
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
fn parse_read_options(args: &[String]) -> Result<ReadOptions<'_>, &'static str> {
|
|
1800
|
+
let mut options = ReadOptions {
|
|
1801
|
+
raw: false,
|
|
1802
|
+
delimiter: b'\n',
|
|
1803
|
+
array: None,
|
|
1804
|
+
names: Vec::new(),
|
|
1805
|
+
};
|
|
1806
|
+
let mut index = 0;
|
|
1807
|
+
while let Some(argument) = args.get(index) {
|
|
1808
|
+
if argument == "--" {
|
|
1809
|
+
index += 1;
|
|
1810
|
+
break;
|
|
1811
|
+
}
|
|
1812
|
+
if !argument.starts_with('-') || argument == "-" {
|
|
1813
|
+
break;
|
|
1814
|
+
}
|
|
1815
|
+
let bytes = argument.as_bytes();
|
|
1816
|
+
let mut offset = 1;
|
|
1817
|
+
while offset < bytes.len() {
|
|
1818
|
+
match bytes[offset] {
|
|
1819
|
+
b'r' => options.raw = true,
|
|
1820
|
+
option @ (b'a' | b'd') => {
|
|
1821
|
+
let value = if offset + 1 < bytes.len() {
|
|
1822
|
+
&argument[offset + 1..]
|
|
1823
|
+
} else {
|
|
1824
|
+
index += 1;
|
|
1825
|
+
args.get(index)
|
|
1826
|
+
.ok_or("read: option requires a value")?
|
|
1827
|
+
.as_str()
|
|
1828
|
+
};
|
|
1829
|
+
if option == b'a' {
|
|
1830
|
+
options.array = Some(value);
|
|
1831
|
+
} else {
|
|
1832
|
+
options.delimiter = value.as_bytes().first().copied().unwrap_or(0);
|
|
1833
|
+
}
|
|
1834
|
+
break;
|
|
1835
|
+
}
|
|
1836
|
+
_ => return Err("read: supported options are -a, -r and -d"),
|
|
1837
|
+
}
|
|
1838
|
+
offset += 1;
|
|
1839
|
+
}
|
|
1840
|
+
index += 1;
|
|
1758
1841
|
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1842
|
+
options
|
|
1843
|
+
.names
|
|
1844
|
+
.extend(args[index..].iter().map(String::as_str));
|
|
1845
|
+
if options.names.iter().any(|name| !shell_identifier(name))
|
|
1846
|
+
|| options.array.is_some_and(|name| !shell_identifier(name))
|
|
1847
|
+
{
|
|
1848
|
+
return Err("read: expected valid variable names");
|
|
1849
|
+
}
|
|
1850
|
+
Ok(options)
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
/// Identify a completed buffered record without consuming bytes after its delimiter.
|
|
1854
|
+
/// Invalid options are complete immediately so they fail without waiting for input.
|
|
1855
|
+
#[derive(Clone, Copy)]
|
|
1856
|
+
pub(crate) struct ReadFraming {
|
|
1857
|
+
delimiter: Option<u8>,
|
|
1858
|
+
raw: bool,
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
impl ReadFraming {
|
|
1862
|
+
pub(crate) fn new(args: &[String]) -> Self {
|
|
1863
|
+
match parse_read_options(args) {
|
|
1864
|
+
Ok(options) => Self {
|
|
1865
|
+
delimiter: Some(options.delimiter),
|
|
1866
|
+
raw: options.raw,
|
|
1867
|
+
},
|
|
1868
|
+
Err(_) => Self {
|
|
1869
|
+
delimiter: None,
|
|
1870
|
+
raw: true,
|
|
1871
|
+
},
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
pub(crate) fn complete(self, input: &[u8]) -> bool {
|
|
1876
|
+
let Some(delimiter) = self.delimiter else {
|
|
1877
|
+
return true;
|
|
1767
1878
|
};
|
|
1768
|
-
|
|
1879
|
+
if input.last().copied() != Some(delimiter) {
|
|
1880
|
+
return false;
|
|
1881
|
+
}
|
|
1882
|
+
self.raw
|
|
1883
|
+
|| input[..input.len() - 1]
|
|
1884
|
+
.iter()
|
|
1885
|
+
.rev()
|
|
1886
|
+
.take_while(|byte| **byte == b'\\')
|
|
1887
|
+
.count()
|
|
1888
|
+
% 2
|
|
1889
|
+
== 0
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
fn cmd_read(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32 {
|
|
1894
|
+
let options = match parse_read_options(args) {
|
|
1895
|
+
Ok(options) => options,
|
|
1896
|
+
Err(message) => {
|
|
1897
|
+
ewln(io.err, message);
|
|
1898
|
+
return 2;
|
|
1899
|
+
}
|
|
1900
|
+
};
|
|
1901
|
+
let (line, terminated) = read_one_record(interp, io, options.delimiter, options.raw);
|
|
1902
|
+
let status = i32::from(!terminated);
|
|
1903
|
+
if let Some(array) = options.array {
|
|
1769
1904
|
let ifs = interp.get_var("IFS").unwrap_or_else(|| " \t\n".to_string());
|
|
1770
|
-
let elems
|
|
1905
|
+
let elems = if ifs.is_empty() {
|
|
1771
1906
|
vec![line]
|
|
1772
1907
|
} else {
|
|
1773
1908
|
split_read_fields(&line, &ifs)
|
|
1774
1909
|
};
|
|
1775
|
-
interp.set_array(
|
|
1776
|
-
return
|
|
1910
|
+
interp.set_array(array, elems);
|
|
1911
|
+
return status;
|
|
1777
1912
|
}
|
|
1778
|
-
|
|
1779
|
-
// cursor (set up by a `< file` redirect on an enclosing loop).
|
|
1780
|
-
let Some(line) = read_one_line(interp, io) else {
|
|
1781
|
-
return 1;
|
|
1782
|
-
};
|
|
1783
|
-
let line = if flags.contains(&'r') {
|
|
1784
|
-
line
|
|
1785
|
-
} else {
|
|
1786
|
-
decode_read_backslashes(&line)
|
|
1787
|
-
};
|
|
1788
|
-
|
|
1913
|
+
let ops = options.names;
|
|
1789
1914
|
let ifs = interp.get_var("IFS").unwrap_or_else(|| " \t\n".to_string());
|
|
1790
1915
|
if ops.is_empty() {
|
|
1791
1916
|
interp.set_var("REPLY", line);
|
|
@@ -1805,7 +1930,7 @@ fn cmd_read(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i3
|
|
|
1805
1930
|
}
|
|
1806
1931
|
}
|
|
1807
1932
|
}
|
|
1808
|
-
|
|
1933
|
+
status
|
|
1809
1934
|
}
|
|
1810
1935
|
|
|
1811
1936
|
/// Split a `read` record according to POSIX IFS classes.
|
|
@@ -1840,21 +1965,6 @@ fn split_read_fields(line: &str, ifs: &str) -> Vec<String> {
|
|
|
1840
1965
|
fields
|
|
1841
1966
|
}
|
|
1842
1967
|
|
|
1843
|
-
fn decode_read_backslashes(line: &str) -> String {
|
|
1844
|
-
let mut decoded = String::with_capacity(line.len());
|
|
1845
|
-
let mut characters = line.chars();
|
|
1846
|
-
while let Some(character) = characters.next() {
|
|
1847
|
-
if character == '\\' {
|
|
1848
|
-
if let Some(escaped) = characters.next() {
|
|
1849
|
-
decoded.push(escaped);
|
|
1850
|
-
}
|
|
1851
|
-
} else {
|
|
1852
|
-
decoded.push(character);
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
decoded
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
1968
|
const MAX_MAPFILE_RECORDS: usize = 100_000;
|
|
1859
1969
|
|
|
1860
1970
|
fn cmd_mapfile(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32 {
|
|
@@ -1997,49 +2107,43 @@ fn shell_identifier(value: &str) -> bool {
|
|
|
1997
2107
|
&& bytes.all(|byte| byte == b'_' || byte.is_ascii_alphanumeric())
|
|
1998
2108
|
}
|
|
1999
2109
|
|
|
2000
|
-
/// Read
|
|
2001
|
-
///
|
|
2002
|
-
fn
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
)
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2110
|
+
/// Read a bounded record and report whether its delimiter was encountered. Shell variables
|
|
2111
|
+
/// discard embedded NUL bytes; an empty `-d` instead uses NUL as the record delimiter.
|
|
2112
|
+
fn read_one_record(interp: &mut Interp, io: &Io, delimiter: u8, raw: bool) -> (String, bool) {
|
|
2113
|
+
let mut record = Vec::new();
|
|
2114
|
+
let mut cursor = 0usize;
|
|
2115
|
+
let mut escaped = false;
|
|
2116
|
+
let mut terminated = false;
|
|
2117
|
+
while cursor < crate::descriptors::MAX_CAPTURE_BYTES {
|
|
2118
|
+
let byte = if !io.stdin.is_empty() {
|
|
2119
|
+
io.stdin.get(cursor).copied()
|
|
2120
|
+
} else if interp.input_pos < interp.input_stream.len() {
|
|
2121
|
+
let byte = interp.input_stream[interp.input_pos];
|
|
2122
|
+
interp.input_pos += 1;
|
|
2123
|
+
Some(byte)
|
|
2124
|
+
} else {
|
|
2125
|
+
match interp.read_fd(0, 1) {
|
|
2126
|
+
Ok(crate::descriptors::IoPoll::Ready(bytes)) => bytes.first().copied(),
|
|
2127
|
+
_ => None,
|
|
2128
|
+
}
|
|
2018
2129
|
};
|
|
2019
|
-
let
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
let mut consumed = false;
|
|
2025
|
-
while line.len() < crate::descriptors::MAX_CAPTURE_BYTES {
|
|
2026
|
-
match interp.read_fd(0, 1).ok()? {
|
|
2027
|
-
crate::descriptors::IoPoll::Ready(bytes) if bytes.is_empty() => break,
|
|
2028
|
-
crate::descriptors::IoPoll::Ready(bytes) => {
|
|
2029
|
-
consumed = true;
|
|
2030
|
-
if bytes[0] == b'\n' {
|
|
2031
|
-
break;
|
|
2032
|
-
}
|
|
2033
|
-
line.push(bytes[0]);
|
|
2130
|
+
let Some(byte) = byte else { break };
|
|
2131
|
+
cursor += 1;
|
|
2132
|
+
if escaped {
|
|
2133
|
+
if byte != b'\n' && byte != 0 {
|
|
2134
|
+
record.push(byte);
|
|
2034
2135
|
}
|
|
2035
|
-
|
|
2136
|
+
escaped = false;
|
|
2137
|
+
} else if byte == delimiter {
|
|
2138
|
+
terminated = true;
|
|
2139
|
+
break;
|
|
2140
|
+
} else if !raw && byte == b'\\' {
|
|
2141
|
+
escaped = true;
|
|
2142
|
+
} else if byte != 0 {
|
|
2143
|
+
record.push(byte);
|
|
2036
2144
|
}
|
|
2037
2145
|
}
|
|
2038
|
-
|
|
2039
|
-
None
|
|
2040
|
-
} else {
|
|
2041
|
-
Some(String::from_utf8_lossy(&line).into_owned())
|
|
2042
|
-
}
|
|
2146
|
+
(String::from_utf8_lossy(&record).into_owned(), terminated)
|
|
2043
2147
|
}
|
|
2044
2148
|
|
|
2045
2149
|
fn cmd_which(interp: &mut CommandContext<'_>, args: &[String], io: &mut Io) -> i32 {
|