docs: def draw_rect(self, x, y, width, height, string, fg=Ellipsis, bg=Ellipsis):
          """Draws a rectangle starting from x and y and extending to width and height.
  
          If width or height are None then it will extend to the edge of the console.
  
          Args:
              x (int): x-coordinate for the top side of the rect.
              y (int): y-coordinate for the left side of the rect.
              width (Optional[int]): The width of the rectangle.
  
                  Can be None to extend to the bottom right of the
                  console or can be a negative number to be sized reltive
                  to the total size of the console.
              height (Optional[int]): The height of the rectangle.
              string (Optional[Union[Text, int]]): An integer, single character
                  string, or None.
  
                  You can set the string parameter as None if you only want
                  to change the colors of an area.
              fg (Optional[Union[Tuple[int, int, int], int, Ellipsis]])
              bg (Optional[Union[Tuple[int, int, int], int, Ellipsis]])
  
          Raises:
              AssertionError: Having x or y values that can't be placed inside
                              of the console will raise an AssertionError.
  
              You can use always use ``((x, y) in console)`` to check if a tile
              is drawable.
          .. seealso:: :any:`clear`, :any:`draw_frame`
          """
          x, y, width, height = self._normalizeRect(x, y, width, height)
          fg, bg = _format_color(fg, self._fg), _format_color(bg, self._bg)
          char = _format_char(string)
          # use itertools to make an x,y grid
          # using ctypes here reduces type converstions later
          #grid = _itertools.product((_ctypes.c_int(x) for x in range(x, x + width)),
          #                          (_ctypes.c_int(y) for y in range(y, y + height)))
          grid = _itertools.product((x for x in range(x, x + width)),
                                    (y for y in range(y, y + height)))
          # zip the single character in a batch variable
          batch = zip(grid, _itertools.repeat(char, width * height))
          self._set_batch(batch, fg, bg, nullChar=(char is None))