Skip to content

Commit a7e902d

Browse files
authored
Merge pull request #452 from juju/johnsca/NoneType-results
#452 Apparently, `list_offers` can return a result with a None value instead of an empty list (or no response key), leading to an error like the following: ```python-traceback Traceback (most recent call last): File "/home/johnsca/juju/projects/kubernetes-jenkins/jobs/integration/conftest.py", line 233, in k8s_model offers = [offer.offer_name for offer in (await k8s_model.list_offers()).results] File "/home/johnsca/juju/projects/kubernetes-jenkins/.tox/py3/lib/python3.8/site-packages/juju/model.py", line 1989, in list_offers return await controller.list_offers(self.info.name) File "/home/johnsca/juju/projects/kubernetes-jenkins/.tox/py3/lib/python3.8/site-packages/juju/controller.py", line 769, in list_offers return await facade.ListApplicationOffers(filters=[params]) File "/home/johnsca/juju/projects/kubernetes-jenkins/.tox/py3/lib/python3.8/site-packages/juju/client/facade.py", line 480, in wrapper reply = await f(*args, **kwargs) File "/home/johnsca/juju/projects/kubernetes-jenkins/.tox/py3/lib/python3.8/site-packages/juju/client/_client2.py", line 2413, in ListApplicationOffers reply = await self.rpc(msg) File "/home/johnsca/juju/projects/kubernetes-jenkins/.tox/py3/lib/python3.8/site-packages/juju/client/facade.py", line 623, in rpc result = await self.connection.rpc(msg, encoder=TypeEncoder) File "/home/johnsca/juju/projects/kubernetes-jenkins/.tox/py3/lib/python3.8/site-packages/juju/client/connection.py", line 484, in rpc for res in result['response']['results']: TypeError: 'NoneType' object is not iterable ```
2 parents f264330 + 928461c commit a7e902d

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

juju/client/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ async def rpc(self, msg, encoder=None):
482482
# errors, or perhaps a keyword parameter to the rpc method
483483
# could be added to trigger this behaviour.
484484
err_results = []
485-
for res in result['response']['results']:
485+
for res in result['response']['results'] or []:
486486
if res.get('error', {}).get('message'):
487487
err_results.append(res['error']['message'])
488488
if err_results:

tests/unit/test_connection.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,33 @@ async def test_follow_redirect(event_loop):
165165
if con:
166166
assert con.connect_params()['endpoint'] == "42.42.42.42:4242"
167167
await con.close()
168+
169+
170+
@pytest.mark.asyncio
171+
async def test_rpc_none_results(event_loop):
172+
ws = WebsocketMock([
173+
{'request-id': 1, 'response': {'results': None}},
174+
])
175+
expected_responses = [
176+
{'request-id': 1, 'response': {'results': None}},
177+
]
178+
minimal_facades = [{'name': 'Pinger', 'versions': [1]}]
179+
con = None
180+
try:
181+
with \
182+
mock.patch('websockets.connect', base.AsyncMock(return_value=ws)), \
183+
mock.patch(
184+
'juju.client.connection.Connection.login',
185+
base.AsyncMock(return_value={'response': {
186+
'facades': minimal_facades,
187+
}}),
188+
), \
189+
mock.patch('juju.client.connection.Connection._get_ssl'), \
190+
mock.patch('juju.client.connection.Connection._pinger', base.AsyncMock()):
191+
con = await Connection.connect('0.1.2.3:999')
192+
actual_responses = []
193+
actual_responses.append(await con.rpc({'version': 1}))
194+
assert actual_responses == expected_responses
195+
finally:
196+
if con:
197+
await con.close()

0 commit comments

Comments
 (0)