Skip to content

Commit 7fb2ab6

Browse files
Jakub Zdroikjgoclawski
Jakub Zdroik
authored andcommitted
Allow query without value.
1 parent 9da9c53 commit 7fb2ab6

File tree

6 files changed

+42
-8
lines changed

6 files changed

+42
-8
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ Now, let's use `count-only`.
236236
CLI: `/ip/dhcp-server/lease/print count-only` (returns 13)
237237

238238
```python
239-
>>> api.get_resource('/ip/dhcp-server/lease').call('print', {'count-only': ''}).done_message
239+
>>> api.get_resource('/ip/dhcp-server/lease').call('print', {'count-only': None}).done_message
240240

241241
{'ret': '13'}
242242
```
@@ -246,7 +246,7 @@ Now, let's use `count-only` and `where`.
246246
CLI: `/ip/dhcp-server/lease/print count-only where server=developers` (returns 4)
247247

248248
```python
249-
>>> api.get_resource('/ip/dhcp-server/lease').call('print', {'count-only': ''}, {'server': 'developers'}).done_message
249+
>>> api.get_resource('/ip/dhcp-server/lease').call('print', {'count-only': None}, {'server': 'developers'}).done_message
250250

251251
{'ret': '4'}
252252
```
@@ -256,7 +256,7 @@ Now, let's use `count-only` and `where` with boolean value.
256256
CLI: `/ip/route/pri count-only where static` (returns 1)
257257

258258
```python
259-
>>> api.get_resource('/ip/route').call('print', {'count-only': ''}, {'static': 'yes'}).done_message
259+
>>> api.get_resource('/ip/route').call('print', {'count-only': None}, {'static': 'yes'}).done_message
260260

261261
{'ret': '1'}
262262
```
@@ -281,7 +281,7 @@ True
281281
CLI command: `/interface/ethernet/poe/monitor numbers=0 once`
282282

283283
```python
284-
>>> response = api.get_resource('/interface/ether/poe').call('monitor', {'numbers': '0', 'once': ''})
284+
>>> response = api.get_resource('/interface/ether/poe').call('monitor', {'numbers': '0', 'once': None})
285285
>>> response
286286
[{'name': 'ether10', 'poe-out': 'auto-on', 'poe-out-status': 'waiting-for-load'}]
287287
```

routeros_api/api_communicator/encoding_decorator.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def transform_dictionary(self, dictionary):
2121

2222
def transform_item(self, item):
2323
key, value = item
24-
if not isinstance(value, bytes):
24+
if value is not None and not isinstance(value, bytes):
2525
logger.warning(
2626
'Non-bytes value passed as item value ({}). You should probably use api.get_resource() instead of '
2727
'api.get_binary_resource() or encode arguments yourself.'.format(value))

routeros_api/resource.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ def transform_dictionary(self, dictionary):
6666

6767
def transform_item(self, item):
6868
key, value = item
69-
return (key, self.structure[key].get_mikrotik_value(value))
69+
if value is None:
70+
return (key, None)
71+
else:
72+
return (key, self.structure[key].get_mikrotik_value(value))
7073

7174
def decorate_promise(self, promise):
7275
return TypedPromiseDecorator(promise, self.structure)
@@ -89,7 +92,10 @@ def transform_dictionary(self, row):
8992

9093
def transform_item(self, item):
9194
key, value = item
92-
return (key, self.structure[key].get_python_value(value))
95+
if value is None:
96+
return (key, None)
97+
else:
98+
return (key, self.structure[key].get_python_value(value))
9399

94100

95101
def clean_path(path):

routeros_api/sentence.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ def __init__(self, path, command, tag=None):
5454
def get_api_format(self):
5555
formated = [self.path + self.command]
5656
for key, value in self.attributes.items():
57-
formated.append(b'=' + key + b'=' + value)
57+
formatted_attribute = b'=' + key
58+
if value:
59+
formatted_attribute += b'=' + value
60+
formated.append(formatted_attribute)
5861
for _query in self.queries:
5962
formated.extend(_query.get_api_format())
6063
if self.tag is not None:

tests/test_api_communicator.py

+16
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ def test_set_call(self):
7373
base.send_sentence.assert_called_once_with(
7474
[b'/interface/set', b'=x=y', b'.tag=1'])
7575

76+
def test_call_with_arguments(self):
77+
base = mock.Mock()
78+
base.receive_sentence.return_value = [b'!done', b'.tag=1']
79+
communicator = api_communicator.ApiCommunicator(base)
80+
communicator.call('/interface/monitor-traffic/', 'monitor', {'interface': 'ether1'})
81+
base.send_sentence.assert_called_once_with(
82+
[b'/interface/monitor-traffic/monitor', b'=interface=ether1', b'.tag=1'])
83+
84+
def test_call_without_arguments(self):
85+
base = mock.Mock()
86+
base.receive_sentence.return_value = [b'!done', b'.tag=1']
87+
communicator = api_communicator.ApiCommunicator(base)
88+
communicator.call('/interface/monitor-traffic/', 'monitor', {'once': None})
89+
base.send_sentence.assert_called_once_with(
90+
[b'/interface/monitor-traffic/monitor', b'=once', b'.tag=1'])
91+
7692
def test_async_error_raises_when_synchronizing(self):
7793
base = mock.Mock()
7894
base.receive_sentence.side_effect = [

tests/test_resource.py

+9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ def test_unknown_resource_set(self):
3333
'/unknown/', 'set', arguments={'x': b'y'}, queries={},
3434
additional_queries=())
3535

36+
def test_unknown_resource_set_with_no_value(self):
37+
communicator = mock.Mock()
38+
some_resource = resource.RouterOsResource(communicator, '/unknown',
39+
structure.default_structure)
40+
some_resource.set(x=None)
41+
communicator.call.assert_called_with(
42+
'/unknown/', 'set', arguments={'x': None}, queries={},
43+
additional_queries=())
44+
3645
def test_string_resource_get(self):
3746
communicator = mock.Mock()
3847
response = base.AsynchronousResponse([{'string': b's'}], command='')

0 commit comments

Comments
 (0)