Skip to content

Commit e80801c

Browse files
committed
fix push/pull for cloudpickle
`@require` still doesn't work, but add an xfail test
1 parent 061bcb1 commit e80801c

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

ipyparallel/tests/test_view.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -858,11 +858,10 @@ def find_ipython():
858858
assert view.apply_sync(find_ipython)
859859

860860
@skip_without('cloudpickle')
861-
@pytest.mark.xfail(reason="cloudpickle doesn't seem to work right now")
862861
def test_use_cloudpickle(self):
863862
view = self.client[:]
864863
view['_a'] = 'engine'
865-
sys.modules['__main__']._a = 'client'
864+
__main__ = sys.modules['__main__']
866865

867866
@interactive
868867
def get_a():
@@ -874,14 +873,52 @@ def get_a():
874873

875874
# enable cloudpickle
876875
view.use_cloudpickle()
877-
# cloudpickle respects engine values *if defined*
876+
877+
# cloudpickle prefers client values
878+
__main__._a = 'client'
878879
a_list = view.apply_sync(get_a)
879-
self.assertEqual(a_list, ['engine'] * len(view))
880-
# cloudpickle uses client values if engine doesn't override
880+
self.assertEqual(a_list, ['client'] * len(view))
881+
882+
# still works even if remote is undefined
881883
view.execute('del _a', block=True)
882884
a_list = view.apply_sync(get_a)
883885
self.assertEqual(a_list, ['client'] * len(view))
886+
884887
# restore pickle, shouldn't resolve
885-
view.execute('del _a', block=True)
886888
view.use_pickle()
887889
self.assertRaisesRemote(NameError, view.apply_sync, get_a)
890+
891+
@skip_without('cloudpickle')
892+
def test_cloudpickle_push_pull(self):
893+
view = self.client[:]
894+
# enable cloudpickle
895+
view.use_cloudpickle()
896+
897+
# push/pull still work
898+
view.push({"key": "pushed"}, block=True)
899+
ar = view.pull("key")
900+
assert ar.get(timeout=10) == ["pushed"] * len(view)
901+
902+
# restore pickle, should get the same value
903+
view.use_pickle()
904+
ar = view.pull("key")
905+
assert ar.get(timeout=10) == ["pushed"] * len(view)
906+
907+
@skip_without('cloudpickle')
908+
@pytest.mark.xfail(reason="@require doesn't work with cloudpickle")
909+
def test_cloudpickle_require(self):
910+
view = self.client[:]
911+
# enable cloudpickle
912+
view.use_cloudpickle()
913+
assert (
914+
'types' not in globals()
915+
), "Test condition isn't met if types is already imported"
916+
917+
@ipp.require("types")
918+
@ipp.interactive
919+
def func(x):
920+
return types.SimpleNamespace(n=x) # noqa: F821
921+
922+
res = view.apply_async(func, 5)
923+
assert res.get(timeout=10) == []
924+
view.use_pickle()

ipyparallel/util.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,9 @@ def interactive(f):
309309
return f
310310

311311

312-
@interactive
313312
def _push(**ns):
314313
"""helper method for implementing `client.push` via `client.apply`"""
315-
user_ns = globals()
314+
user_ns = get_ipython().user_global_ns
316315
tmp = '_IP_PUSH_TMP_'
317316
while tmp in user_ns:
318317
tmp = tmp + '_'
@@ -324,19 +323,19 @@ def _push(**ns):
324323
user_ns.pop(tmp, None)
325324

326325

327-
@interactive
328326
def _pull(keys):
329327
"""helper method for implementing `client.pull` via `client.apply`"""
328+
user_ns = get_ipython().user_global_ns
330329
if isinstance(keys, (list, tuple, set)):
331-
return [eval(key, globals()) for key in keys]
330+
return [eval(key, user_ns) for key in keys]
332331
else:
333-
return eval(keys, globals())
332+
return eval(keys, user_ns)
334333

335334

336-
@interactive
337335
def _execute(code):
338336
"""helper method for implementing `client.execute` via `client.apply`"""
339-
exec(code, globals())
337+
user_ns = get_ipython().user_global_ns
338+
exec(code, user_ns)
340339

341340

342341
# --------------------------------------------------------------------------

0 commit comments

Comments
 (0)