prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  AttributeError: 'datetime.timedelta' object has no attribute 'isoformat'
  On the latest 0.9.2-rc:
  
  ```
  [2016-01-21 14:30:36,838: ERROR/MainProcess] Task redash.tasks.execute_query[766d3f9f-68a6-4a64-8cd9-b7e4e18bf2af] raised unexpected: AttributeError("'datetime.timedelta' object has no attribute 'isoformat'",)
  Traceback (most recent call last):
    File "/usr/local/lib/python2.7/dist-packages/celery/app/trace.py", line 240, in trace_task
      R = retval = fun(*args, **kwargs)
    File "/opt/redash/redash/tasks.py", line 31, in __call__
      return super(BaseTask, self).__call__(*args, **kwargs)
    File "/usr/local/lib/python2.7/dist-packages/celery/app/trace.py", line 437, in __protected_call__
      return self.run(*args, **kwargs)
    File "/opt/redash/redash/tasks.py", line 286, in execute_query
      data, error = query_runner.run_query(annotated_query)
    File "/opt/redash/redash/query_runner/pg.py", line 132, in run_query
      json_data = json.dumps(data, cls=JSONEncoder)
    File "/usr/lib/python2.7/json/__init__.py", line 250, in dumps
      sort_keys=sort_keys, **kw).encode(obj)
    File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
      chunks = self.iterencode(o, _one_shot=True)
    File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
      return _iterencode(o, 0)
    File "/opt/redash/redash/utils.py", line 57, in default
      return o.isoformat()
  AttributeError: 'datetime.timedelta' object has no attribute 'isoformat'
  ```
  
  
  </issue>
  <code>
  [start of redash/utils.py]
  1 import cStringIO
  2 import csv
  3 import codecs
  4 import decimal
  5 import datetime
  6 import json
  7 import random
  8 import re
  9 import hashlib
  10 import pytz
  11 
  12 COMMENTS_REGEX = re.compile("/\*.*?\*/")
  13 
  14 
  15 def utcnow():
  16     """Return datetime.now value with timezone specified.
  17 
  18     Without the timezone data, when the timestamp stored to the database it gets the current timezone of the server,
  19     which leads to errors in calculations.
  20     """
  21     return datetime.datetime.now(pytz.utc)
  22 
  23 
  24 def slugify(s):
  25     return re.sub('[^a-z0-9_\-]+', '-', s.lower())
  26 
  27 
  28 def gen_query_hash(sql):
  29     """Returns hash of the given query after stripping all comments, line breaks and multiple
  30     spaces, and lower casing all text.
  31 
  32     TODO: possible issue - the following queries will get the same id:
  33         1. SELECT 1 FROM table WHERE column='Value';
  34         2. SELECT 1 FROM table where column='value';
  35     """
  36     sql = COMMENTS_REGEX.sub("", sql)
  37     sql = "".join(sql.split()).lower()
  38     return hashlib.md5(sql.encode('utf-8')).hexdigest()
  39 
  40 
  41 def generate_token(length):
  42     chars = ('abcdefghijklmnopqrstuvwxyz'
  43              'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  44              '0123456789')
  45 
  46     rand = random.SystemRandom()
  47     return ''.join(rand.choice(chars) for x in range(length))
  48 
  49 class JSONEncoder(json.JSONEncoder):
  50     """Custom JSON encoding class, to handle Decimal and datetime.date instances.
  51     """
  52     def default(self, o):
  53         if isinstance(o, decimal.Decimal):
  54             return float(o)
  55 
  56         if isinstance(o, (datetime.date, datetime.time, datetime.timedelta)):
  57             return o.isoformat()
  58             
  59         super(JSONEncoder, self).default(o)
  60 
  61 
  62 def json_dumps(data):
  63     return json.dumps(data, cls=JSONEncoder)
  64 
  65 
  66 def build_url(request, host, path):
  67     parts = request.host.split(':')
  68     if len(parts) > 1:
  69         port = parts[1]
  70         if (port, request.scheme) not in (('80', 'http'), ('443', 'https')):
  71             host = '{}:{}'.format(host, port)
  72 
  73     return "{}://{}{}".format(request.scheme, host, path)
  74 
  75 
  76 class UnicodeWriter:
  77     """
  78     A CSV writer which will write rows to CSV file "f",
  79     which is encoded in the given encoding.
  80     """
  81     def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
  82         # Redirect output to a queue
  83         self.queue = cStringIO.StringIO()
  84         self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
  85         self.stream = f
  86         self.encoder = codecs.getincrementalencoder(encoding)()
  87 
  88     def _encode_utf8(self, val):
  89         if isinstance(val, (unicode, str)):
  90             return val.encode('utf-8')
  91 
  92         return val
  93 
  94     def writerow(self, row):
  95         self.writer.writerow([self._encode_utf8(s) for s in row])
  96         # Fetch UTF-8 output from the queue ...
  97         data = self.queue.getvalue()
  98         data = data.decode("utf-8")
  99         # ... and reencode it into the target encoding
  100         data = self.encoder.encode(data)
  101         # write to the target stream
  102         self.stream.write(data)
  103         # empty queue
  104         self.queue.truncate(0)
  105 
  106     def writerows(self, rows):
  107         for row in rows:
  108             self.writerow(row)
  109
  [end of redash/utils.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/utils.py b/redash/utils.py
  --- a/redash/utils.py
  +++ b/redash/utils.py
  @@ -53,9 +53,12 @@
           if isinstance(o, decimal.Decimal):
               return float(o)
   
  -        if isinstance(o, (datetime.date, datetime.time, datetime.timedelta)):
  +        if isinstance(o, (datetime.date, datetime.time)):
               return o.isoformat()
  -            
  +
  +        if isinstance(o, datetime.timedelta):
  +            return str(o)
  +
           super(JSONEncoder, self).default(o)
  
verification_info: {"golden_diff": "diff --git a/redash/utils.py b/redash/utils.py\n--- a/redash/utils.py\n+++ b/redash/utils.py\n@@ -53,9 +53,12 @@\n         if isinstance(o, decimal.Decimal):\n             return float(o)\n \n-        if isinstance(o, (datetime.date, datetime.time, datetime.timedelta)):\n+        if isinstance(o, (datetime.date, datetime.time)):\n             return o.isoformat()\n-            \n+\n+        if isinstance(o, datetime.timedelta):\n+            return str(o)\n+\n         super(JSONEncoder, self).default(o)\n", "issue": "AttributeError: 'datetime.timedelta' object has no attribute 'isoformat'\nOn the latest 0.9.2-rc:\n\n```\n[2016-01-21 14:30:36,838: ERROR/MainProcess] Task redash.tasks.execute_query[766d3f9f-68a6-4a64-8cd9-b7e4e18bf2af] raised unexpected: AttributeError(\"'datetime.timedelta' object has no attribute 'isoformat'\",)\nTraceback (most recent call last):\n  File \"/usr/local/lib/python2.7/dist-packages/celery/app/trace.py\", line 240, in trace_task\n    R = retval = fun(*args, **kwargs)\n  File \"/opt/redash/redash/tasks.py\", line 31, in __call__\n    return super(BaseTask, self).__call__(*args, **kwargs)\n  File \"/usr/local/lib/python2.7/dist-packages/celery/app/trace.py\", line 437, in __protected_call__\n    return self.run(*args, **kwargs)\n  File \"/opt/redash/redash/tasks.py\", line 286, in execute_query\n    data, error = query_runner.run_query(annotated_query)\n  File \"/opt/redash/redash/query_runner/pg.py\", line 132, in run_query\n    json_data = json.dumps(data, cls=JSONEncoder)\n  File \"/usr/lib/python2.7/json/__init__.py\", line 250, in dumps\n    sort_keys=sort_keys, **kw).encode(obj)\n  File \"/usr/lib/python2.7/json/encoder.py\", line 207, in encode\n    chunks = self.iterencode(o, _one_shot=True)\n  File \"/usr/lib/python2.7/json/encoder.py\", line 270, in iterencode\n    return _iterencode(o, 0)\n  File \"/opt/redash/redash/utils.py\", line 57, in default\n    return o.isoformat()\nAttributeError: 'datetime.timedelta' object has no attribute 'isoformat'\n```\n\n", "before_files": [{"content": "import cStringIO\nimport csv\nimport codecs\nimport decimal\nimport datetime\nimport json\nimport random\nimport re\nimport hashlib\nimport pytz\n\nCOMMENTS_REGEX = re.compile(\"/\\*.*?\\*/\")\n\n\ndef utcnow():\n    \"\"\"Return datetime.now value with timezone specified.\n\n    Without the timezone data, when the timestamp stored to the database it gets the current timezone of the server,\n    which leads to errors in calculations.\n    \"\"\"\n    return datetime.datetime.now(pytz.utc)\n\n\ndef slugify(s):\n    return re.sub('[^a-z0-9_\\-]+', '-', s.lower())\n\n\ndef gen_query_hash(sql):\n    \"\"\"Returns hash of the given query after stripping all comments, line breaks and multiple\n    spaces, and lower casing all text.\n\n    TODO: possible issue - the following queries will get the same id:\n        1. SELECT 1 FROM table WHERE column='Value';\n        2. SELECT 1 FROM table where column='value';\n    \"\"\"\n    sql = COMMENTS_REGEX.sub(\"\", sql)\n    sql = \"\".join(sql.split()).lower()\n    return hashlib.md5(sql.encode('utf-8')).hexdigest()\n\n\ndef generate_token(length):\n    chars = ('abcdefghijklmnopqrstuvwxyz'\n             'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n             '0123456789')\n\n    rand = random.SystemRandom()\n    return ''.join(rand.choice(chars) for x in range(length))\n\nclass JSONEncoder(json.JSONEncoder):\n    \"\"\"Custom JSON encoding class, to handle Decimal and datetime.date instances.\n    \"\"\"\n    def default(self, o):\n        if isinstance(o, decimal.Decimal):\n            return float(o)\n\n        if isinstance(o, (datetime.date, datetime.time, datetime.timedelta)):\n            return o.isoformat()\n            \n        super(JSONEncoder, self).default(o)\n\n\ndef json_dumps(data):\n    return json.dumps(data, cls=JSONEncoder)\n\n\ndef build_url(request, host, path):\n    parts = request.host.split(':')\n    if len(parts) > 1:\n        port = parts[1]\n        if (port, request.scheme) not in (('80', 'http'), ('443', 'https')):\n            host = '{}:{}'.format(host, port)\n\n    return \"{}://{}{}\".format(request.scheme, host, path)\n\n\nclass UnicodeWriter:\n    \"\"\"\n    A CSV writer which will write rows to CSV file \"f\",\n    which is encoded in the given encoding.\n    \"\"\"\n    def __init__(self, f, dialect=csv.excel, encoding=\"utf-8\", **kwds):\n        # Redirect output to a queue\n        self.queue = cStringIO.StringIO()\n        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)\n        self.stream = f\n        self.encoder = codecs.getincrementalencoder(encoding)()\n\n    def _encode_utf8(self, val):\n        if isinstance(val, (unicode, str)):\n            return val.encode('utf-8')\n\n        return val\n\n    def writerow(self, row):\n        self.writer.writerow([self._encode_utf8(s) for s in row])\n        # Fetch UTF-8 output from the queue ...\n        data = self.queue.getvalue()\n        data = data.decode(\"utf-8\")\n        # ... and reencode it into the target encoding\n        data = self.encoder.encode(data)\n        # write to the target stream\n        self.stream.write(data)\n        # empty queue\n        self.queue.truncate(0)\n\n    def writerows(self, rows):\n        for row in rows:\n            self.writerow(row)\n", "path": "redash/utils.py"}]}