code: def test_study2(self):
      eq = self.assertEqual
      p = self.parser
      setcode = p.set_code
      study = p._study2
  
      TestInfo = namedtuple(
          "TestInfo",
          [
              "string",
              "start",
              "end",
              "lastch",
              "openbracket",
              "bracketing",
          ],
      )
      tests = (
          TestInfo("", 0, 0, "", None, ((0, 0),)),
          TestInfo(
              "'''This is a multiline continuation docstring.\n\n",
              0,
              48,
              "'",
              None,
              ((0, 0), (0, 1), (48, 0)),
          ),
          TestInfo(
              " # Comment\\\n",
              0,
              12,
              "",
              None,
              ((0, 0), (1, 1), (12, 0)),
          ),
          # A comment without a space is a special case
          TestInfo(" #Comment\\\n", 0, 0, "", None, ((0, 0),)),
          # Backslash continuation.
          TestInfo(
              "a = (1 + 2) - 5 *\\\n",
              0,
              19,
              "*",
              None,
              ((0, 0), (4, 1), (11, 0)),
          ),
          # Bracket continuation with close.
          TestInfo(
              "\n   def function1(self, a,\n                 b):\n",
              1,
              48,
              ":",
              None,
              ((1, 0), (17, 1), (46, 0)),
          ),
          # Bracket continuation with unneeded backslash.
          TestInfo(
              "\n   def function1(self, a,\\\n",
              1,
              28,
              ",",
              17,
              ((1, 0), (17, 1)),
          ),
          # Bracket continuation.
          TestInfo(
              "\n   def function1(self, a,\n",
              1,
              27,
              ",",
              17,
              ((1, 0), (17, 1)),
          ),
          # Bracket continuation with comment at end of line with text.
          TestInfo(
              "\n   def function1(self, a,  # End of line comment.\n",
              1,
              51,
              ",",
              17,
              ((1, 0), (17, 1), (28, 2), (51, 1)),
          ),
          # Multi-line statement with comment line in between code lines.
          TestInfo(
              '  a = ["first item",\n  # Comment line\n    "next item",\n',
              0,
              55,
              ",",
              6,
              (
                  (0, 0),
                  (6, 1),
                  (7, 2),
                  (19, 1),
                  (23, 2),
                  (38, 1),
                  (42, 2),
                  (53, 1),
              ),
          ),
          TestInfo(
              "())\n", 0, 4, ")", None, ((0, 0), (0, 1), (2, 0), (3, 0))
          ),
          TestInfo(")(\n", 0, 3, "(", 1, ((0, 0), (1, 0), (1, 1))),
          # Wrong closers still decrement stack level.
          TestInfo(
              "{)(]\n",
              0,
              5,
              "]",
              None,
              ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0)),
          ),
          # Character after backslash.
          TestInfo(":\\a\n", 0, 4, "\\a", None, ((0, 0),)),
          TestInfo("\n", 0, 0, "", None, ((0, 0),)),
      )
  
      for test in tests:
          with self.subTest(string=test.string):
              setcode(test.string)
              study()
              eq(p.study_level, 2)
              eq(p.stmt_start, test.start)
              eq(p.stmt_end, test.end)
              eq(p.lastch, test.lastch)
              eq(p.lastopenbracketpos, test.openbracket)
              eq(p.stmt_bracketing, test.bracketing)
  
      # Called again, just returns without reprocessing.
      self.assertIsNone(study())
  
imports: from idlelib import pyparse
  import unittest
  from collections import namedtuple
label_desc: Use image node_id 9 for calling the PyParseTest obj's underlying member method code with example usage: obj.test_study2() without return types