code: def test_ModuleAnalyzer_find_attr_docs():
      code = (
          "class Foo(object):\n"
          '    """class Foo!"""\n'
          "    #: comment before attr1\n"
          "    attr1 = None\n"
          "    attr2 = None  # attribute comment for attr2 (without colon)\n"
          "    attr3 = None  #: attribute comment for attr3\n"
          "    attr4 = None  #: long attribute comment\n"
          "                  #: for attr4\n"
          "    #: comment before attr5\n"
          "    attr5 = None  #: attribute comment for attr5\n"
          "    attr6, attr7 = 1, 2  #: this comment is ignored\n"
          "\n"
          "    def __init__(self):\n"
          "       self.attr8 = None  #: first attribute comment (ignored)\n"
          "       self.attr8 = None  #: attribute comment for attr8\n"
          "       #: comment before attr9\n"
          "       self.attr9 = None  #: comment after attr9\n"
          '       "string after attr9"\n'
          "\n"
          "    def bar(self, arg1, arg2=True, *args, **kwargs):\n"
          '       """method Foo.bar"""\n'
          "       pass\n"
          "\n"
          "def baz():\n"
          '   """function baz"""\n'
          "   pass\n"
          "\n"
          "class Qux: attr1 = 1; attr2 = 2"
      )
      analyzer = ModuleAnalyzer.for_string(code, "module")
      docs = analyzer.find_attr_docs()
      assert set(docs) == {
          ("Foo", "attr1"),
          ("Foo", "attr3"),
          ("Foo", "attr4"),
          ("Foo", "attr5"),
          ("Foo", "attr6"),
          ("Foo", "attr7"),
          ("Foo", "attr8"),
          ("Foo", "attr9"),
      }
      assert docs[("Foo", "attr1")] == ["comment before attr1", ""]
      assert docs[("Foo", "attr3")] == [
          "attribute comment for attr3",
          "",
      ]
      assert docs[("Foo", "attr4")] == ["long attribute comment", ""]
      assert docs[("Foo", "attr4")] == ["long attribute comment", ""]
      assert docs[("Foo", "attr5")] == [
          "attribute comment for attr5",
          "",
      ]
      assert docs[("Foo", "attr6")] == ["this comment is ignored", ""]
      assert docs[("Foo", "attr7")] == ["this comment is ignored", ""]
      assert docs[("Foo", "attr8")] == [
          "attribute comment for attr8",
          "",
      ]
      assert docs[("Foo", "attr9")] == ["string after attr9", ""]
      assert analyzer.tagorder == {
          "Foo": 0,
          "Foo.__init__": 8,
          "Foo.attr1": 1,
          "Foo.attr2": 2,
          "Foo.attr3": 3,
          "Foo.attr4": 4,
          "Foo.attr5": 5,
          "Foo.attr6": 6,
          "Foo.attr7": 7,
          "Foo.attr8": 10,
          "Foo.attr9": 12,
          "Foo.bar": 13,
          "baz": 14,
          "Qux": 15,
          "Qux.attr1": 16,
          "Qux.attr2": 17,
      }
  
file_path: sphinx/tests/test_pycode/test_pycode.py
imports: import os
  import sys
  import pytest
  import sphinx
  from sphinx.errors import PycodeError
  from sphinx.pycode import ModuleAnalyzer
label_desc: Use image node_id 6 for calling a global function with example usage: test_ModuleAnalyzer_find_attr_docs() without return types