just-bash 0.1.5__py3-none-any.whl
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.
- just_bash/__init__.py +55 -0
- just_bash/ast/__init__.py +213 -0
- just_bash/ast/factory.py +320 -0
- just_bash/ast/types.py +953 -0
- just_bash/bash.py +220 -0
- just_bash/commands/__init__.py +23 -0
- just_bash/commands/argv/__init__.py +5 -0
- just_bash/commands/argv/argv.py +21 -0
- just_bash/commands/awk/__init__.py +5 -0
- just_bash/commands/awk/awk.py +1168 -0
- just_bash/commands/base64/__init__.py +5 -0
- just_bash/commands/base64/base64.py +138 -0
- just_bash/commands/basename/__init__.py +5 -0
- just_bash/commands/basename/basename.py +72 -0
- just_bash/commands/bash/__init__.py +5 -0
- just_bash/commands/bash/bash.py +188 -0
- just_bash/commands/cat/__init__.py +5 -0
- just_bash/commands/cat/cat.py +173 -0
- just_bash/commands/checksum/__init__.py +5 -0
- just_bash/commands/checksum/checksum.py +179 -0
- just_bash/commands/chmod/__init__.py +5 -0
- just_bash/commands/chmod/chmod.py +216 -0
- just_bash/commands/column/__init__.py +5 -0
- just_bash/commands/column/column.py +180 -0
- just_bash/commands/comm/__init__.py +5 -0
- just_bash/commands/comm/comm.py +150 -0
- just_bash/commands/compression/__init__.py +5 -0
- just_bash/commands/compression/compression.py +298 -0
- just_bash/commands/cp/__init__.py +5 -0
- just_bash/commands/cp/cp.py +149 -0
- just_bash/commands/curl/__init__.py +5 -0
- just_bash/commands/curl/curl.py +801 -0
- just_bash/commands/cut/__init__.py +5 -0
- just_bash/commands/cut/cut.py +327 -0
- just_bash/commands/date/__init__.py +5 -0
- just_bash/commands/date/date.py +258 -0
- just_bash/commands/diff/__init__.py +5 -0
- just_bash/commands/diff/diff.py +118 -0
- just_bash/commands/dirname/__init__.py +5 -0
- just_bash/commands/dirname/dirname.py +56 -0
- just_bash/commands/du/__init__.py +5 -0
- just_bash/commands/du/du.py +150 -0
- just_bash/commands/echo/__init__.py +5 -0
- just_bash/commands/echo/echo.py +125 -0
- just_bash/commands/env/__init__.py +5 -0
- just_bash/commands/env/env.py +163 -0
- just_bash/commands/expand/__init__.py +5 -0
- just_bash/commands/expand/expand.py +299 -0
- just_bash/commands/expr/__init__.py +5 -0
- just_bash/commands/expr/expr.py +273 -0
- just_bash/commands/file/__init__.py +5 -0
- just_bash/commands/file/file.py +274 -0
- just_bash/commands/find/__init__.py +5 -0
- just_bash/commands/find/find.py +623 -0
- just_bash/commands/fold/__init__.py +5 -0
- just_bash/commands/fold/fold.py +160 -0
- just_bash/commands/grep/__init__.py +5 -0
- just_bash/commands/grep/grep.py +418 -0
- just_bash/commands/head/__init__.py +5 -0
- just_bash/commands/head/head.py +167 -0
- just_bash/commands/help/__init__.py +5 -0
- just_bash/commands/help/help.py +67 -0
- just_bash/commands/hostname/__init__.py +5 -0
- just_bash/commands/hostname/hostname.py +21 -0
- just_bash/commands/html_to_markdown/__init__.py +5 -0
- just_bash/commands/html_to_markdown/html_to_markdown.py +191 -0
- just_bash/commands/join/__init__.py +5 -0
- just_bash/commands/join/join.py +252 -0
- just_bash/commands/jq/__init__.py +5 -0
- just_bash/commands/jq/jq.py +280 -0
- just_bash/commands/ln/__init__.py +5 -0
- just_bash/commands/ln/ln.py +127 -0
- just_bash/commands/ls/__init__.py +5 -0
- just_bash/commands/ls/ls.py +280 -0
- just_bash/commands/mkdir/__init__.py +5 -0
- just_bash/commands/mkdir/mkdir.py +92 -0
- just_bash/commands/mv/__init__.py +5 -0
- just_bash/commands/mv/mv.py +142 -0
- just_bash/commands/nl/__init__.py +5 -0
- just_bash/commands/nl/nl.py +180 -0
- just_bash/commands/od/__init__.py +5 -0
- just_bash/commands/od/od.py +157 -0
- just_bash/commands/paste/__init__.py +5 -0
- just_bash/commands/paste/paste.py +100 -0
- just_bash/commands/printf/__init__.py +5 -0
- just_bash/commands/printf/printf.py +157 -0
- just_bash/commands/pwd/__init__.py +5 -0
- just_bash/commands/pwd/pwd.py +23 -0
- just_bash/commands/read/__init__.py +5 -0
- just_bash/commands/read/read.py +185 -0
- just_bash/commands/readlink/__init__.py +5 -0
- just_bash/commands/readlink/readlink.py +86 -0
- just_bash/commands/registry.py +844 -0
- just_bash/commands/rev/__init__.py +5 -0
- just_bash/commands/rev/rev.py +74 -0
- just_bash/commands/rg/__init__.py +5 -0
- just_bash/commands/rg/rg.py +1048 -0
- just_bash/commands/rm/__init__.py +5 -0
- just_bash/commands/rm/rm.py +106 -0
- just_bash/commands/search_engine/__init__.py +13 -0
- just_bash/commands/search_engine/matcher.py +170 -0
- just_bash/commands/search_engine/regex.py +159 -0
- just_bash/commands/sed/__init__.py +5 -0
- just_bash/commands/sed/sed.py +863 -0
- just_bash/commands/seq/__init__.py +5 -0
- just_bash/commands/seq/seq.py +190 -0
- just_bash/commands/shell/__init__.py +5 -0
- just_bash/commands/shell/shell.py +206 -0
- just_bash/commands/sleep/__init__.py +5 -0
- just_bash/commands/sleep/sleep.py +62 -0
- just_bash/commands/sort/__init__.py +5 -0
- just_bash/commands/sort/sort.py +411 -0
- just_bash/commands/split/__init__.py +5 -0
- just_bash/commands/split/split.py +237 -0
- just_bash/commands/sqlite3/__init__.py +5 -0
- just_bash/commands/sqlite3/sqlite3_cmd.py +505 -0
- just_bash/commands/stat/__init__.py +5 -0
- just_bash/commands/stat/stat.py +150 -0
- just_bash/commands/strings/__init__.py +5 -0
- just_bash/commands/strings/strings.py +150 -0
- just_bash/commands/tac/__init__.py +5 -0
- just_bash/commands/tac/tac.py +158 -0
- just_bash/commands/tail/__init__.py +5 -0
- just_bash/commands/tail/tail.py +180 -0
- just_bash/commands/tar/__init__.py +5 -0
- just_bash/commands/tar/tar.py +1067 -0
- just_bash/commands/tee/__init__.py +5 -0
- just_bash/commands/tee/tee.py +63 -0
- just_bash/commands/timeout/__init__.py +5 -0
- just_bash/commands/timeout/timeout.py +188 -0
- just_bash/commands/touch/__init__.py +5 -0
- just_bash/commands/touch/touch.py +91 -0
- just_bash/commands/tr/__init__.py +5 -0
- just_bash/commands/tr/tr.py +297 -0
- just_bash/commands/tree/__init__.py +5 -0
- just_bash/commands/tree/tree.py +139 -0
- just_bash/commands/true/__init__.py +5 -0
- just_bash/commands/true/true.py +32 -0
- just_bash/commands/uniq/__init__.py +5 -0
- just_bash/commands/uniq/uniq.py +323 -0
- just_bash/commands/wc/__init__.py +5 -0
- just_bash/commands/wc/wc.py +169 -0
- just_bash/commands/which/__init__.py +5 -0
- just_bash/commands/which/which.py +52 -0
- just_bash/commands/xan/__init__.py +5 -0
- just_bash/commands/xan/xan.py +1663 -0
- just_bash/commands/xargs/__init__.py +5 -0
- just_bash/commands/xargs/xargs.py +136 -0
- just_bash/commands/yq/__init__.py +5 -0
- just_bash/commands/yq/yq.py +848 -0
- just_bash/fs/__init__.py +29 -0
- just_bash/fs/in_memory_fs.py +621 -0
- just_bash/fs/mountable_fs.py +504 -0
- just_bash/fs/overlay_fs.py +894 -0
- just_bash/fs/read_write_fs.py +455 -0
- just_bash/interpreter/__init__.py +37 -0
- just_bash/interpreter/builtins/__init__.py +92 -0
- just_bash/interpreter/builtins/alias.py +154 -0
- just_bash/interpreter/builtins/cd.py +76 -0
- just_bash/interpreter/builtins/control.py +127 -0
- just_bash/interpreter/builtins/declare.py +336 -0
- just_bash/interpreter/builtins/export.py +56 -0
- just_bash/interpreter/builtins/let.py +44 -0
- just_bash/interpreter/builtins/local.py +57 -0
- just_bash/interpreter/builtins/mapfile.py +152 -0
- just_bash/interpreter/builtins/misc.py +378 -0
- just_bash/interpreter/builtins/readonly.py +80 -0
- just_bash/interpreter/builtins/set.py +234 -0
- just_bash/interpreter/builtins/shopt.py +201 -0
- just_bash/interpreter/builtins/source.py +136 -0
- just_bash/interpreter/builtins/test.py +290 -0
- just_bash/interpreter/builtins/unset.py +53 -0
- just_bash/interpreter/conditionals.py +387 -0
- just_bash/interpreter/control_flow.py +381 -0
- just_bash/interpreter/errors.py +116 -0
- just_bash/interpreter/expansion.py +1156 -0
- just_bash/interpreter/interpreter.py +813 -0
- just_bash/interpreter/types.py +134 -0
- just_bash/network/__init__.py +1 -0
- just_bash/parser/__init__.py +39 -0
- just_bash/parser/lexer.py +948 -0
- just_bash/parser/parser.py +2162 -0
- just_bash/py.typed +0 -0
- just_bash/query_engine/__init__.py +83 -0
- just_bash/query_engine/builtins/__init__.py +1283 -0
- just_bash/query_engine/evaluator.py +578 -0
- just_bash/query_engine/parser.py +525 -0
- just_bash/query_engine/tokenizer.py +329 -0
- just_bash/query_engine/types.py +373 -0
- just_bash/types.py +180 -0
- just_bash-0.1.5.dist-info/METADATA +410 -0
- just_bash-0.1.5.dist-info/RECORD +193 -0
- just_bash-0.1.5.dist-info/WHEEL +4 -0
just_bash/__init__.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
just-bash: A pure Python bash interpreter with in-memory virtual filesystem.
|
|
3
|
+
|
|
4
|
+
Designed for AI agents needing a secure, sandboxed bash environment.
|
|
5
|
+
|
|
6
|
+
Example usage:
|
|
7
|
+
from just_bash import Bash
|
|
8
|
+
|
|
9
|
+
bash = Bash()
|
|
10
|
+
result = await bash.exec("echo hello world")
|
|
11
|
+
print(result.stdout) # "hello world\\n"
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .bash import Bash
|
|
15
|
+
from .types import (
|
|
16
|
+
ExecResult,
|
|
17
|
+
BashExecResult,
|
|
18
|
+
ExecutionLimits,
|
|
19
|
+
NetworkConfig,
|
|
20
|
+
IFileSystem,
|
|
21
|
+
FsStat,
|
|
22
|
+
CommandContext,
|
|
23
|
+
Command,
|
|
24
|
+
OK,
|
|
25
|
+
FAIL,
|
|
26
|
+
)
|
|
27
|
+
from .fs import InMemoryFs
|
|
28
|
+
from .parser import Parser, parse, ParseException
|
|
29
|
+
|
|
30
|
+
__version__ = "0.1.0"
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
# Main API
|
|
34
|
+
"Bash",
|
|
35
|
+
# Core types
|
|
36
|
+
"ExecResult",
|
|
37
|
+
"BashExecResult",
|
|
38
|
+
"ExecutionLimits",
|
|
39
|
+
"NetworkConfig",
|
|
40
|
+
"IFileSystem",
|
|
41
|
+
"FsStat",
|
|
42
|
+
"CommandContext",
|
|
43
|
+
"Command",
|
|
44
|
+
# Filesystem
|
|
45
|
+
"InMemoryFs",
|
|
46
|
+
# Parser
|
|
47
|
+
"Parser",
|
|
48
|
+
"parse",
|
|
49
|
+
"ParseException",
|
|
50
|
+
# Constants
|
|
51
|
+
"OK",
|
|
52
|
+
"FAIL",
|
|
53
|
+
# Version
|
|
54
|
+
"__version__",
|
|
55
|
+
]
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""AST types and factory functions for just-bash."""
|
|
2
|
+
|
|
3
|
+
from .types import (
|
|
4
|
+
# Base types
|
|
5
|
+
Position,
|
|
6
|
+
Span,
|
|
7
|
+
# Script & Statements
|
|
8
|
+
ScriptNode,
|
|
9
|
+
StatementNode,
|
|
10
|
+
# Pipelines & Commands
|
|
11
|
+
PipelineNode,
|
|
12
|
+
SimpleCommandNode,
|
|
13
|
+
CommandNode,
|
|
14
|
+
CompoundCommandNode,
|
|
15
|
+
# Control flow
|
|
16
|
+
IfNode,
|
|
17
|
+
IfClause,
|
|
18
|
+
ForNode,
|
|
19
|
+
CStyleForNode,
|
|
20
|
+
WhileNode,
|
|
21
|
+
UntilNode,
|
|
22
|
+
CaseNode,
|
|
23
|
+
CaseItemNode,
|
|
24
|
+
SubshellNode,
|
|
25
|
+
GroupNode,
|
|
26
|
+
ArithmeticCommandNode,
|
|
27
|
+
ConditionalCommandNode,
|
|
28
|
+
# Functions
|
|
29
|
+
FunctionDefNode,
|
|
30
|
+
# Assignments
|
|
31
|
+
AssignmentNode,
|
|
32
|
+
# Redirections
|
|
33
|
+
RedirectionNode,
|
|
34
|
+
RedirectionOperator,
|
|
35
|
+
HereDocNode,
|
|
36
|
+
# Words
|
|
37
|
+
WordNode,
|
|
38
|
+
WordPart,
|
|
39
|
+
LiteralPart,
|
|
40
|
+
SingleQuotedPart,
|
|
41
|
+
DoubleQuotedPart,
|
|
42
|
+
EscapedPart,
|
|
43
|
+
GlobPart,
|
|
44
|
+
TildeExpansionPart,
|
|
45
|
+
# Parameter expansion
|
|
46
|
+
ParameterExpansionPart,
|
|
47
|
+
ParameterOperation,
|
|
48
|
+
DefaultValueOp,
|
|
49
|
+
AssignDefaultOp,
|
|
50
|
+
ErrorIfUnsetOp,
|
|
51
|
+
UseAlternativeOp,
|
|
52
|
+
LengthOp,
|
|
53
|
+
LengthSliceErrorOp,
|
|
54
|
+
SubstringOp,
|
|
55
|
+
PatternRemovalOp,
|
|
56
|
+
PatternReplacementOp,
|
|
57
|
+
CaseModificationOp,
|
|
58
|
+
TransformOp,
|
|
59
|
+
IndirectionOp,
|
|
60
|
+
ArrayKeysOp,
|
|
61
|
+
VarNamePrefixOp,
|
|
62
|
+
# Command substitution
|
|
63
|
+
CommandSubstitutionPart,
|
|
64
|
+
# Arithmetic
|
|
65
|
+
ArithmeticExpansionPart,
|
|
66
|
+
ArithmeticExpressionNode,
|
|
67
|
+
ArithExpr,
|
|
68
|
+
ArithNumberNode,
|
|
69
|
+
ArithVariableNode,
|
|
70
|
+
ArithBinaryNode,
|
|
71
|
+
ArithBinaryOperator,
|
|
72
|
+
ArithUnaryNode,
|
|
73
|
+
ArithUnaryOperator,
|
|
74
|
+
ArithTernaryNode,
|
|
75
|
+
ArithAssignmentNode,
|
|
76
|
+
ArithAssignmentOperator,
|
|
77
|
+
ArithGroupNode,
|
|
78
|
+
ArithNestedNode,
|
|
79
|
+
ArithCommandSubstNode,
|
|
80
|
+
ArithBracedExpansionNode,
|
|
81
|
+
ArithDynamicBaseNode,
|
|
82
|
+
ArithDynamicNumberNode,
|
|
83
|
+
ArithConcatNode,
|
|
84
|
+
ArithArrayElementNode,
|
|
85
|
+
ArithDoubleSubscriptNode,
|
|
86
|
+
ArithNumberSubscriptNode,
|
|
87
|
+
# Process substitution
|
|
88
|
+
ProcessSubstitutionPart,
|
|
89
|
+
# Brace expansion
|
|
90
|
+
BraceExpansionPart,
|
|
91
|
+
BraceItem,
|
|
92
|
+
BraceWordItem,
|
|
93
|
+
BraceRangeItem,
|
|
94
|
+
# Conditional expressions
|
|
95
|
+
ConditionalExpressionNode,
|
|
96
|
+
CondBinaryNode,
|
|
97
|
+
CondBinaryOperator,
|
|
98
|
+
CondUnaryNode,
|
|
99
|
+
CondUnaryOperator,
|
|
100
|
+
CondNotNode,
|
|
101
|
+
CondAndNode,
|
|
102
|
+
CondOrNode,
|
|
103
|
+
CondGroupNode,
|
|
104
|
+
CondWordNode,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
from . import factory as AST
|
|
108
|
+
|
|
109
|
+
__all__ = [
|
|
110
|
+
# Base types
|
|
111
|
+
"Position",
|
|
112
|
+
"Span",
|
|
113
|
+
# Script & Statements
|
|
114
|
+
"ScriptNode",
|
|
115
|
+
"StatementNode",
|
|
116
|
+
# Pipelines & Commands
|
|
117
|
+
"PipelineNode",
|
|
118
|
+
"SimpleCommandNode",
|
|
119
|
+
"CommandNode",
|
|
120
|
+
"CompoundCommandNode",
|
|
121
|
+
# Control flow
|
|
122
|
+
"IfNode",
|
|
123
|
+
"IfClause",
|
|
124
|
+
"ForNode",
|
|
125
|
+
"CStyleForNode",
|
|
126
|
+
"WhileNode",
|
|
127
|
+
"UntilNode",
|
|
128
|
+
"CaseNode",
|
|
129
|
+
"CaseItemNode",
|
|
130
|
+
"SubshellNode",
|
|
131
|
+
"GroupNode",
|
|
132
|
+
"ArithmeticCommandNode",
|
|
133
|
+
"ConditionalCommandNode",
|
|
134
|
+
# Functions
|
|
135
|
+
"FunctionDefNode",
|
|
136
|
+
# Assignments
|
|
137
|
+
"AssignmentNode",
|
|
138
|
+
# Redirections
|
|
139
|
+
"RedirectionNode",
|
|
140
|
+
"RedirectionOperator",
|
|
141
|
+
"HereDocNode",
|
|
142
|
+
# Words
|
|
143
|
+
"WordNode",
|
|
144
|
+
"WordPart",
|
|
145
|
+
"LiteralPart",
|
|
146
|
+
"SingleQuotedPart",
|
|
147
|
+
"DoubleQuotedPart",
|
|
148
|
+
"EscapedPart",
|
|
149
|
+
"GlobPart",
|
|
150
|
+
"TildeExpansionPart",
|
|
151
|
+
# Parameter expansion
|
|
152
|
+
"ParameterExpansionPart",
|
|
153
|
+
"ParameterOperation",
|
|
154
|
+
"DefaultValueOp",
|
|
155
|
+
"AssignDefaultOp",
|
|
156
|
+
"ErrorIfUnsetOp",
|
|
157
|
+
"UseAlternativeOp",
|
|
158
|
+
"LengthOp",
|
|
159
|
+
"LengthSliceErrorOp",
|
|
160
|
+
"SubstringOp",
|
|
161
|
+
"PatternRemovalOp",
|
|
162
|
+
"PatternReplacementOp",
|
|
163
|
+
"CaseModificationOp",
|
|
164
|
+
"TransformOp",
|
|
165
|
+
"IndirectionOp",
|
|
166
|
+
"ArrayKeysOp",
|
|
167
|
+
"VarNamePrefixOp",
|
|
168
|
+
# Command substitution
|
|
169
|
+
"CommandSubstitutionPart",
|
|
170
|
+
# Arithmetic
|
|
171
|
+
"ArithmeticExpansionPart",
|
|
172
|
+
"ArithmeticExpressionNode",
|
|
173
|
+
"ArithExpr",
|
|
174
|
+
"ArithNumberNode",
|
|
175
|
+
"ArithVariableNode",
|
|
176
|
+
"ArithBinaryNode",
|
|
177
|
+
"ArithBinaryOperator",
|
|
178
|
+
"ArithUnaryNode",
|
|
179
|
+
"ArithUnaryOperator",
|
|
180
|
+
"ArithTernaryNode",
|
|
181
|
+
"ArithAssignmentNode",
|
|
182
|
+
"ArithAssignmentOperator",
|
|
183
|
+
"ArithGroupNode",
|
|
184
|
+
"ArithNestedNode",
|
|
185
|
+
"ArithCommandSubstNode",
|
|
186
|
+
"ArithBracedExpansionNode",
|
|
187
|
+
"ArithDynamicBaseNode",
|
|
188
|
+
"ArithDynamicNumberNode",
|
|
189
|
+
"ArithConcatNode",
|
|
190
|
+
"ArithArrayElementNode",
|
|
191
|
+
"ArithDoubleSubscriptNode",
|
|
192
|
+
"ArithNumberSubscriptNode",
|
|
193
|
+
# Process substitution
|
|
194
|
+
"ProcessSubstitutionPart",
|
|
195
|
+
# Brace expansion
|
|
196
|
+
"BraceExpansionPart",
|
|
197
|
+
"BraceItem",
|
|
198
|
+
"BraceWordItem",
|
|
199
|
+
"BraceRangeItem",
|
|
200
|
+
# Conditional expressions
|
|
201
|
+
"ConditionalExpressionNode",
|
|
202
|
+
"CondBinaryNode",
|
|
203
|
+
"CondBinaryOperator",
|
|
204
|
+
"CondUnaryNode",
|
|
205
|
+
"CondUnaryOperator",
|
|
206
|
+
"CondNotNode",
|
|
207
|
+
"CondAndNode",
|
|
208
|
+
"CondOrNode",
|
|
209
|
+
"CondGroupNode",
|
|
210
|
+
"CondWordNode",
|
|
211
|
+
# Factory module
|
|
212
|
+
"AST",
|
|
213
|
+
]
|
just_bash/ast/factory.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AST Factory Functions
|
|
3
|
+
|
|
4
|
+
Convenience functions for building AST nodes, matching the TypeScript AST object pattern.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional, Sequence
|
|
8
|
+
|
|
9
|
+
from .types import (
|
|
10
|
+
# Core nodes
|
|
11
|
+
ScriptNode,
|
|
12
|
+
StatementNode,
|
|
13
|
+
PipelineNode,
|
|
14
|
+
SimpleCommandNode,
|
|
15
|
+
WordNode,
|
|
16
|
+
WordPart,
|
|
17
|
+
AssignmentNode,
|
|
18
|
+
RedirectionNode,
|
|
19
|
+
RedirectionOperator,
|
|
20
|
+
HereDocNode,
|
|
21
|
+
# Word parts
|
|
22
|
+
LiteralPart,
|
|
23
|
+
SingleQuotedPart,
|
|
24
|
+
DoubleQuotedPart,
|
|
25
|
+
EscapedPart,
|
|
26
|
+
ParameterExpansionPart,
|
|
27
|
+
ParameterOperation,
|
|
28
|
+
CommandSubstitutionPart,
|
|
29
|
+
ArithmeticExpansionPart,
|
|
30
|
+
ArithmeticExpressionNode,
|
|
31
|
+
# Control flow
|
|
32
|
+
IfNode,
|
|
33
|
+
IfClause,
|
|
34
|
+
ForNode,
|
|
35
|
+
WhileNode,
|
|
36
|
+
UntilNode,
|
|
37
|
+
CaseNode,
|
|
38
|
+
CaseItemNode,
|
|
39
|
+
SubshellNode,
|
|
40
|
+
GroupNode,
|
|
41
|
+
FunctionDefNode,
|
|
42
|
+
ConditionalCommandNode,
|
|
43
|
+
ArithmeticCommandNode,
|
|
44
|
+
CompoundCommandNode,
|
|
45
|
+
ConditionalExpressionNode,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def script(statements: Sequence[StatementNode]) -> ScriptNode:
|
|
50
|
+
"""Create a script node."""
|
|
51
|
+
return ScriptNode(statements=tuple(statements))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def statement(
|
|
55
|
+
pipelines: Sequence[PipelineNode],
|
|
56
|
+
operators: Sequence[str] | None = None,
|
|
57
|
+
background: bool = False,
|
|
58
|
+
) -> StatementNode:
|
|
59
|
+
"""Create a statement node."""
|
|
60
|
+
ops = tuple(operators) if operators else ()
|
|
61
|
+
return StatementNode(
|
|
62
|
+
pipelines=tuple(pipelines),
|
|
63
|
+
operators=ops, # type: ignore
|
|
64
|
+
background=background,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def pipeline(
|
|
69
|
+
commands: Sequence["CommandNode"], # type: ignore
|
|
70
|
+
negated: bool = False,
|
|
71
|
+
) -> PipelineNode:
|
|
72
|
+
"""Create a pipeline node."""
|
|
73
|
+
return PipelineNode(commands=tuple(commands), negated=negated)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def simple_command(
|
|
77
|
+
name: WordNode | None = None,
|
|
78
|
+
args: Sequence[WordNode] | None = None,
|
|
79
|
+
assignments: Sequence[AssignmentNode] | None = None,
|
|
80
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
81
|
+
) -> SimpleCommandNode:
|
|
82
|
+
"""Create a simple command node."""
|
|
83
|
+
return SimpleCommandNode(
|
|
84
|
+
name=name,
|
|
85
|
+
args=tuple(args) if args else (),
|
|
86
|
+
assignments=tuple(assignments) if assignments else (),
|
|
87
|
+
redirections=tuple(redirections) if redirections else (),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def word(parts: Sequence[WordPart]) -> WordNode:
|
|
92
|
+
"""Create a word node."""
|
|
93
|
+
return WordNode(parts=tuple(parts))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def literal(value: str) -> LiteralPart:
|
|
97
|
+
"""Create a literal part."""
|
|
98
|
+
return LiteralPart(value=value)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def single_quoted(value: str) -> SingleQuotedPart:
|
|
102
|
+
"""Create a single-quoted part."""
|
|
103
|
+
return SingleQuotedPart(value=value)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def double_quoted(parts: Sequence[WordPart]) -> DoubleQuotedPart:
|
|
107
|
+
"""Create a double-quoted part."""
|
|
108
|
+
return DoubleQuotedPart(parts=tuple(parts))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def escaped(value: str) -> EscapedPart:
|
|
112
|
+
"""Create an escaped character part."""
|
|
113
|
+
return EscapedPart(value=value)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def parameter_expansion(
|
|
117
|
+
parameter: str,
|
|
118
|
+
operation: ParameterOperation | None = None,
|
|
119
|
+
) -> ParameterExpansionPart:
|
|
120
|
+
"""Create a parameter expansion part."""
|
|
121
|
+
return ParameterExpansionPart(parameter=parameter, operation=operation)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def command_substitution(
|
|
125
|
+
body: ScriptNode,
|
|
126
|
+
legacy: bool = False,
|
|
127
|
+
) -> CommandSubstitutionPart:
|
|
128
|
+
"""Create a command substitution part."""
|
|
129
|
+
return CommandSubstitutionPart(body=body, legacy=legacy)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def arithmetic_expansion(
|
|
133
|
+
expression: ArithmeticExpressionNode,
|
|
134
|
+
) -> ArithmeticExpansionPart:
|
|
135
|
+
"""Create an arithmetic expansion part."""
|
|
136
|
+
return ArithmeticExpansionPart(expression=expression)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def assignment(
|
|
140
|
+
name: str,
|
|
141
|
+
value: WordNode | None = None,
|
|
142
|
+
append: bool = False,
|
|
143
|
+
array: Sequence[WordNode] | None = None,
|
|
144
|
+
) -> AssignmentNode:
|
|
145
|
+
"""Create an assignment node."""
|
|
146
|
+
return AssignmentNode(
|
|
147
|
+
name=name,
|
|
148
|
+
value=value,
|
|
149
|
+
append=append,
|
|
150
|
+
array=tuple(array) if array else None,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def redirection(
|
|
155
|
+
operator: RedirectionOperator,
|
|
156
|
+
target: WordNode | HereDocNode,
|
|
157
|
+
fd: int | None = None,
|
|
158
|
+
) -> RedirectionNode:
|
|
159
|
+
"""Create a redirection node."""
|
|
160
|
+
return RedirectionNode(fd=fd, operator=operator, target=target)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def here_doc(
|
|
164
|
+
delimiter: str,
|
|
165
|
+
content: WordNode,
|
|
166
|
+
strip_tabs: bool = False,
|
|
167
|
+
quoted: bool = False,
|
|
168
|
+
) -> HereDocNode:
|
|
169
|
+
"""Create a here-document node."""
|
|
170
|
+
return HereDocNode(
|
|
171
|
+
delimiter=delimiter,
|
|
172
|
+
content=content,
|
|
173
|
+
strip_tabs=strip_tabs,
|
|
174
|
+
quoted=quoted,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def if_node(
|
|
179
|
+
clauses: Sequence[IfClause],
|
|
180
|
+
else_body: Sequence[StatementNode] | None = None,
|
|
181
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
182
|
+
) -> IfNode:
|
|
183
|
+
"""Create an if node."""
|
|
184
|
+
return IfNode(
|
|
185
|
+
clauses=tuple(clauses),
|
|
186
|
+
else_body=tuple(else_body) if else_body else None,
|
|
187
|
+
redirections=tuple(redirections) if redirections else (),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def if_clause(
|
|
192
|
+
condition: Sequence[StatementNode],
|
|
193
|
+
body: Sequence[StatementNode],
|
|
194
|
+
) -> IfClause:
|
|
195
|
+
"""Create an if clause."""
|
|
196
|
+
return IfClause(condition=tuple(condition), body=tuple(body))
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def for_node(
|
|
200
|
+
variable: str,
|
|
201
|
+
words: Sequence[WordNode] | None,
|
|
202
|
+
body: Sequence[StatementNode],
|
|
203
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
204
|
+
) -> ForNode:
|
|
205
|
+
"""Create a for node."""
|
|
206
|
+
return ForNode(
|
|
207
|
+
variable=variable,
|
|
208
|
+
words=tuple(words) if words else None,
|
|
209
|
+
body=tuple(body),
|
|
210
|
+
redirections=tuple(redirections) if redirections else (),
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def while_node(
|
|
215
|
+
condition: Sequence[StatementNode],
|
|
216
|
+
body: Sequence[StatementNode],
|
|
217
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
218
|
+
) -> WhileNode:
|
|
219
|
+
"""Create a while node."""
|
|
220
|
+
return WhileNode(
|
|
221
|
+
condition=tuple(condition),
|
|
222
|
+
body=tuple(body),
|
|
223
|
+
redirections=tuple(redirections) if redirections else (),
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def until_node(
|
|
228
|
+
condition: Sequence[StatementNode],
|
|
229
|
+
body: Sequence[StatementNode],
|
|
230
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
231
|
+
) -> UntilNode:
|
|
232
|
+
"""Create an until node."""
|
|
233
|
+
return UntilNode(
|
|
234
|
+
condition=tuple(condition),
|
|
235
|
+
body=tuple(body),
|
|
236
|
+
redirections=tuple(redirections) if redirections else (),
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def case_node(
|
|
241
|
+
word: WordNode,
|
|
242
|
+
items: Sequence[CaseItemNode],
|
|
243
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
244
|
+
) -> CaseNode:
|
|
245
|
+
"""Create a case node."""
|
|
246
|
+
return CaseNode(
|
|
247
|
+
word=word,
|
|
248
|
+
items=tuple(items),
|
|
249
|
+
redirections=tuple(redirections) if redirections else (),
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def case_item(
|
|
254
|
+
patterns: Sequence[WordNode],
|
|
255
|
+
body: Sequence[StatementNode],
|
|
256
|
+
terminator: str = ";;",
|
|
257
|
+
) -> CaseItemNode:
|
|
258
|
+
"""Create a case item node."""
|
|
259
|
+
return CaseItemNode(
|
|
260
|
+
patterns=tuple(patterns),
|
|
261
|
+
body=tuple(body),
|
|
262
|
+
terminator=terminator, # type: ignore
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def subshell(
|
|
267
|
+
body: Sequence[StatementNode],
|
|
268
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
269
|
+
) -> SubshellNode:
|
|
270
|
+
"""Create a subshell node."""
|
|
271
|
+
return SubshellNode(
|
|
272
|
+
body=tuple(body),
|
|
273
|
+
redirections=tuple(redirections) if redirections else (),
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def group(
|
|
278
|
+
body: Sequence[StatementNode],
|
|
279
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
280
|
+
) -> GroupNode:
|
|
281
|
+
"""Create a command group node."""
|
|
282
|
+
return GroupNode(
|
|
283
|
+
body=tuple(body),
|
|
284
|
+
redirections=tuple(redirections) if redirections else (),
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def function_def(
|
|
289
|
+
name: str,
|
|
290
|
+
body: CompoundCommandNode,
|
|
291
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
292
|
+
) -> FunctionDefNode:
|
|
293
|
+
"""Create a function definition node."""
|
|
294
|
+
return FunctionDefNode(
|
|
295
|
+
name=name,
|
|
296
|
+
body=body,
|
|
297
|
+
redirections=tuple(redirections) if redirections else (),
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def conditional_command(
|
|
302
|
+
expression: ConditionalExpressionNode,
|
|
303
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
304
|
+
) -> ConditionalCommandNode:
|
|
305
|
+
"""Create a conditional command node ([[ ]])."""
|
|
306
|
+
return ConditionalCommandNode(
|
|
307
|
+
expression=expression,
|
|
308
|
+
redirections=tuple(redirections) if redirections else (),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def arithmetic_command(
|
|
313
|
+
expression: ArithmeticExpressionNode,
|
|
314
|
+
redirections: Sequence[RedirectionNode] | None = None,
|
|
315
|
+
) -> ArithmeticCommandNode:
|
|
316
|
+
"""Create an arithmetic command node ((( )))."""
|
|
317
|
+
return ArithmeticCommandNode(
|
|
318
|
+
expression=expression,
|
|
319
|
+
redirections=tuple(redirections) if redirections else (),
|
|
320
|
+
)
|