prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Don't allow more than 2 dimensional input for `Inline/ReplyKeyboardMarkup`
  ### What kind of feature are you missing? Where do you notice a shortcoming of PTB?
  
  When a user passes their list to `Inline/ReplyKeyboardMarkup`, we currently check if their input is valid (exactly 2 dimensional input is valid), i.e. 
  
  * the input is a sequence, not just a single button
  * it's not just a simple sequence (sequence of buttons)
  
  However it doesn't check if it's more than 2D, i.e. `[[[KeyboardButton(...)], [...], ]]` is invalid.
  
  ### Describe the solution you'd like
  
  Modify `tg._utils.markup.check_keyboard_type` to return `False` if we find another sequence.
  
  ### Describe alternatives you've considered
  
  _No response_
  
  ### Additional context
  
  _No response_
  
  </issue>
  <code>
  [start of telegram/_utils/markup.py]
  1 #!/usr/bin/env python
  2 #
  3 # A library that provides a Python interface to the Telegram Bot API
  4 # Copyright (C) 2015-2023
  5 # Leandro Toledo de Souza <devs@python-telegram-bot.org>
  6 #
  7 # This program is free software: you can redistribute it and/or modify
  8 # it under the terms of the GNU Lesser Public License as published by
  9 # the Free Software Foundation, either version 3 of the License, or
  10 # (at your option) any later version.
  11 #
  12 # This program is distributed in the hope that it will be useful,
  13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 # GNU Lesser Public License for more details.
  16 #
  17 # You should have received a copy of the GNU Lesser Public License
  18 # along with this program.  If not, see [http://www.gnu.org/licenses/].
  19 """This module contains a helper function for Telegram's ReplyMarkups
  20 
  21 .. versionchanged:: 20.0
  22    Previously, the contents of this module were available through the (no longer existing)
  23    class ``telegram.ReplyMarkup``.
  24 
  25 Warning:
  26     Contents of this module are intended to be used internally by the library and *not* by the
  27     user. Changes to this module are not considered breaking changes and may not be documented in
  28     the changelog.
  29 """
  30 from collections.abc import Sequence
  31 
  32 
  33 def check_keyboard_type(keyboard: object) -> bool:
  34     """Checks if the keyboard provided is of the correct type - A list of lists.
  35     Implicitly tested in the init-tests of `{Inline, Reply}KeyboardMarkup`
  36     """
  37     # string and bytes may actually be used for ReplyKeyboardMarkup in which case each button
  38     # would contain a single character. But that use case should be discouraged and we don't
  39     # allow it here.
  40     if not isinstance(keyboard, Sequence) or isinstance(keyboard, (str, bytes)):
  41         return False
  42     for row in keyboard:
  43         if not isinstance(row, Sequence) or isinstance(row, (str, bytes)):
  44             return False
  45     return True
  46
  [end of telegram/_utils/markup.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/telegram/_utils/markup.py b/telegram/_utils/markup.py
  --- a/telegram/_utils/markup.py
  +++ b/telegram/_utils/markup.py
  @@ -31,7 +31,7 @@
   
   
   def check_keyboard_type(keyboard: object) -> bool:
  -    """Checks if the keyboard provided is of the correct type - A list of lists.
  +    """Checks if the keyboard provided is of the correct type - A sequence of sequences.
       Implicitly tested in the init-tests of `{Inline, Reply}KeyboardMarkup`
       """
       # string and bytes may actually be used for ReplyKeyboardMarkup in which case each button
  @@ -39,7 +39,11 @@
       # allow it here.
       if not isinstance(keyboard, Sequence) or isinstance(keyboard, (str, bytes)):
           return False
  +
       for row in keyboard:
           if not isinstance(row, Sequence) or isinstance(row, (str, bytes)):
               return False
  +        for inner in row:
  +            if isinstance(inner, Sequence) and not isinstance(inner, str):
  +                return False
       return True
  
verification_info: {"golden_diff": "diff --git a/telegram/_utils/markup.py b/telegram/_utils/markup.py\n--- a/telegram/_utils/markup.py\n+++ b/telegram/_utils/markup.py\n@@ -31,7 +31,7 @@\n \n \n def check_keyboard_type(keyboard: object) -> bool:\n-    \"\"\"Checks if the keyboard provided is of the correct type - A list of lists.\n+    \"\"\"Checks if the keyboard provided is of the correct type - A sequence of sequences.\n     Implicitly tested in the init-tests of `{Inline, Reply}KeyboardMarkup`\n     \"\"\"\n     # string and bytes may actually be used for ReplyKeyboardMarkup in which case each button\n@@ -39,7 +39,11 @@\n     # allow it here.\n     if not isinstance(keyboard, Sequence) or isinstance(keyboard, (str, bytes)):\n         return False\n+\n     for row in keyboard:\n         if not isinstance(row, Sequence) or isinstance(row, (str, bytes)):\n             return False\n+        for inner in row:\n+            if isinstance(inner, Sequence) and not isinstance(inner, str):\n+                return False\n     return True\n", "issue": "Don't allow more than 2 dimensional input for `Inline/ReplyKeyboardMarkup`\n### What kind of feature are you missing? Where do you notice a shortcoming of PTB?\n\nWhen a user passes their list to `Inline/ReplyKeyboardMarkup`, we currently check if their input is valid (exactly 2 dimensional input is valid), i.e. \r\n\r\n* the input is a sequence, not just a single button\r\n* it's not just a simple sequence (sequence of buttons)\r\n\r\nHowever it doesn't check if it's more than 2D, i.e. `[[[KeyboardButton(...)], [...], ]]` is invalid.\n\n### Describe the solution you'd like\n\nModify `tg._utils.markup.check_keyboard_type` to return `False` if we find another sequence.\n\n### Describe alternatives you've considered\n\n_No response_\n\n### Additional context\n\n_No response_\n", "before_files": [{"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2023\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"This module contains a helper function for Telegram's ReplyMarkups\n\n.. versionchanged:: 20.0\n   Previously, the contents of this module were available through the (no longer existing)\n   class ``telegram.ReplyMarkup``.\n\nWarning:\n    Contents of this module are intended to be used internally by the library and *not* by the\n    user. Changes to this module are not considered breaking changes and may not be documented in\n    the changelog.\n\"\"\"\nfrom collections.abc import Sequence\n\n\ndef check_keyboard_type(keyboard: object) -> bool:\n    \"\"\"Checks if the keyboard provided is of the correct type - A list of lists.\n    Implicitly tested in the init-tests of `{Inline, Reply}KeyboardMarkup`\n    \"\"\"\n    # string and bytes may actually be used for ReplyKeyboardMarkup in which case each button\n    # would contain a single character. But that use case should be discouraged and we don't\n    # allow it here.\n    if not isinstance(keyboard, Sequence) or isinstance(keyboard, (str, bytes)):\n        return False\n    for row in keyboard:\n        if not isinstance(row, Sequence) or isinstance(row, (str, bytes)):\n            return False\n    return True\n", "path": "telegram/_utils/markup.py"}]}