diff --git a/IPython/parallel/client/asyncresult.py b/IPython/parallel/client/asyncresult.py index 7ae200d..23fed54 100644 --- a/IPython/parallel/client/asyncresult.py +++ b/IPython/parallel/client/asyncresult.py @@ -62,6 +62,7 @@ class AsyncResult(object): self._tracker = tracker self._ready = False self._success = None + self._metadata = None if len(msg_ids) == 1: self._single_result = not isinstance(targets, (list, tuple)) else: @@ -231,13 +232,13 @@ class AsyncResult(object): else: raise TypeError("Invalid key type %r, must be 'int','slice', or 'str'"%type(key)) - @check_ready def __getattr__(self, key): """getattr maps to getitem for convenient attr access to metadata.""" - if key not in self._metadata[0].keys(): + try: + return self.__getitem__(key) + except (error.TimeoutError, KeyError): raise AttributeError("%r object has no attribute %r"%( self.__class__.__name__, key)) - return self.__getitem__(key) # asynchronous iterator: def __iter__(self): diff --git a/IPython/parallel/tests/test_asyncresult.py b/IPython/parallel/tests/test_asyncresult.py index f9448ad..30dae4b 100644 --- a/IPython/parallel/tests/test_asyncresult.py +++ b/IPython/parallel/tests/test_asyncresult.py @@ -70,4 +70,46 @@ class AsyncResultTest(ClusterTestCase): self.assertEquals(sorted(d.keys()), sorted(self.client.ids)) for eid,r in d.iteritems(): self.assertEquals(r, 5) + + def test_list_amr(self): + ar = self.client.load_balanced_view().map_async(wait, [0.1]*5) + rlist = list(ar) + + def test_getattr(self): + ar = self.client[:].apply_async(wait, 0.5) + self.assertRaises(AttributeError, lambda : ar._foo) + self.assertRaises(AttributeError, lambda : ar.__length_hint__()) + self.assertRaises(AttributeError, lambda : ar.foo) + self.assertRaises(AttributeError, lambda : ar.engine_id) + self.assertFalse(hasattr(ar, '__length_hint__')) + self.assertFalse(hasattr(ar, 'foo')) + self.assertFalse(hasattr(ar, 'engine_id')) + ar.get(5) + self.assertRaises(AttributeError, lambda : ar._foo) + self.assertRaises(AttributeError, lambda : ar.__length_hint__()) + self.assertRaises(AttributeError, lambda : ar.foo) + self.assertTrue(isinstance(ar.engine_id, list)) + self.assertEquals(ar.engine_id, ar['engine_id']) + self.assertFalse(hasattr(ar, '__length_hint__')) + self.assertFalse(hasattr(ar, 'foo')) + self.assertTrue(hasattr(ar, 'engine_id')) + + def test_getitem(self): + ar = self.client[:].apply_async(wait, 0.5) + self.assertRaises(TimeoutError, lambda : ar['foo']) + self.assertRaises(TimeoutError, lambda : ar['engine_id']) + ar.get(5) + self.assertRaises(KeyError, lambda : ar['foo']) + self.assertTrue(isinstance(ar['engine_id'], list)) + self.assertEquals(ar.engine_id, ar['engine_id']) + + def test_single_result(self): + ar = self.client[-1].apply_async(wait, 0.5) + self.assertRaises(TimeoutError, lambda : ar['foo']) + self.assertRaises(TimeoutError, lambda : ar['engine_id']) + self.assertTrue(ar.get(5) == 0.5) + self.assertTrue(isinstance(ar['engine_id'], int)) + self.assertTrue(isinstance(ar.engine_id, int)) + self.assertEquals(ar.engine_id, ar['engine_id']) + diff --git a/IPython/parallel/tests/test_lbview.py b/IPython/parallel/tests/test_lbview.py index ae8eac2..39ac107 100644 --- a/IPython/parallel/tests/test_lbview.py +++ b/IPython/parallel/tests/test_lbview.py @@ -68,10 +68,11 @@ class TestLoadBalancedView(ClusterTestCase): data = range(16,0,-1) reference = map(f, data) - amr = self.view.map_async(f, data, ordered=False) + amr = self.view.map_async(slow_f, data, ordered=False) self.assertTrue(isinstance(amr, pmod.AsyncMapResult)) - # check individual elements, retrieved as they come (uses __iter__) - astheycame = list(amr) + # check individual elements, retrieved as they come + # list comprehension uses __iter__ + astheycame = [ r for r in amr ] # Ensure that at least one result came out of order: self.assertNotEquals(astheycame, reference, "should not have preserved order") self.assertEquals(sorted(astheycame, reverse=True), reference, "result corrupted") @@ -86,9 +87,10 @@ class TestLoadBalancedView(ClusterTestCase): data = range(16,0,-1) reference = map(f, data) - amr = self.view.map_async(f, data) + amr = self.view.map_async(slow_f, data) self.assertTrue(isinstance(amr, pmod.AsyncMapResult)) - # check individual elements, retrieved as they come (uses __iter__) + # check individual elements, retrieved as they come + # list(amr) uses __iter__ astheycame = list(amr) # Ensure that results came in order self.assertEquals(astheycame, reference)