aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/tools/docs
diff options
context:
space:
mode:
authorGravatar Mark Daoust <markdaoust@google.com>2017-10-25 20:46:06 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2017-10-25 20:49:56 -0700
commit65616777d73913346ec446df80b6d7aa64e54b24 (patch)
treef7c5f5aa50f85bbb3eb370b2d5168824e03e52c0 /tensorflow/tools/docs
parentff7b9a6c496823c1bffdd0d74bf68aafacb8caca (diff)
Update the ReferenceResolver to output html links.
PiperOrigin-RevId: 173491069
Diffstat (limited to 'tensorflow/tools/docs')
-rw-r--r--tensorflow/tools/docs/parser.py70
-rw-r--r--tensorflow/tools/docs/parser_test.py31
2 files changed, 69 insertions, 32 deletions
diff --git a/tensorflow/tools/docs/parser.py b/tensorflow/tools/docs/parser.py
index 1015103077..3db164c2b5 100644
--- a/tensorflow/tools/docs/parser.py
+++ b/tensorflow/tools/docs/parser.py
@@ -107,23 +107,40 @@ def _get_raw_docstring(py_object):
# A regular expression for capturing a @{symbol} reference.
-SYMBOL_REFERENCE_RE = re.compile(r'@\{([^}]+)\}')
+SYMBOL_REFERENCE_RE = re.compile(
+ r"""
+ # Start with a literal "@{".
+ @\{
+ # Group at least 1 symbol: not "}" or "\n".
+ ([^}\n]+)
+ # Followed by a closing "}"
+ \}
+ """,
+ flags=re.VERBOSE)
class ReferenceResolver(object):
"""Class for replacing @{...} references with Markdown links.
- Args:
- duplicate_of: A map from duplicate names to preferred names of API
- symbols.
- doc_index: A `dict` mapping symbol name strings to objects with `url`
- and `title` fields. Used to resolve @{$doc} references in docstrings.
- index: A map from all full names to python objects.
- py_module_names: A list of string names of Python modules.
+ Attributes:
+ current_doc_full_name: A string (or None) indicating the name of the
+ document currently being processed, so errors can reference the broken
+ doc.
"""
def __init__(self, duplicate_of, doc_index, is_class, is_module,
py_module_names):
+ """Initializes a Reference Resolver.
+
+ Args:
+ duplicate_of: A map from duplicate names to preferred names of API
+ symbols.
+ doc_index: A `dict` mapping symbol name strings to objects with `url`
+ and `title` fields. Used to resolve @{$doc} references in docstrings.
+ is_class: A map from full names to bool for each symbol.
+ is_module: A map from full names to bool for each symbol.
+ py_module_names: A list of string names of Python modules.
+ """
self._duplicate_of = duplicate_of
self._doc_index = doc_index
self._is_class = is_class
@@ -249,11 +266,19 @@ class ReferenceResolver(object):
Returns:
A markdown link to the documentation page of `ref_full_name`.
"""
- link = self.reference_to_url(ref_full_name, relative_path_to_root)
+ url = self.reference_to_url(ref_full_name, relative_path_to_root)
+
if code_ref:
- return '[`%s`](%s)' % (link_text, link)
+ link_text = link_text.join(['<code>', '</code>'])
else:
- return '[%s](%s)' % (link_text, link)
+ link_text = self._link_text_to_html(link_text)
+
+ return '<a href="{}">{}</a>'.format(url, link_text)
+
+ @staticmethod
+ def _link_text_to_html(link_text):
+ code_re = '`(.*?)`'
+ return re.sub(code_re, r'<code>\1</code>', link_text)
def py_master_name(self, full_name):
"""Return the master name for a Python symbol name."""
@@ -322,13 +347,13 @@ class ReferenceResolver(object):
# Handle different types of references.
if string.startswith('$'): # Doc reference
- return self._doc_link(
- string, link_text, manual_link_text, relative_path_to_root)
+ return self._doc_link(string, link_text, manual_link_text,
+ relative_path_to_root)
elif string.startswith('tensorflow::'):
# C++ symbol
- return self._cc_link(
- string, link_text, manual_link_text, relative_path_to_root)
+ return self._cc_link(string, link_text, manual_link_text,
+ relative_path_to_root)
else:
is_python = False
@@ -337,8 +362,11 @@ class ReferenceResolver(object):
is_python = True
break
if is_python: # Python symbol
- return self.python_link(link_text, string, relative_path_to_root,
- code_ref=not manual_link_text)
+ return self.python_link(
+ link_text,
+ string,
+ relative_path_to_root,
+ code_ref=not manual_link_text)
# Error!
self.add_error('Did not understand "%s"' % match.group(0))
@@ -361,7 +389,9 @@ class ReferenceResolver(object):
if not manual_link_text: link_text = self._doc_index[string].title
url = os.path.normpath(os.path.join(
relative_path_to_root, '../..', self._doc_index[string].url))
- return '[%s](%s%s)' % (link_text, url, hash_tag)
+ link_text = self._link_text_to_html(link_text)
+ return '<a href="{}{}">{}</a>'.format(url, hash_tag, link_text)
+
return self._doc_missing(string, hash_tag, link_text, manual_link_text,
relative_path_to_root)
@@ -392,7 +422,9 @@ class ReferenceResolver(object):
# to api_docs/cc, and then add ret.
cc_relative_path = os.path.normpath(os.path.join(
relative_path_to_root, '../cc', ret))
- return '[`%s`](%s)' % (link_text, cc_relative_path)
+
+ return '<a href="{}"><code>{}</code></a>'.format(cc_relative_path,
+ link_text)
# TODO(aselle): Collect these into a big list for all modules and functions
diff --git a/tensorflow/tools/docs/parser_test.py b/tensorflow/tools/docs/parser_test.py
index 3b74a13f08..8a0e9af521 100644
--- a/tensorflow/tools/docs/parser_test.py
+++ b/tensorflow/tools/docs/parser_test.py
@@ -75,8 +75,9 @@ class ParserTest(googletest.TestCase):
def foo(self):
pass
- string = ('A @{tf.reference}, another @{tf.reference}, '
- 'a member @{tf.reference.foo}, and a @{tf.third}.')
+ string = (
+ 'A @{tf.reference}, another @{tf.reference}, a member '
+ '@{tf.reference.foo}, and a @{tf.third$link `text` with `code` in it}.')
duplicate_of = {'tf.third': 'tf.fourth'}
index = {'tf.reference': HasOneMember,
'tf.reference.foo': HasOneMember.foo,
@@ -89,12 +90,15 @@ class ParserTest(googletest.TestCase):
visitor=visitor, doc_index={}, py_module_names=['tf'])
result = reference_resolver.replace_references(string, '../..')
- self.assertEqual(
- 'A [`tf.reference`](../../tf/reference.md), another '
- '[`tf.reference`](../../tf/reference.md), '
- 'a member [`tf.reference.foo`](../../tf/reference.md#foo), '
- 'and a [`tf.third`](../../tf/fourth.md).',
- result)
+ self.assertEqual('A <a href="../../tf/reference.md">'
+ '<code>tf.reference</code></a>, '
+ 'another <a href="../../tf/reference.md">'
+ '<code>tf.reference</code></a>, '
+ 'a member <a href="../../tf/reference.md#foo">'
+ '<code>tf.reference.foo</code></a>, '
+ 'and a <a href="../../tf/fourth.md">link '
+ '<code>text</code> with '
+ '<code>code</code> in it</a>.', result)
def test_doc_replace_references(self):
string = '@{$doc1} @{$doc1#abc} @{$doc1$link} @{$doc1#def$zelda} @{$do/c2}'
@@ -114,10 +118,11 @@ class ParserTest(googletest.TestCase):
reference_resolver = parser.ReferenceResolver.from_visitor(
visitor=visitor, doc_index=doc_index, py_module_names=['tf'])
result = reference_resolver.replace_references(string, 'python')
- self.assertEqual(
- '[Title1](../URL1) [Title1](../URL1#abc) [link](../URL1) '
- '[zelda](../URL1#def) [Two words](../somewhere/else)',
- result)
+ self.assertEqual('<a href="../URL1">Title1</a> '
+ '<a href="../URL1#abc">Title1</a> '
+ '<a href="../URL1">link</a> '
+ '<a href="../URL1#def">zelda</a> '
+ '<a href="../somewhere/else">Two words</a>', result)
def test_docs_for_class(self):
@@ -389,7 +394,7 @@ class ParserTest(googletest.TestCase):
self.assertIn('TestModule.test_function', docs)
# Leading backtick to make sure it's included top-level.
# This depends on formatting, but should be stable.
- self.assertIn('`test_function', docs)
+ self.assertIn('<code>test_function', docs)
def test_argspec_for_functools_partial(self):