Skip to content

Commit d3766eb

Browse files
committed
Checkpoint. Many tests working, multiline seems broken
1 parent 560133d commit d3766eb

2 files changed

Lines changed: 70 additions & 14 deletions

File tree

cmd2.py

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,35 +2311,86 @@ def _test_transcript(self, fname, transcript):
23112311
fname, line_num, command, expected, result)
23122312
self.assertTrue(re.match(expected, result, re.MULTILINE | re.DOTALL), message)
23132313

2314-
def _transform_transcript_expected(self, expected):
2315-
"""parse the expected text from the transcript into a valid regex"""
2314+
def _transform_transcript_expected(self, s):
2315+
"""parse the string with slashed regexes into a valid regex"""
23162316
slash = '/'
23172317
backslash = '\\'
23182318
regex = ''
23192319
start = 0
2320+
23202321
while True:
2321-
first_slash_pos = expected.find(slash, start)
2322+
(regex, first_slash_pos, start) = self._escaped_find(regex, s, start, False)
23222323
if first_slash_pos == -1:
23232324
# no more slashes, add the rest of the string and bail
2324-
regex += re.escape(expected[start:])
2325+
regex += re.escape(s[start:])
23252326
break
23262327
else:
2327-
# there is a slash, go find the next one
2328-
second_slash_pos = expected.find(slash, first_slash_pos+1)
2328+
# there is a slash, add everything we have found so far
2329+
# add stuff before the first slash as plain text
2330+
regex += re.escape(s[start:first_slash_pos])
2331+
start = first_slash_pos+1
2332+
# and go find the next one
2333+
(regex, second_slash_pos, start) = self._escaped_find(regex, s, start, True)
23292334
if second_slash_pos > 0:
2330-
# add everything before the first slash as plain text
2331-
regex += re.escape(expected[start:first_slash_pos])
23322335
# add everything between the slashes (but not the slashes)
23332336
# as a regular expression
2334-
regex += expected[first_slash_pos+1:second_slash_pos]
2337+
regex += s[start:second_slash_pos]
23352338
# and change where we start looking for slashed on the
23362339
# turn through the loop
23372340
start = second_slash_pos + 1
23382341
else:
23392342
# no closing slash, treat it all as plain text
2340-
regex += re.escape(expected[start:])
2343+
regex += re.escape(s[start:])
23412344
return regex
2345+
2346+
def _escaped_find(self, regex, s, start, in_regex):
2347+
"""
2348+
Find the next slash in {s} after {start} that is not preceded by a backslash.
2349+
2350+
If we find an escaped slash, add everything up to and including it to regex,
2351+
updating {start}. {start} therefore serves two purposes, tells us where to start
2352+
looking for the next thing, and also tells us where in {s} we have already
2353+
added things to {regex}
23422354
2355+
{in_regex} specifies whether we are currently searching in a regex, we behave
2356+
differently if we are or if we aren't.
2357+
"""
2358+
2359+
while True:
2360+
pos = s.find('/', start)
2361+
if pos == -1:
2362+
# no match, return to caller
2363+
break
2364+
elif pos == 0:
2365+
# slash at the beginning of the string, so it can't be
2366+
# escaped. We found it.
2367+
break
2368+
else:
2369+
# check if the slash is preceeded by a backslash
2370+
if s[pos-1:pos] == '\\':
2371+
# it is.
2372+
if in_regex:
2373+
# add everything up to the backslash as a
2374+
# regular expression
2375+
regex += s[start:pos-1]
2376+
# skip the backslash, and add the slash
2377+
regex += s[pos]
2378+
else:
2379+
# add everything up to the backslash as escaped
2380+
# plain text
2381+
regex += re.escape(s[start:pos-1])
2382+
# and then add the slash as escaped
2383+
# plain text
2384+
regex += re.escape(s[pos])
2385+
# update start to show we have handled everything
2386+
# before it
2387+
start = pos+1
2388+
# and continue to look
2389+
else:
2390+
# slash is not escaped, this is what we are looking for
2391+
break
2392+
return (regex, pos, start)
2393+
23432394
def tearDown(self):
23442395
if self.cmdapp:
23452396
# Restore stdout

tests/test_transcript.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,17 @@ def test_invalid_syntax(_cmdline_app, capsys):
256256
('spaces.txt', False),
257257
])
258258
def test_transcript(request, capsys, filename, feedback_to_output):
259-
# Create a cmd2.Cmd() instance and make sure basic settings are like we want for test
259+
# Create a cmd2.Cmd() instance and make sure basic settings are
260+
# like we want for test
260261
app = CmdLineApp()
261262
app.feedback_to_output = feedback_to_output
262263

263264
# Get location of the transcript
264265
test_dir = os.path.dirname(request.module.__file__)
265266
transcript_file = os.path.join(test_dir, 'transcripts', filename)
266267

267-
# Need to patch sys.argv so cmd2 doesn't think it was called with arguments equal to the py.test args
268+
# Need to patch sys.argv so cmd2 doesn't think it was called with
269+
# arguments equal to the py.test args
268270
testargs = ['prog', '-t', transcript_file]
269271
with mock.patch.object(sys, 'argv', testargs):
270272
# Run the command loop
@@ -288,6 +290,11 @@ def test_transcript(request, capsys, filename, feedback_to_output):
288290
( '/.*/', '.*'),
289291
( 'specials ^ and + /[0-9]+/', 'specials\ \^\ and\ \+\ [0-9]+'),
290292
( '/a{6}/ but not a{6} with /.*?/ more', 'a{6}\ but\ not\ a\{6\}\ with\ .*?\ more'),
293+
( 'not this slash\/ or this one\/', 'not\ this\ slash\\/\ or\ this\ one\\/'),
294+
( 'not \/, use /\|?/, not \/', 'not\ \\/\,\ use\ \|?\,\ not\ \\/'),
295+
# inception: we have a slashes in our regex: backslashed on input, bare on output
296+
( 'not \/, use /\/?/, not \/', 'not\ \\/\,\ use\ /?\,\ not\ \\/'),
297+
( 'the /\/?/ more /.*/ stuff', 'the\ /?\ more\ .*\ stuff')
291298
])
292299
def test_parse_transcript_expected(expected, transformed):
293300
app = CmdLineApp()
@@ -296,6 +303,4 @@ class TestMyAppCase(Cmd2TestCase):
296303
cmdapp = app
297304

298305
testcase = TestMyAppCase()
299-
300306
assert testcase._transform_transcript_expected(expected) == transformed
301-

0 commit comments

Comments
 (0)