prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Invalid session timeout value on CKAN 2.10 (logged out users unexpectedly)
  ## CKAN version
  2.10
  
  ## Describe the bug
  
  According to our config declaration for [`beaker.session.timeout`](https://github.com/ckan/ckan/blob/656a39de2e7ed0ce47e15080f0f5d42b66b4929b/ckan/config/config_declaration.yaml#L306):
  
  > Defaults to never expiring.
  
  But the defined default value is 600 :upside_down_face: 
  Apart from the inconsistency, this is problematic because now that the logged-in user id is stored in the session by Flask-login, this means that users are logged out every 10 minutes.
  
  The fix is to default it to never expire as described on the docs (which is also the [Beaker default](https://beaker.readthedocs.io/en/latest/configuration.html#session-options)), but the problem is that I can set it to `None` because then Beaker complains that the value is not an int:
  
  ```
    File "/home/adria/dev/pyenvs/gates/lib/python3.8/site-packages/beaker/util.py", line 290, in verify_rules
      params[key] = verify_options(params[key], types, message)
    File "/home/adria/dev/pyenvs/gates/lib/python3.8/site-packages/beaker/util.py", line 281, in verify_options
      raise Exception(error)
  Exception: Session timeout must be an integer.
  ```
  This is because our config parsing does not support "int or None", and leaves the string "None" as the value. I guess the alternative is to put a really big number but would be good to handle it better.
  
  
  </issue>
  <code>
  [start of ckan/cli/shell.py]
  1 # encoding: utf-8
  2 import click
  3 import logging
  4 
  5 import ckan.model as model
  6 
  7 from typing import Any, Mapping
  8 
  9 from ckan.plugins import toolkit
  10 
  11 
  12 log = logging.getLogger(__name__)
  13 
  14 
  15 _banner = """
  16 ****** Welcome to the CKAN shell ******
  17 
  18 This session has some variables pre-populated:
  19   - app (CKAN Application object)
  20   - config (CKAN config dictionary)
  21   - model (CKAN model module to access the Database)
  22   - toolkit (CKAN toolkit module)
  23     """
  24 
  25 
  26 def ipython(namespace: Mapping[str, Any], banner: str) -> None:
  27     import IPython
  28     from traitlets.config.loader import Config
  29 
  30     c = Config()
  31     c.TerminalInteractiveShell.banner2 = banner  # type: ignore
  32 
  33     IPython.start_ipython([], user_ns=namespace, config=c)
  34 
  35 
  36 def python(namespace: Mapping[str, Any], banner: str) -> None:
  37     import code
  38     code.interact(banner=banner, local=namespace)
  39 
  40 
  41 @click.command()
  42 @click.help_option("-h", "--help")
  43 @click.pass_context
  44 def shell(ctx: click.Context):
  45     """Run an interactive IPython shell with the context of the
  46     CKAN instance.
  47 
  48     It will try to use IPython, if not installed it will callback
  49     to the default Python's shell.
  50     """
  51 
  52     namespace = {
  53         "app": ctx.obj.app._wsgi_app,
  54         "model": model,
  55         "config": ctx.obj.config,
  56         "toolkit": toolkit,
  57     }
  58 
  59     try:
  60         ipython(namespace, _banner)
  61     except ImportError:
  62         log.debug("`ipython` library is missing. Using default python shell.")
  63         python(namespace, _banner)
  64
  [end of ckan/cli/shell.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/ckan/cli/shell.py b/ckan/cli/shell.py
  --- a/ckan/cli/shell.py
  +++ b/ckan/cli/shell.py
  @@ -28,7 +28,7 @@
       from traitlets.config.loader import Config
   
       c = Config()
  -    c.TerminalInteractiveShell.banner2 = banner  # type: ignore
  +    c.TerminalInteractiveShell.banner2 = banner
   
       IPython.start_ipython([], user_ns=namespace, config=c)
  
verification_info: {"golden_diff": "diff --git a/ckan/cli/shell.py b/ckan/cli/shell.py\n--- a/ckan/cli/shell.py\n+++ b/ckan/cli/shell.py\n@@ -28,7 +28,7 @@\n     from traitlets.config.loader import Config\n \n     c = Config()\n-    c.TerminalInteractiveShell.banner2 = banner  # type: ignore\n+    c.TerminalInteractiveShell.banner2 = banner\n \n     IPython.start_ipython([], user_ns=namespace, config=c)\n", "issue": "Invalid session timeout value on CKAN 2.10 (logged out users unexpectedly)\n## CKAN version\r\n2.10\r\n\r\n## Describe the bug\r\n\r\nAccording to our config declaration for [`beaker.session.timeout`](https://github.com/ckan/ckan/blob/656a39de2e7ed0ce47e15080f0f5d42b66b4929b/ckan/config/config_declaration.yaml#L306):\r\n\r\n> Defaults to never expiring.\r\n\r\nBut the defined default value is 600 :upside_down_face: \r\nApart from the inconsistency, this is problematic because now that the logged-in user id is stored in the session by Flask-login, this means that users are logged out every 10 minutes.\r\n\r\nThe fix is to default it to never expire as described on the docs (which is also the [Beaker default](https://beaker.readthedocs.io/en/latest/configuration.html#session-options)), but the problem is that I can set it to `None` because then Beaker complains that the value is not an int:\r\n\r\n```\r\n  File \"/home/adria/dev/pyenvs/gates/lib/python3.8/site-packages/beaker/util.py\", line 290, in verify_rules\r\n    params[key] = verify_options(params[key], types, message)\r\n  File \"/home/adria/dev/pyenvs/gates/lib/python3.8/site-packages/beaker/util.py\", line 281, in verify_options\r\n    raise Exception(error)\r\nException: Session timeout must be an integer.\r\n```\r\nThis is because our config parsing does not support \"int or None\", and leaves the string \"None\" as the value. I guess the alternative is to put a really big number but would be good to handle it better.\r\n\n", "before_files": [{"content": "# encoding: utf-8\nimport click\nimport logging\n\nimport ckan.model as model\n\nfrom typing import Any, Mapping\n\nfrom ckan.plugins import toolkit\n\n\nlog = logging.getLogger(__name__)\n\n\n_banner = \"\"\"\n****** Welcome to the CKAN shell ******\n\nThis session has some variables pre-populated:\n  - app (CKAN Application object)\n  - config (CKAN config dictionary)\n  - model (CKAN model module to access the Database)\n  - toolkit (CKAN toolkit module)\n    \"\"\"\n\n\ndef ipython(namespace: Mapping[str, Any], banner: str) -> None:\n    import IPython\n    from traitlets.config.loader import Config\n\n    c = Config()\n    c.TerminalInteractiveShell.banner2 = banner  # type: ignore\n\n    IPython.start_ipython([], user_ns=namespace, config=c)\n\n\ndef python(namespace: Mapping[str, Any], banner: str) -> None:\n    import code\n    code.interact(banner=banner, local=namespace)\n\n\n@click.command()\n@click.help_option(\"-h\", \"--help\")\n@click.pass_context\ndef shell(ctx: click.Context):\n    \"\"\"Run an interactive IPython shell with the context of the\n    CKAN instance.\n\n    It will try to use IPython, if not installed it will callback\n    to the default Python's shell.\n    \"\"\"\n\n    namespace = {\n        \"app\": ctx.obj.app._wsgi_app,\n        \"model\": model,\n        \"config\": ctx.obj.config,\n        \"toolkit\": toolkit,\n    }\n\n    try:\n        ipython(namespace, _banner)\n    except ImportError:\n        log.debug(\"`ipython` library is missing. Using default python shell.\")\n        python(namespace, _banner)\n", "path": "ckan/cli/shell.py"}]}