prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Can't serialize timedelta column
  If you have a data frame with a column of timedeltas, then make a ColumnDataSource out of it, the ColumnDataSource will be created:
  
  ``` python
  In [9]: source.data['delta']
  Out[9]:
  [Timedelta('0 days 00:33:00'),
   Timedelta('0 days 00:35:00'),
   Timedelta('0 days 03:01:00')]
  ```
  
  But if you use that source in a plot, even if you don't use the column, when it comes time to serialize (show/save/embed etc) the plot, it fails:
  
  ``` python
  Timedelta('0 days 00:33:00') is not JSON serializable
  ```
  
  Maybe we can provide some validation on ColumnDataSource creation? Or, at least provide a more helpful message on failure, as it's not immediately obvious what went wrong.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `bokeh/core/json_encoder.py`
  Content:
  ```
  1 ''' Provide a custom JSON encoder for serializing Bokeh models.
  2 
  3 '''
  4 from __future__ import absolute_import
  5 
  6 import logging
  7 log = logging.getLogger(__name__)
  8 
  9 import datetime as dt
  10 import decimal
  11 import json
  12 import time
  13 
  14 import numpy as np
  15 
  16 from ..settings import settings
  17 from ..util.dependencies import import_optional
  18 from ..util.serialization import transform_series, transform_array
  19 
  20 pd = import_optional('pandas')
  21 rd = import_optional("dateutil.relativedelta")
  22 
  23 class BokehJSONEncoder(json.JSONEncoder):
  24     ''' Encode values to be used in Bokeh documents or communicated to
  25     a Bokeh server.
  26 
  27     '''
  28     def transform_python_types(self, obj):
  29         ''' Handle special scalars, use default json encoder otherwise
  30 
  31         '''
  32         # Pandas Timestamp
  33         if pd and isinstance(obj, pd.tslib.Timestamp):
  34             return obj.value / 10**6.0  #nanosecond to millisecond
  35         elif np.issubdtype(type(obj), np.float):
  36             return float(obj)
  37         elif np.issubdtype(type(obj), np.int):
  38             return int(obj)
  39         elif np.issubdtype(type(obj), np.bool_):
  40             return bool(obj)
  41         # Datetime
  42         # datetime is a subclass of date.
  43         elif isinstance(obj, dt.datetime):
  44             return time.mktime(obj.timetuple()) * 1000. + obj.microsecond / 1000.
  45         # Date
  46         elif isinstance(obj, dt.date):
  47             return time.mktime(obj.timetuple()) * 1000.
  48         # Numpy datetime64
  49         elif isinstance(obj, np.datetime64):
  50             epoch_delta = obj - np.datetime64('1970-01-01T00:00:00Z')
  51             return (epoch_delta / np.timedelta64(1, 'ms'))
  52         # Time
  53         elif isinstance(obj, dt.time):
  54             return (obj.hour * 3600 + obj.minute * 60 + obj.second) * 1000 + obj.microsecond / 1000.
  55         elif rd and isinstance(obj, rd.relativedelta):
  56             return dict(years=obj.years, months=obj.months, days=obj.days, hours=obj.hours,
  57                 minutes=obj.minutes, seconds=obj.seconds, microseconds=obj.microseconds)
  58         # Decimal
  59         elif isinstance(obj, decimal.Decimal):
  60             return float(obj)
  61         else:
  62             return super(BokehJSONEncoder, self).default(obj)
  63 
  64     def default(self, obj):
  65         #argh! local import!
  66         from ..model import Model
  67         from ..colors import Color
  68         from .properties import HasProps
  69         ## array types
  70         if pd and isinstance(obj, (pd.Series, pd.Index)):
  71             return transform_series(obj)
  72         elif isinstance(obj, np.ndarray):
  73             return transform_array(obj)
  74         elif isinstance(obj, Model):
  75             return obj.ref
  76         elif isinstance(obj, HasProps):
  77             return obj.properties_with_values(include_defaults=False)
  78         elif isinstance(obj, Color):
  79             return obj.to_css()
  80         else:
  81             return self.transform_python_types(obj)
  82 
  83 def serialize_json(obj, encoder=BokehJSONEncoder, indent=None, **kwargs):
  84     ''' Return a serialized JSON representation of a Bokeh model.
  85 
  86     '''
  87     pretty = settings.pretty(False)
  88 
  89     if pretty:
  90         separators=(",", ": ")
  91     else:
  92         separators=(",", ":")
  93 
  94     if pretty and indent is None:
  95         indent = 2
  96 
  97     return json.dumps(obj, cls=encoder, allow_nan=False, indent=indent, separators=separators, sort_keys=True, **kwargs)
  98
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/bokeh/core/json_encoder.py b/bokeh/core/json_encoder.py
  --- a/bokeh/core/json_encoder.py
  +++ b/bokeh/core/json_encoder.py
  @@ -42,6 +42,10 @@
           # datetime is a subclass of date.
           elif isinstance(obj, dt.datetime):
               return time.mktime(obj.timetuple()) * 1000. + obj.microsecond / 1000.
  +        # Timedelta
  +        # timedelta is class in the datetime library
  +        elif isinstance(obj, dt.timedelta):
  +            return dict(days=obj.days, seconds=obj.seconds, microseconds=obj.microseconds)
           # Date
           elif isinstance(obj, dt.date):
               return time.mktime(obj.timetuple()) * 1000.
  
verification_info: {"golden_diff": "diff --git a/bokeh/core/json_encoder.py b/bokeh/core/json_encoder.py\n--- a/bokeh/core/json_encoder.py\n+++ b/bokeh/core/json_encoder.py\n@@ -42,6 +42,10 @@\n         # datetime is a subclass of date.\n         elif isinstance(obj, dt.datetime):\n             return time.mktime(obj.timetuple()) * 1000. + obj.microsecond / 1000.\n+        # Timedelta\n+        # timedelta is class in the datetime library\n+        elif isinstance(obj, dt.timedelta):\n+            return dict(days=obj.days, seconds=obj.seconds, microseconds=obj.microseconds)\n         # Date\n         elif isinstance(obj, dt.date):\n             return time.mktime(obj.timetuple()) * 1000.\n", "issue": "Can't serialize timedelta column\nIf you have a data frame with a column of timedeltas, then make a ColumnDataSource out of it, the ColumnDataSource will be created:\n\n``` python\nIn [9]: source.data['delta']\nOut[9]:\n[Timedelta('0 days 00:33:00'),\n Timedelta('0 days 00:35:00'),\n Timedelta('0 days 03:01:00')]\n```\n\nBut if you use that source in a plot, even if you don't use the column, when it comes time to serialize (show/save/embed etc) the plot, it fails:\n\n``` python\nTimedelta('0 days 00:33:00') is not JSON serializable\n```\n\nMaybe we can provide some validation on ColumnDataSource creation? Or, at least provide a more helpful message on failure, as it's not immediately obvious what went wrong.\n\n", "before_files": [{"content": "''' Provide a custom JSON encoder for serializing Bokeh models.\n\n'''\nfrom __future__ import absolute_import\n\nimport logging\nlog = logging.getLogger(__name__)\n\nimport datetime as dt\nimport decimal\nimport json\nimport time\n\nimport numpy as np\n\nfrom ..settings import settings\nfrom ..util.dependencies import import_optional\nfrom ..util.serialization import transform_series, transform_array\n\npd = import_optional('pandas')\nrd = import_optional(\"dateutil.relativedelta\")\n\nclass BokehJSONEncoder(json.JSONEncoder):\n    ''' Encode values to be used in Bokeh documents or communicated to\n    a Bokeh server.\n\n    '''\n    def transform_python_types(self, obj):\n        ''' Handle special scalars, use default json encoder otherwise\n\n        '''\n        # Pandas Timestamp\n        if pd and isinstance(obj, pd.tslib.Timestamp):\n            return obj.value / 10**6.0  #nanosecond to millisecond\n        elif np.issubdtype(type(obj), np.float):\n            return float(obj)\n        elif np.issubdtype(type(obj), np.int):\n            return int(obj)\n        elif np.issubdtype(type(obj), np.bool_):\n            return bool(obj)\n        # Datetime\n        # datetime is a subclass of date.\n        elif isinstance(obj, dt.datetime):\n            return time.mktime(obj.timetuple()) * 1000. + obj.microsecond / 1000.\n        # Date\n        elif isinstance(obj, dt.date):\n            return time.mktime(obj.timetuple()) * 1000.\n        # Numpy datetime64\n        elif isinstance(obj, np.datetime64):\n            epoch_delta = obj - np.datetime64('1970-01-01T00:00:00Z')\n            return (epoch_delta / np.timedelta64(1, 'ms'))\n        # Time\n        elif isinstance(obj, dt.time):\n            return (obj.hour * 3600 + obj.minute * 60 + obj.second) * 1000 + obj.microsecond / 1000.\n        elif rd and isinstance(obj, rd.relativedelta):\n            return dict(years=obj.years, months=obj.months, days=obj.days, hours=obj.hours,\n                minutes=obj.minutes, seconds=obj.seconds, microseconds=obj.microseconds)\n        # Decimal\n        elif isinstance(obj, decimal.Decimal):\n            return float(obj)\n        else:\n            return super(BokehJSONEncoder, self).default(obj)\n\n    def default(self, obj):\n        #argh! local import!\n        from ..model import Model\n        from ..colors import Color\n        from .properties import HasProps\n        ## array types\n        if pd and isinstance(obj, (pd.Series, pd.Index)):\n            return transform_series(obj)\n        elif isinstance(obj, np.ndarray):\n            return transform_array(obj)\n        elif isinstance(obj, Model):\n            return obj.ref\n        elif isinstance(obj, HasProps):\n            return obj.properties_with_values(include_defaults=False)\n        elif isinstance(obj, Color):\n            return obj.to_css()\n        else:\n            return self.transform_python_types(obj)\n\ndef serialize_json(obj, encoder=BokehJSONEncoder, indent=None, **kwargs):\n    ''' Return a serialized JSON representation of a Bokeh model.\n\n    '''\n    pretty = settings.pretty(False)\n\n    if pretty:\n        separators=(\",\", \": \")\n    else:\n        separators=(\",\", \":\")\n\n    if pretty and indent is None:\n        indent = 2\n\n    return json.dumps(obj, cls=encoder, allow_nan=False, indent=indent, separators=separators, sort_keys=True, **kwargs)\n", "path": "bokeh/core/json_encoder.py"}], "after_files": [{"content": "''' Provide a custom JSON encoder for serializing Bokeh models.\n\n'''\nfrom __future__ import absolute_import\n\nimport logging\nlog = logging.getLogger(__name__)\n\nimport datetime as dt\nimport decimal\nimport json\nimport time\n\nimport numpy as np\n\nfrom ..settings import settings\nfrom ..util.dependencies import import_optional\nfrom ..util.serialization import transform_series, transform_array\n\npd = import_optional('pandas')\nrd = import_optional(\"dateutil.relativedelta\")\n\nclass BokehJSONEncoder(json.JSONEncoder):\n    ''' Encode values to be used in Bokeh documents or communicated to\n    a Bokeh server.\n\n    '''\n    def transform_python_types(self, obj):\n        ''' Handle special scalars, use default json encoder otherwise\n\n        '''\n        # Pandas Timestamp\n        if pd and isinstance(obj, pd.tslib.Timestamp):\n            return obj.value / 10**6.0  #nanosecond to millisecond\n        elif np.issubdtype(type(obj), np.float):\n            return float(obj)\n        elif np.issubdtype(type(obj), np.int):\n            return int(obj)\n        elif np.issubdtype(type(obj), np.bool_):\n            return bool(obj)\n        # Datetime\n        # datetime is a subclass of date.\n        elif isinstance(obj, dt.datetime):\n            return time.mktime(obj.timetuple()) * 1000. + obj.microsecond / 1000.\n        # Timedelta\n        # timedelta is class in the datetime library\n        elif isinstance(obj, dt.timedelta):\n            return dict(days=obj.days, seconds=obj.seconds, microseconds=obj.microseconds)\n        # Date\n        elif isinstance(obj, dt.date):\n            return time.mktime(obj.timetuple()) * 1000.\n        # Numpy datetime64\n        elif isinstance(obj, np.datetime64):\n            epoch_delta = obj - np.datetime64('1970-01-01T00:00:00Z')\n            return (epoch_delta / np.timedelta64(1, 'ms'))\n        # Time\n        elif isinstance(obj, dt.time):\n            return (obj.hour * 3600 + obj.minute * 60 + obj.second) * 1000 + obj.microsecond / 1000.\n        elif rd and isinstance(obj, rd.relativedelta):\n            return dict(years=obj.years, months=obj.months, days=obj.days, hours=obj.hours,\n                minutes=obj.minutes, seconds=obj.seconds, microseconds=obj.microseconds)\n        # Decimal\n        elif isinstance(obj, decimal.Decimal):\n            return float(obj)\n        else:\n            return super(BokehJSONEncoder, self).default(obj)\n\n    def default(self, obj):\n        #argh! local import!\n        from ..model import Model\n        from ..colors import Color\n        from .properties import HasProps\n        ## array types\n        if pd and isinstance(obj, (pd.Series, pd.Index)):\n            return transform_series(obj)\n        elif isinstance(obj, np.ndarray):\n            return transform_array(obj)\n        elif isinstance(obj, Model):\n            return obj.ref\n        elif isinstance(obj, HasProps):\n            return obj.properties_with_values(include_defaults=False)\n        elif isinstance(obj, Color):\n            return obj.to_css()\n        else:\n            return self.transform_python_types(obj)\n\ndef serialize_json(obj, encoder=BokehJSONEncoder, indent=None, **kwargs):\n    ''' Return a serialized JSON representation of a Bokeh model.\n\n    '''\n    pretty = settings.pretty(False)\n\n    if pretty:\n        separators=(\",\", \": \")\n    else:\n        separators=(\",\", \":\")\n\n    if pretty and indent is None:\n        indent = 2\n\n    return json.dumps(obj, cls=encoder, allow_nan=False, indent=indent, separators=separators, sort_keys=True, **kwargs)\n", "path": "bokeh/core/json_encoder.py"}]}