Repository: softlayer/softlayer-python
Pull request #508 (2015-03-25 20:53:52)

Fixes bug that occurs when using iter=True with arguments
When passing a 'batch' and 'iter=True' param into call() it will attempt to pass in both the default and user-supplied batch parameter into iter_call() instead of just using the user-supplied value.

This should be reproducible with the following snippet:
```python
import SoftLayer
client = SoftLayer.client()
client.call('service', 'method', 'param1', iter=True, batch=100)
```

To avoid this, this fix will use `**kwargs` to get the batch, limit and offset values instead of mixing keyword arguments with `*args` and `**kwargs` magic.


Patch:
diff --git a/SoftLayer/API.py b/SoftLayer/API.py
index 18ca338d..5b75fd96 100644
--- a/SoftLayer/API.py
+++ b/SoftLayer/API.py
@@ -188,18 +188,21 @@ def call(self, service, method, *args, **kwargs):
 
     __call__ = call
 
-    def iter_call(self, service, method,
-                  chunk=100, limit=None, offset=0, *args, **kwargs):
+    def iter_call(self, service, method, *args, **kwargs):
         """A generator that deals with paginating through results.
 
         :param service: the name of the SoftLayer API service
         :param method: the method to call on the service
-        :param integer chunk: result size for each API call
+        :param integer chunk: result size for each API call (defaults to 100)
         :param \\*args: same optional arguments that ``Service.call`` takes
         :param \\*\\*kwargs: same optional keyword arguments that
                            ``Service.call`` takes
 
         """
+        chunk = kwargs.pop('chunk', 100)
+        limit = kwargs.pop('limit', None)
+        offset = kwargs.pop('offset', 0)
+
         if chunk <= 0:
             raise AttributeError("Chunk size should be greater than zero.")
 
@@ -217,6 +220,7 @@ def iter_call(self, service, method,
                 # Don't over-fetch past the given limit
                 if chunk + result_count > limit:
                     chunk = limit - result_count
+
             results = self.call(service, method,
                                 offset=offset, limit=chunk, *args, **kwargs)
 
diff --git a/SoftLayer/CLI/rwhois/edit.py b/SoftLayer/CLI/rwhois/edit.py
index 343796ae..69488255 100644
--- a/SoftLayer/CLI/rwhois/edit.py
+++ b/SoftLayer/CLI/rwhois/edit.py
@@ -52,4 +52,4 @@ def cli(env, abuse, address1, address2, city, company, country, firstname,
         raise exceptions.CLIAbort(
             "You must specify at least one field to update.")
 
-    mgr.edit_rwhois(**update)  # pylint: disable=W0142
+    mgr.edit_rwhois(**update)


Test patch:
diff --git a/SoftLayer/tests/api_tests.py b/SoftLayer/tests/api_tests.py
index 95b69138..baf873aa 100644
--- a/SoftLayer/tests/api_tests.py
+++ b/SoftLayer/tests/api_tests.py
@@ -127,8 +127,13 @@ def test_iterate(self, _iter_call):
 
     @mock.patch('SoftLayer.API.Client.iter_call')
     def test_service_iter_call(self, _iter_call):
-        self.client['SERVICE'].iter_call('METHOD')
-        _iter_call.assert_called_with('SERVICE', 'METHOD')
+        self.client['SERVICE'].iter_call('METHOD', 'ARG')
+        _iter_call.assert_called_with('SERVICE', 'METHOD', 'ARG')
+
+    @mock.patch('SoftLayer.API.Client.iter_call')
+    def test_service_iter_call_with_chunk(self, _iter_call):
+        self.client['SERVICE'].iter_call('METHOD', 'ARG', chunk=2)
+        _iter_call.assert_called_with('SERVICE', 'METHOD', 'ARG', chunk=2)
 
     @mock.patch('SoftLayer.API.Client.call')
     def test_iter_call(self, _call):
@@ -176,12 +181,17 @@ def test_iter_call(self, _call):
 
         # chunk=25, limit=30, offset=12
         _call.side_effect = [list(range(0, 25)), list(range(25, 30))]
-        result = list(self.client.iter_call(
-            'SERVICE', 'METHOD', iter=True, limit=30, chunk=25, offset=12))
+        result = list(self.client.iter_call('SERVICE', 'METHOD', 'ARG',
+                                            iter=True,
+                                            limit=30,
+                                            chunk=25,
+                                            offset=12))
         self.assertEqual(list(range(30)), result)
         _call.assert_has_calls([
-            mock.call('SERVICE', 'METHOD', iter=False, limit=25, offset=12),
-            mock.call('SERVICE', 'METHOD', iter=False, limit=5, offset=37),
+            mock.call('SERVICE', 'METHOD', 'ARG',
+                      iter=False, limit=25, offset=12),
+            mock.call('SERVICE', 'METHOD', 'ARG',
+                      iter=False, limit=5, offset=37),
         ])
 
         # Chunk size of 0 is invalid