]> granicus.if.org Git - python/commitdiff
Reverted the addition of a NORMALIZE_NUMBERS option, per Tim Peter's
authorEdward Loper <edloper@gradient.cis.upenn.edu>
Tue, 28 Sep 2004 05:50:57 +0000 (05:50 +0000)
committerEdward Loper <edloper@gradient.cis.upenn.edu>
Tue, 28 Sep 2004 05:50:57 +0000 (05:50 +0000)
request.  Tim says that "correct 'fuzzy' comparison of floats cannot
be automated."  (The motivation behind adding the new option
was verifying interactive examples in Python's latex documentation;
several such examples use numbers that don't print consistently on
different platforms.)

Doc/lib/libdoctest.tex
Lib/doctest.py
Lib/test/test_doctest.py

index a30a432de317ca4730cb5b68b3feae764e4666d6..26354864732cd37f64e534f6382b7b2b763a5815 100644 (file)
@@ -581,17 +581,6 @@ TypeError: object doesn't support item assignment
 
 \end{datadesc}
 
-\begin{datadesc}{NORMALIZE_NUMBERS}
-    When specified, number literals in the expected output will match
-    corresponding number literals in the actual output if their values
-    are equal (to ten digits of precision).  For example, \code{1.1}
-    will match \code{1.1000000000000001}; and \code{1L} will match
-    \code{1} and \code{1.0}.  Currently, \constant{NORMALIZE_NUMBERS}
-    can fail to normalize numbers when used in conjunction with
-    ellipsis.  In particular, if an ellipsis marker matches one or
-    more numbers, then number normalization is not supported.
-\end{datadesc}
-
 \begin{datadesc}{COMPARISON_FLAGS}
     A bitmask or'ing together all the comparison flags above.
 \end{datadesc}
@@ -713,7 +702,7 @@ can be useful.
 
 \versionchanged[Constants \constant{DONT_ACCEPT_BLANKLINE},
     \constant{NORMALIZE_WHITESPACE}, \constant{ELLIPSIS},
-    \constant{IGNORE_EXCEPTION_DETAIL}, \constant{NORMALIZE_NUMBERS},
+    \constant{IGNORE_EXCEPTION_DETAIL},
     \constant{REPORT_UDIFF}, \constant{REPORT_CDIFF},
     \constant{REPORT_NDIFF}, \constant{REPORT_ONLY_FIRST_FAILURE},
     \constant{COMPARISON_FLAGS} and \constant{REPORTING_FLAGS}
@@ -751,7 +740,6 @@ in any particular order, so a test like
 
 % Hey! What happened to Monty Python examples?
 % Tim: ask Guido -- it's his example!
-% doctest: ignore
 \begin{verbatim}
 >>> foo()
 {"Hermione": "hippogryph", "Harry": "broomstick"}
@@ -759,7 +747,6 @@ in any particular order, so a test like
 
 is vulnerable!  One workaround is to do
 
-% doctest: ignore
 \begin{verbatim}
 >>> foo() == {"Hermione": "hippogryph", "Harry": "broomstick"}
 True
@@ -767,7 +754,6 @@ True
 
 instead.  Another is to do
 
-% doctest: ignore
 \begin{verbatim}
 >>> d = foo().items()
 >>> d.sort()
@@ -779,7 +765,6 @@ There are others, but you get the idea.
 
 Another bad idea is to print things that embed an object address, like
 
-% doctest: ignore
 \begin{verbatim}
 >>> id(1.0) # certain to fail some of the time
 7948648
@@ -791,7 +776,6 @@ Another bad idea is to print things that embed an object address, like
 The \constant{ELLIPSIS} directive gives a nice approach for the last
 example:
 
-% doctest: ignore
 \begin{verbatim}
 >>> C() #doctest: +ELLIPSIS
 <__main__.C instance at 0x...>
@@ -801,7 +785,6 @@ Floating-point numbers are also subject to small output variations across
 platforms, because Python defers to the platform C library for float
 formatting, and C libraries vary widely in quality here.
 
-% doctest: ignore
 \begin{verbatim}
 >>> 1./7  # risky
 0.14285714285714285
@@ -1635,7 +1618,6 @@ Doctest provides several mechanisms for debugging doctest examples:
 
       Then an interactive Python session may look like this:
 
-% doctest: ignore
 \begin{verbatim}
 >>> import a, doctest
 >>> doctest.testmod(a)
index dfd8bb9275e6682f16b863d677bbec37478634c5..26a89144689ac39801276b51f2e55d5af5d3d4c7 100644 (file)
@@ -55,7 +55,6 @@ __all__ = [
     'NORMALIZE_WHITESPACE',
     'ELLIPSIS',
     'IGNORE_EXCEPTION_DETAIL',
-    'NORMALIZE_NUMBERS',
     'COMPARISON_FLAGS',
     'REPORT_UDIFF',
     'REPORT_CDIFF',
@@ -140,14 +139,12 @@ DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
 NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
 ELLIPSIS = register_optionflag('ELLIPSIS')
 IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
-NORMALIZE_NUMBERS = register_optionflag('NORMALIZE_NUMBERS')
 
 COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |
                     DONT_ACCEPT_BLANKLINE |
                     NORMALIZE_WHITESPACE |
                     ELLIPSIS |
-                    IGNORE_EXCEPTION_DETAIL |
-                    NORMALIZE_NUMBERS)
+                    IGNORE_EXCEPTION_DETAIL)
 
 REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
 REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
@@ -280,72 +277,6 @@ class _SpoofOut(StringIO):
         if hasattr(self, "softspace"):
             del self.softspace
 
-# The number of digits of precision that must be equal for
-# NORMALIZE_NUMBERS to consider two numbers equal.
-_NORMALIZE_NUMBERS_PRECISION_THRESHOLD = 10
-
-# A regular expression that matches Python number literals.  This is
-# used by _normalize_numbers to look for numbers that should be
-# normalized.
-_NUMBER_LITERAL = re.compile(r'''
-    (\d+[.]\d*(?:[eE][-+]?\d+)?[jJ]? | # float (w/ digits left of ".")
-        [.]\d+(?:[eE][-+]?\d+)?[jJ]? | # float (no digits left of ".")
-     \d+      (?:[eE][-+]?\d+) [jJ]? | # float (no ".", exponent only)
-     \d                        [jJ]  | # float (no ".", imaginary only)
-     0[xX]\d+[lL]?                   | # hexint
-     0[0-7]*[lL]?                    | # octint or zero
-     \d+[lL]?                        ) # decint
-     ''', re.VERBOSE)
-
-def _normalize_numbers(want, got):
-    """
-    If all the numbers in `want` and `got` match (one-for-one), then
-    return a new version of `got` with the exact number strings from
-    `want` spliced in.  Two numbers match if `str` of their float
-    values are equal.  (I.e., `x` matches `y` if
-    `str(float(x))==str(float(y))`).
-    """
-    want_pieces = _NUMBER_LITERAL.split(want)
-    got_pieces = _NUMBER_LITERAL.split(got)
-
-    # If they don't have the same number of numbers, fail immediately.
-    if len(want_pieces) != len(got_pieces):
-        return got
-
-    # If any individual numbers don't match, then fail.
-    for i in range(1, len(got_pieces), 2):
-        w, g = eval(want_pieces[i]), eval(got_pieces[i])
-        if not _numbers_match(w, g):
-            return got
-
-    # Success; replace numbers in got w/ numbers from want.
-    for i in range(1, len(got_pieces), 2):
-        got_pieces[i] = want_pieces[i]
-    return ''.join(got_pieces)
-
-def _numbers_match(x, y):
-    """
-    A helper function for _normalize_numbers, that returns true if the
-    numbers `x` and `y` are close enough to match for NORMALIZE_NUMBERS.
-    """
-    # Equal numbers match.
-    if x == y:
-        return True
-    # Split up complex numbers into real & imag.
-    if isinstance(x, complex):
-        return (isinstance(y, complex) and
-                _numbers_match(x.real, y.real) and
-                _numbers_match(x.imag, y.imag))
-    # If the signs are different, they don't match.
-    if x*y < 0:
-        return False
-    # If one is zero and the other isn't, they don't match.
-    if x==0 or y==0:
-        return False
-    # They're not exactly equal, but are they close enough?
-    threshold = 10**-_NORMALIZE_NUMBERS_PRECISION_THRESHOLD
-    return (abs(x-y) / min(abs(x), abs(y))) < threshold
-
 # Worst-case linear-time ellipsis matching.
 def _ellipsis_match(want, got):
     """
@@ -1572,13 +1503,6 @@ class OutputChecker:
             if got == want:
                 return True
 
-        # This flag causes doctest to treat numbers that are within a
-        # small threshold as if they are equal.
-        if optionflags & NORMALIZE_NUMBERS:
-            got = _normalize_numbers(want, got)
-            if got == want:
-                return True
-
         # The ELLIPSIS flag says to let the sequence "..." in `want`
         # match any substring in `got`.
         if optionflags & ELLIPSIS:
@@ -1859,7 +1783,6 @@ def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
         NORMALIZE_WHITESPACE
         ELLIPSIS
         IGNORE_EXCEPTION_DETAIL
-        NORMALIZE_NUMBERS
         REPORT_UDIFF
         REPORT_CDIFF
         REPORT_NDIFF
@@ -1982,7 +1905,6 @@ def testfile(filename, module_relative=True, name=None, package=None,
         NORMALIZE_WHITESPACE
         ELLIPSIS
         IGNORE_EXCEPTION_DETAIL
-        NORMALIZE_NUMBERS
         REPORT_UDIFF
         REPORT_CDIFF
         REPORT_NDIFF
index eb0b10cd78ae940cc53a84d08a3d9e66c2256779..d17ca1a401511f4757091567850a52b9712d9c3e 100644 (file)
@@ -1032,107 +1032,6 @@ treated as equal:
     [0,   1,  2,  3,  4,  5,  6,  7,  8,  9,
     10,  11, 12, 13, 14, 15, 16, 17, 18, 19]
 
-The NORMALIZE_NUMBERS flag causes numbers that are equal (to
-approximately 10 decimal places) but formatted differently to match.
-
-    >>> def f(x): '''
-    ...     Numbers will match if they are exactly equal:
-    ...
-    ...     >>> print 1.1, 'intervening text', 1L # should match
-    ...     1.1 intervening text 1L
-    ...     >>> print 1.0j, 22, 22.0, 1, 1e1      # should match
-    ...     1j 22.0 22 1 10.0
-    ...
-    ...     Numbers will match if they are equal to 14 digits of
-    ...     precision:
-    ...
-    ...     >>> 2.00000000001                      # should match
-    ...     1.99999999999
-    ...     >>> 2.000000001                        # should not match
-    ...     1.999999999
-    ...     >>> 2.00000000001e10                   # should match
-    ...     1.99999999999e10
-    ...     >>> 2.000000001e10                     # should not match
-    ...     1.999999999e10
-    ...     '''
-
-    >>> # Without the flag:
-    >>> test = doctest.DocTestFinder().find(f)[0]
-    >>> doctest.DocTestRunner(verbose=False).run(test)
-    ... # doctest: +ELLIPSIS
-    **********************************************************************
-    File ..., line 4, in f
-    Failed example:
-        print 1.1, 'intervening text', 1L # should match
-    Expected:
-        1.1 intervening text 1L
-    Got:
-        1.1 intervening text 1
-    **********************************************************************
-    File ..., line 6, in f
-    Failed example:
-        print 1.0j, 22, 22.0, 1, 1e1      # should match
-    Expected:
-        1j 22.0 22 1 10.0
-    Got:
-        1j 22 22.0 1 10.0
-    **********************************************************************
-    File ..., line 12, in f
-    Failed example:
-        2.00000000001                      # should match
-    Expected:
-        1.99999999999
-    Got:
-        2.00000000001
-    **********************************************************************
-    File ..., line 14, in f
-    Failed example:
-        2.000000001                        # should not match
-    Expected:
-        1.999999999
-    Got:
-        2.0000000010000001
-    **********************************************************************
-    File ..., line 16, in f
-    Failed example:
-        2.00000000001e10                   # should match
-    Expected:
-        1.99999999999e10
-    Got:
-        20000000000.099998
-    **********************************************************************
-    File ..., line 18, in f
-    Failed example:
-        2.000000001e10                     # should not match
-    Expected:
-        1.999999999e10
-    Got:
-        20000000010.0
-    (6, 6)
-
-    >>> # With the flag:
-    >>> test = doctest.DocTestFinder().find(f)[0]
-    >>> flags = doctest.NORMALIZE_NUMBERS
-    >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
-    ... # doctest: +ELLIPSIS
-    **********************************************************************
-    File ..., line 14, in f
-    Failed example:
-        2.000000001                        # should not match
-    Expected:
-        1.999999999
-    Got:
-        2.0000000010000001
-    **********************************************************************
-    File ..., line 18, in f
-    Failed example:
-        2.000000001e10                     # should not match
-    Expected:
-        1.999999999e10
-    Got:
-        20000000010.0
-    (2, 6)
-
 The ELLIPSIS flag causes ellipsis marker ("...") in the expected
 output to match any substring in the actual output: