diff --git a/tensorflow/tools/docs/parser.py b/tensorflow/tools/docs/parser.py index 5d70a52e5f0..15f754cc710 100644 --- a/tensorflow/tools/docs/parser.py +++ b/tensorflow/tools/docs/parser.py @@ -152,6 +152,27 @@ def replace_references(string, relative_path_to_root, duplicate_of): string) +# TODO(aselle): Collect these into a big list for all modules and functions +# and make a rosetta stone page. +def _handle_compatibility(doc): + """Parse and remove compatibility blocks from the main docstring. + + Args: + doc: The docstring that contains compatibility notes" + + Returns: + a tuple of the modified doc string and a hash that maps from compatibility + note type to the text of the note. + """ + compatibility_notes = {} + match_compatibility = re.compile(r'[ \t]*@compatibility\((\w+)\)\s*\n' + r'((?:[^@\n]*\n)+)' + r'\s*@end_compatibility') + for f in match_compatibility.finditer(doc): + compatibility_notes[f.group(1)] = f.group(2) + return match_compatibility.subn(r'', doc)[0], compatibility_notes + + def _md_docstring(py_object, relative_path_to_root, duplicate_of): """Get the docstring from an object and make it into nice Markdown. @@ -177,6 +198,9 @@ def _md_docstring(py_object, relative_path_to_root, duplicate_of): """ # TODO(wicke): If this is a partial, use the .func docstring and add a note. raw_docstring = _get_raw_docstring(py_object) + raw_docstring = replace_references(raw_docstring, relative_path_to_root, + duplicate_of) + raw_docstring, compatibility = _handle_compatibility(raw_docstring) raw_lines = raw_docstring.split('\n') # Define regular expressions used during parsing below. @@ -189,10 +213,9 @@ def _md_docstring(py_object, relative_path_to_root, duplicate_of): def is_section_start(i): # Previous line is empty, line i is "Word:", and next line is indented. - return (i > 0 and not raw_lines[i-1].strip() and + return (i > 0 and i < len(raw_lines) and not raw_lines[i-1].strip() and re.match(section_re, raw_lines[i]) and len(raw_lines) > i+1 and raw_lines[i+1].startswith(' ')) - for i, line in enumerate(raw_lines): if not in_special_section and is_section_start(i): in_special_section = True @@ -210,13 +233,14 @@ def _md_docstring(py_object, relative_path_to_root, duplicate_of): lines.append(symbol_list_item_re.sub(r'* `\1`: ', line)) else: lines.append(line) - docstring = '\n'.join(lines) - + sorted_keys = compatibility.keys() + sorted_keys.sort() + for key in sorted_keys: + value = compatibility[key] + docstring += ('\n\n#### %s compatibility\n%s\n' % (key, value)) # TODO(deannarubin): Improve formatting for devsite - # TODO(deannarubin): Interpret @compatibility and other formatting notes. - - return replace_references(docstring, relative_path_to_root, duplicate_of) + return docstring def _get_arg_spec(func): diff --git a/tensorflow/tools/docs/parser_test.py b/tensorflow/tools/docs/parser_test.py index c92d7f968c5..d77ed344535 100644 --- a/tensorflow/tools/docs/parser_test.py +++ b/tensorflow/tools/docs/parser_test.py @@ -51,6 +51,17 @@ def test_function_with_fancy_docstring(arg): Returns: arg: the input, and arg: the input, again. + + @compatibility(numpy) + NumPy has nothing as awesome as this function. + @end_compatibility + + @compatibility(theano) + Theano has nothing as awesome as this function. + + Check it out. + @end_compatibility + """ return arg, arg @@ -178,7 +189,6 @@ class ParserTest(googletest.TestCase): # Make sure docstring shows up. self.assertTrue(inspect.getdoc(test_function) in docs) - # Make sure the extracted signature is good. self.assertTrue( 'test_function(unused_arg, unused_kwarg=\'default\')' in docs) @@ -246,7 +256,6 @@ class ParserTest(googletest.TestCase): py_object=test_function_with_fancy_docstring, duplicate_of={}, duplicates={}, index=index, tree=tree, reverse_index={}, base_dir='/') - expected = '\n'.join([ 'Function with a fancy docstring.', '', @@ -259,6 +268,22 @@ class ParserTest(googletest.TestCase): '', '* `arg`: the input, and', '* `arg`: the input, again.', + '', + '', + '', + '', + '', + '#### numpy compatibility', + 'NumPy has nothing as awesome as this function.', + '', + '', + '', + '#### theano compatibility', + 'Theano has nothing as awesome as this function.', + '', + 'Check it out.', + '', + '', '']) self.assertTrue(expected in docs)