Handle special scalars such as (Python, NumPy, or Pandas)
        datetimes, or Decimal values.

        Args:
            obj (obj) :

                The object to encode. Anything not specifically handled in
                this method is passed on to the default system JSON encoder.

def transform_python_types(self, obj):
        ''' Handle special scalars such as (Python, NumPy, or Pandas)
        datetimes, or Decimal values.

        Args:
            obj (obj) :

                The object to encode. Anything not specifically handled in
                this method is passed on to the default system JSON encoder.

        '''

        # date/time values that get serialized as milliseconds
        if is_datetime_type(obj):
            return convert_datetime_type(obj)

        if is_timedelta_type(obj):
            return convert_timedelta_type(obj)

        # slice objects
        elif isinstance(obj, slice):
            return dict(start=obj.start, stop=obj.stop, step=obj.step)

        # NumPy scalars
        elif np.issubdtype(type(obj), np.floating):
            return float(obj)
        elif np.issubdtype(type(obj), np.integer):
            return int(obj)
        elif np.issubdtype(type(obj), np.bool_):
            return bool(obj)

        # Decimal values
        elif isinstance(obj, decimal.Decimal):
            return float(obj)

        # RelativeDelta gets serialized as a dict
        elif rd and isinstance(obj, rd.relativedelta):
            return dict(years=obj.years,
                    months=obj.months,
                    days=obj.days,
                    hours=obj.hours,
                    minutes=obj.minutes,
                    seconds=obj.seconds,
                    microseconds=obj.microseconds)

        else:
            return super(BokehJSONEncoder, self).default(obj)