prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  More flexible widgets grid (allow finer control over height/width)
  ## User should be able to control widget's placement, width and height
  
  ### Current implementation
  
  Currently editing a dashboard works as follow:
  
  1. When adding a widget you select its width: regular (half width) or double (full width). Height is set based on the content.
  2. When opening the "Edit Dashboard" dialog, you can rearrange the order of the widgets.
  
  ![Edit Dashboard Dialog](https://user-images.githubusercontent.com/71468/30966534-e52b506e-a461-11e7-86f4-cd3220b51d12.png)
  
  Issues with the current approach:
  
  * You can't change widget size after placing it.
  * You can't change widget's height.
  * You can't control widget's width beyond the current two options.
  
  ### Solution
  
  To solve this we want to have a flexible (_but still responsive_) grid that the user can freely place and move widgets on. 
  
  * Each visualization will define minimum width and height sizes (derived from the visualization type). This will be the default sizes for the widget when placed on the grid, but the user will be able to resize it to be larger (but not smaller) afterwards.
  * Once entering dashboard "edit mode", the user will be able to move around and resize the widgets in place instead of a dedicated UI.
  * We should probably change other behaviors in the UI (move add widget to be part of the edit mode, change dashboard title editing to be in place, etc), but we will leave it to second iteration after the grid behavior is implemented.
  
  ### Technical Notes
  
  * We currently use `angular-gridster` to allow moving around the widgets in the Edit Dashboard dialog. Maybe we can use it for the grid or a similar library.
  * Currently the widget knows nothing about its placement, but only its size (width). The dashboard has a layout property, which is an array of arrays of widgets ids (each item in the array is a row/array of widgets). This is error prone and makes layout changes harder. If possible, it will be better if each widget retains its own placement information.
  * The API to update a widget currently supports only updating a textbox widget. We will need to extend it to support all widget types.
  
  </issue>
  <code>
  [start of redash/handlers/widgets.py]
  1 import json
  2 
  3 from flask import request
  4 from redash import models
  5 from redash.handlers.base import BaseResource
  6 from redash.permissions import (require_access,
  7                                 require_object_modify_permission,
  8                                 require_permission, view_only)
  9 
  10 
  11 class WidgetListResource(BaseResource):
  12     @require_permission('edit_dashboard')
  13     def post(self):
  14         """
  15         Add a widget to a dashboard.
  16 
  17         :<json number dashboard_id: The ID for the dashboard being added to
  18         :<json visualization_id: The ID of the visualization to put in this widget
  19         :<json object options: Widget options
  20         :<json string text: Text box contents
  21         :<json number width: Width for widget display
  22 
  23         :>json object widget: The created widget
  24         :>json array layout: The new layout of the dashboard this widget was added to
  25         :>json boolean new_row: Whether this widget was added on a new row or not
  26         :>json number version: The revision number of the dashboard
  27         """
  28         widget_properties = request.get_json(force=True)
  29         dashboard = models.Dashboard.get_by_id_and_org(widget_properties.pop('dashboard_id'), self.current_org)
  30         require_object_modify_permission(dashboard, self.current_user)
  31 
  32         widget_properties['options'] = json.dumps(widget_properties['options'])
  33         widget_properties.pop('id', None)
  34         widget_properties['dashboard'] = dashboard
  35 
  36         visualization_id = widget_properties.pop('visualization_id')
  37         if visualization_id:
  38             visualization = models.Visualization.get_by_id_and_org(visualization_id, self.current_org)
  39             require_access(visualization.query_rel.groups, self.current_user, view_only)
  40         else:
  41             visualization = None
  42 
  43         widget_properties['visualization'] = visualization
  44 
  45         widget = models.Widget(**widget_properties)
  46         models.db.session.add(widget)
  47         models.db.session.commit()
  48 
  49         layout = json.loads(widget.dashboard.layout)
  50         new_row = True
  51 
  52         if len(layout) == 0 or widget.width == 2:
  53             layout.append([widget.id])
  54         elif len(layout[-1]) == 1:
  55             neighbour_widget = models.Widget.query.get(layout[-1][0])
  56             if neighbour_widget.width == 1:
  57                 layout[-1].append(widget.id)
  58                 new_row = False
  59             else:
  60                 layout.append([widget.id])
  61         else:
  62             layout.append([widget.id])
  63 
  64         widget.dashboard.layout = json.dumps(layout)
  65         models.db.session.add(widget.dashboard)
  66         models.db.session.commit()
  67         return {'widget': widget.to_dict(), 'layout': layout, 'new_row': new_row, 'version': dashboard.version}
  68 
  69 
  70 class WidgetResource(BaseResource):
  71     @require_permission('edit_dashboard')
  72     def post(self, widget_id):
  73         """
  74         Updates a widget in a dashboard.
  75         This method currently handles Text Box widgets only.
  76 
  77         :param number widget_id: The ID of the widget to modify
  78 
  79         :<json string text: The new contents of the text box
  80         """
  81         widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
  82         require_object_modify_permission(widget.dashboard, self.current_user)
  83         widget_properties = request.get_json(force=True)
  84         widget.text = widget_properties['text']
  85         models.db.session.commit()
  86         return widget.to_dict()
  87 
  88     @require_permission('edit_dashboard')
  89     def delete(self, widget_id):
  90         """
  91         Remove a widget from a dashboard.
  92 
  93         :param number widget_id: ID of widget to remove
  94 
  95         :>json array layout: New layout of dashboard this widget was removed from
  96         :>json number version: Revision number of dashboard
  97         """
  98         widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
  99         require_object_modify_permission(widget.dashboard, self.current_user)
  100         widget.delete()
  101         models.db.session.commit()
  102         return {'layout': widget.dashboard.layout, 'version': widget.dashboard.version}
  103
  [end of redash/handlers/widgets.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/redash/handlers/widgets.py b/redash/handlers/widgets.py
  --- a/redash/handlers/widgets.py
  +++ b/redash/handlers/widgets.py
  @@ -82,6 +82,7 @@
           require_object_modify_permission(widget.dashboard, self.current_user)
           widget_properties = request.get_json(force=True)
           widget.text = widget_properties['text']
  +        widget.options = json.dumps(widget_properties['options'])
           models.db.session.commit()
           return widget.to_dict()
  
verification_info: {"golden_diff": "diff --git a/redash/handlers/widgets.py b/redash/handlers/widgets.py\n--- a/redash/handlers/widgets.py\n+++ b/redash/handlers/widgets.py\n@@ -82,6 +82,7 @@\n         require_object_modify_permission(widget.dashboard, self.current_user)\n         widget_properties = request.get_json(force=True)\n         widget.text = widget_properties['text']\n+        widget.options = json.dumps(widget_properties['options'])\n         models.db.session.commit()\n         return widget.to_dict()\n", "issue": "More flexible widgets grid (allow finer control over height/width)\n## User should be able to control widget's placement, width and height\r\n\r\n### Current implementation\r\n\r\nCurrently editing a dashboard works as follow:\r\n\r\n1. When adding a widget you select its width: regular (half width) or double (full width). Height is set based on the content.\r\n2. When opening the \"Edit Dashboard\" dialog, you can rearrange the order of the widgets.\r\n\r\n![Edit Dashboard Dialog](https://user-images.githubusercontent.com/71468/30966534-e52b506e-a461-11e7-86f4-cd3220b51d12.png)\r\n\r\nIssues with the current approach:\r\n\r\n* You can't change widget size after placing it.\r\n* You can't change widget's height.\r\n* You can't control widget's width beyond the current two options.\r\n\r\n### Solution\r\n\r\nTo solve this we want to have a flexible (_but still responsive_) grid that the user can freely place and move widgets on. \r\n\r\n* Each visualization will define minimum width and height sizes (derived from the visualization type). This will be the default sizes for the widget when placed on the grid, but the user will be able to resize it to be larger (but not smaller) afterwards.\r\n* Once entering dashboard \"edit mode\", the user will be able to move around and resize the widgets in place instead of a dedicated UI.\r\n* We should probably change other behaviors in the UI (move add widget to be part of the edit mode, change dashboard title editing to be in place, etc), but we will leave it to second iteration after the grid behavior is implemented.\r\n\r\n### Technical Notes\r\n\r\n* We currently use `angular-gridster` to allow moving around the widgets in the Edit Dashboard dialog. Maybe we can use it for the grid or a similar library.\r\n* Currently the widget knows nothing about its placement, but only its size (width). The dashboard has a layout property, which is an array of arrays of widgets ids (each item in the array is a row/array of widgets). This is error prone and makes layout changes harder. If possible, it will be better if each widget retains its own placement information.\r\n* The API to update a widget currently supports only updating a textbox widget. We will need to extend it to support all widget types.\n", "before_files": [{"content": "import json\n\nfrom flask import request\nfrom redash import models\nfrom redash.handlers.base import BaseResource\nfrom redash.permissions import (require_access,\n                                require_object_modify_permission,\n                                require_permission, view_only)\n\n\nclass WidgetListResource(BaseResource):\n    @require_permission('edit_dashboard')\n    def post(self):\n        \"\"\"\n        Add a widget to a dashboard.\n\n        :<json number dashboard_id: The ID for the dashboard being added to\n        :<json visualization_id: The ID of the visualization to put in this widget\n        :<json object options: Widget options\n        :<json string text: Text box contents\n        :<json number width: Width for widget display\n\n        :>json object widget: The created widget\n        :>json array layout: The new layout of the dashboard this widget was added to\n        :>json boolean new_row: Whether this widget was added on a new row or not\n        :>json number version: The revision number of the dashboard\n        \"\"\"\n        widget_properties = request.get_json(force=True)\n        dashboard = models.Dashboard.get_by_id_and_org(widget_properties.pop('dashboard_id'), self.current_org)\n        require_object_modify_permission(dashboard, self.current_user)\n\n        widget_properties['options'] = json.dumps(widget_properties['options'])\n        widget_properties.pop('id', None)\n        widget_properties['dashboard'] = dashboard\n\n        visualization_id = widget_properties.pop('visualization_id')\n        if visualization_id:\n            visualization = models.Visualization.get_by_id_and_org(visualization_id, self.current_org)\n            require_access(visualization.query_rel.groups, self.current_user, view_only)\n        else:\n            visualization = None\n\n        widget_properties['visualization'] = visualization\n\n        widget = models.Widget(**widget_properties)\n        models.db.session.add(widget)\n        models.db.session.commit()\n\n        layout = json.loads(widget.dashboard.layout)\n        new_row = True\n\n        if len(layout) == 0 or widget.width == 2:\n            layout.append([widget.id])\n        elif len(layout[-1]) == 1:\n            neighbour_widget = models.Widget.query.get(layout[-1][0])\n            if neighbour_widget.width == 1:\n                layout[-1].append(widget.id)\n                new_row = False\n            else:\n                layout.append([widget.id])\n        else:\n            layout.append([widget.id])\n\n        widget.dashboard.layout = json.dumps(layout)\n        models.db.session.add(widget.dashboard)\n        models.db.session.commit()\n        return {'widget': widget.to_dict(), 'layout': layout, 'new_row': new_row, 'version': dashboard.version}\n\n\nclass WidgetResource(BaseResource):\n    @require_permission('edit_dashboard')\n    def post(self, widget_id):\n        \"\"\"\n        Updates a widget in a dashboard.\n        This method currently handles Text Box widgets only.\n\n        :param number widget_id: The ID of the widget to modify\n\n        :<json string text: The new contents of the text box\n        \"\"\"\n        widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)\n        require_object_modify_permission(widget.dashboard, self.current_user)\n        widget_properties = request.get_json(force=True)\n        widget.text = widget_properties['text']\n        models.db.session.commit()\n        return widget.to_dict()\n\n    @require_permission('edit_dashboard')\n    def delete(self, widget_id):\n        \"\"\"\n        Remove a widget from a dashboard.\n\n        :param number widget_id: ID of widget to remove\n\n        :>json array layout: New layout of dashboard this widget was removed from\n        :>json number version: Revision number of dashboard\n        \"\"\"\n        widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)\n        require_object_modify_permission(widget.dashboard, self.current_user)\n        widget.delete()\n        models.db.session.commit()\n        return {'layout': widget.dashboard.layout, 'version': widget.dashboard.version}\n", "path": "redash/handlers/widgets.py"}]}