bpo-32916: IDLE: Change `str` to `code` in pyparse (GH-5830)
Adjust tests and user modules to match.
(cherry picked from commit c29c03a34a
)
Co-authored-by: Cheryl Sabella <cheryl.sabella@gmail.com>
This commit is contained in:
parent
cffe0467ab
commit
cd2112f0b9
|
@ -1302,7 +1302,7 @@ class EditorWindow(object):
|
||||||
startat = max(lno - context, 1)
|
startat = max(lno - context, 1)
|
||||||
startatindex = repr(startat) + ".0"
|
startatindex = repr(startat) + ".0"
|
||||||
rawtext = text.get(startatindex, "insert")
|
rawtext = text.get(startatindex, "insert")
|
||||||
y.set_str(rawtext)
|
y.set_code(rawtext)
|
||||||
bod = y.find_good_parse_start(
|
bod = y.find_good_parse_start(
|
||||||
self.context_use_ps1,
|
self.context_use_ps1,
|
||||||
self._build_char_in_string_func(startatindex))
|
self._build_char_in_string_func(startatindex))
|
||||||
|
@ -1316,7 +1316,7 @@ class EditorWindow(object):
|
||||||
else:
|
else:
|
||||||
startatindex = "1.0"
|
startatindex = "1.0"
|
||||||
rawtext = text.get(startatindex, "insert")
|
rawtext = text.get(startatindex, "insert")
|
||||||
y.set_str(rawtext)
|
y.set_code(rawtext)
|
||||||
y.set_lo(0)
|
y.set_lo(0)
|
||||||
|
|
||||||
c = y.get_continuation_type()
|
c = y.get_continuation_type()
|
||||||
|
|
|
@ -44,7 +44,7 @@ class HyperParser:
|
||||||
# at end. We add a space so that index won't be at end
|
# at end. We add a space so that index won't be at end
|
||||||
# of line, so that its status will be the same as the
|
# of line, so that its status will be the same as the
|
||||||
# char before it, if should.
|
# char before it, if should.
|
||||||
parser.set_str(text.get(startatindex, stopatindex)+' \n')
|
parser.set_code(text.get(startatindex, stopatindex)+' \n')
|
||||||
bod = parser.find_good_parse_start(
|
bod = parser.find_good_parse_start(
|
||||||
editwin._build_char_in_string_func(startatindex))
|
editwin._build_char_in_string_func(startatindex))
|
||||||
if bod is not None or startat == 1:
|
if bod is not None or startat == 1:
|
||||||
|
@ -60,12 +60,12 @@ class HyperParser:
|
||||||
# We add the newline because PyParse requires it. We add a
|
# We add the newline because PyParse requires it. We add a
|
||||||
# space so that index won't be at end of line, so that its
|
# space so that index won't be at end of line, so that its
|
||||||
# status will be the same as the char before it, if should.
|
# status will be the same as the char before it, if should.
|
||||||
parser.set_str(text.get(startatindex, stopatindex)+' \n')
|
parser.set_code(text.get(startatindex, stopatindex)+' \n')
|
||||||
parser.set_lo(0)
|
parser.set_lo(0)
|
||||||
|
|
||||||
# We want what the parser has, minus the last newline and space.
|
# We want what the parser has, minus the last newline and space.
|
||||||
self.rawtext = parser.str[:-2]
|
self.rawtext = parser.code[:-2]
|
||||||
# Parser.str apparently preserves the statement we are in, so
|
# Parser.code apparently preserves the statement we are in, so
|
||||||
# that stopatindex can be used to synchronize the string with
|
# that stopatindex can be used to synchronize the string with
|
||||||
# the text box indices.
|
# the text box indices.
|
||||||
self.stopatindex = stopatindex
|
self.stopatindex = stopatindex
|
||||||
|
|
|
@ -62,32 +62,32 @@ class PyParseTest(unittest.TestCase):
|
||||||
self.assertEqual(self.parser.indentwidth, 4)
|
self.assertEqual(self.parser.indentwidth, 4)
|
||||||
self.assertEqual(self.parser.tabwidth, 4)
|
self.assertEqual(self.parser.tabwidth, 4)
|
||||||
|
|
||||||
def test_set_str(self):
|
def test_set_code(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
|
|
||||||
# Not empty and doesn't end with newline.
|
# Not empty and doesn't end with newline.
|
||||||
with self.assertRaises(AssertionError):
|
with self.assertRaises(AssertionError):
|
||||||
setstr('a')
|
setcode('a')
|
||||||
|
|
||||||
tests = ('',
|
tests = ('',
|
||||||
'a\n')
|
'a\n')
|
||||||
|
|
||||||
for string in tests:
|
for string in tests:
|
||||||
with self.subTest(string=string):
|
with self.subTest(string=string):
|
||||||
setstr(string)
|
setcode(string)
|
||||||
eq(p.str, string)
|
eq(p.code, string)
|
||||||
eq(p.study_level, 0)
|
eq(p.study_level, 0)
|
||||||
|
|
||||||
def test_find_good_parse_start(self):
|
def test_find_good_parse_start(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
start = p.find_good_parse_start
|
start = p.find_good_parse_start
|
||||||
|
|
||||||
# Split def across lines.
|
# Split def across lines.
|
||||||
setstr('"""This is a module docstring"""\n'
|
setcode('"""This is a module docstring"""\n'
|
||||||
'class C():\n'
|
'class C():\n'
|
||||||
' def __init__(self, a,\n'
|
' def __init__(self, a,\n'
|
||||||
' b=True):\n'
|
' b=True):\n'
|
||||||
|
@ -117,7 +117,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
# Code without extra line break in def line - mostly returns the same
|
# Code without extra line break in def line - mostly returns the same
|
||||||
# values.
|
# values.
|
||||||
setstr('"""This is a module docstring"""\n'
|
setcode('"""This is a module docstring"""\n'
|
||||||
'class C():\n'
|
'class C():\n'
|
||||||
' def __init__(self, a, b=True):\n'
|
' def __init__(self, a, b=True):\n'
|
||||||
' pass\n'
|
' pass\n'
|
||||||
|
@ -138,19 +138,19 @@ class PyParseTest(unittest.TestCase):
|
||||||
' pass\n'
|
' pass\n'
|
||||||
)
|
)
|
||||||
p = self.parser
|
p = self.parser
|
||||||
p.set_str(code)
|
p.set_code(code)
|
||||||
|
|
||||||
# Previous character is not a newline.
|
# Previous character is not a newline.
|
||||||
with self.assertRaises(AssertionError):
|
with self.assertRaises(AssertionError):
|
||||||
p.set_lo(5)
|
p.set_lo(5)
|
||||||
|
|
||||||
# A value of 0 doesn't change self.str.
|
# A value of 0 doesn't change self.code.
|
||||||
p.set_lo(0)
|
p.set_lo(0)
|
||||||
self.assertEqual(p.str, code)
|
self.assertEqual(p.code, code)
|
||||||
|
|
||||||
# An index that is preceded by a newline.
|
# An index that is preceded by a newline.
|
||||||
p.set_lo(44)
|
p.set_lo(44)
|
||||||
self.assertEqual(p.str, code[44:])
|
self.assertEqual(p.code, code[44:])
|
||||||
|
|
||||||
def test_tran(self):
|
def test_tran(self):
|
||||||
self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran),
|
self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran),
|
||||||
|
@ -159,7 +159,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
def test_study1(self):
|
def test_study1(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
study = p._study1
|
study = p._study1
|
||||||
|
|
||||||
(NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
|
(NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
|
||||||
|
@ -197,7 +197,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string) # resets study_level
|
setcode(test.string) # resets study_level
|
||||||
study()
|
study()
|
||||||
eq(p.study_level, 1)
|
eq(p.study_level, 1)
|
||||||
eq(p.goodlines, test.goodlines)
|
eq(p.goodlines, test.goodlines)
|
||||||
|
@ -209,7 +209,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
def test_get_continuation_type(self):
|
def test_get_continuation_type(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
gettype = p.get_continuation_type
|
gettype = p.get_continuation_type
|
||||||
|
|
||||||
(NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
|
(NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
|
||||||
|
@ -224,13 +224,13 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
eq(gettype(), test.continuation)
|
eq(gettype(), test.continuation)
|
||||||
|
|
||||||
def test_study2(self):
|
def test_study2(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
study = p._study2
|
study = p._study2
|
||||||
|
|
||||||
TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch',
|
TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch',
|
||||||
|
@ -276,7 +276,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
study()
|
study()
|
||||||
eq(p.study_level, 2)
|
eq(p.study_level, 2)
|
||||||
eq(p.stmt_start, test.start)
|
eq(p.stmt_start, test.start)
|
||||||
|
@ -291,7 +291,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
def test_get_num_lines_in_stmt(self):
|
def test_get_num_lines_in_stmt(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
getlines = p.get_num_lines_in_stmt
|
getlines = p.get_num_lines_in_stmt
|
||||||
|
|
||||||
TestInfo = namedtuple('TestInfo', ['string', 'lines'])
|
TestInfo = namedtuple('TestInfo', ['string', 'lines'])
|
||||||
|
@ -307,19 +307,19 @@ class PyParseTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Blank string doesn't have enough elements in goodlines.
|
# Blank string doesn't have enough elements in goodlines.
|
||||||
setstr('')
|
setcode('')
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
getlines()
|
getlines()
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
eq(getlines(), test.lines)
|
eq(getlines(), test.lines)
|
||||||
|
|
||||||
def test_compute_bracket_indent(self):
|
def test_compute_bracket_indent(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
indent = p.compute_bracket_indent
|
indent = p.compute_bracket_indent
|
||||||
|
|
||||||
TestInfo = namedtuple('TestInfo', ['string', 'spaces'])
|
TestInfo = namedtuple('TestInfo', ['string', 'spaces'])
|
||||||
|
@ -340,18 +340,18 @@ class PyParseTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Must be C_BRACKET continuation type.
|
# Must be C_BRACKET continuation type.
|
||||||
setstr('def function1(self, a, b):\n')
|
setcode('def function1(self, a, b):\n')
|
||||||
with self.assertRaises(AssertionError):
|
with self.assertRaises(AssertionError):
|
||||||
indent()
|
indent()
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
eq(indent(), test.spaces)
|
eq(indent(), test.spaces)
|
||||||
|
|
||||||
def test_compute_backslash_indent(self):
|
def test_compute_backslash_indent(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
indent = p.compute_backslash_indent
|
indent = p.compute_backslash_indent
|
||||||
|
|
||||||
# Must be C_BACKSLASH continuation type.
|
# Must be C_BACKSLASH continuation type.
|
||||||
|
@ -361,7 +361,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
for string in errors:
|
for string in errors:
|
||||||
with self.subTest(string=string):
|
with self.subTest(string=string):
|
||||||
setstr(string)
|
setcode(string)
|
||||||
with self.assertRaises(AssertionError):
|
with self.assertRaises(AssertionError):
|
||||||
indent()
|
indent()
|
||||||
|
|
||||||
|
@ -384,13 +384,13 @@ class PyParseTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
eq(indent(), test.spaces)
|
eq(indent(), test.spaces)
|
||||||
|
|
||||||
def test_get_base_indent_string(self):
|
def test_get_base_indent_string(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
baseindent = p.get_base_indent_string
|
baseindent = p.get_base_indent_string
|
||||||
|
|
||||||
TestInfo = namedtuple('TestInfo', ['string', 'indent'])
|
TestInfo = namedtuple('TestInfo', ['string', 'indent'])
|
||||||
|
@ -405,14 +405,14 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
eq(baseindent(), test.indent)
|
eq(baseindent(), test.indent)
|
||||||
|
|
||||||
def test_is_block_opener(self):
|
def test_is_block_opener(self):
|
||||||
yes = self.assertTrue
|
yes = self.assertTrue
|
||||||
no = self.assertFalse
|
no = self.assertFalse
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
opener = p.is_block_opener
|
opener = p.is_block_opener
|
||||||
|
|
||||||
TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
|
TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
|
||||||
|
@ -433,14 +433,14 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
test.assert_(opener())
|
test.assert_(opener())
|
||||||
|
|
||||||
def test_is_block_closer(self):
|
def test_is_block_closer(self):
|
||||||
yes = self.assertTrue
|
yes = self.assertTrue
|
||||||
no = self.assertFalse
|
no = self.assertFalse
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
closer = p.is_block_closer
|
closer = p.is_block_closer
|
||||||
|
|
||||||
TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
|
TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
|
||||||
|
@ -462,13 +462,13 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
test.assert_(closer())
|
test.assert_(closer())
|
||||||
|
|
||||||
def test_get_last_stmt_bracketing(self):
|
def test_get_last_stmt_bracketing(self):
|
||||||
eq = self.assertEqual
|
eq = self.assertEqual
|
||||||
p = self.parser
|
p = self.parser
|
||||||
setstr = p.set_str
|
setcode = p.set_code
|
||||||
bracketing = p.get_last_stmt_bracketing
|
bracketing = p.get_last_stmt_bracketing
|
||||||
|
|
||||||
TestInfo = namedtuple('TestInfo', ['string', 'bracket'])
|
TestInfo = namedtuple('TestInfo', ['string', 'bracket'])
|
||||||
|
@ -489,7 +489,7 @@ class PyParseTest(unittest.TestCase):
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
with self.subTest(string=test.string):
|
with self.subTest(string=test.string):
|
||||||
setstr(test.string)
|
setcode(test.string)
|
||||||
eq(bracketing(), test.bracket)
|
eq(bracketing(), test.bracket)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -149,9 +149,9 @@ class Parser:
|
||||||
self.indentwidth = indentwidth
|
self.indentwidth = indentwidth
|
||||||
self.tabwidth = tabwidth
|
self.tabwidth = tabwidth
|
||||||
|
|
||||||
def set_str(self, s):
|
def set_code(self, s):
|
||||||
assert len(s) == 0 or s[-1] == '\n'
|
assert len(s) == 0 or s[-1] == '\n'
|
||||||
self.str = s
|
self.code = s
|
||||||
self.study_level = 0
|
self.study_level = 0
|
||||||
|
|
||||||
def find_good_parse_start(self, is_char_in_string=None,
|
def find_good_parse_start(self, is_char_in_string=None,
|
||||||
|
@ -168,7 +168,7 @@ class Parser:
|
||||||
function, meaning that when it says "no", it's absolutely
|
function, meaning that when it says "no", it's absolutely
|
||||||
guaranteed that the char is not in a string.
|
guaranteed that the char is not in a string.
|
||||||
"""
|
"""
|
||||||
str, pos = self.str, None
|
code, pos = self.code, None
|
||||||
|
|
||||||
if not is_char_in_string:
|
if not is_char_in_string:
|
||||||
# no clue -- make the caller pass everything
|
# no clue -- make the caller pass everything
|
||||||
|
@ -177,13 +177,13 @@ class Parser:
|
||||||
# Peek back from the end for a good place to start,
|
# Peek back from the end for a good place to start,
|
||||||
# but don't try too often; pos will be left None, or
|
# but don't try too often; pos will be left None, or
|
||||||
# bumped to a legitimate synch point.
|
# bumped to a legitimate synch point.
|
||||||
limit = len(str)
|
limit = len(code)
|
||||||
for tries in range(5):
|
for tries in range(5):
|
||||||
i = str.rfind(":\n", 0, limit)
|
i = code.rfind(":\n", 0, limit)
|
||||||
if i < 0:
|
if i < 0:
|
||||||
break
|
break
|
||||||
i = str.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0)
|
i = code.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0)
|
||||||
m = _synchre(str, i, limit)
|
m = _synchre(code, i, limit)
|
||||||
if m and not is_char_in_string(m.start()):
|
if m and not is_char_in_string(m.start()):
|
||||||
pos = m.start()
|
pos = m.start()
|
||||||
break
|
break
|
||||||
|
@ -197,7 +197,7 @@ class Parser:
|
||||||
# going to have to parse the whole thing to be sure, so
|
# going to have to parse the whole thing to be sure, so
|
||||||
# give it one last try from the start, but stop wasting
|
# give it one last try from the start, but stop wasting
|
||||||
# time here regardless of the outcome.
|
# time here regardless of the outcome.
|
||||||
m = _synchre(str)
|
m = _synchre(code)
|
||||||
if m and not is_char_in_string(m.start()):
|
if m and not is_char_in_string(m.start()):
|
||||||
pos = m.start()
|
pos = m.start()
|
||||||
return pos
|
return pos
|
||||||
|
@ -206,7 +206,7 @@ class Parser:
|
||||||
# matches.
|
# matches.
|
||||||
i = pos + 1
|
i = pos + 1
|
||||||
while 1:
|
while 1:
|
||||||
m = _synchre(str, i)
|
m = _synchre(code, i)
|
||||||
if m:
|
if m:
|
||||||
s, i = m.span()
|
s, i = m.span()
|
||||||
if not is_char_in_string(s):
|
if not is_char_in_string(s):
|
||||||
|
@ -220,9 +220,9 @@ class Parser:
|
||||||
|
|
||||||
Intended to be called with the result of find_good_parse_start().
|
Intended to be called with the result of find_good_parse_start().
|
||||||
"""
|
"""
|
||||||
assert lo == 0 or self.str[lo-1] == '\n'
|
assert lo == 0 or self.code[lo-1] == '\n'
|
||||||
if lo > 0:
|
if lo > 0:
|
||||||
self.str = self.str[lo:]
|
self.code = self.code[lo:]
|
||||||
|
|
||||||
# Build a translation table to map uninteresting chars to 'x', open
|
# Build a translation table to map uninteresting chars to 'x', open
|
||||||
# brackets to '(', close brackets to ')' while preserving quotes,
|
# brackets to '(', close brackets to ')' while preserving quotes,
|
||||||
|
@ -249,13 +249,13 @@ class Parser:
|
||||||
# to "(", all close brackets to ")", then collapse runs of
|
# to "(", all close brackets to ")", then collapse runs of
|
||||||
# uninteresting characters. This can cut the number of chars
|
# uninteresting characters. This can cut the number of chars
|
||||||
# by a factor of 10-40, and so greatly speed the following loop.
|
# by a factor of 10-40, and so greatly speed the following loop.
|
||||||
str = self.str
|
code = self.code
|
||||||
str = str.translate(self._tran)
|
code = code.translate(self._tran)
|
||||||
str = str.replace('xxxxxxxx', 'x')
|
code = code.replace('xxxxxxxx', 'x')
|
||||||
str = str.replace('xxxx', 'x')
|
code = code.replace('xxxx', 'x')
|
||||||
str = str.replace('xx', 'x')
|
code = code.replace('xx', 'x')
|
||||||
str = str.replace('xx', 'x')
|
code = code.replace('xx', 'x')
|
||||||
str = str.replace('\nx', '\n')
|
code = code.replace('\nx', '\n')
|
||||||
# Replacing x\n with \n would be incorrect because
|
# Replacing x\n with \n would be incorrect because
|
||||||
# x may be preceded by a backslash.
|
# x may be preceded by a backslash.
|
||||||
|
|
||||||
|
@ -266,9 +266,9 @@ class Parser:
|
||||||
level = lno = 0 # level is nesting level; lno is line number
|
level = lno = 0 # level is nesting level; lno is line number
|
||||||
self.goodlines = goodlines = [0]
|
self.goodlines = goodlines = [0]
|
||||||
push_good = goodlines.append
|
push_good = goodlines.append
|
||||||
i, n = 0, len(str)
|
i, n = 0, len(code)
|
||||||
while i < n:
|
while i < n:
|
||||||
ch = str[i]
|
ch = code[i]
|
||||||
i = i+1
|
i = i+1
|
||||||
|
|
||||||
# cases are checked in decreasing order of frequency
|
# cases are checked in decreasing order of frequency
|
||||||
|
@ -295,19 +295,19 @@ class Parser:
|
||||||
if ch == '"' or ch == "'":
|
if ch == '"' or ch == "'":
|
||||||
# consume the string
|
# consume the string
|
||||||
quote = ch
|
quote = ch
|
||||||
if str[i-1:i+2] == quote * 3:
|
if code[i-1:i+2] == quote * 3:
|
||||||
quote = quote * 3
|
quote = quote * 3
|
||||||
firstlno = lno
|
firstlno = lno
|
||||||
w = len(quote) - 1
|
w = len(quote) - 1
|
||||||
i = i+w
|
i = i+w
|
||||||
while i < n:
|
while i < n:
|
||||||
ch = str[i]
|
ch = code[i]
|
||||||
i = i+1
|
i = i+1
|
||||||
|
|
||||||
if ch == 'x':
|
if ch == 'x':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if str[i-1:i+w] == quote:
|
if code[i-1:i+w] == quote:
|
||||||
i = i+w
|
i = i+w
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ class Parser:
|
||||||
|
|
||||||
if ch == '\\':
|
if ch == '\\':
|
||||||
assert i < n
|
assert i < n
|
||||||
if str[i] == '\n':
|
if code[i] == '\n':
|
||||||
lno = lno + 1
|
lno = lno + 1
|
||||||
i = i+1
|
i = i+1
|
||||||
continue
|
continue
|
||||||
|
@ -333,7 +333,7 @@ class Parser:
|
||||||
# didn't break out of the loop, so we're still
|
# didn't break out of the loop, so we're still
|
||||||
# inside a string
|
# inside a string
|
||||||
if (lno - 1) == firstlno:
|
if (lno - 1) == firstlno:
|
||||||
# before the previous \n in str, we were in the first
|
# before the previous \n in code, we were in the first
|
||||||
# line of the string
|
# line of the string
|
||||||
continuation = C_STRING_FIRST_LINE
|
continuation = C_STRING_FIRST_LINE
|
||||||
else:
|
else:
|
||||||
|
@ -342,13 +342,13 @@ class Parser:
|
||||||
|
|
||||||
if ch == '#':
|
if ch == '#':
|
||||||
# consume the comment
|
# consume the comment
|
||||||
i = str.find('\n', i)
|
i = code.find('\n', i)
|
||||||
assert i >= 0
|
assert i >= 0
|
||||||
continue
|
continue
|
||||||
|
|
||||||
assert ch == '\\'
|
assert ch == '\\'
|
||||||
assert i < n
|
assert i < n
|
||||||
if str[i] == '\n':
|
if code[i] == '\n':
|
||||||
lno = lno + 1
|
lno = lno + 1
|
||||||
if i+1 == n:
|
if i+1 == n:
|
||||||
continuation = C_BACKSLASH
|
continuation = C_BACKSLASH
|
||||||
|
@ -397,9 +397,9 @@ class Parser:
|
||||||
self.study_level = 2
|
self.study_level = 2
|
||||||
|
|
||||||
# Set p and q to slice indices of last interesting stmt.
|
# Set p and q to slice indices of last interesting stmt.
|
||||||
str, goodlines = self.str, self.goodlines
|
code, goodlines = self.code, self.goodlines
|
||||||
i = len(goodlines) - 1 # Index of newest line.
|
i = len(goodlines) - 1 # Index of newest line.
|
||||||
p = len(str) # End of goodlines[i]
|
p = len(code) # End of goodlines[i]
|
||||||
while i:
|
while i:
|
||||||
assert p
|
assert p
|
||||||
# Make p be the index of the stmt at line number goodlines[i].
|
# Make p be the index of the stmt at line number goodlines[i].
|
||||||
|
@ -407,10 +407,10 @@ class Parser:
|
||||||
q = p
|
q = p
|
||||||
for nothing in range(goodlines[i-1], goodlines[i]):
|
for nothing in range(goodlines[i-1], goodlines[i]):
|
||||||
# tricky: sets p to 0 if no preceding newline
|
# tricky: sets p to 0 if no preceding newline
|
||||||
p = str.rfind('\n', 0, p-1) + 1
|
p = code.rfind('\n', 0, p-1) + 1
|
||||||
# The stmt str[p:q] isn't a continuation, but may be blank
|
# The stmt code[p:q] isn't a continuation, but may be blank
|
||||||
# or a non-indenting comment line.
|
# or a non-indenting comment line.
|
||||||
if _junkre(str, p):
|
if _junkre(code, p):
|
||||||
i = i-1
|
i = i-1
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
@ -428,21 +428,21 @@ class Parser:
|
||||||
bracketing = [(p, 0)]
|
bracketing = [(p, 0)]
|
||||||
while p < q:
|
while p < q:
|
||||||
# suck up all except ()[]{}'"#\\
|
# suck up all except ()[]{}'"#\\
|
||||||
m = _chew_ordinaryre(str, p, q)
|
m = _chew_ordinaryre(code, p, q)
|
||||||
if m:
|
if m:
|
||||||
# we skipped at least one boring char
|
# we skipped at least one boring char
|
||||||
newp = m.end()
|
newp = m.end()
|
||||||
# back up over totally boring whitespace
|
# back up over totally boring whitespace
|
||||||
i = newp - 1 # index of last boring char
|
i = newp - 1 # index of last boring char
|
||||||
while i >= p and str[i] in " \t\n":
|
while i >= p and code[i] in " \t\n":
|
||||||
i = i-1
|
i = i-1
|
||||||
if i >= p:
|
if i >= p:
|
||||||
lastch = str[i]
|
lastch = code[i]
|
||||||
p = newp
|
p = newp
|
||||||
if p >= q:
|
if p >= q:
|
||||||
break
|
break
|
||||||
|
|
||||||
ch = str[p]
|
ch = code[p]
|
||||||
|
|
||||||
if ch in "([{":
|
if ch in "([{":
|
||||||
push_stack(p)
|
push_stack(p)
|
||||||
|
@ -469,14 +469,14 @@ class Parser:
|
||||||
# have to.
|
# have to.
|
||||||
bracketing.append((p, len(stack)+1))
|
bracketing.append((p, len(stack)+1))
|
||||||
lastch = ch
|
lastch = ch
|
||||||
p = _match_stringre(str, p, q).end()
|
p = _match_stringre(code, p, q).end()
|
||||||
bracketing.append((p, len(stack)))
|
bracketing.append((p, len(stack)))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if ch == '#':
|
if ch == '#':
|
||||||
# consume comment and trailing newline
|
# consume comment and trailing newline
|
||||||
bracketing.append((p, len(stack)+1))
|
bracketing.append((p, len(stack)+1))
|
||||||
p = str.find('\n', p, q) + 1
|
p = code.find('\n', p, q) + 1
|
||||||
assert p > 0
|
assert p > 0
|
||||||
bracketing.append((p, len(stack)))
|
bracketing.append((p, len(stack)))
|
||||||
continue
|
continue
|
||||||
|
@ -484,9 +484,9 @@ class Parser:
|
||||||
assert ch == '\\'
|
assert ch == '\\'
|
||||||
p = p+1 # beyond backslash
|
p = p+1 # beyond backslash
|
||||||
assert p < q
|
assert p < q
|
||||||
if str[p] != '\n':
|
if code[p] != '\n':
|
||||||
# the program is invalid, but can't complain
|
# the program is invalid, but can't complain
|
||||||
lastch = ch + str[p]
|
lastch = ch + code[p]
|
||||||
p = p+1 # beyond escaped char
|
p = p+1 # beyond escaped char
|
||||||
|
|
||||||
# end while p < q:
|
# end while p < q:
|
||||||
|
@ -503,28 +503,28 @@ class Parser:
|
||||||
self._study2()
|
self._study2()
|
||||||
assert self.continuation == C_BRACKET
|
assert self.continuation == C_BRACKET
|
||||||
j = self.lastopenbracketpos
|
j = self.lastopenbracketpos
|
||||||
str = self.str
|
code = self.code
|
||||||
n = len(str)
|
n = len(code)
|
||||||
origi = i = str.rfind('\n', 0, j) + 1
|
origi = i = code.rfind('\n', 0, j) + 1
|
||||||
j = j+1 # one beyond open bracket
|
j = j+1 # one beyond open bracket
|
||||||
# find first list item; set i to start of its line
|
# find first list item; set i to start of its line
|
||||||
while j < n:
|
while j < n:
|
||||||
m = _itemre(str, j)
|
m = _itemre(code, j)
|
||||||
if m:
|
if m:
|
||||||
j = m.end() - 1 # index of first interesting char
|
j = m.end() - 1 # index of first interesting char
|
||||||
extra = 0
|
extra = 0
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# this line is junk; advance to next line
|
# this line is junk; advance to next line
|
||||||
i = j = str.find('\n', j) + 1
|
i = j = code.find('\n', j) + 1
|
||||||
else:
|
else:
|
||||||
# nothing interesting follows the bracket;
|
# nothing interesting follows the bracket;
|
||||||
# reproduce the bracket line's indentation + a level
|
# reproduce the bracket line's indentation + a level
|
||||||
j = i = origi
|
j = i = origi
|
||||||
while str[j] in " \t":
|
while code[j] in " \t":
|
||||||
j = j+1
|
j = j+1
|
||||||
extra = self.indentwidth
|
extra = self.indentwidth
|
||||||
return len(str[i:j].expandtabs(self.tabwidth)) + extra
|
return len(code[i:j].expandtabs(self.tabwidth)) + extra
|
||||||
|
|
||||||
def get_num_lines_in_stmt(self):
|
def get_num_lines_in_stmt(self):
|
||||||
"""Return number of physical lines in last stmt.
|
"""Return number of physical lines in last stmt.
|
||||||
|
@ -544,18 +544,18 @@ class Parser:
|
||||||
"""
|
"""
|
||||||
self._study2()
|
self._study2()
|
||||||
assert self.continuation == C_BACKSLASH
|
assert self.continuation == C_BACKSLASH
|
||||||
str = self.str
|
code = self.code
|
||||||
i = self.stmt_start
|
i = self.stmt_start
|
||||||
while str[i] in " \t":
|
while code[i] in " \t":
|
||||||
i = i+1
|
i = i+1
|
||||||
startpos = i
|
startpos = i
|
||||||
|
|
||||||
# See whether the initial line starts an assignment stmt; i.e.,
|
# See whether the initial line starts an assignment stmt; i.e.,
|
||||||
# look for an = operator
|
# look for an = operator
|
||||||
endpos = str.find('\n', startpos) + 1
|
endpos = code.find('\n', startpos) + 1
|
||||||
found = level = 0
|
found = level = 0
|
||||||
while i < endpos:
|
while i < endpos:
|
||||||
ch = str[i]
|
ch = code[i]
|
||||||
if ch in "([{":
|
if ch in "([{":
|
||||||
level = level + 1
|
level = level + 1
|
||||||
i = i+1
|
i = i+1
|
||||||
|
@ -564,14 +564,14 @@ class Parser:
|
||||||
level = level - 1
|
level = level - 1
|
||||||
i = i+1
|
i = i+1
|
||||||
elif ch == '"' or ch == "'":
|
elif ch == '"' or ch == "'":
|
||||||
i = _match_stringre(str, i, endpos).end()
|
i = _match_stringre(code, i, endpos).end()
|
||||||
elif ch == '#':
|
elif ch == '#':
|
||||||
# This line is unreachable because the # makes a comment of
|
# This line is unreachable because the # makes a comment of
|
||||||
# everything after it.
|
# everything after it.
|
||||||
break
|
break
|
||||||
elif level == 0 and ch == '=' and \
|
elif level == 0 and ch == '=' and \
|
||||||
(i == 0 or str[i-1] not in "=<>!") and \
|
(i == 0 or code[i-1] not in "=<>!") and \
|
||||||
str[i+1] != '=':
|
code[i+1] != '=':
|
||||||
found = 1
|
found = 1
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
@ -581,16 +581,16 @@ class Parser:
|
||||||
# found a legit =, but it may be the last interesting
|
# found a legit =, but it may be the last interesting
|
||||||
# thing on the line
|
# thing on the line
|
||||||
i = i+1 # move beyond the =
|
i = i+1 # move beyond the =
|
||||||
found = re.match(r"\s*\\", str[i:endpos]) is None
|
found = re.match(r"\s*\\", code[i:endpos]) is None
|
||||||
|
|
||||||
if not found:
|
if not found:
|
||||||
# oh well ... settle for moving beyond the first chunk
|
# oh well ... settle for moving beyond the first chunk
|
||||||
# of non-whitespace chars
|
# of non-whitespace chars
|
||||||
i = startpos
|
i = startpos
|
||||||
while str[i] not in " \t\n":
|
while code[i] not in " \t\n":
|
||||||
i = i+1
|
i = i+1
|
||||||
|
|
||||||
return len(str[self.stmt_start:i].expandtabs(\
|
return len(code[self.stmt_start:i].expandtabs(\
|
||||||
self.tabwidth)) + 1
|
self.tabwidth)) + 1
|
||||||
|
|
||||||
def get_base_indent_string(self):
|
def get_base_indent_string(self):
|
||||||
|
@ -600,10 +600,10 @@ class Parser:
|
||||||
self._study2()
|
self._study2()
|
||||||
i, n = self.stmt_start, self.stmt_end
|
i, n = self.stmt_start, self.stmt_end
|
||||||
j = i
|
j = i
|
||||||
str = self.str
|
code = self.code
|
||||||
while j < n and str[j] in " \t":
|
while j < n and code[j] in " \t":
|
||||||
j = j + 1
|
j = j + 1
|
||||||
return str[i:j]
|
return code[i:j]
|
||||||
|
|
||||||
def is_block_opener(self):
|
def is_block_opener(self):
|
||||||
"Return True if the last interesting statemtent opens a block."
|
"Return True if the last interesting statemtent opens a block."
|
||||||
|
@ -613,7 +613,7 @@ class Parser:
|
||||||
def is_block_closer(self):
|
def is_block_closer(self):
|
||||||
"Return True if the last interesting statement closes a block."
|
"Return True if the last interesting statement closes a block."
|
||||||
self._study2()
|
self._study2()
|
||||||
return _closere(self.str, self.stmt_start) is not None
|
return _closere(self.code, self.stmt_start) is not None
|
||||||
|
|
||||||
def get_last_stmt_bracketing(self):
|
def get_last_stmt_bracketing(self):
|
||||||
"""Return bracketing structure of the last interesting statement.
|
"""Return bracketing structure of the last interesting statement.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Change ``str`` to ``code`` in pyparse.
|
Loading…
Reference in New Issue