class_docstr: Applies various transformations to a cell or code block.
  
  The key methods for external use are ``transform_cell()``
  and ``check_complete()``.
class_docstr_tok: ["Applies","various","transformations","to","a","cell","or","code","block",".","The","key","methods","for","external","use","are","``","transform_cell","(",")","``","and","``","check_complete","(",")","``","."]
docstr: Return whether a block of code is ready to execute, or should be continued
  
  Parameters
  ----------
  cell : string
      Python input code, which can be multiline.
  
  Returns
  -------
  status : str
      One of 'complete', 'incomplete', or 'invalid' if source is not a
      prefix of valid code.
  indent_spaces : int or None
      The number of spaces by which to indent the next line of code. If
      status is not 'incomplete', this is None.
docstr_tok: ["Return","whether","a","block","of","code","is","ready","to","execute",",","or","should","be","continued","Parameters","--","--","--","--","--","cell",":","string","Python","input","code",",","which","can","be","multiline",".","Returns","--","--","--","-","status",":","str","One","of","'complete","'",",","'incomplete","'",",","or","'invalid","'","if","source","is","not","a","prefix","of","valid","code",".","indent_spaces",":","int","or","None","The","number","of","spaces","by","which","to","indent","the","next","line","of","code",".","If","status","is","not","'incomplete","'",",","this","is","None","."]
code: def check_complete(self, cell: str):
      """Return whether a block of code is ready to execute, or should be continued
  
      Parameters
      ----------
      cell : string
          Python input code, which can be multiline.
  
      Returns
      -------
      status : str
          One of 'complete', 'incomplete', or 'invalid' if source is not a
          prefix of valid code.
      indent_spaces : int or None
          The number of spaces by which to indent the next line of code. If
          status is not 'incomplete', this is None.
      """
      # Remember if the lines ends in a new line.
      ends_with_newline = False
      for character in reversed(cell):
          if character == "\n":
              ends_with_newline = True
              break
          elif character.strip():
              break
          else:
              continue
  
      if not ends_with_newline:
          # Append an newline for consistent tokenization
          # See https://bugs.python.org/issue33899
          cell += "\n"
  
      lines = cell.splitlines(keepends=True)
  
      if not lines:
          return "complete", None
  
      for line in reversed(lines):
          if not line.strip():
              continue
          elif line.strip("\n").endswith("\\"):
              return "incomplete", find_last_indent(lines)
          else:
              break
  
      try:
          for transform in self.cleanup_transforms:
              if not getattr(transform, "has_side_effects", False):
                  lines = transform(lines)
      except SyntaxError:
          return "invalid", None
  
      if lines[0].startswith("%%"):
          # Special case for cell magics - completion marked by blank line
          if lines[-1].strip():
              return "incomplete", find_last_indent(lines)
          else:
              return "complete", None
  
      try:
          for transform in self.line_transforms:
              if not getattr(transform, "has_side_effects", False):
                  lines = transform(lines)
          lines = self.do_token_transforms(lines)
      except SyntaxError:
          return "invalid", None
  
      tokens_by_line = make_tokens_by_line(lines)
  
      # Bail if we got one line and there are more closing parentheses than
      # the opening ones
      if (
          len(lines) == 1
          and tokens_by_line
          and has_sunken_brackets(tokens_by_line[0])
      ):
          return "invalid", None
  
      if not tokens_by_line:
          return "incomplete", find_last_indent(lines)
  
      if (
          tokens_by_line[-1][-1].type != tokenize.ENDMARKER
          and tokens_by_line[-1][-1].type != tokenize.ERRORTOKEN
      ):
          # We're in a multiline string or expression
          return "incomplete", find_last_indent(lines)
  
      newline_types = {tokenize.NEWLINE, tokenize.COMMENT, tokenize.ENDMARKER}  # type: ignore
  
      # Pop the last line which only contains DEDENTs and ENDMARKER
      last_token_line = None
      if {t.type for t in tokens_by_line[-1]} in [
          {tokenize.DEDENT, tokenize.ENDMARKER},
          {tokenize.ENDMARKER},
      ] and len(tokens_by_line) > 1:
          last_token_line = tokens_by_line.pop()
  
      while (
          tokens_by_line[-1]
          and tokens_by_line[-1][-1].type in newline_types
      ):
          tokens_by_line[-1].pop()
  
      if not tokens_by_line[-1]:
          return "incomplete", find_last_indent(lines)
  
      if tokens_by_line[-1][-1].string == ":":
          # The last line starts a block (e.g. 'if foo:')
          ix = 0
          while tokens_by_line[-1][ix].type in {
              tokenize.INDENT,
              tokenize.DEDENT,
          }:
              ix += 1
  
          indent = tokens_by_line[-1][ix].start[1]
          return "incomplete", indent + 4
  
      if tokens_by_line[-1][0].line.endswith("\\"):
          return "incomplete", None
  
      # At this point, our checks think the code is complete (or invalid).
      # We'll use codeop.compile_command to check this with the real parser
      try:
          with warnings.catch_warnings():
              warnings.simplefilter("error", SyntaxWarning)
              res = compile_command("".join(lines), symbol="exec")
      except (
          SyntaxError,
          OverflowError,
          ValueError,
          TypeError,
          MemoryError,
          SyntaxWarning,
      ):
          return "invalid", None
      else:
          if res is None:
              return "incomplete", find_last_indent(lines)
  
      if last_token_line and last_token_line[0].type == tokenize.DEDENT:
          if ends_with_newline:
              return "complete", None
          return "incomplete", find_last_indent(lines)
  
      # If there's a blank line at the end, assume we're ready to execute
      if not lines[-1].strip():
          return "complete", None
  
      return "complete", None
  
imports: import ast
  from codeop import CommandCompiler, Compile
  import re
  import sys
  import tokenize
  from typing import List, Tuple, Optional, Any
  import warnings
  from IPython.utils import tokenutil
label_desc: Use image node_id 5 for calling the TransformerManager obj's underlying member method code with example usage: obj.check_complete(cell) and returns: str,  None, str,  None, str,  None, str,  find_last_indent, str,  find_last_indent, str,  find_last_indent, str,  unknown, str,  None, str,  find_last_indent, str,  None, str,  None, str,  find_last_indent, str,  None, str,  None, str,  None, str,  find_last_indent, str,  None, str,  find_last_indent