Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ prof-traces
test/ds/good.args
test/autocomplete_byexample.sh
.check-secrets-impl.sh
build/
1 change: 1 addition & 0 deletions byexample/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class Example(object):

>>> example.options
{'capture': True,
'ignore_first_empty_lines': True,
'input_prefix_range': (6, 12),
'norm_ws': False,
'rm': [],
Expand Down
4 changes: 2 additions & 2 deletions byexample/expected.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class _LinearExpected(Expected):
>>> from byexample.options import Options
>>> from byexample.finder import _build_fake_example as build_example

>>> opts = {'norm_ws': False, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6,12)}
>>> opts = {'norm_ws': False, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6,12), 'ignore_first_empty_lines': True}

Consider the following example with a named capture in the expected:

Expand Down Expand Up @@ -145,7 +145,7 @@ class _LinearExpected(Expected):

(See byexample.parser docs)

>>> opts = {'norm_ws': True, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6, 12)}
>>> opts = {'norm_ws': True, 'tags': True, 'capture': True, 'rm': [], 'type': False, 'input_prefix_range': (6, 12), 'ignore_first_empty_lines': True}
>>> ex = build_example('f()', '\n <a>A \n\nB <bc> C\n<c>', opts=opts)
>>> exp = ex.expected

Expand Down
3 changes: 2 additions & 1 deletion byexample/finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ class F:
'capture': True,
'rm': [],
'type': False,
'input_prefix_range': (6, 12)
'input_prefix_range': (6, 12),
'ignore_first_empty_lines': True,
}
)
parser.extract_options = lambda x: opts
Expand Down
6 changes: 6 additions & 0 deletions byexample/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,12 @@ def get_default_options_parser(cmdline_args):
options_parser.add_flag(
"norm-ws", default=False, help="ignore the amount of whitespaces."
)
options_parser.add_flag(
"ignore-first-empty-lines",
default=True,
help=
"ignore any empty or whitespace-only lines at the begin of the got string."
)
options_parser.add_flag(
"pass",
default=False,
Expand Down
44 changes: 32 additions & 12 deletions byexample/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ def parse(self, example, concerns):
input_prefix_len_range = options['input_prefix_range']
expected_regexs, charnos, rcounts, tags_by_idx, input_list = self.expected_as_regexs(
example.expected_str, options['tags'], options['capture'],
options['type'], options['norm_ws'], input_prefix_len_range
options['type'], options['norm_ws'], input_prefix_len_range,
options['ignore_first_empty_lines']
)

ExpectedClass = _LinearExpected
Expand Down Expand Up @@ -230,8 +231,14 @@ def parse(self, example, concerns):

@profile
def expected_as_regexs(
self, expected, tags_enabled, capture_enabled, input_enabled,
normalize_whitespace, input_prefix_len_range
self,
expected,
tags_enabled,
capture_enabled,
input_enabled,
normalize_whitespace,
input_prefix_len_range,
ignore_first_empty_lines=True
):
r'''
From the expected string create a list of regular expressions that
Expand Down Expand Up @@ -262,8 +269,8 @@ def expected_as_regexs(

We return the regexs

>>> regexs
('\\A', 'a', '(?P<foo>.*?)', 'b', '(?P<bar>.*?)', 'c', '\\n*\\Z')
>>> regexs # byexample: +norm-ws
('\\A(?:[ \\t]*\\n)*?', 'a', '(?P<foo>.*?)', 'b', '(?P<bar>.*?)', 'c', '\\n*\\Z')

>>> m = re.compile(''.join(regexs), re.MULTILINE | re.DOTALL)
>>> m.match('axxbyyyc').groups()
Expand Down Expand Up @@ -300,7 +307,7 @@ def expected_as_regexs(
>>> regexs, _, _, tags_by_idx, _ = _as_regexs(expected, normalize_whitespace=True)

>>> regexs # byexample: +norm-ws
('\\A', 'a', '(?:.*?)(?<!\\s)', '\\s+(?!\\s)', '(?P<foo_bar>.*?)', 'c', '\\s*\\Z')
('\\A\\s*?', 'a', '(?:.*?)(?<!\\s)', '\\s+(?!\\s)', '(?P<foo_bar>.*?)', 'c', '\\s*\\Z')

>>> tags_by_idx
{2: None, 4: 'foo-bar'}
Expand All @@ -315,7 +322,7 @@ def expected_as_regexs(
>>> regexs, _, _, tags_by_idx, _ = _as_regexs(expected)

>>> regexs
('\\A', 'a<foo>b<bar>c', '\\n*\\Z')
('\\A(?:[ \\t]*\\n)*?', 'a<foo>b<bar>c', '\\n*\\Z')

>>> tags_by_idx
{}
Expand All @@ -324,11 +331,24 @@ def expected_as_regexs(
>>> regexs, _, _, tags_by_idx, _ = _as_regexs(expected)

>>> regexs
('\\A', 'a', '(?:.*?)', 'b<bar>c', '\\n*\\Z')
('\\A(?:[ \\t]*\\n)*?', 'a', '(?:.*?)', 'b<bar>c', '\\n*\\Z')

>>> tags_by_idx
{2: None}

When ignore_first_empty_lines is False the begin anchor is a plain \\A,
so the got string must start exactly at the first expected character.

>>> regexs, _, _, _, _ = _as_regexs('foo', ignore_first_empty_lines=False)

>>> regexs
('\\A', 'foo', '\\n*\\Z')

>>> regexs, _, _, _, _ = _as_regexs('foo', normalize_whitespace=True, ignore_first_empty_lines=False)

>>> regexs
('\\A', 'foo', '\\s*\\Z')

'''
if capture_enabled:
tag_regexs = self.tag_regexs()
Expand All @@ -338,12 +358,12 @@ def expected_as_regexs(
if normalize_whitespace:
sm = SM_NormWS(
tag_regexs, self.input_regexs(), self.ellipsis_marker(),
input_prefix_len_range
input_prefix_len_range, ignore_first_empty_lines
)
else:
sm = SM_NotNormWS(
tag_regexs, self.input_regexs(), self.ellipsis_marker(),
input_prefix_len_range
input_prefix_len_range, ignore_first_empty_lines
)

return sm.parse(expected, tags_enabled, input_enabled)
Expand Down Expand Up @@ -433,7 +453,7 @@ def _extend_parser_and_parse_options_strictly_and_cache(self, optlist):
>>> regexs, _, _, _, _ = _as_regexs(expected, normalize_whitespace=True)

>>> regexs
('\\A',
('\\A\\s*?',
'ex',
'\\s',
'(?:\\s*(?!\\s)(?:.+)(?<!\\s))?',
Expand All @@ -450,7 +470,7 @@ def _extend_parser_and_parse_options_strictly_and_cache(self, optlist):
>>> regexs, _, _, _, _ = _as_regexs(expected, normalize_whitespace=True)

>>> regexs
('\\A',
('\\A\\s*?',
'ex',
'\\s',
'(?:\\s*(?!\\s)(?P<foo>.+?)(?<!\\s))?',
Expand Down
Loading
Loading