Exemple #1
0
def write_docs(output_dir, parser_config, yaml_toc, root_title='TensorFlow'):
  """Write previously extracted docs to disk.

  Write a docs page for each symbol included in the indices of parser_config to
  a tree of docs at `output_dir`.

  Symbols with multiple aliases will have only one page written about
  them, which is referenced for all aliases.

  Args:
    output_dir: Directory to write documentation markdown files to. Will be
      created if it doesn't exist.
    parser_config: A `parser.ParserConfig` object, containing all the necessary
      indices.
    yaml_toc: Set to `True` to generate a "_toc.yaml" file.
    root_title: The title name for the root level index.md.

  Raises:
    ValueError: if `output_dir` is not an absolute path
  """
  # Make output_dir.
  if not os.path.isabs(output_dir):
    raise ValueError("'output_dir' must be an absolute path.\n"
                     "    output_dir='%s'" % output_dir)

  try:
    if not os.path.exists(output_dir):
      os.makedirs(output_dir)
  except OSError as e:
    print('Creating output dir "%s" failed: %s' % (output_dir, e))
    raise

  # These dictionaries are used for table-of-contents generation below
  # They will contain, after the for-loop below::
  #  - module name(string):classes and functions the module contains(list)
  module_children = {}
  #  - symbol name(string):pathname (string)
  symbol_to_file = {}

  # Parse and write Markdown pages, resolving cross-links (@{symbol}).
  for full_name, py_object in six.iteritems(parser_config.index):
    parser_config.reference_resolver.current_doc_full_name = full_name

    if full_name in parser_config.duplicate_of:
      continue

    # Methods and some routines are documented only as part of their class.
    if not (tf_inspect.ismodule(py_object) or tf_inspect.isclass(py_object) or
            _is_free_function(py_object, full_name, parser_config.index)):
      continue

    sitepath = os.path.join('api_docs/python',
                            parser.documentation_path(full_name)[:-3])

    # For TOC, we need to store a mapping from full_name to the file
    # we're generating
    symbol_to_file[full_name] = sitepath

    # For a module, remember the module for the table-of-contents
    if tf_inspect.ismodule(py_object):
      if full_name in parser_config.tree:
        module_children.setdefault(full_name, [])

    # For something else that's documented,
    # figure out what module it lives in
    else:
      subname = str(full_name)
      while True:
        subname = subname[:subname.rindex('.')]
        if tf_inspect.ismodule(parser_config.index[subname]):
          module_children.setdefault(subname, []).append(full_name)
          break

    print('Writing docs for %s (%r).' % (full_name, py_object))

    # Generate docs for `py_object`, resolving references.
    page_info = parser.docs_for_object(full_name, py_object, parser_config)

    path = os.path.join(output_dir, parser.documentation_path(full_name))
    directory = os.path.dirname(path)
    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))
    except OSError as e:
      print('Cannot write documentation for %s to %s: %s' % (full_name,
                                                             directory, e))
      raise

  if yaml_toc:
    # Generate table of contents

    # Put modules in alphabetical order, case-insensitive
    modules = sorted(module_children.keys(), key=lambda a: a.upper())

    leftnav_path = os.path.join(output_dir, '_toc.yaml')
    with open(leftnav_path, 'w') as f:

      # Generate header
      f.write('# Automatically generated file; please do not edit\ntoc:\n')
      for module in modules:
        indent_num = module.count('.')
        # Don't list `tf.submodule` inside `tf`
        indent_num = max(indent_num, 1)
        indent = '  '*indent_num

        if indent_num > 1:
          # tf.contrib.baysflow.entropy will be under
          #   tf.contrib->baysflow->entropy
          title = module.split('.')[-1]
        else:
          title = module

        header = [
            '- title: ' + title,
            '  section:',
            '  - title: Overview',
            '    path: /TARGET_DOC_ROOT/VERSION/' + symbol_to_file[module]]
        header = ''.join([indent+line+'\n' for line in header])
        f.write(header)

        symbols_in_module = module_children.get(module, [])
        # Sort case-insensitive, if equal sort case sensitive (upper first)
        symbols_in_module.sort(key=lambda a: (a.upper(), a))

        for full_name in symbols_in_module:
          item = [
              '  - title: ' + full_name[len(module) + 1:],
              '    path: /TARGET_DOC_ROOT/VERSION/' + symbol_to_file[full_name]]
          item = ''.join([indent+line+'\n' for line in item])
          f.write(item)

  # Write a global index containing all full names with links.
  with open(os.path.join(output_dir, 'index.md'), 'w') as f:
    f.write(
        parser.generate_global_index(root_title, parser_config.index,
                                     parser_config.reference_resolver))
 def test_documentation_path(self):
   self.assertEqual('test.md', parser.documentation_path('test'))
   self.assertEqual('test/module.md', parser.documentation_path('test.module'))
Exemple #3
0
def write_docs(output_dir, parser_config, duplicate_of, index, yaml_toc):
  """Write previously extracted docs to disk.

  Write a docs page for each symbol in `index` to a tree of docs at
  `output_dir`.

  Symbols with multiple aliases will have only one page written about
  them, which is referenced for all aliases.

  Args:
    output_dir: Directory to write documentation markdown files to. Will be
      created if it doesn't exist.
    parser_config: A `parser.ParserConfig` object.
    duplicate_of: A `dict` mapping fully qualified names to "master" names.
      Used to determine which docs pages to write.
    index: A `dict` mapping fully qualified names to the corresponding Python
      objects. Used to produce docs for child objects.
    yaml_toc: Set to `True` to generate a "_toc.yaml" file.
  """
  # Make output_dir.
  try:
    if not os.path.exists(output_dir):
      os.makedirs(output_dir)
  except OSError as e:
    print('Creating output dir "%s" failed: %s' % (output_dir, e))
    raise

  # These dictionaries are used for table-of-contents generation below
  # They will contain, after the for-loop below::
  #  - module name(string):classes and functions the module contains(list)
  module_children = {}
  #  - symbol name(string):pathname (string)
  symbol_to_file = {}

  # Parse and write Markdown pages, resolving cross-links (@{symbol}).
  for full_name, py_object in six.iteritems(index):

    if full_name in duplicate_of:
      continue

    # Methods and some routines are documented only as part of their class.
    if not (inspect.ismodule(py_object) or
            inspect.isclass(py_object) or
            _is_free_function(py_object, full_name, index)):
      continue

    sitepath = os.path.join('api_docs/python',
                            parser.documentation_path(full_name)[:-3])

    # For TOC, we need to store a mapping from full_name to the file
    # we're generating
    symbol_to_file[full_name] = sitepath

    # For a module, remember the module for the table-of-contents
    if inspect.ismodule(py_object):
      if full_name in parser_config.tree:
        module_children.setdefault(full_name, [])

    # For something else that's documented,
    # figure out what module it lives in
    else:
      subname = str(full_name)
      while True:
        subname = subname[:subname.rindex('.')]
        if inspect.ismodule(index[subname]):
          module_children.setdefault(subname, []).append(full_name)
          break

    print('Writing docs for %s (%r).' % (full_name, py_object))

    # Generate docs for `py_object`, resolving references.
    page_info = parser.docs_for_object(full_name, py_object, parser_config)

    path = os.path.join(output_dir, parser.documentation_path(full_name))
    directory = os.path.dirname(path)
    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))
    except OSError as e:
      print('Cannot write documentation for %s to %s: %s' % (full_name,
                                                             directory, e))
      raise

  if yaml_toc:
    # Generate table of contents

    # Put modules in alphabetical order, case-insensitive
    modules = sorted(module_children.keys(), key=lambda a: a.upper())

    leftnav_path = os.path.join(output_dir, '_toc.yaml')
    with open(leftnav_path, 'w') as f:

      # Generate header
      f.write('# Automatically generated file; please do not edit\ntoc:\n')
      for module in modules:
        f.write('  - title: ' + module + '\n'
                '    section:\n' +
                '    - title: Overview\n' +
                '      path: /TARGET_DOC_ROOT/' + symbol_to_file[module] + '\n')

        symbols_in_module = module_children.get(module, [])
        symbols_in_module.sort(key=lambda a: a.upper())

        for full_name in symbols_in_module:
          f.write('    - title: ' + full_name[len(module)+1:] + '\n'
                  '      path: /TARGET_DOC_ROOT/' +
                  symbol_to_file[full_name] + '\n')

  # Write a global index containing all full names with links.
  with open(os.path.join(output_dir, 'index.md'), 'w') as f:
    f.write(parser.generate_global_index(
        'TensorFlow', index, parser_config.reference_resolver))
Exemple #4
0
def write_docs(output_dir, parser_config, yaml_toc, root_title='TensorFlow'):
    """Write previously extracted docs to disk.

  Write a docs page for each symbol included in the indices of parser_config to
  a tree of docs at `output_dir`.

  Symbols with multiple aliases will have only one page written about
  them, which is referenced for all aliases.

  Args:
    output_dir: Directory to write documentation markdown files to. Will be
      created if it doesn't exist.
    parser_config: A `parser.ParserConfig` object, containing all the necessary
      indices.
    yaml_toc: Set to `True` to generate a "_toc.yaml" file.
    root_title: The title name for the root level index.md.

  Raises:
    ValueError: if `output_dir` is not an absolute path
  """
    # Make output_dir.
    if not os.path.isabs(output_dir):
        raise ValueError("'output_dir' must be an absolute path.\n"
                         "    output_dir='%s'" % output_dir)

    try:
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
    except OSError as e:
        print('Creating output dir "%s" failed: %s' % (output_dir, e))
        raise

    # These dictionaries are used for table-of-contents generation below
    # They will contain, after the for-loop below::
    #  - module name(string):classes and functions the module contains(list)
    module_children = {}
    #  - symbol name(string):pathname (string)
    symbol_to_file = {}

    # Parse and write Markdown pages, resolving cross-links (@{symbol}).
    for full_name, py_object in six.iteritems(parser_config.index):
        parser_config.reference_resolver.current_doc_full_name = full_name

        if full_name in parser_config.duplicate_of:
            continue

        # Methods and some routines are documented only as part of their class.
        if not (tf_inspect.ismodule(py_object)
                or tf_inspect.isclass(py_object) or _is_free_function(
                    py_object, full_name, parser_config.index)):
            continue

        sitepath = os.path.join('api_docs/python',
                                parser.documentation_path(full_name)[:-3])

        # For TOC, we need to store a mapping from full_name to the file
        # we're generating
        symbol_to_file[full_name] = sitepath

        # For a module, remember the module for the table-of-contents
        if tf_inspect.ismodule(py_object):
            if full_name in parser_config.tree:
                module_children.setdefault(full_name, [])

        # For something else that's documented,
        # figure out what module it lives in
        else:
            subname = str(full_name)
            while True:
                subname = subname[:subname.rindex('.')]
                if tf_inspect.ismodule(parser_config.index[subname]):
                    module_children.setdefault(subname, []).append(full_name)
                    break

        print('Writing docs for %s (%r).' % (full_name, py_object))

        # Generate docs for `py_object`, resolving references.
        page_info = parser.docs_for_object(full_name, py_object, parser_config)

        path = os.path.join(output_dir, parser.documentation_path(full_name))
        directory = os.path.dirname(path)
        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))
        except OSError as e:
            print('Cannot write documentation for %s to %s: %s' %
                  (full_name, directory, e))
            raise

    if yaml_toc:
        # Generate table of contents

        # Put modules in alphabetical order, case-insensitive
        modules = sorted(module_children.keys(), key=lambda a: a.upper())

        leftnav_path = os.path.join(output_dir, '_toc.yaml')
        with open(leftnav_path, 'w') as f:

            # Generate header
            f.write(
                '# Automatically generated file; please do not edit\ntoc:\n')
            for module in modules:
                f.write('  - title: ' + module + '\n'
                        '    section:\n' + '    - title: Overview\n' +
                        '      path: /TARGET_DOC_ROOT/VERSION/' +
                        symbol_to_file[module] + '\n')

                symbols_in_module = module_children.get(module, [])
                # Sort case-insensitive, if equal sort case sensitive (upper first)
                symbols_in_module.sort(key=lambda a: (a.upper(), a))

                for full_name in symbols_in_module:
                    f.write('    - title: ' + full_name[len(module) + 1:] +
                            '\n'
                            '      path: /TARGET_DOC_ROOT/VERSION/' +
                            symbol_to_file[full_name] + '\n')

    # Write a global index containing all full names with links.
    with open(os.path.join(output_dir, 'index.md'), 'w') as f:
        f.write(
            parser.generate_global_index(root_title, parser_config.index,
                                         parser_config.reference_resolver))
Exemple #5
0
def write_docs(output_dir, base_dir, duplicate_of, duplicates, index, tree,
               reverse_index, guide_index):
  """Write previously extracted docs to disk.

  Write a docs page for each symbol in `index` to a tree of docs at
  `output_dir`.

  Symbols with multiple aliases will have only one page written about them,
  which is referenced for all aliases. `duplicate_of` and `duplicates` are used
  to determine which docs pages to write.

  Args:
    output_dir: Directory to write documentation markdown files to. Will be
      created if it doesn't exist.
    base_dir: Base directory of the code being documented. This prefix is
      stripped from all file paths that are part of the documentation.
    duplicate_of: A `dict` mapping fully qualified names to "master" names. This
      is used to resolve "@{symbol}" references to the "master" name.
    duplicates: A `dict` mapping fully qualified names to a set of all
      aliases of this name. This is used to automatically generate a list of all
      aliases for each name.
    index: A `dict` mapping fully qualified names to the corresponding Python
      objects. Used to produce docs for child objects, and to check the validity
      of "@{symbol}" references.
    tree: A `dict` mapping a fully qualified name to the names of all its
      members. Used to populate the members section of a class or module page.
    reverse_index: A `dict` mapping object ids to fully qualified names.
    guide_index: A `dict` mapping symbol name strings to GuideRef.
  """
  # Make output_dir.
  try:
    if not os.path.exists(output_dir):
      os.makedirs(output_dir)
  except OSError as e:
    print('Creating output dir "%s" failed: %s' % (output_dir, e))
    raise

  # Parse and write Markdown pages, resolving cross-links (@{symbol}).
  for full_name, py_object in six.iteritems(index):

    if full_name in duplicate_of:
      print('Not writing docs for %s, duplicate of %s.' % (
          full_name, duplicate_of[full_name]))
      continue

    # Methods and some routines are documented only as part of their class.
    if not (inspect.ismodule(py_object) or
            inspect.isclass(py_object) or
            inspect.isfunction(py_object)):
      print('Not writing docs for %s, not a class, module, or function.' % (
          full_name))
      continue

    print('Writing docs for %s (%r).' % (full_name, py_object))

    # Generate docs for `py_object`, resolving references.
    markdown = parser.generate_markdown(full_name, py_object,
                                        duplicate_of=duplicate_of,
                                        duplicates=duplicates,
                                        index=index,
                                        tree=tree,
                                        reverse_index=reverse_index,
                                        guide_index=guide_index,
                                        base_dir=base_dir)

    # TODO(deannarubin): use _tree to generate sidebar information.

    path = os.path.join(output_dir, parser.documentation_path(full_name))
    directory = os.path.dirname(path)
    try:
      if not os.path.exists(directory):
        os.makedirs(directory)
      with open(path, 'w') as f:
        f.write(markdown)
    except OSError as e:
      print('Cannot write documentation for %s to %s: %s' % (full_name,
                                                             directory, e))
      raise
    # TODO(deannarubin): write sidebar file?

  # Write a global index containing all full names with links.
  with open(os.path.join(output_dir, 'index.md'), 'w') as f:
    f.write(parser.generate_global_index('TensorFlow', index, duplicate_of))
Exemple #6
0
 def test_documentation_path(self):
     self.assertEqual('test.md', parser.documentation_path('test'))
     self.assertEqual('test/module.md',
                      parser.documentation_path('test.module'))
Exemple #7
0
def write_docs(output_dir,
               parser_config,
               yaml_toc,
               root_title='TensorFlow',
               search_hints=True,
               site_api_path='api_docs/python'):
    """Write previously extracted docs to disk.

  Write a docs page for each symbol included in the indices of parser_config to
  a tree of docs at `output_dir`.

  Symbols with multiple aliases will have only one page written about
  them, which is referenced for all aliases.

  Args:
    output_dir: Directory to write documentation markdown files to. Will be
      created if it doesn't exist.
    parser_config: A `parser.ParserConfig` object, containing all the necessary
      indices.
    yaml_toc: Set to `True` to generate a "_toc.yaml" file.
    root_title: The title name for the root level index.md.
    search_hints: (bool) include meta-data search hints at the top of each
      output file.
    site_api_path: The output path relative to the site root. Used in the
      `_toc.yaml` and `_redirects.yaml` files.

  Raises:
    ValueError: if `output_dir` is not an absolute path
  """
    # Make output_dir.
    if not os.path.isabs(output_dir):
        raise ValueError("'output_dir' must be an absolute path.\n"
                         "    output_dir='%s'" % output_dir)

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # These dictionaries are used for table-of-contents generation below
    # They will contain, after the for-loop below::
    #  - module name(string):classes and functions the module contains(list)
    module_children = {}
    #  - symbol name(string):pathname (string)
    symbol_to_file = {}

    # Collect redirects for an api _redirects.yaml file.
    redirects = []

    # Parse and write Markdown pages, resolving cross-links (@{symbol}).
    for full_name, py_object in six.iteritems(parser_config.index):
        parser_config.reference_resolver.current_doc_full_name = full_name

        if full_name in parser_config.duplicate_of:
            continue

        # Methods and some routines are documented only as part of their class.
        if not (tf_inspect.ismodule(py_object)
                or tf_inspect.isclass(py_object) or parser.is_free_function(
                    py_object, full_name, parser_config.index)):
            continue

        sitepath = os.path.join(parser.documentation_path(full_name)[:-3])

        # For TOC, we need to store a mapping from full_name to the file
        # we're generating
        symbol_to_file[full_name] = sitepath

        # For a module, remember the module for the table-of-contents
        if tf_inspect.ismodule(py_object):
            if full_name in parser_config.tree:
                module_children.setdefault(full_name, [])

        # For something else that's documented,
        # figure out what module it lives in
        else:
            subname = str(full_name)
            while True:
                subname = subname[:subname.rindex('.')]
                if tf_inspect.ismodule(parser_config.index[subname]):
                    module_children.setdefault(subname, []).append(full_name)
                    break

        # Generate docs for `py_object`, resolving references.
        page_info = parser.docs_for_object(full_name, py_object, parser_config)

        path = os.path.join(output_dir, parser.documentation_path(full_name))
        directory = os.path.dirname(path)
        try:
            if not os.path.exists(directory):
                os.makedirs(directory)
            # This function returns raw bytes in PY2 or unicode in PY3.
            if search_hints:
                content = [page_info.get_metadata_html()]
            else:
                content = ['']

            content.append(pretty_docs.build_md_page(page_info))
            text = '\n'.join(content)
            if six.PY3:
                text = text.encode('utf-8')
            with open(path, 'wb') as f:
                f.write(text)
        except OSError:
            raise OSError('Cannot write documentation for %s to %s' %
                          (full_name, directory))

        duplicates = parser_config.duplicates.get(full_name, [])
        if not duplicates:
            continue

        duplicates = [item for item in duplicates if item != full_name]

        for dup in duplicates:
            from_path = os.path.join(site_api_path, dup.replace('.', '/'))
            to_path = os.path.join(site_api_path, full_name.replace('.', '/'))
            redirects.append(
                (os.path.join('/', from_path), os.path.join('/', to_path)))

    if redirects:
        redirects = sorted(redirects)
        template = ('- from: {}\n' '  to: {}\n')
        redirects = [template.format(f, t) for f, t in redirects]
        api_redirects_path = os.path.join(output_dir, '_redirects.yaml')
        with open(api_redirects_path, 'w') as redirect_file:
            redirect_file.write('redirects:\n')
            redirect_file.write(''.join(redirects))

    if yaml_toc:
        # Generate table of contents

        # Put modules in alphabetical order, case-insensitive
        modules = sorted(module_children.keys(), key=lambda a: a.upper())

        leftnav_path = os.path.join(output_dir, '_toc.yaml')
        with open(leftnav_path, 'w') as f:

            # Generate header
            f.write(
                '# Automatically generated file; please do not edit\ntoc:\n')
            for module in modules:
                indent_num = module.count('.')
                # Don't list `tf.submodule` inside `tf`
                indent_num = max(indent_num, 1)
                indent = '  ' * indent_num

                if indent_num > 1:
                    # tf.contrib.baysflow.entropy will be under
                    #   tf.contrib->baysflow->entropy
                    title = module.split('.')[-1]
                else:
                    title = module

                header = [
                    '- title: ' + title, '  section:', '  - title: Overview',
                    '    path: ' +
                    os.path.join('/', site_api_path, symbol_to_file[module])
                ]
                header = ''.join([indent + line + '\n' for line in header])
                f.write(header)

                symbols_in_module = module_children.get(module, [])
                # Sort case-insensitive, if equal sort case sensitive (upper first)
                symbols_in_module.sort(key=lambda a: (a.upper(), a))

                for full_name in symbols_in_module:
                    item = [
                        '  - title: ' + full_name[len(module) + 1:],
                        '    path: ' + os.path.join('/', site_api_path,
                                                    symbol_to_file[full_name])
                    ]
                    item = ''.join([indent + line + '\n' for line in item])
                    f.write(item)

    # Write a global index containing all full names with links.
    with open(os.path.join(output_dir, 'index.md'), 'w') as f:
        f.write(
            parser.generate_global_index(root_title, parser_config.index,
                                         parser_config.reference_resolver))
def write_docs(output_dir,
               parser_config,
               yaml_toc,
               root_title='TensorFlow',
               search_hints=True,
               site_api_path=''):
  """Write previously extracted docs to disk.

  Write a docs page for each symbol included in the indices of parser_config to
  a tree of docs at `output_dir`.

  Symbols with multiple aliases will have only one page written about
  them, which is referenced for all aliases.

  Args:
    output_dir: Directory to write documentation markdown files to. Will be
      created if it doesn't exist.
    parser_config: A `parser.ParserConfig` object, containing all the necessary
      indices.
    yaml_toc: Set to `True` to generate a "_toc.yaml" file.
    root_title: The title name for the root level index.md.
    search_hints: (bool) include meta-data search hints at the top of each
      output file.
    site_api_path: The output path relative to the site root. Used in the
      `_toc.yaml` and `_redirects.yaml` files.

  Raises:
    ValueError: if `output_dir` is not an absolute path
  """
  # Make output_dir.
  if not os.path.isabs(output_dir):
    raise ValueError("'output_dir' must be an absolute path.\n"
                     "    output_dir='%s'" % output_dir)

  if not os.path.exists(output_dir):
    os.makedirs(output_dir)

  # These dictionaries are used for table-of-contents generation below
  # They will contain, after the for-loop below::
  #  - module name(string):classes and functions the module contains(list)
  module_children = {}
  #  - symbol name(string):pathname (string)
  symbol_to_file = {}

  # Collect redirects for an api _redirects.yaml file.
  redirects = []

  # Parse and write Markdown pages, resolving cross-links (@{symbol}).
  for full_name, py_object in six.iteritems(parser_config.index):
    parser_config.reference_resolver.current_doc_full_name = full_name

    if full_name in parser_config.duplicate_of:
      continue

    # Methods and some routines are documented only as part of their class.
    if not (tf_inspect.ismodule(py_object) or tf_inspect.isclass(py_object) or
            parser.is_free_function(py_object, full_name, parser_config.index)):
      continue

    sitepath = os.path.join('api_docs/python',
                            parser.documentation_path(full_name)[:-3])

    # For TOC, we need to store a mapping from full_name to the file
    # we're generating
    symbol_to_file[full_name] = sitepath

    # For a module, remember the module for the table-of-contents
    if tf_inspect.ismodule(py_object):
      if full_name in parser_config.tree:
        module_children.setdefault(full_name, [])

    # For something else that's documented,
    # figure out what module it lives in
    else:
      subname = str(full_name)
      while True:
        subname = subname[:subname.rindex('.')]
        if tf_inspect.ismodule(parser_config.index[subname]):
          module_children.setdefault(subname, []).append(full_name)
          break

    # Generate docs for `py_object`, resolving references.
    page_info = parser.docs_for_object(full_name, py_object, parser_config)

    path = os.path.join(output_dir, parser.documentation_path(full_name))
    directory = os.path.dirname(path)
    try:
      if not os.path.exists(directory):
        os.makedirs(directory)
      # This function returns raw bytes in PY2 or unicode in PY3.
      if search_hints:
        content = [page_info.get_metadata_html()]
      else:
        content = ['']

      content.append(pretty_docs.build_md_page(page_info))
      text = '\n'.join(content)
      if six.PY3:
        text = text.encode('utf-8')
      with open(path, 'wb') as f:
        f.write(text)
    except OSError:
      raise OSError(
          'Cannot write documentation for %s to %s' % (full_name, directory))

    duplicates = parser_config.duplicates.get(full_name, [])
    if not duplicates:
      continue

    duplicates = [item for item in duplicates if item != full_name]

    for dup in duplicates:
      from_path = os.path.join(site_api_path, dup.replace('.', '/'))
      to_path = os.path.join(site_api_path, full_name.replace('.', '/'))
      redirects.append((
          os.path.join('/', from_path),
          os.path.join('/', to_path)))

  if redirects:
    redirects = sorted(redirects)
    template = ('- from: {}\n'
                '  to: {}\n')
    redirects = [template.format(f, t) for f, t in redirects]
    api_redirects_path = os.path.join(output_dir, '_redirects.yaml')
    with open(api_redirects_path, 'w') as redirect_file:
      redirect_file.write('redirects:\n')
      redirect_file.write(''.join(redirects))

  if yaml_toc:
    # Generate table of contents

    # Put modules in alphabetical order, case-insensitive
    modules = sorted(module_children.keys(), key=lambda a: a.upper())

    leftnav_path = os.path.join(output_dir, '_toc.yaml')
    with open(leftnav_path, 'w') as f:

      # Generate header
      f.write('# Automatically generated file; please do not edit\ntoc:\n')
      for module in modules:
        indent_num = module.count('.')
        # Don't list `tf.submodule` inside `tf`
        indent_num = max(indent_num, 1)
        indent = '  '*indent_num

        if indent_num > 1:
          # tf.contrib.baysflow.entropy will be under
          #   tf.contrib->baysflow->entropy
          title = module.split('.')[-1]
        else:
          title = module

        header = [
            '- title: ' + title,
            '  section:',
            '  - title: Overview',
            '    path: ' + os.path.join('/', site_api_path,
                                        symbol_to_file[module])]
        header = ''.join([indent+line+'\n' for line in header])
        f.write(header)

        symbols_in_module = module_children.get(module, [])
        # Sort case-insensitive, if equal sort case sensitive (upper first)
        symbols_in_module.sort(key=lambda a: (a.upper(), a))

        for full_name in symbols_in_module:
          item = [
              '  - title: ' + full_name[len(module) + 1:],
              '    path: ' + os.path.join('/', site_api_path,
                                          symbol_to_file[full_name])]
          item = ''.join([indent+line+'\n' for line in item])
          f.write(item)

  # Write a global index containing all full names with links.
  with open(os.path.join(output_dir, 'index.md'), 'w') as f:
    f.write(
        parser.generate_global_index(root_title, parser_config.index,
                                     parser_config.reference_resolver))
Exemple #9
0
def write_docs(output_dir, base_dir, duplicate_of, duplicates, index, tree,
               reverse_index, doc_index, guide_index):
    """Write previously extracted docs to disk.

  Write a docs page for each symbol in `index` to a tree of docs at
  `output_dir`.

  Symbols with multiple aliases will have only one page written about them,
  which is referenced for all aliases. `duplicate_of` and `duplicates` are used
  to determine which docs pages to write.

  Args:
    output_dir: Directory to write documentation markdown files to. Will be
      created if it doesn't exist.
    base_dir: Base directory of the code being documented. This prefix is
      stripped from all file paths that are part of the documentation.
    duplicate_of: A `dict` mapping fully qualified names to "master" names. This
      is used to resolve "@{symbol}" references to the "master" name.
    duplicates: A `dict` mapping fully qualified names to a set of all
      aliases of this name. This is used to automatically generate a list of all
      aliases for each name.
    index: A `dict` mapping fully qualified names to the corresponding Python
      objects. Used to produce docs for child objects, and to check the validity
      of "@{symbol}" references.
    tree: A `dict` mapping a fully qualified name to the names of all its
      members. Used to populate the members section of a class or module page.
    reverse_index: A `dict` mapping object ids to fully qualified names.
    doc_index: A `dict` mapping a doc key to a DocInfo.
    guide_index: A `dict` mapping symbol name strings to GuideRef.
  """
    # Make output_dir.
    try:
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
    except OSError as e:
        print('Creating output dir "%s" failed: %s' % (output_dir, e))
        raise

    # These dictionaries are used for table-of-contents generation below
    # They will contain, after the for-loop below::
    #  - module name(string):classes and functions the module contains(list)
    module_children = {}
    #  - symbol name(string):pathname (string)
    symbol_to_file = {}

    # Parse and write Markdown pages, resolving cross-links (@{symbol}).
    for full_name, py_object in six.iteritems(index):

        if full_name in duplicate_of:
            continue

        # Methods and some routines are documented only as part of their class.
        if not (inspect.ismodule(py_object) or inspect.isclass(py_object)
                or inspect.isfunction(py_object)):
            continue

        sitepath = os.path.join('api_docs/python',
                                parser.documentation_path(full_name)[:-3])

        # For TOC, we need to store a mapping from full_name to the file
        # we're generating
        symbol_to_file[full_name] = sitepath

        # For a module, remember the module for the table-of-contents
        if inspect.ismodule(py_object):
            if full_name in tree:
                module_children.setdefault(full_name, [])

        # For something else that's documented,
        # figure out what module it lives in
        else:
            subname = str(full_name)
            while True:
                subname = subname[:subname.rindex('.')]
                if inspect.ismodule(index[subname]):
                    module_children.setdefault(subname, []).append(full_name)
                    break

        print('Writing docs for %s (%r).' % (full_name, py_object))

        # Generate docs for `py_object`, resolving references.
        markdown = parser.generate_markdown(full_name,
                                            py_object,
                                            duplicate_of=duplicate_of,
                                            duplicates=duplicates,
                                            index=index,
                                            tree=tree,
                                            reverse_index=reverse_index,
                                            doc_index=doc_index,
                                            guide_index=guide_index,
                                            base_dir=base_dir)

        path = os.path.join(output_dir, parser.documentation_path(full_name))
        directory = os.path.dirname(path)
        try:
            if not os.path.exists(directory):
                os.makedirs(directory)
            with open(path, 'w') as f:
                f.write(markdown)
        except OSError as e:
            print('Cannot write documentation for %s to %s: %s' %
                  (full_name, directory, e))
            raise

    # Generate table of contents

    # Put modules in alphabetical order, case-insensitive
    modules = sorted(module_children.keys(), key=lambda a: a.upper())

    leftnav_path = os.path.join(output_dir, '_toc.yaml')
    with open(leftnav_path, 'w') as f:

        # Generate header
        f.write('# Automatically generated file; please do not edit\ntoc:\n')
        for module in modules:
            f.write('  - title: ' + module + '\n'
                    '    section:\n' + '    - title: Overview\n' +
                    '      path: /TARGET_DOC_ROOT/' + symbol_to_file[module] +
                    '\n')

            symbols_in_module = module_children.get(module, [])
            symbols_in_module.sort(key=lambda a: a.upper())

            for full_name in symbols_in_module:
                f.write('    - title: ' + full_name[len(module) + 1:] + '\n'
                        '      path: /TARGET_DOC_ROOT/' +
                        symbol_to_file[full_name] + '\n')

    # Write a global index containing all full names with links.
    with open(os.path.join(output_dir, 'index.md'), 'w') as f:
        f.write(parser.generate_global_index('TensorFlow', index,
                                             duplicate_of))
Exemple #10
0
 def test_documentation_path_empty(self):
   self.assertEqual('index.md', parser.documentation_path(''))