Skip to content

Commit f6c1baf

Browse files
authored
Merge pull request #286 from byexamples/Issue-275-Ignore-empty-space-at-begin
Issue 275 ignore empty space at begin
2 parents af3962b + 7cf3ff8 commit f6c1baf

10 files changed

Lines changed: 264 additions & 40 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ prof-traces
1818
test/ds/good.args
1919
test/autocomplete_byexample.sh
2020
.check-secrets-impl.sh
21+
build/

byexample/example.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class Example(object):
8282
8383
>>> example.options
8484
{'capture': True,
85+
'ignore_first_empty_lines': True,
8586
'input_prefix_range': (6, 12),
8687
'norm_ws': False,
8788
'rm': [],

byexample/expected.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class _LinearExpected(Expected):
3232
>>> from byexample.options import Options
3333
>>> from byexample.finder import _build_fake_example as build_example
3434
35-
>>> opts = {'norm_ws': False, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6,12)}
35+
>>> opts = {'norm_ws': False, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6,12), 'ignore_first_empty_lines': True}
3636
3737
Consider the following example with a named capture in the expected:
3838
@@ -145,7 +145,7 @@ class _LinearExpected(Expected):
145145
146146
(See byexample.parser docs)
147147
148-
>>> opts = {'norm_ws': True, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6, 12)}
148+
>>> opts = {'norm_ws': True, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6, 12), 'ignore_first_empty_lines': True}
149149
>>> ex = build_example('f()', '\n <a>A \n\nB <bc> C\n<c>', opts=opts)
150150
>>> exp = ex.expected
151151

byexample/finder.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ class F:
5151
'capture': True,
5252
'rm': [],
5353
'type': False,
54-
'input_prefix_range': (6, 12)
54+
'input_prefix_range': (6, 12),
55+
'ignore_first_empty_lines': True,
5556
}
5657
)
5758
parser.extract_options = lambda x: opts

byexample/init.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@ def get_default_options_parser(cmdline_args):
386386
options_parser.add_flag(
387387
"norm-ws", default=False, help="ignore the amount of whitespaces."
388388
)
389+
options_parser.add_flag(
390+
"ignore-first-empty-lines",
391+
default=True,
392+
help=
393+
"ignore any empty or whitespace-only lines at the begin of the got string."
394+
)
389395
options_parser.add_flag(
390396
"pass",
391397
default=False,

byexample/parser.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ def parse(self, example, concerns):
193193
input_prefix_len_range = options['input_prefix_range']
194194
expected_regexs, charnos, rcounts, tags_by_idx, input_list = self.expected_as_regexs(
195195
example.expected_str, options['tags'], options['capture'],
196-
options['type'], options['norm_ws'], input_prefix_len_range
196+
options['type'], options['norm_ws'], input_prefix_len_range,
197+
options['ignore_first_empty_lines']
197198
)
198199

199200
ExpectedClass = _LinearExpected
@@ -230,8 +231,14 @@ def parse(self, example, concerns):
230231

231232
@profile
232233
def expected_as_regexs(
233-
self, expected, tags_enabled, capture_enabled, input_enabled,
234-
normalize_whitespace, input_prefix_len_range
234+
self,
235+
expected,
236+
tags_enabled,
237+
capture_enabled,
238+
input_enabled,
239+
normalize_whitespace,
240+
input_prefix_len_range,
241+
ignore_first_empty_lines=True
235242
):
236243
r'''
237244
From the expected string create a list of regular expressions that
@@ -262,8 +269,8 @@ def expected_as_regexs(
262269
263270
We return the regexs
264271
265-
>>> regexs
266-
('\\A', 'a', '(?P<foo>.*?)', 'b', '(?P<bar>.*?)', 'c', '\\n*\\Z')
272+
>>> regexs # byexample: +norm-ws
273+
('\\A(?:[ \\t]*\\n)*?', 'a', '(?P<foo>.*?)', 'b', '(?P<bar>.*?)', 'c', '\\n*\\Z')
267274
268275
>>> m = re.compile(''.join(regexs), re.MULTILINE | re.DOTALL)
269276
>>> m.match('axxbyyyc').groups()
@@ -300,7 +307,7 @@ def expected_as_regexs(
300307
>>> regexs, _, _, tags_by_idx, _ = _as_regexs(expected, normalize_whitespace=True)
301308
302309
>>> regexs # byexample: +norm-ws
303-
('\\A', 'a', '(?:.*?)(?<!\\s)', '\\s+(?!\\s)', '(?P<foo_bar>.*?)', 'c', '\\s*\\Z')
310+
('\\A\\s*?', 'a', '(?:.*?)(?<!\\s)', '\\s+(?!\\s)', '(?P<foo_bar>.*?)', 'c', '\\s*\\Z')
304311
305312
>>> tags_by_idx
306313
{2: None, 4: 'foo-bar'}
@@ -315,7 +322,7 @@ def expected_as_regexs(
315322
>>> regexs, _, _, tags_by_idx, _ = _as_regexs(expected)
316323
317324
>>> regexs
318-
('\\A', 'a<foo>b<bar>c', '\\n*\\Z')
325+
('\\A(?:[ \\t]*\\n)*?', 'a<foo>b<bar>c', '\\n*\\Z')
319326
320327
>>> tags_by_idx
321328
{}
@@ -324,11 +331,24 @@ def expected_as_regexs(
324331
>>> regexs, _, _, tags_by_idx, _ = _as_regexs(expected)
325332
326333
>>> regexs
327-
('\\A', 'a', '(?:.*?)', 'b<bar>c', '\\n*\\Z')
334+
('\\A(?:[ \\t]*\\n)*?', 'a', '(?:.*?)', 'b<bar>c', '\\n*\\Z')
328335
329336
>>> tags_by_idx
330337
{2: None}
331338
339+
When ignore_first_empty_lines is False the begin anchor is a plain \\A,
340+
so the got string must start exactly at the first expected character.
341+
342+
>>> regexs, _, _, _, _ = _as_regexs('foo', ignore_first_empty_lines=False)
343+
344+
>>> regexs
345+
('\\A', 'foo', '\\n*\\Z')
346+
347+
>>> regexs, _, _, _, _ = _as_regexs('foo', normalize_whitespace=True, ignore_first_empty_lines=False)
348+
349+
>>> regexs
350+
('\\A', 'foo', '\\s*\\Z')
351+
332352
'''
333353
if capture_enabled:
334354
tag_regexs = self.tag_regexs()
@@ -338,12 +358,12 @@ def expected_as_regexs(
338358
if normalize_whitespace:
339359
sm = SM_NormWS(
340360
tag_regexs, self.input_regexs(), self.ellipsis_marker(),
341-
input_prefix_len_range
361+
input_prefix_len_range, ignore_first_empty_lines
342362
)
343363
else:
344364
sm = SM_NotNormWS(
345365
tag_regexs, self.input_regexs(), self.ellipsis_marker(),
346-
input_prefix_len_range
366+
input_prefix_len_range, ignore_first_empty_lines
347367
)
348368

349369
return sm.parse(expected, tags_enabled, input_enabled)
@@ -433,7 +453,7 @@ def _extend_parser_and_parse_options_strictly_and_cache(self, optlist):
433453
>>> regexs, _, _, _, _ = _as_regexs(expected, normalize_whitespace=True)
434454
435455
>>> regexs
436-
('\\A',
456+
('\\A\\s*?',
437457
'ex',
438458
'\\s',
439459
'(?:\\s*(?!\\s)(?:.+)(?<!\\s))?',
@@ -450,7 +470,7 @@ def _extend_parser_and_parse_options_strictly_and_cache(self, optlist):
450470
>>> regexs, _, _, _, _ = _as_regexs(expected, normalize_whitespace=True)
451471
452472
>>> regexs
453-
('\\A',
473+
('\\A\\s*?',
454474
'ex',
455475
'\\s',
456476
'(?:\\s*(?!\\s)(?P<foo>.+?)(?<!\\s))?',

0 commit comments

Comments
 (0)