mirror of
https://github.com/python/cpython.git
synced 2025-08-11 12:29:34 +00:00
ELLIPSIS implementation: an ellipsis couldn't match nothing if it
appeared at the end of a line. Repaired that. Also noted that it's too easy to provoke this implementation into requiring exponential time, and especially when a test fails. I'll replace the implementation with an always-efficient one later.
This commit is contained in:
parent
caa9798410
commit
1cf3aa6e66
2 changed files with 31 additions and 4 deletions
|
@ -1468,7 +1468,7 @@ class OutputChecker:
|
||||||
# This flag causes doctest to ignore any differences in the
|
# This flag causes doctest to ignore any differences in the
|
||||||
# contents of whitespace strings. Note that this can be used
|
# contents of whitespace strings. Note that this can be used
|
||||||
# in conjunction with the ELLISPIS flag.
|
# in conjunction with the ELLISPIS flag.
|
||||||
if (optionflags & NORMALIZE_WHITESPACE):
|
if optionflags & NORMALIZE_WHITESPACE:
|
||||||
got = ' '.join(got.split())
|
got = ' '.join(got.split())
|
||||||
want = ' '.join(want.split())
|
want = ' '.join(want.split())
|
||||||
if got == want:
|
if got == want:
|
||||||
|
@ -1477,10 +1477,14 @@ class OutputChecker:
|
||||||
# The ELLIPSIS flag says to let the sequence "..." in `want`
|
# The ELLIPSIS flag says to let the sequence "..." in `want`
|
||||||
# match any substring in `got`. We implement this by
|
# match any substring in `got`. We implement this by
|
||||||
# transforming `want` into a regular expression.
|
# transforming `want` into a regular expression.
|
||||||
if (optionflags & ELLIPSIS):
|
if optionflags & ELLIPSIS:
|
||||||
|
# Remove \n from ...\n, else the newline will be required,
|
||||||
|
# and (for example) ... on a line by itself can't match
|
||||||
|
# nothing gracefully.
|
||||||
|
want_re = want.replace(ELLIPSIS_MARKER + '\n', ELLIPSIS_MARKER)
|
||||||
# Escape any special regexp characters
|
# Escape any special regexp characters
|
||||||
want_re = re.escape(want)
|
want_re = re.escape(want_re)
|
||||||
# Replace ellipsis markers ('...') with .*
|
# Replace escaped ellipsis markers ('\.\.\.') with .*
|
||||||
want_re = want_re.replace(re.escape(ELLIPSIS_MARKER), '.*')
|
want_re = want_re.replace(re.escape(ELLIPSIS_MARKER), '.*')
|
||||||
# Require that it matches the entire string; and set the
|
# Require that it matches the entire string; and set the
|
||||||
# re.DOTALL flag (with '(?s)').
|
# re.DOTALL flag (with '(?s)').
|
||||||
|
|
|
@ -780,6 +780,29 @@ output to match any substring in the actual output:
|
||||||
>>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
|
>>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
|
||||||
(0, 1)
|
(0, 1)
|
||||||
|
|
||||||
|
... should also match nothing gracefully:
|
||||||
|
XXX This can be provoked into requiring exponential time by adding more
|
||||||
|
XXX ellipses; the implementation should change. It's much easier to
|
||||||
|
XXX provoke exponential time with expected output that doesn't match,
|
||||||
|
XXX BTW (then multiple regexp .* thingies each try all possiblities,
|
||||||
|
XXX multiplicatively, without hope of success). That's the real danger,
|
||||||
|
XXX that a failing test will appear to be hung.
|
||||||
|
|
||||||
|
>>> for i in range(100):
|
||||||
|
... print i**2 #doctest: +ELLIPSIS
|
||||||
|
0
|
||||||
|
...
|
||||||
|
1
|
||||||
|
...
|
||||||
|
36
|
||||||
|
...
|
||||||
|
...
|
||||||
|
49
|
||||||
|
64
|
||||||
|
......
|
||||||
|
9801
|
||||||
|
...
|
||||||
|
|
||||||
The UNIFIED_DIFF flag causes failures that involve multi-line expected
|
The UNIFIED_DIFF flag causes failures that involve multi-line expected
|
||||||
and actual outputs to be displayed using a unified diff:
|
and actual outputs to be displayed using a unified diff:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue