diff --git a/IPython/frontend/html/notebook/__init__.py b/IPython/frontend/html/notebook/__init__.py
index c99e4a8..bfa5317 100644
--- a/IPython/frontend/html/notebook/__init__.py
+++ b/IPython/frontend/html/notebook/__init__.py
@@ -13,3 +13,8 @@ except AttributeError:
if version_info < (2,1,0):
raise ImportError(msg + ", but you have %s" % tornado.version)
del msg
+
+# check for pyzmq 2.1.4
+from IPython.zmq import check_for_zmq
+check_for_zmq('2.1.4', 'IPython.frontend.html.notebook')
+del check_for_zmq
diff --git a/IPython/frontend/html/notebook/notebookapp.py b/IPython/frontend/html/notebook/notebookapp.py
index 2387fc8..9c34df4 100644
--- a/IPython/frontend/html/notebook/notebookapp.py
+++ b/IPython/frontend/html/notebook/notebookapp.py
@@ -35,13 +35,7 @@ import zmq
# Install the pyzmq ioloop. This has to be done before anything else from
# tornado is imported.
from zmq.eventloop import ioloop
-# FIXME: ioloop.install is new in pyzmq-2.1.7, so remove this conditional
-# when pyzmq dependency is updated beyond that.
-if hasattr(ioloop, 'install'):
- ioloop.install()
-else:
- import tornado.ioloop
- tornado.ioloop.IOLoop = ioloop.IOLoop
+ioloop.install()
from tornado import httpserver
from tornado import web
diff --git a/IPython/zmq/__init__.py b/IPython/zmq/__init__.py
index 6986364..7f558fd 100644
--- a/IPython/zmq/__init__.py
+++ b/IPython/zmq/__init__.py
@@ -12,6 +12,40 @@
import warnings
from distutils.version import LooseVersion as V
+
+def patch_pyzmq():
+ """backport a few patches from newer pyzmq
+
+ These can be removed as we bump our minimum pyzmq version
+ """
+
+ import zmq
+
+ # ioloop.install, introduced in pyzmq 2.1.7
+ from zmq.eventloop import ioloop
+
+ def install():
+ import tornado.ioloop
+ tornado.ioloop.IOLoop = ioloop.IOLoop
+
+ if not hasattr(ioloop, 'install'):
+ ioloop.install = install
+
+ # fix missing DEALER/ROUTER aliases in pyzmq < 2.1.9
+ if not hasattr(zmq, 'DEALER'):
+ zmq.DEALER = zmq.XREQ
+ if not hasattr(zmq, 'ROUTER'):
+ zmq.ROUTER = zmq.XREP
+
+ # fallback on stdlib json if jsonlib is selected, because jsonlib breaks things.
+ # jsonlib support is removed from pyzmq >= 2.2.0
+
+ from zmq.utils import jsonapi
+ if jsonapi.jsonmod.__name__ == 'jsonlib':
+ import json
+ jsonapi.jsonmod = json
+
+
def check_for_zmq(minimum_version, module='IPython.zmq'):
try:
import zmq
@@ -24,12 +58,6 @@ def check_for_zmq(minimum_version, module='IPython.zmq'):
raise ImportError("%s requires pyzmq >= %s, but you have %s"%(
module, minimum_version, pyzmq_version))
- # fix missing DEALER/ROUTER aliases in pyzmq < 2.1.9
- if not hasattr(zmq, 'DEALER'):
- zmq.DEALER = zmq.XREQ
- if not hasattr(zmq, 'ROUTER'):
- zmq.ROUTER = zmq.XREP
-
if V(zmq.zmq_version()) >= V('4.0.0'):
warnings.warn("""libzmq 4 detected.
It is unlikely that IPython's zmq code will work properly.
@@ -37,3 +65,4 @@ def check_for_zmq(minimum_version, module='IPython.zmq'):
RuntimeWarning)
check_for_zmq('2.1.4')
+patch_pyzmq()
diff --git a/IPython/zmq/session.py b/IPython/zmq/session.py
index e92254d..46eedd7 100644
--- a/IPython/zmq/session.py
+++ b/IPython/zmq/session.py
@@ -74,21 +74,9 @@ def squash_unicode(obj):
#-----------------------------------------------------------------------------
-# jsonlib behaves a bit differently, so handle that where it affects us
-if jsonapi.jsonmod.__name__ == 'jsonlib':
- # kwarg for serializing unknown types (datetime) is different
- dumps_kwargs = dict(on_unknown=date_default)
- # By default, jsonlib unpacks floats as Decimal instead of float,
- # which can foul things up
- loads_kwargs = dict(use_float=True)
-else:
- # ISO8601-ify datetime objects
- dumps_kwargs = dict(default=date_default)
- # nothing to specify for loads
- loads_kwargs = dict()
-
-json_packer = lambda obj: jsonapi.dumps(obj, **dumps_kwargs)
-json_unpacker = lambda s: extract_dates(jsonapi.loads(s, **loads_kwargs))
+# ISO8601-ify datetime objects
+json_packer = lambda obj: jsonapi.dumps(obj, default=date_default)
+json_unpacker = lambda s: extract_dates(jsonapi.loads(s))
pickle_packer = lambda o: pickle.dumps(o,-1)
pickle_unpacker = pickle.loads