Repository: bokeh/bokeh

Issue:
Improve PyPy compatibility
Running the following code using PyPy and Jupyter notebook will raise several exceptions:

```
import numpy as np
import random
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
import bokeh

# plot inline
output_notebook()

# prepare some data
x = range(100)
y = [random.randint(0,100) for i in x]

# create a new plot with a title and axis labels
p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')

# add a line renderer with legend and line thickness
p.line(x, y, legend="Temp.", line_width=2)

# show the results
show(p)
```

The issue is related to the fact that numpy for PyPy doesn't have np.datetime64 implemented yet.
The solution is quite easy to implement and it is roughly described here: [http://stackoverflow.com/questions/37570376/is-there-any-2d-plotting-library-compatible-with-pypy/37588552#37588552](http://stackoverflow.com/questions/37570376/is-there-any-2d-plotting-library-compatible-with-pypy/37588552#37588552)



Discussion:

Resolving patch:
diff --git a/bokeh/core/properties.py b/bokeh/core/properties.py
--- a/bokeh/core/properties.py
+++ b/bokeh/core/properties.py
@@ -1545,8 +1545,15 @@ def validate(self, value):
         try:
             import numpy as np
             datetime_types += (np.datetime64,)
-        except ImportError:
-            pass
+        except (ImportError, AttributeError) as e:
+            if e.args == ("'module' object has no attribute 'datetime64'",):
+                import sys
+                if 'PyPy' in sys.version:
+                    pass
+                else:
+                    raise e
+            else:
+                pass
 
         if (isinstance(value, datetime_types)):
             return
@@ -1576,8 +1583,15 @@ def validate(self, value):
         try:
             import numpy as np
             timedelta_types += (np.timedelta64,)
-        except ImportError:
-            pass
+        except (ImportError, AttributeError) as e:
+            if e.args == ("'module' object has no attribute 'timedelta64'",):
+                import sys
+                if 'PyPy' in sys.version:
+                    pass
+                else:
+                    raise e
+            else:
+                pass
 
         if (isinstance(value, timedelta_types)):
             return
diff --git a/bokeh/util/serialization.py b/bokeh/util/serialization.py
--- a/bokeh/util/serialization.py
+++ b/bokeh/util/serialization.py
@@ -57,9 +57,22 @@ def transform_array(obj):
     nans and infs with strings
     """
     # Check for astype failures (putative Numpy < 1.7)
-    dt2001 = np.datetime64('2001')
-    legacy_datetime64 = (dt2001.astype('int64') ==
-                         dt2001.astype('datetime64[ms]').astype('int64'))
+    try:
+        dt2001 = np.datetime64('2001')
+        legacy_datetime64 = (dt2001.astype('int64') ==
+                             dt2001.astype('datetime64[ms]').astype('int64'))
+    ## For compatibility with PyPy that doesn't have datetime64
+    except AttributeError as e:
+        if e.args == ("'module' object has no attribute 'datetime64'",):
+            import sys
+            if 'PyPy' in sys.version:
+                legacy_datetime64 = False
+                pass
+            else:
+                raise e
+        else:
+            raise e
+
     ## not quite correct, truncates to ms..
     if obj.dtype.kind == 'M':
         if legacy_datetime64:


Test patch: