示例#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'))
示例#2
0
    def test_doc_in_current_and_subclasses(self):
        class Parent:
            @doc_controls.do_not_doc_in_subclasses
            def my_method(self):
                pass

        class Child1(Parent):
            @doc_controls.doc_in_current_and_subclasses
            def my_method(self):
                pass

        class Child11(Child1):
            pass

        class Child2(Parent):
            pass

        self.assertFalse(
            doc_controls.should_skip_class_attr(Parent, 'my_method'))
        self.assertFalse(
            doc_controls.should_skip_class_attr(Child1, 'my_method'))
        self.assertFalse(
            doc_controls.should_skip_class_attr(Child11, 'my_method'))
        self.assertTrue(
            doc_controls.should_skip_class_attr(Child2, 'my_method'))
示例#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'))
示例#4
0
  def test_for_subclass_implementers(self):

    class GrandParent(object):

      def my_method(self):
        pass

    class Parent(GrandParent):

      @doc_controls.for_subclass_implementers
      def my_method(self):
        pass

    class Child(Parent):
      pass

    class GrandChild(Child):

      def my_method(self):
        pass

    class Grand2Child(Child):
      pass

    self.assertFalse(
        doc_controls.should_skip_class_attr(GrandParent, 'my_method'))
    self.assertFalse(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'))
    self.assertTrue(
        doc_controls.should_skip_class_attr(Grand2Child, 'my_method'))
示例#5
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'))
示例#6
0
    def test_lowest_decorator_wins(self):
        class GrandParent(object):
            @doc_controls.for_subclass_implementers
            def my_method(self):
                pass

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

        class Child(Parent):
            @doc_controls.doc_in_current_and_subclasses
            def my_method(self):
                pass

        class GrandChild(Child):
            @doc_controls.for_subclass_implementers
            def my_method(self):
                pass

        class Grand2Child(GrandChild):
            pass

        self.assertFalse(
            doc_controls.should_skip_class_attr(GrandParent, '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'))
        self.assertTrue(
            doc_controls.should_skip_class_attr(Grand2Child, 'my_method'))
示例#7
0
    def test_for_subclass_implementers_short_circuit(self):
        class GrandParent(object):
            @doc_controls.for_subclass_implementers
            def my_method(self):
                pass

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

        class Child(Parent):
            @doc_controls.do_not_doc_inheritable
            def my_method(self):
                pass

        class GrandChild(Child):
            @doc_controls.for_subclass_implementers
            def my_method(self):
                pass

        class Grand2Child(Child):
            pass

        self.assertFalse(
            doc_controls.should_skip_class_attr(GrandParent, '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.assertFalse(
            doc_controls.should_skip_class_attr(GrandChild, 'my_method'))
        self.assertTrue(
            doc_controls.should_skip_class_attr(Grand2Child, 'my_method'))
  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'))
示例#9
0
    def _is_private(self, path, parent, name, obj):
        """Returns whether a name is private or not."""

        # Skip objects blocked by doc_controls.
        if doc_controls.should_skip(obj):
            return True

        if isinstance(obj, type):
            if doc_controls.should_skip_class_attr(parent, name):
                return True

        if doc_controls.should_doc_private(obj):
            return False

        if inspect.ismodule(obj):
            mod_base_dirs = get_module_base_dirs(obj)
            # This check only handles normal packages/modules. Namespace-package
            # contents will get filtered when the submodules are checked.
            if len(mod_base_dirs) == 1:
                mod_base_dir = mod_base_dirs[0]
                # Check that module is in one of the `self._base_dir`s
                if not any(base in mod_base_dir.parents
                           for base in self._base_dir):
                    return True

        # Skip objects blocked by the private_map
        if name in self._private_map.get('.'.join(path), []):
            return True

        # Skip "_" hidden attributes
        if name.startswith('_') and name not in ALLOWED_DUNDER_METHODS:
            return True

        return False
示例#10
0
    def test_nested_class_do_not_document(self):
        class Outer1:
            @doc_controls.do_not_generate_docs
            class Inner:
                pass

        class Outer2:
            Inner = Outer1.Inner

        class Outer3:
            class Inner(Outer1.Inner):
                pass

        self.assertTrue(doc_controls.should_skip_class_attr(Outer1, 'Inner'))
        self.assertTrue(doc_controls.should_skip_class_attr(Outer2, 'Inner'))
        self.assertFalse(doc_controls.should_skip_class_attr(Outer3, 'Inner'))
示例#11
0
    def test_nested_class_inheritable_decorators(self):
        class Outer1:
            @doc_controls.do_not_doc_inheritable
            class Inner:
                pass

        class Outer2(Outer1):
            pass

        class Outer3(Outer2):
            @doc_controls.doc_in_current_and_subclasses
            class Inner(Outer2.Inner):
                pass

        self.assertTrue(doc_controls.should_skip_class_attr(Outer1, 'Inner'))
        self.assertTrue(doc_controls.should_skip_class_attr(Outer2, 'Inner'))
        self.assertFalse(doc_controls.should_skip_class_attr(Outer3, 'Inner'))
示例#12
0
def filter_doc_controls_skip(path: Sequence[str], parent: Any,
                             children: Children) -> Children:
    del path
    for name, child in children:
        if doc_controls.should_skip(child):
            continue
        if isinstance(parent, type):
            if doc_controls.should_skip_class_attr(parent, name):
                continue
        yield (name, child)
示例#13
0
  def test_skip_class_short_circuit(self):

    class GrandParent(object):

      def my_method(self):
        pass

    @doc_controls.do_not_generate_docs
    class Parent(GrandParent):
      pass

    class Child(Parent):
      pass

    self.assertFalse(doc_controls.should_skip(Child))
    self.assertTrue(doc_controls.should_skip(Parent))
    self.assertFalse(doc_controls.should_skip(GrandParent))

    self.assertFalse(
        doc_controls.should_skip_class_attr(GrandParent, 'my_method'))
    self.assertFalse(doc_controls.should_skip_class_attr(Parent, 'my_method'))
    self.assertTrue(doc_controls.should_skip_class_attr(Child, 'my_method'))
示例#14
0
    def test_skip_class_short_circuit(self):
        class GrandParent(object):
            def my_method(self):
                pass

        @doc_controls.do_not_generate_docs
        class Parent(GrandParent):
            pass

        class Child(Parent):
            pass

        self.assertFalse(doc_controls.should_skip(Child))
        self.assertTrue(doc_controls.should_skip(Parent))
        self.assertFalse(doc_controls.should_skip(GrandParent))

        self.assertFalse(
            doc_controls.should_skip_class_attr(GrandParent, 'my_method'))
        self.assertFalse(
            doc_controls.should_skip_class_attr(Parent, 'my_method'))
        self.assertFalse(
            doc_controls.should_skip_class_attr(Child, 'my_method'))
示例#15
0
    def collect_docs(self):
        """Collects information necessary specifically for a class's doc page.

    Mainly, this is details about the class's members.
    """
        py_class = self.py_object

        self._set_bases()

        class_path_node = self.parser_config.path_tree[self.api_node.path]
        for _, path_node in sorted(class_path_node.children.items()):
            # Don't document anything that is defined in object or by protobuf.
            defining_class = parser.get_defining_class(py_class,
                                                       path_node.short_name)
            if defining_class in [
                    object, type, tuple, BaseException, Exception
            ]:
                continue

            # The following condition excludes most protobuf-defined symbols.
            if (defining_class and defining_class.__name__
                    in ['CMessage', 'Message', 'MessageMeta']):
                continue

            if doc_controls.should_skip_class_attr(py_class,
                                                   path_node.short_name):
                continue

            child_doc = parser.parse_md_docstring(path_node.py_object,
                                                  self.full_name,
                                                  self.parser_config,
                                                  self._extra_docs)

            child_url = self.parser_config.reference_resolver.reference_to_url(
                path_node.full_name)

            member_info = base_page.MemberInfo(path_node.short_name,
                                               path_node.full_name,
                                               path_node.py_object, child_doc,
                                               child_url)
            self._add_member(member_info, defining_class)

        self.set_attr_block(self._augment_attributes(self.doc.docstring_parts))
示例#16
0
  def collect_docs_for_class(self, py_class, parser_config):
    """Collects information necessary specifically for a class's doc page.

    Mainly, this is details about the class's members.

    Args:
      py_class: The class object being documented
      parser_config: An instance of ParserConfig.
    """
    self.set_namedtuplefields(py_class)
    doc_path = documentation_path(self.full_name)
    relative_path = os.path.relpath(
        path='.', start=os.path.dirname(doc_path) or '.')

    self._set_bases(relative_path, parser_config)

    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__',
          '__str__', '__repr__', '__hash__', '__reduce__'
      ]:
        continue

      child_name = '.'.join([self.full_name, short_name])
      child = parser_config.py_name_to_object(child_name)

      # Don't document anything that is defined in object or by protobuf.
      defining_class = _get_defining_class(py_class, short_name)
      if defining_class in [object, type, tuple, BaseException, Exception]:
        continue

      # The following condition excludes most protobuf-defined symbols.
      if (defining_class and
          defining_class.__name__ in ['CMessage', 'Message', 'MessageMeta']):
        continue
      # TODO(markdaoust): Add a note in child docs showing the defining class.

      if doc_controls.should_skip_class_attr(py_class, short_name):
        continue

      child_doc = _parse_md_docstring(child, relative_path,
                                      parser_config.reference_resolver)

      if isinstance(child, property):
        self._add_property(short_name, child_name, child, child_doc)

      elif tf_inspect.isclass(child):
        if defining_class is None:
          continue
        url = parser_config.reference_resolver.reference_to_url(
            child_name, relative_path)
        self._add_class(short_name, child_name, child, child_doc, url)

      elif (tf_inspect.ismethod(child) or tf_inspect.isfunction(child) or
            tf_inspect.isroutine(child)):
        if defining_class is None:
          continue

        # Omit methods defined by namedtuple.
        original_method = defining_class.__dict__[short_name]
        if (hasattr(original_method, '__module__') and
            (original_method.__module__ or '').startswith('namedtuple')):
          continue

        # Some methods are often overridden without documentation. Because it's
        # 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 [
            '__del__', '__copy__'
        ]:
          continue

        try:
          child_signature = _generate_signature(child,
                                                parser_config.reverse_index)
        except TypeError:
          # If this is a (dynamically created) slot wrapper, tf_inspect will
          # raise typeerror when trying to get to the code. Ignore such
          # functions.
          continue

        child_decorators = []
        try:
          if isinstance(py_class.__dict__[short_name], classmethod):
            child_decorators.append('classmethod')
        except KeyError:
          pass

        try:
          if isinstance(py_class.__dict__[short_name], staticmethod):
            child_decorators.append('staticmethod')
        except KeyError:
          pass

        self._add_method(short_name, child_name, child, child_doc,
                         child_signature, child_decorators)
      else:
        # Exclude members defined by protobuf that are useless
        if issubclass(py_class, ProtoMessage):
          if (short_name.endswith('_FIELD_NUMBER') or
              short_name in ['__slots__', 'DESCRIPTOR']):
            continue

        # TODO(wicke): We may want to also remember the object itself.
        self._add_other_member(short_name, child_name, child, child_doc)