aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/tools/docs
diff options
context:
space:
mode:
authorGravatar Scott Zhu <scottzhu@google.com>2018-04-13 17:52:20 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-04-13 17:57:27 -0700
commit3652556dab3ebfe0152232facc7304fe5754aecb (patch)
tree9a9cecde4c85dc53548a185f9bd6d7c6e0591262 /tensorflow/tools/docs
parentef24ad14502e992716c49fdd5c63e6b2c2fb6b5a (diff)
Merge changes from github.
PiperOrigin-RevId: 192850372
Diffstat (limited to 'tensorflow/tools/docs')
-rw-r--r--tensorflow/tools/docs/BUILD2
-rw-r--r--tensorflow/tools/docs/build_docs_test.py5
-rw-r--r--tensorflow/tools/docs/generate_lib.py19
-rw-r--r--tensorflow/tools/docs/generate_lib_test.py3
-rw-r--r--tensorflow/tools/docs/parser.py56
-rw-r--r--tensorflow/tools/docs/parser_test.py80
-rw-r--r--tensorflow/tools/docs/pretty_docs.py12
-rw-r--r--tensorflow/tools/docs/py_guide_parser.py2
8 files changed, 117 insertions, 62 deletions
diff --git a/tensorflow/tools/docs/BUILD b/tensorflow/tools/docs/BUILD
index d370fbd246..0c1fd0cf9d 100644
--- a/tensorflow/tools/docs/BUILD
+++ b/tensorflow/tools/docs/BUILD
@@ -37,7 +37,7 @@ py_library(
srcs = ["parser.py"],
srcs_version = "PY2AND3",
visibility = ["//visibility:public"],
- deps = ["@com_github_andreif_codegen"],
+ deps = ["@astor_archive//:astor"],
)
py_test(
diff --git a/tensorflow/tools/docs/build_docs_test.py b/tensorflow/tools/docs/build_docs_test.py
index ae293f6576..0cbf8b478f 100644
--- a/tensorflow/tools/docs/build_docs_test.py
+++ b/tensorflow/tools/docs/build_docs_test.py
@@ -19,7 +19,6 @@ from __future__ import division
from __future__ import print_function
import os
-import sys
import textwrap
import tensorflow as tf
@@ -39,10 +38,6 @@ class Flags(object):
class BuildDocsTest(googletest.TestCase):
def testBuildDocs(self):
- if sys.version_info >= (3, 0):
- print('Warning: Doc generation is not supported from python3.')
- return
-
doc_generator = generate_lib.DocGenerator()
doc_generator.set_py_modules([('tf', tf), ('tfdbg', tf_debug)])
diff --git a/tensorflow/tools/docs/generate_lib.py b/tensorflow/tools/docs/generate_lib.py
index 9cc261d7dd..111d54d820 100644
--- a/tensorflow/tools/docs/generate_lib.py
+++ b/tensorflow/tools/docs/generate_lib.py
@@ -21,7 +21,6 @@ from __future__ import print_function
import argparse
import fnmatch
import os
-import sys
import six
@@ -134,8 +133,12 @@ def write_docs(output_dir, parser_config, yaml_toc, root_title='TensorFlow'):
try:
if not os.path.exists(directory):
os.makedirs(directory)
- with open(path, 'w') as f:
- f.write(pretty_docs.build_md_page(page_info))
+ # This function returns raw bytes in PY2 or unicode in PY3.
+ text = pretty_docs.build_md_page(page_info)
+ if six.PY3:
+ text = text.encode('utf-8')
+ with open(path, 'wb') as f:
+ f.write(text)
except OSError as e:
print('Cannot write documentation for %s to %s: %s' % (full_name,
directory, e))
@@ -437,19 +440,19 @@ def _other_docs(src_dir, output_dir, reference_resolver, file_pattern='*.md'):
full_out_path = os.path.join(output_dir, suffix)
if not fnmatch.fnmatch(base_name, file_pattern):
print('Copying un-matched file %s...' % suffix)
- open(full_out_path, 'w').write(open(full_in_path).read())
+ open(full_out_path, 'wb').write(open(full_in_path, 'rb').read())
continue
if dirpath.endswith('/api_guides/python'):
print('Processing Python guide %s...' % base_name)
content = tag_updater.process(full_in_path)
else:
print('Processing doc %s...' % suffix)
- content = open(full_in_path).read()
+ content = open(full_in_path, 'rb').read().decode('utf-8')
content = reference_resolver.replace_references(content,
relative_path_to_root)
- with open(full_out_path, 'w') as f:
- f.write(content)
+ with open(full_out_path, 'wb') as f:
+ f.write(content.encode('utf-8'))
print('Done.')
@@ -458,8 +461,6 @@ class DocGenerator(object):
"""Main entry point for generating docs."""
def __init__(self):
- if sys.version_info >= (3, 0):
- sys.exit('Doc generation is not supported from python3.')
self.argument_parser = argparse.ArgumentParser()
self._py_modules = None
self._private_map = _get_default_private_map()
diff --git a/tensorflow/tools/docs/generate_lib_test.py b/tensorflow/tools/docs/generate_lib_test.py
index 1ceaf31f1c..ea6d28a02b 100644
--- a/tensorflow/tools/docs/generate_lib_test.py
+++ b/tensorflow/tools/docs/generate_lib_test.py
@@ -52,9 +52,6 @@ class DummyVisitor(object):
class GenerateTest(googletest.TestCase):
def test_write(self):
- if sys.version_info >= (3, 0):
- self.skipTest('Warning: Doc generation is not supported from python3.')
-
module = sys.modules[__name__]
index = {
diff --git a/tensorflow/tools/docs/parser.py b/tensorflow/tools/docs/parser.py
index d2a63ecc49..fb0bd2c2ff 100644
--- a/tensorflow/tools/docs/parser.py
+++ b/tensorflow/tools/docs/parser.py
@@ -26,7 +26,7 @@ import os
import re
import sys
-import codegen
+import astor
import six
from google.protobuf.message import Message as ProtoMessage
@@ -621,20 +621,20 @@ def _parse_md_docstring(py_object, relative_path_to_root, reference_resolver):
def _get_arg_spec(func):
"""Extracts signature information from a function or functools.partial object.
- For functions, uses `tf_inspect.getargspec`. For `functools.partial` objects,
- corrects the signature of the underlying function to take into account the
- removed arguments.
+ For functions, uses `tf_inspect.getfullargspec`. For `functools.partial`
+ objects, corrects the signature of the underlying function to take into
+ account the removed arguments.
Args:
func: A function whose signature to extract.
Returns:
- An `ArgSpec` namedtuple `(args, varargs, keywords, defaults)`, as returned
- by `tf_inspect.getargspec`.
+ An `FullArgSpec` namedtuple `(args, varargs, varkw, defaults, etc.)`,
+ as returned by `tf_inspect.getfullargspec`.
"""
- # getargspec does not work for functools.partial objects directly.
+ # getfullargspec does not work for functools.partial objects directly.
if isinstance(func, functools.partial):
- argspec = tf_inspect.getargspec(func.func)
+ argspec = tf_inspect.getfullargspec(func.func)
# Remove the args from the original function that have been used up.
first_default_arg = (
len(argspec.args or []) - len(argspec.defaults or []))
@@ -657,12 +657,16 @@ def _get_arg_spec(func):
argspec_defaults.pop(i-first_default_arg)
else:
first_default_arg -= 1
- return tf_inspect.ArgSpec(args=argspec_args,
- varargs=argspec.varargs,
- keywords=argspec.keywords,
- defaults=tuple(argspec_defaults))
+ return tf_inspect.FullArgSpec(
+ args=argspec_args,
+ varargs=argspec.varargs,
+ varkw=argspec.varkw,
+ defaults=tuple(argspec_defaults),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
else: # Regular function or method, getargspec will work fine.
- return tf_inspect.getargspec(func)
+ return tf_inspect.getfullargspec(func)
def _remove_first_line_indent(string):
@@ -670,11 +674,14 @@ def _remove_first_line_indent(string):
return '\n'.join([line[indent:] for line in string.split('\n')])
+PAREN_NUMBER_RE = re.compile(r'^\(([0-9.e-]+)\)')
+
+
def _generate_signature(func, reverse_index):
"""Given a function, returns a list of strings representing its args.
This function produces a list of strings representing the arguments to a
- python function. It uses tf_inspect.getargspec, which
+ python function. It uses tf_inspect.getfullargspec, which
does not generalize well to Python 3.x, which is more flexible in how *args
and **kwargs are handled. This is not a problem in TF, since we have to remain
compatible to Python 2.7 anyway.
@@ -725,7 +732,11 @@ def _generate_signature(func, reverse_index):
if id(default) in reverse_index:
default_text = reverse_index[id(default)]
elif ast_default is not None:
- default_text = codegen.to_source(ast_default)
+ default_text = (
+ astor.to_source(ast_default).rstrip('\n').replace('\t', '\\t')
+ .replace('\n', '\\n').replace('"""', "'"))
+ default_text = PAREN_NUMBER_RE.sub('\\1', default_text)
+
if default_text != repr(default):
# This may be an internal name. If so, handle the ones we know about.
# TODO(wicke): This should be replaced with a lookup in the index.
@@ -758,8 +769,8 @@ def _generate_signature(func, reverse_index):
# Add *args and *kwargs.
if argspec.varargs:
args_list.append('*' + argspec.varargs)
- if argspec.keywords:
- args_list.append('**' + argspec.keywords)
+ if argspec.varkw:
+ args_list.append('**' + argspec.varkw)
return args_list
@@ -1136,9 +1147,11 @@ class _ClassPageInfo(object):
for short_name in parser_config.tree[self.full_name]:
# Remove builtin members that we never want to document.
- if short_name in ['__class__', '__base__', '__weakref__', '__doc__',
- '__module__', '__dict__', '__abstractmethods__',
- '__slots__', '__getnewargs__']:
+ if short_name in [
+ '__class__', '__base__', '__weakref__', '__doc__', '__module__',
+ '__dict__', '__abstractmethods__', '__slots__', '__getnewargs__',
+ '__str__', '__repr__', '__hash__'
+ ]:
continue
child_name = '.'.join([self.full_name, short_name])
@@ -1183,7 +1196,8 @@ class _ClassPageInfo(object):
# obvious what they do, don't include them in the docs if there's no
# docstring.
if not child_doc.brief.strip() and short_name in [
- '__str__', '__repr__', '__hash__', '__del__', '__copy__']:
+ '__del__', '__copy__'
+ ]:
print('Skipping %s, defined in %s, no docstring.' % (child_name,
defining_class))
continue
diff --git a/tensorflow/tools/docs/parser_test.py b/tensorflow/tools/docs/parser_test.py
index fca5436ca5..274d48ef66 100644
--- a/tensorflow/tools/docs/parser_test.py
+++ b/tensorflow/tools/docs/parser_test.py
@@ -398,7 +398,6 @@ class ParserTest(googletest.TestCase):
self.assertIn('<code>test_function', docs)
def test_argspec_for_functools_partial(self):
-
# pylint: disable=unused-argument
def test_function_for_partial1(arg1, arg2, kwarg1=1, kwarg2=2):
pass
@@ -409,42 +408,95 @@ class ParserTest(googletest.TestCase):
# pylint: disable=protected-access
# Make sure everything works for regular functions.
- expected = tf_inspect.ArgSpec(['arg1', 'arg2', 'kwarg1', 'kwarg2'], None,
- None, (1, 2))
+ expected = tf_inspect.FullArgSpec(
+ args=['arg1', 'arg2', 'kwarg1', 'kwarg2'],
+ varargs=None,
+ varkw=None,
+ defaults=(1, 2),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
self.assertEqual(expected, parser._get_arg_spec(test_function_for_partial1))
# Make sure doing nothing works.
- expected = tf_inspect.ArgSpec(['arg1', 'arg2', 'kwarg1', 'kwarg2'], None,
- None, (1, 2))
+ expected = tf_inspect.FullArgSpec(
+ args=['arg1', 'arg2', 'kwarg1', 'kwarg2'],
+ varargs=None,
+ varkw=None,
+ defaults=(1, 2),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
partial = functools.partial(test_function_for_partial1)
self.assertEqual(expected, parser._get_arg_spec(partial))
# Make sure setting args from the front works.
- expected = tf_inspect.ArgSpec(['arg2', 'kwarg1', 'kwarg2'], None, None,
- (1, 2))
+ expected = tf_inspect.FullArgSpec(
+ args=['arg2', 'kwarg1', 'kwarg2'],
+ varargs=None,
+ varkw=None,
+ defaults=(1, 2),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
partial = functools.partial(test_function_for_partial1, 1)
self.assertEqual(expected, parser._get_arg_spec(partial))
- expected = tf_inspect.ArgSpec(['kwarg2',], None, None, (2,))
+ expected = tf_inspect.FullArgSpec(
+ args=['kwarg2'],
+ varargs=None,
+ varkw=None,
+ defaults=(2,),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
partial = functools.partial(test_function_for_partial1, 1, 2, 3)
self.assertEqual(expected, parser._get_arg_spec(partial))
# Make sure setting kwargs works.
- expected = tf_inspect.ArgSpec(['arg1', 'arg2', 'kwarg2'], None, None, (2,))
+ expected = tf_inspect.FullArgSpec(
+ args=['arg1', 'arg2', 'kwarg2'],
+ varargs=None,
+ varkw=None,
+ defaults=(2,),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
partial = functools.partial(test_function_for_partial1, kwarg1=0)
self.assertEqual(expected, parser._get_arg_spec(partial))
- expected = tf_inspect.ArgSpec(['arg1', 'arg2', 'kwarg1'], None, None, (1,))
+ expected = tf_inspect.FullArgSpec(
+ args=['arg1', 'arg2', 'kwarg1'],
+ varargs=None,
+ varkw=None,
+ defaults=(1,),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
partial = functools.partial(test_function_for_partial1, kwarg2=0)
self.assertEqual(expected, parser._get_arg_spec(partial))
- expected = tf_inspect.ArgSpec(['arg1'], None, None, ())
+ expected = tf_inspect.FullArgSpec(
+ args=['arg1'],
+ varargs=None,
+ varkw=None,
+ defaults=(),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
partial = functools.partial(test_function_for_partial1,
arg2=0, kwarg1=0, kwarg2=0)
self.assertEqual(expected, parser._get_arg_spec(partial))
# Make sure *args, *kwargs is accounted for.
- expected = tf_inspect.ArgSpec([], 'my_args', 'my_kwargs', ())
+ expected = tf_inspect.FullArgSpec(
+ args=[],
+ varargs='my_args',
+ varkw='my_kwargs',
+ defaults=(),
+ kwonlyargs=[],
+ kwonlydefaults=None,
+ annotations={})
partial = functools.partial(test_function_for_partial2, 0, 1)
self.assertEqual(expected, parser._get_arg_spec(partial))
@@ -524,10 +576,6 @@ class TestParseFunctionDetails(googletest.TestCase):
class TestGenerateSignature(googletest.TestCase):
def test_known_object(self):
- if sys.version_info >= (3, 0):
- print('Warning: Doc generation is not supported from python3.')
- return
-
known_object = object()
reverse_index = {id(known_object): 'location.of.object.in.api'}
diff --git a/tensorflow/tools/docs/pretty_docs.py b/tensorflow/tools/docs/pretty_docs.py
index 543b5fa6fe..55ab5bdd49 100644
--- a/tensorflow/tools/docs/pretty_docs.py
+++ b/tensorflow/tools/docs/pretty_docs.py
@@ -101,7 +101,7 @@ def _build_class_page(page_info):
link_template = '[`{short_name}`]({url})'
parts.append(', '.join(
- link_template.format(**base.__dict__) for base in page_info.bases))
+ link_template.format(**base._asdict()) for base in page_info.bases))
parts.append('\n\n')
@@ -159,7 +159,7 @@ def _build_class_page(page_info):
h3 = ('<h3 id="{short_name}">'
'<code>{short_name}</code>'
'</h3>\n\n')
- parts.append(h3.format(**method_info.__dict__))
+ parts.append(h3.format(**method_info._asdict()))
if method_info.signature is not None:
parts.append(_build_signature(method_info, use_full_name=False))
@@ -217,7 +217,7 @@ def _build_module_page(page_info):
template = '[`{short_name}`]({url}) module'
for item in page_info.modules:
- parts.append(template.format(**item.__dict__))
+ parts.append(template.format(**item._asdict()))
if item.doc.brief:
parts.append(': ' + item.doc.brief)
@@ -229,7 +229,7 @@ def _build_module_page(page_info):
template = '[`class {short_name}`]({url})'
for item in page_info.classes:
- parts.append(template.format(**item.__dict__))
+ parts.append(template.format(**item._asdict()))
if item.doc.brief:
parts.append(': ' + item.doc.brief)
@@ -241,7 +241,7 @@ def _build_module_page(page_info):
template = '[`{short_name}(...)`]({url})'
for item in page_info.functions:
- parts.append(template.format(**item.__dict__))
+ parts.append(template.format(**item._asdict()))
if item.doc.brief:
parts.append(': ' + item.doc.brief)
@@ -254,7 +254,7 @@ def _build_module_page(page_info):
parts.append('## Other Members\n\n')
for item in page_info.other_members:
- parts.append('`{short_name}`\n\n'.format(**item.__dict__))
+ parts.append('`{short_name}`\n\n'.format(**item._asdict()))
return ''.join(parts)
diff --git a/tensorflow/tools/docs/py_guide_parser.py b/tensorflow/tools/docs/py_guide_parser.py
index 216353ecee..328f42d18f 100644
--- a/tensorflow/tools/docs/py_guide_parser.py
+++ b/tensorflow/tools/docs/py_guide_parser.py
@@ -44,7 +44,7 @@ class PyGuideParser(object):
def process(self, full_path):
"""Read and process the file at `full_path`."""
- md_string = open(full_path).read()
+ md_string = open(full_path, 'rb').read().decode('utf-8')
self._lines = md_string.split('\n')
seen = set()