Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ordered queries #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 51 additions & 21 deletions rosapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,10 @@ def __init__(self, api, namespace):
self.api = api
self.namespace = namespace

def call(self, command, set_kwargs, query_kwargs=None):
query_kwargs = query_kwargs or {}
query_arguments = self._prepare_arguments(True, **query_kwargs)
set_arguments = self._prepare_arguments(False, **set_kwargs)
def call(self, command, set_kwargs, query_args=None):
query_args = query_args or []
query_arguments = self._prepare_arguments(True, query_args)
set_arguments = self._prepare_arguments(False, set_kwargs.items())
query = ([('%s/%s' % (self.namespace, command)).encode('ascii')] +
query_arguments + set_arguments)
response = self.api.api_client.talk(query)
Expand All @@ -219,15 +219,19 @@ def call(self, command, set_kwargs, query_kwargs=None):
return output

@staticmethod
def _prepare_arguments(is_query, **kwargs):
def _prepare_arguments(is_query, args):
command_arguments = []
for key, value in kwargs.items():
for key, value in args:
if key in ['id', 'proplist']:
key = '.%s' % key
key = key.replace('_', '-')
selector_char = '?' if is_query else '='
command_arguments.append(
('%s%s=' % (selector_char, key)).encode('ascii') + value)
if is_query and value is None:
# support valueless queries like '?name' which checks if property 'name' exists
command_arguments.append(('?%s' % (key,)).encode('ascii'))
else:
command_arguments.append(
('%s%s=' % (selector_char, key)).encode('ascii') + value)

return command_arguments

Expand All @@ -241,11 +245,36 @@ def _remove_first_char_from_keys(dictionary):
elements.append((key, value))
return dict(elements)

def get(self, **kwargs):
return self.call('print', {}, kwargs)

def detailed_get(self, **kwargs):
return self.call('print', {'detail': b''}, kwargs)
def get(self, *args, **kwargs):
"""
Accepts multiple parameters, each should be a key-value pair.
For example, the following query:

/interface/print
?type=ether
?type=vlan
?#|

Would be called as:
>>> resource.get( ('type', 'ether'), ('type', 'vlan'), ('#|', None) )

(Note: the #| syntax ORs the result of the previous two queries together,
thus this is a query for "type=ether OR type=vlan". Correct order of query
words is required for this stack-based syntax to work.)

This parameter syntax is used because order of query words is significant
(according to the Routerboard API documentation), and since dicts
are inherently unordered, kwargs cannot be used here.

For compatibility, the old kwargs syntax is still accepted, but
parameters might be sent in any order.
"""
args += tuple(kwargs.items())
return self.call('print', {}, args)

def detailed_get(self, *args, **kwargs):
args += tuple(kwargs.items())
return self.call('print', {'detail': b''}, args)

def set(self, **kwargs):
return self.call('set', kwargs)
Expand All @@ -258,21 +287,22 @@ def remove(self, **kwargs):


class RouterboardResource(BaseRouterboardResource):
def detailed_get(self, **kwargs):
return self.call('print', {'detail': ''}, kwargs)
def detailed_get(self, *args, **kwargs):
args += tuple(kwargs.items())
return self.call('print', {'detail': ''}, args)

def call(self, command, set_kwargs, query_kwargs=None):
query_kwargs = query_kwargs or {}
def call(self, command, set_kwargs, query_args=None):
query_args = query_args or []
result = super(RouterboardResource, self).call(
command, self._encode_kwargs(set_kwargs),
self._encode_kwargs(query_kwargs))
command, dict(self._encode_items(set_kwargs.items())),
self._encode_items(query_args))
for item in result:
for k in item:
item[k] = item[k].decode('ascii')
return result

def _encode_kwargs(self, kwargs):
return dict((k, v.encode('ascii')) for k, v in kwargs.items())
def _encode_items(self, items):
return [(k, v.encode('ascii')) for k, v in items]


class RouterboardAPI(object):
Expand Down