Skip to content

Commit 16adabd

Browse files
various bug fixes for judo
1 parent bc45d50 commit 16adabd

File tree

11 files changed

+63
-54
lines changed

11 files changed

+63
-54
lines changed

bashparser.egg-info/PKG-INFO

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Metadata-Version: 2.1
22
Name: bashparser
3-
Version: 0.5
3+
Version: 0.6
44
Summary: A framework for manipulating and analysing bash scripts
55
Home-page: https://github.com/BlankCanvasStudio/bashparse
66
Author: Spencer Stingley

bashparser/ast.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,13 @@ def apply_fn(node):
4444
for part in cmd.parts:
4545
word += str(NodeVisitor(part)) + ' '
4646
word = word[:-1] + ')'
47-
47+
self._string = self._string + word + ' '
4848
return DONT_DESCEND
4949

50-
elif hasattr(node, 'word'): word = node.word
50+
elif hasattr(node, 'word'):
51+
word = node.word
52+
self._string = self._string + word + ' '
53+
return DONT_DESCEND
5154
else:
5255
print('node: ', node.dump())
5356
raise ValueError('Error! Unsupported node kind encountered when converting NodeVisitor to string: ', node.kind)

bashparser/chunk.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ def apply_fn(node, vstr, chunk_index, node_num):
3737
if node.kind == 'assignment':
3838
name = node.word.split('=', maxsplit=1)[0]
3939
if name not in chunk_index:
40-
new_chunk = Chunk(name, start=vstr.path, end=None)
40+
new_chunk = Chunk(name, start=[node_num] + vstr.path, end=None)
4141
chunk_index[name] = [new_chunk] # We use an array here cause there could be multiple chunks per variable
4242
else:
4343
chunk_index[name][-1].end = vstr.path
44-
new_chunk = Chunk(name, start=vstr.path, end=None)
44+
new_chunk = Chunk(name, start=[node_num] + vstr.path, end=None)
4545
chunk_index[name] += new_chunk
4646
if node.kind == 'parameter':
4747
name = node.value
4848
if name in chunk_index: # check to see if variable has been declared
49-
chunk_index[name][-1].end = vstr.path[:-1] # This is going to update every time. Also path should be to word node not param node (imo)
49+
chunk_index[name][-1].end = [node_num] + vstr.path[:-1] # This is going to update every time. Also path should be to word node not param node (imo)
5050
# A condition could be added here to iterate up the path until we hit a command node or an equivalent. But not useful quite yet
5151
return CONT
5252

bashparser/test/test_ast.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from unittest import TestCase
2-
from bashparse import NodeVisitor
3-
import bashlex, bashparse.ast, copy
2+
from bashparser import NodeVisitor
3+
import bashlex, bashparser.ast, copy
44

55
class TestAst(TestCase):
66

@@ -55,13 +55,13 @@ def test_apply(self):
5555
def apply_fn(node, vstr):
5656
if vstr.path == [1]:
5757
node.word = 'DONT_DESCEND'
58-
return bashparse.ast.DONT_DESCEND
58+
return bashparser.ast.DONT_DESCEND
5959
elif vstr.path == [2,0]:
6060
node.word = 'HALT'
61-
return bashparse.ast.HALT
61+
return bashparser.ast.HALT
6262
else:
6363
node.word = 'TOUCHED'
64-
return bashparse.ast.CONT
64+
return bashparser.ast.CONT
6565
vstr.apply(apply_fn, vstr)
6666

6767
# build correct solution by hand so bugs don't interfere with eachother
@@ -92,7 +92,7 @@ def test_expand_ast_along_path(self):
9292
for i, child in enumerate(root.parts): setattr(child, 'parts', copy.deepcopy(children[:i]))
9393
vstr = NodeVisitor(root)
9494
# Expand the ast
95-
bashparse.ast.expand_ast_along_path(root, [5,3], 2)
95+
bashparser.ast.expand_ast_along_path(root, [5,3], 2)
9696
# Verify the expansion
9797
def apply_fn(node, vstr):
9898
path_expanded_on = [5,3]

bashparser/test/test_chunk.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from unittest import TestCase
2-
import bashparse
2+
import bashparser
33

44
class TestChunk(TestCase):
55
def test_variable_chunking(self):
@@ -9,7 +9,7 @@ def test_variable_chunking(self):
99
echo $tmp
1010
cd there;
1111
"""
12-
nodes = bashparse.parse(string_to_chunk)
13-
chunk = bashparse.find_variable_chunks(nodes)[0]
12+
nodes = bashparser.parse(string_to_chunk)
13+
chunk = bashparser.find_variable_chunks(nodes)[0]
1414
self.assertTrue(chunk.start == [0,0])
1515
self.assertTrue(chunk.end == [2,1])

bashparser/test/test_command.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from unittest import TestCase
2-
from bashparse.commands import *
3-
import bashlex, bashparse
2+
from bashparser.commands import *
3+
import bashlex, bashparser
44

55
class TestVariables(TestCase):
66

bashparser/test/test_features.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,32 @@
33
I need to make sure every new update keeps the important featuers"""
44

55
from unittest import TestCase
6-
import bashparse
7-
import bashparse.variables as bpvar
8-
from bashparse import NodeVisitor
6+
import bashparser
7+
import bashparser.variables as bpvar
8+
from bashparser import NodeVisitor
99
import os
1010

1111

1212

1313
class TestFeatures(TestCase):
1414

1515
def test_scoping_unrolling_and_functions(self):
16-
expected_results = bashparse.parse('yep() { \n echo global vars: $i $j\n echo functional vars: $1\n }') \
17-
+ bashparse.parse('for i in 1 2; do \n for j in a b; do\n echo 1 a foo\n echo global vars: 1 a\n echo functional vars: "1 .. a" \n done\n done ') \
18-
+ bashparse.parse('for i in 1 2; do \n for j in a b; do\n echo 1 b foo\n echo global vars: 1 b\n echo functional vars: "1 .. b" \n done\n done ') \
19-
+ bashparse.parse('for i in 1 2; do \n for j in a b; do\n echo 2 a foo\n echo global vars: 2 a\n echo functional vars: "2 .. a" \n done\n done ') \
20-
+ bashparse.parse('for i in 1 2; do \n for j in a b; do\n echo 2 b foo\n echo global vars: 2 b\n echo functional vars: "2 .. b" \n done\n done ')
16+
expected_results = bashparser.parse('yep() { \n echo global vars: $i $j\n echo functional vars: $1\n }') \
17+
+ bashparser.parse('for i in 1 2; do \n for j in a b; do\n echo 1 a foo\n echo global vars: 1 a\n echo functional vars: "1 .. a" \n done\n done ') \
18+
+ bashparser.parse('for i in 1 2; do \n for j in a b; do\n echo 1 b foo\n echo global vars: 1 b\n echo functional vars: "1 .. b" \n done\n done ') \
19+
+ bashparser.parse('for i in 1 2; do \n for j in a b; do\n echo 2 a foo\n echo global vars: 2 a\n echo functional vars: "2 .. a" \n done\n done ') \
20+
+ bashparser.parse('for i in 1 2; do \n for j in a b; do\n echo 2 b foo\n echo global vars: 2 b\n echo functional vars: "2 .. b" \n done\n done ')
2121

2222
for i, result in enumerate(expected_results):
2323
expected_results[i] = NodeVisitor(expected_results[i]).justify()
2424

25-
nodes = bashparse.parse('yep() { \n echo global vars: $i $j\n echo functional vars: $1\n }') \
26-
+ bashparse.parse('for i in 1 2; do \n for j in a b; do\n echo $i $j foo\n yep "$i .. $j"\n done\n done')
25+
nodes = bashparser.parse('yep() { \n echo global vars: $i $j\n echo functional vars: $1\n }') \
26+
+ bashparser.parse('for i in 1 2; do \n for j in a b; do\n echo $i $j foo\n yep "$i .. $j"\n done\n done')
2727

2828
for i, node in enumerate(nodes): nodes[i] = NodeVisitor(node).justify()
2929
function_dict = {}
3030
var_list = {}
31-
unrolled_nodes = bashparse.build_and_resolve_fns(nodes, function_dict)
31+
unrolled_nodes = bashparser.build_and_resolve_fns(nodes, function_dict)
3232

3333
actual_results = []
3434
for node in unrolled_nodes:

bashparser/test/test_functions.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
from unittest import TestCase
2-
import bashparse
2+
import bashparser
33

44
class TestFunctions(TestCase):
55
def test_build_fn_table(self):
6-
fn_node = bashparse.parse('somefn () { echo this; cd that; echo else; }')[0]
7-
fn_table = bashparse.build_fn_table(fn_node)
8-
self.assertTrue(bashparse.parse('echo this; cd that; echo else;')[0] == fn_table['somefn'])
6+
fn_node = bashparser.parse('somefn () { echo this; cd that; echo else; }')[0]
7+
fn_table = bashparser.build_fn_table(fn_node)
8+
self.assertTrue(bashparser.parse('echo this; cd that; echo else;')[0] == fn_table['somefn'])
99

1010
def test_resolve_functions(self):
1111
# This test actually covers both the replacement case AND the event where the top level node is the one to be replaced. very good
12-
fn_node = bashparse.parse('somefn () { echo $1; cd there; }')[0]
13-
fn_table = bashparse.build_fn_table(fn_node)
14-
calling_node = bashparse.parse('somefn an_argument')[0]
15-
resolved_node = bashparse.resolve_functions(calling_node, fn_table)[0]
16-
proper_resolution = bashparse.parse('echo an_argument; cd there;')[0]
12+
fn_node = bashparser.parse('somefn () { echo $1; cd there; }')[0]
13+
fn_table = bashparser.build_fn_table(fn_node)
14+
calling_node = bashparser.parse('somefn an_argument')[0]
15+
resolved_node = bashparser.resolve_functions(calling_node, fn_table)[0]
16+
proper_resolution = bashparser.parse('echo an_argument; cd there;')[0]
1717
self.assertTrue(resolved_node == proper_resolution)
1818

1919
def test_build_and_resolve_fn(self):
2020
# Tests nested replacement and build&resolve fn.
2121
# Note the extra space at the end of the function replacement in correctly_resolved_node. Intentional cause keeping the spacing is way too hard for what its worth. Might need some consistency around it though
22-
fn_node = bashparse.parse('somefn () { echo $1; cd there; }')[0]
23-
calling_node = bashparse.parse('for a in $(dir); do somefn an_argument; done')[0]
22+
fn_node = bashparser.parse('somefn () { echo $1; cd there; }')[0]
23+
calling_node = bashparser.parse('for a in $(dir); do somefn an_argument; done')[0]
2424
nodes = [ fn_node ] + [ calling_node ]
25-
resolved_nodes = bashparse.build_and_resolve_fns(nodes)
26-
correctly_resolved_node = bashparse.parse('for a in $(dir); do echo an_argument; cd there ; done')[0]
25+
resolved_nodes = bashparser.build_and_resolve_fns(nodes)
26+
correctly_resolved_node = bashparser.parse('for a in $(dir); do echo an_argument; cd there ; done')[0]
2727
self.assertTrue(resolved_nodes[1] == correctly_resolved_node)

bashparser/test/test_unroll.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from unittest import TestCase
2-
import bashparse
2+
import bashparser
33

44
class TestUnroll(TestCase):
55
def test_basic_cmd_stripping(self):
@@ -8,13 +8,13 @@ def test_basic_cmd_stripping(self):
88
cd there;
99
dir | grep this;
1010
"""
11-
nodes = bashparse.parse(orig_string)
12-
commands_stripped = bashparse.unroll.strip_cmd(nodes)
13-
commands_stripped = [ bashparse.justify(x) for x in commands_stripped ]
11+
nodes = bashparser.parse(orig_string)
12+
commands_stripped = bashparser.unroll.strip_cmd(nodes)
13+
commands_stripped = [ bashparser.justify(x) for x in commands_stripped ]
1414

15-
correct_results = bashparse.parse('echo this') \
16-
+ bashparse.parse('echo that') \
17-
+ bashparse.parse('cd there') \
18-
+ bashparse.parse('dir | grep this')
15+
correct_results = bashparser.parse('echo this') \
16+
+ bashparser.parse('echo that') \
17+
+ bashparser.parse('cd there') \
18+
+ bashparser.parse('dir | grep this')
1919

2020
self.assertTrue(correct_results == commands_stripped)

bashparser/test/test_variable.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from unittest import TestCase
2-
from bashparse.variables import *
2+
from bashparser.variables import *
33
import bashlex
44

55
class TestVariables(TestCase):
@@ -102,13 +102,17 @@ def test_update_variable_list(self):
102102
for_node = bashlex.parse('for a in "$(echo this)"\n do\n echo something\n done')[0].list[0]
103103
new_var_list = update_var_list_with_for_loop(for_node, {})
104104
self.assertTrue(new_var_list == {'a':['$(echo this)']})
105+
# Verify that if for loop iterator has no value, an empty array is appended
106+
for_node = bashlex.parse('for a in "$testing"\n do\n echo something\n done')[0].list[0]
107+
new_var_list = update_var_list_with_for_loop(for_node, {})
108+
self.assertTrue(new_var_list == {'a':[]})
105109

106110
# test two updates in a row doesn't append the new values
107111
var_list = {}
108-
node = bashparse.parse('a=3')[0]
112+
node = bashparser.parse('a=3')[0]
109113
new_var_list = update_variable_list(node, var_list)
110114
self.assertTrue({'a':['3']} == new_var_list)
111-
node = bashparse.parse('a=4')[0]
115+
node = bashparser.parse('a=4')[0]
112116
new_var_list = update_variable_list(node, new_var_list)
113117
self.assertTrue({'a':['3', '4']} == new_var_list)
114118

0 commit comments

Comments
 (0)