prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  [BUG] `cd sphinx; make serve` doesn't work
  #### ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)
  Bokeh 2.0.2-76-ga417746c9
  
  #### Description of expected behavior and the observed behavior
  The page at https://docs.bokeh.org/en/latest/docs/dev_guide/documentation.html mentions that it's possible to run `make serve` to serve the documentation locally. But running it results in:
  ```
  Exception in thread Thread-2:
  Traceback (most recent call last):
    File "/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/threading.py", line 917, in _bootstrap_inner
      self.run()
    File "/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/threading.py", line 865, in run
      self._target(*self._args, **self._kwargs)
    File "docserver.py", line 43, in open_browser
      webbrowser.open("http://localhost:%d/en/latest/index.html" % PORT, new="tab")
    File "/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/webbrowser.py", line 78, in open
      if browser.open(url, new, autoraise):
    File "/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/webbrowser.py", line 251, in open
      "expected 0, 1, or 2, got %s" % new)
  webbrowser.Error: Bad 'new' parameter to open(); expected 0, 1, or 2, got tab
  ```
  Not sure where `"tab"` has come from, but it has been there forever.
  
  </issue>
  <code>
  [start of sphinx/docserver.py]
  1 import os
  2 import sys
  3 import threading
  4 import time
  5 import webbrowser
  6 
  7 import flask
  8 import tornado
  9 from tornado.httpserver import HTTPServer
  10 from tornado.ioloop import IOLoop
  11 from tornado.wsgi import WSGIContainer
  12 
  13 _basedir = os.path.join("..", os.path.dirname(__file__))
  14 
  15 app = flask.Flask(__name__, static_folder="/unused")
  16 PORT=5009
  17 http_server = HTTPServer(WSGIContainer(app))
  18 
  19 @app.route('/')
  20 def welcome():
  21     return """
  22     <h1>Welcome to the Bokeh documentation server</h1>
  23     You probably want to go to <a href="/en/latest/index.html"> Index</a>
  24     """
  25 
  26 @app.route('/versions.json')
  27 def send_versions():
  28     return flask.send_from_directory(
  29         os.path.join(_basedir, "sphinx"), "test_versions.json")
  30 
  31 @app.route('/alert.html')
  32 def send_alert():
  33     return os.environ.get("BOKEH_DOCS_ALERT", "")
  34 
  35 @app.route('/en/latest/<path:filename>')
  36 def send_docs(filename):
  37     return flask.send_from_directory(
  38         os.path.join(_basedir, "sphinx/build/html/"), filename)
  39 
  40 def open_browser():
  41     # Child process
  42     time.sleep(0.5)
  43     webbrowser.open("http://localhost:%d/en/latest/index.html" % PORT, new="tab")
  44 
  45 data = {}
  46 
  47 def serve_http():
  48     data['ioloop'] = IOLoop()
  49     http_server.listen(PORT)
  50     IOLoop.current().start()
  51 
  52 def shutdown_server():
  53     ioloop = data['ioloop']
  54     ioloop.add_callback(ioloop.stop)
  55     print("Asked Server to shut down.")
  56 
  57 def ui():
  58     try:
  59         time.sleep(0.5)
  60         input("Press <ENTER> to exit...\n")  # lgtm [py/use-of-input]
  61     except KeyboardInterrupt:
  62         pass
  63 
  64 if __name__ == "__main__":
  65 
  66     if tornado.version_info[0] == 4:
  67         print('docserver.py script requires tornado 5 or higher')
  68         sys.exit(1)
  69 
  70     print("\nStarting Bokeh plot server on port %d..." % PORT)
  71     print("Visit http://localhost:%d/en/latest/index.html to see plots\n" % PORT)
  72 
  73     t_server = threading.Thread(target=serve_http)
  74     t_server.start()
  75     t_browser = threading.Thread(target=open_browser)
  76     t_browser.start()
  77 
  78     ui()
  79 
  80     shutdown_server()
  81     t_server.join()
  82     t_browser.join()
  83     print("Server shut down.")
  84
  [end of sphinx/docserver.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/sphinx/docserver.py b/sphinx/docserver.py
  --- a/sphinx/docserver.py
  +++ b/sphinx/docserver.py
  @@ -40,7 +40,7 @@
   def open_browser():
       # Child process
       time.sleep(0.5)
  -    webbrowser.open("http://localhost:%d/en/latest/index.html" % PORT, new="tab")
  +    webbrowser.open("http://localhost:%d/en/latest/index.html" % PORT, new=2)
   
   data = {}
  
verification_info: {"golden_diff": "diff --git a/sphinx/docserver.py b/sphinx/docserver.py\n--- a/sphinx/docserver.py\n+++ b/sphinx/docserver.py\n@@ -40,7 +40,7 @@\n def open_browser():\n     # Child process\n     time.sleep(0.5)\n-    webbrowser.open(\"http://localhost:%d/en/latest/index.html\" % PORT, new=\"tab\")\n+    webbrowser.open(\"http://localhost:%d/en/latest/index.html\" % PORT, new=2)\n \n data = {}\n", "issue": "[BUG] `cd sphinx; make serve` doesn't work\n#### ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)\r\nBokeh 2.0.2-76-ga417746c9\r\n\r\n#### Description of expected behavior and the observed behavior\r\nThe page at https://docs.bokeh.org/en/latest/docs/dev_guide/documentation.html mentions that it's possible to run `make serve` to serve the documentation locally. But running it results in:\r\n```\r\nException in thread Thread-2:\r\nTraceback (most recent call last):\r\n  File \"/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/threading.py\", line 917, in _bootstrap_inner\r\n    self.run()\r\n  File \"/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/threading.py\", line 865, in run\r\n    self._target(*self._args, **self._kwargs)\r\n  File \"docserver.py\", line 43, in open_browser\r\n    webbrowser.open(\"http://localhost:%d/en/latest/index.html\" % PORT, new=\"tab\")\r\n  File \"/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/webbrowser.py\", line 78, in open\r\n    if browser.open(url, new, autoraise):\r\n  File \"/home/p-himik/soft/miniconda3/envs/bokeh-dev/lib/python3.7/webbrowser.py\", line 251, in open\r\n    \"expected 0, 1, or 2, got %s\" % new)\r\nwebbrowser.Error: Bad 'new' parameter to open(); expected 0, 1, or 2, got tab\r\n```\r\nNot sure where `\"tab\"` has come from, but it has been there forever.\n", "before_files": [{"content": "import os\nimport sys\nimport threading\nimport time\nimport webbrowser\n\nimport flask\nimport tornado\nfrom tornado.httpserver import HTTPServer\nfrom tornado.ioloop import IOLoop\nfrom tornado.wsgi import WSGIContainer\n\n_basedir = os.path.join(\"..\", os.path.dirname(__file__))\n\napp = flask.Flask(__name__, static_folder=\"/unused\")\nPORT=5009\nhttp_server = HTTPServer(WSGIContainer(app))\n\n@app.route('/')\ndef welcome():\n    return \"\"\"\n    <h1>Welcome to the Bokeh documentation server</h1>\n    You probably want to go to <a href=\"/en/latest/index.html\"> Index</a>\n    \"\"\"\n\n@app.route('/versions.json')\ndef send_versions():\n    return flask.send_from_directory(\n        os.path.join(_basedir, \"sphinx\"), \"test_versions.json\")\n\n@app.route('/alert.html')\ndef send_alert():\n    return os.environ.get(\"BOKEH_DOCS_ALERT\", \"\")\n\n@app.route('/en/latest/<path:filename>')\ndef send_docs(filename):\n    return flask.send_from_directory(\n        os.path.join(_basedir, \"sphinx/build/html/\"), filename)\n\ndef open_browser():\n    # Child process\n    time.sleep(0.5)\n    webbrowser.open(\"http://localhost:%d/en/latest/index.html\" % PORT, new=\"tab\")\n\ndata = {}\n\ndef serve_http():\n    data['ioloop'] = IOLoop()\n    http_server.listen(PORT)\n    IOLoop.current().start()\n\ndef shutdown_server():\n    ioloop = data['ioloop']\n    ioloop.add_callback(ioloop.stop)\n    print(\"Asked Server to shut down.\")\n\ndef ui():\n    try:\n        time.sleep(0.5)\n        input(\"Press <ENTER> to exit...\\n\")  # lgtm [py/use-of-input]\n    except KeyboardInterrupt:\n        pass\n\nif __name__ == \"__main__\":\n\n    if tornado.version_info[0] == 4:\n        print('docserver.py script requires tornado 5 or higher')\n        sys.exit(1)\n\n    print(\"\\nStarting Bokeh plot server on port %d...\" % PORT)\n    print(\"Visit http://localhost:%d/en/latest/index.html to see plots\\n\" % PORT)\n\n    t_server = threading.Thread(target=serve_http)\n    t_server.start()\n    t_browser = threading.Thread(target=open_browser)\n    t_browser.start()\n\n    ui()\n\n    shutdown_server()\n    t_server.join()\n    t_browser.join()\n    print(\"Server shut down.\")\n", "path": "sphinx/docserver.py"}]}