Exemplo n.º 1
0
    def test_do_not_doc_inheritable_property(self):
        class Parent(object):
            @property
            @doc_controls.do_not_doc_inheritable
            def my_method(self):
                pass

        class Child(Parent):
            @property
            def my_method(self):
                pass

        class GrandChild(Child):
            pass

        self.assertTrue(doc_controls.should_skip(Parent.my_method))
        self.assertFalse(doc_controls.should_skip(Child.my_method))
        self.assertFalse(doc_controls.should_skip(GrandChild.my_method))

        self.assertTrue(
            doc_controls.should_skip_class_attr(Parent, 'my_method'))
        self.assertTrue(doc_controls.should_skip_class_attr(
            Child, 'my_method'))
        self.assertTrue(
            doc_controls.should_skip_class_attr(GrandChild, 'my_method'))
Exemplo n.º 2
0
  def test_do_not_doc_inheritable_property(self):

    class Parent(object):

      @property
      @doc_controls.do_not_doc_inheritable
      def my_method(self):
        pass

    class Child(Parent):

      @property
      def my_method(self):
        pass

    class GrandChild(Child):
      pass

    self.assertTrue(doc_controls.should_skip(Parent.my_method))
    self.assertFalse(doc_controls.should_skip(Child.my_method))
    self.assertFalse(doc_controls.should_skip(GrandChild.my_method))

    self.assertTrue(doc_controls.should_skip_class_attr(Parent, 'my_method'))
    self.assertTrue(doc_controls.should_skip_class_attr(Child, 'my_method'))
    self.assertTrue(
        doc_controls.should_skip_class_attr(GrandChild, 'my_method'))
Exemplo n.º 3
0
  def test_do_not_doc_on_method(self):
    """The simple decorator is not aware of inheritance."""

    class Parent(object):

      @doc_controls.do_not_generate_docs
      def my_method(self):
        pass

    class Child(Parent):

      def my_method(self):
        pass

    class GrandChild(Child):
      pass

    self.assertTrue(doc_controls.should_skip(Parent.my_method))
    self.assertFalse(doc_controls.should_skip(Child.my_method))
    self.assertFalse(doc_controls.should_skip(GrandChild.my_method))

    self.assertTrue(doc_controls.should_skip_class_attr(Parent, 'my_method'))
    self.assertFalse(doc_controls.should_skip_class_attr(Child, 'my_method'))
    self.assertFalse(
        doc_controls.should_skip_class_attr(GrandChild, 'my_method'))
Exemplo n.º 4
0
  def test_do_not_generate_docs(self):

    @doc_controls.do_not_generate_docs
    def dummy_function():
      pass

    self.assertTrue(doc_controls.should_skip(dummy_function))
Exemplo n.º 5
0
    def test_do_not_doc_on_method(self):
        """The simple decorator is not aware of inheritance."""
        class Parent(object):
            @doc_controls.do_not_generate_docs
            def my_method(self):
                pass

        class Child(Parent):
            def my_method(self):
                pass

        class GrandChild(Child):
            pass

        self.assertTrue(doc_controls.should_skip(Parent.my_method))
        self.assertFalse(doc_controls.should_skip(Child.my_method))
        self.assertFalse(doc_controls.should_skip(GrandChild.my_method))

        self.assertTrue(
            doc_controls.should_skip_class_attr(Parent, 'my_method'))
        self.assertFalse(
            doc_controls.should_skip_class_attr(Child, 'my_method'))
        self.assertFalse(
            doc_controls.should_skip_class_attr(GrandChild, 'my_method'))
Exemplo n.º 6
0
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
            _is_free_function(py_object, full_name, parser_config.index)):
      continue

    if doc_controls.should_skip(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 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)))

  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 _is_private(self, path, name, obj):
     if doc_controls.should_skip(obj):
         return True
     return super(DocControlsAwareCrawler,
                  self)._is_private(path, name, obj)
Exemplo n.º 8
0
def write_docs(output_dir,
               parser_config,
               yaml_toc,
               root_title='TensorFlow',
               search_hints=True,
               site_api_path=None):
  """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: Used to write the api-duplicates _redirects.yaml file. if
      None (the default) the file is not generated.

  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
            _is_free_function(py_object, full_name, parser_config.index)):
      continue

    if doc_controls.should_skip(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 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))

    if site_api_path:
      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((from_path, to_path))

  if site_api_path and 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: /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))
Exemplo n.º 9
0
 def _is_private(self, path, name, obj):
   if doc_controls.should_skip(obj):
     return True
   return super(DocControlsAwareCrawler, self)._is_private(path, name, obj)
Exemplo n.º 10
0
    def test_do_not_generate_docs(self):
        @doc_controls.do_not_generate_docs
        def dummy_function():
            pass

        self.assertTrue(doc_controls.should_skip(dummy_function))