def parse_tolerance(source, want): """ Returns a version of ``want`` marked up with the tolerance tags specified in ``source``. INPUT: - ``source`` -- a string, the source of a doctest - ``want`` -- a string, the desired output of the doctest OUTPUT: - ``want`` if there are no tolerance tags specified; a :class:`MarkedOutput` version otherwise. EXAMPLES:: sage: from sage.doctest.parsing import parse_tolerance sage: marked = parse_tolerance("sage: s.update(abs_tol = .0000001)", "") sage: type(marked) <... 'str'> sage: marked = parse_tolerance("sage: s.update(tol = 0.1); s.rel_tol # abs tol 0.01 ", "") sage: marked.tol 0 sage: marked.rel_tol 0 sage: marked.abs_tol 0.010000000000000000000...? """ safe, literals, state = strip_string_literals(source) first_line = safe.split('\n', 1)[0] if '#' not in first_line: return want comment = first_line[first_line.find('#') + 1:] comment = comment[comment.index('(') + 1:comment.rindex(')')] # strip_string_literals replaces comments comment = literals[comment] if random_marker.search(comment): want = MarkedOutput(want).update(random=True) else: m = tolerance_pattern.search(comment) if m: rel_or_abs, epsilon = m.groups() if epsilon is None: epsilon = RIFtol("1e-15") else: epsilon = RIFtol(epsilon) if rel_or_abs is None: want = MarkedOutput(want).update(tol=epsilon) elif rel_or_abs.startswith('rel'): want = MarkedOutput(want).update(rel_tol=epsilon) elif rel_or_abs.startswith('abs'): want = MarkedOutput(want).update(abs_tol=epsilon) else: raise RuntimeError return want
def parse_tolerance(source, want): """ Returns a version of ``want`` marked up with the tolerance tags specified in ``source``. INPUT: - ``source`` -- a string, the source of a doctest - ``want`` -- a string, the desired output of the doctest OUTPUT: - ``want`` if there are no tolerance tags specified; a :class:`MarkedOutput` version otherwise. EXAMPLES:: sage: from sage.doctest.parsing import parse_tolerance sage: marked = parse_tolerance("sage: s.update(abs_tol = .0000001)", "") sage: type(marked) <... 'str'> sage: marked = parse_tolerance("sage: s.update(tol = 0.1); s.rel_tol # abs tol 0.01 ", "") sage: marked.tol 0 sage: marked.rel_tol 0 sage: marked.abs_tol 0.010000000000000000000? """ safe, literals, state = strip_string_literals(source) first_line = safe.split('\n', 1)[0] if '#' not in first_line: return want comment = first_line[first_line.find('#')+1:] comment = comment[comment.index('(')+1 : comment.rindex(')')] # strip_string_literals replaces comments comment = literals[comment] if random_marker.search(comment): want = MarkedOutput(want).update(random=True) else: m = tolerance_pattern.search(comment) if m: rel_or_abs, epsilon = m.groups() if epsilon is None: epsilon = RIFtol("1e-15") else: epsilon = RIFtol(epsilon) if rel_or_abs is None: want = MarkedOutput(want).update(tol=epsilon) elif rel_or_abs.startswith('rel'): want = MarkedOutput(want).update(rel_tol=epsilon) elif rel_or_abs.startswith('abs'): want = MarkedOutput(want).update(abs_tol=epsilon) else: raise RuntimeError return want
def parse_optional_tags(string): """ Returns a set consisting of the optional tags from the following set that occur in a comment on the first line of the input string. - 'long time' - 'not implemented' - 'not tested' - 'known bug' - 'py2' - 'py3' - 'optional: PKG_NAME' -- the set will just contain 'PKG_NAME' EXAMPLES:: sage: from sage.doctest.parsing import parse_optional_tags sage: parse_optional_tags("sage: magma('2 + 2')# optional: magma") {'magma'} sage: parse_optional_tags("sage: #optional -- mypkg") {'mypkg'} sage: parse_optional_tags("sage: print(1) # parentheses are optional here") set() sage: parse_optional_tags("sage: print(1) # optional") {''} sage: sorted(list(parse_optional_tags("sage: #optional -- foo bar, baz"))) ['bar', 'foo'] sage: sorted(list(parse_optional_tags(" sage: factor(10^(10^10) + 1) # LoNg TiME, NoT TeSTED; OptioNAL -- P4cka9e"))) ['long time', 'not tested', 'p4cka9e'] sage: parse_optional_tags(" sage: raise RuntimeError # known bug") {'bug'} sage: sorted(list(parse_optional_tags(" sage: determine_meaning_of_life() # long time, not implemented"))) ['long time', 'not implemented'] We don't parse inside strings:: sage: parse_optional_tags(" sage: print(' # long time')") set() sage: parse_optional_tags(" sage: print(' # long time') # not tested") {'not tested'} UTF-8 works:: sage: parse_optional_tags("'ěščřžýáíéďĎ'") set() """ safe, literals, state = strip_string_literals(string) first_line = safe.split('\n', 1)[0] if '#' not in first_line: return set() comment = first_line[first_line.find('#') + 1:] comment = comment[comment.index('(') + 1:comment.rindex(')')] # strip_string_literals replaces comments comment = "#" + (literals[comment]).lower() tags = [] for m in optional_regex.finditer(comment): cmd = m.group(1) if cmd == 'known bug': tags.append( 'bug' ) # so that such tests will be run by sage -t ... -only-optional=bug elif cmd: tags.append(cmd) else: tags.extend(m.group(3).split() or [""]) return set(tags)
def preparse(line, reset=True, do_time=False, ignore_prompts=False, numeric_literals=True): r""" Preparses a line of input. The code is taken from sage.repl.preparse and modified to increase numerical stability. INPUT: - ``line`` - a string - ``reset`` - a boolean (default: True) - ``do_time`` - a boolean (default: False) - ``ignore_prompts`` - a boolean (default: False) - ``numeric_literals`` - a boolean (default: True) OUTPUT: - a string """ global quote_state if reset: quote_state = None L = line.lstrip() if len(L) > 0 and L[0] in ['#', '!']: return line if L.startswith('...'): i = line.find('...') return line[:i+3] + preparse(line[i+3:], reset=reset, do_time=do_time, ignore_prompts=ignore_prompts) if ignore_prompts: # Get rid of leading sage: and >>> so that pasting of examples from # the documentation works. line = strip_prompts(line) # This part handles lines with semi-colons all at once # Then can also handle multiple lines more efficiently, but # that optimization can be done later. L, literals, quote_state = strip_string_literals(line, quote_state) # Ellipsis Range # [1..n] try: L = parse_ellipsis(L, preparse_step=False) except SyntaxError: pass if implicit_mul_level: # Implicit Multiplication # 2x -> 2*x L = implicit_mul(L, level = implicit_mul_level) if numeric_literals: # Wrapping # 1 + 0.5 -> Integer(1) + RealNumber('0.5') L = preparse_numeric_literals(L) # Generators # R.0 -> R.gen(0) L = re.sub(r'([_a-zA-Z]\w*|[)\]])\.(\d+)', r'\1.gen(\2)', L) # Use ^ for exponentiation and ^^ for xor # (A side effect is that **** becomes xor as well.) L = L.replace('^', '**').replace('****', '^') # Make it easy to match statement ends L = ';%s;' % L.replace('\n', ';\n;') if do_time: # Separate time statement L = re.sub(r';(\s*)time +(\w)', r';time;\1\2', L) # Construction with generators # R.<...> = obj() # R.<...> = R[] L = preparse_generators(L) # Calculus functions # f(x,y) = x^3 - sin(y) L = preparse_calculus(L) # Backslash L = re.sub(r'''\\\s*([^\t ;#])''', r' * BackslashOperator() * \1', L) if do_time: # Time keyword L = re.sub(r';time;(\s*)(\S[^;]*)', r';\1__time__=misc.cputime(); __wall__=misc.walltime(); \2; print(' + '"Time: CPU %%.2f s, Wall: %%.2f s"%%(misc.cputime(__time__), misc.walltime(__wall__)))', L) # Remove extra ;'s L = L.replace(';\n;', '\n')[1:-1] line = L % literals return line
def parse_optional_tags(string): """ Returns a set consisting of the optional tags from the following set that occur in a comment on the first line of the input string. - 'long time' - 'not implemented' - 'not tested' - 'known bug' - 'py2' - 'py3' - 'optional: PKG_NAME' -- the set will just contain 'PKG_NAME' EXAMPLES:: sage: from sage.doctest.parsing import parse_optional_tags sage: parse_optional_tags("sage: magma('2 + 2')# optional: magma") {'magma'} sage: parse_optional_tags("sage: #optional -- mypkg") {'mypkg'} sage: parse_optional_tags("sage: print(1) # parentheses are optional here") set() sage: parse_optional_tags("sage: print(1) # optional") {''} sage: sorted(list(parse_optional_tags("sage: #optional -- foo bar, baz"))) ['bar', 'foo'] sage: sorted(list(parse_optional_tags(" sage: factor(10^(10^10) + 1) # LoNg TiME, NoT TeSTED; OptioNAL -- P4cka9e"))) ['long time', 'not tested', 'p4cka9e'] sage: parse_optional_tags(" sage: raise RuntimeError # known bug") {'bug'} sage: sorted(list(parse_optional_tags(" sage: determine_meaning_of_life() # long time, not implemented"))) ['long time', 'not implemented'] We don't parse inside strings:: sage: parse_optional_tags(" sage: print(' # long time')") set() sage: parse_optional_tags(" sage: print(' # long time') # not tested") {'not tested'} UTF-8 works:: sage: parse_optional_tags("'ěščřžýáíéďĎ'") set() """ safe, literals, state = strip_string_literals(string) first_line = safe.split('\n', 1)[0] if '#' not in first_line: return set() comment = first_line[first_line.find('#')+1:] comment = comment[comment.index('(')+1 : comment.rindex(')')] # strip_string_literals replaces comments comment = "#" + (literals[comment]).lower() tags = [] for m in optional_regex.finditer(comment): cmd = m.group(1) if cmd == 'known bug': tags.append('bug') # so that such tests will be run by sage -t ... -only-optional=bug elif cmd: tags.append(cmd) else: tags.extend(m.group(3).split() or [""]) return set(tags)