Refactor.

This commit is contained in:
Jakub Skiepko 2014-06-28 13:35:01 +02:00
parent fa9bb3542c
commit 43ae8ff4cb
5 changed files with 76 additions and 33 deletions

View file

@ -8,8 +8,8 @@ from routeros_api import base_api
def connect(host, username='admin', password='', port=8728):
socket = api_socket.get_socket(host, port)
base = base_api.Connection(socket)
communicator = api_communicator.ApiCommunicator(base)
close_handler = api_socket.CloseConnectionExceptionHandler(socket)
communicator = api_communicator.ApiCommunicator(base, close_handler)
communicator.add_handler(close_handler)
api = RouterOsApi(communicator, socket)
api.login(username, password)
@ -22,15 +22,15 @@ class RouterOsApi(object):
self.socket = socket
def login(self, login, password):
response = self.communicator.call('/', 'login', include_done=True)
response = self.get_resource('/').call('login', include_done=True)
token = binascii.unhexlify(response[0]['ret'])
hasher = hashlib.md5()
hasher.update(b'\x00')
hasher.update(password.encode())
hasher.update(token)
hashed = b'00' + hasher.hexdigest().encode('ascii')
self.communicator.call('/', 'login',
{'name': login, 'response': hashed})
self.get_resource('/').call('login',
{'name': login, 'response': hashed})
def get_resource(self, path):
return RouterOsResource(self.communicator, path)

View file

@ -1,7 +1,12 @@
from routeros_api.api_communicator import base
from routeros_api.api_communicator import exception_decorator
from routeros_api.api_communicator import encoding_decorator
def ApiCommunicator(base_api):
return exception_decorator.ExceptionAwareApiCommunicator(
base.ApiCommunicatorBase(base_api)
)
def ApiCommunicator(base_api, exception_handler):
communicator = base.ApiCommunicatorBase(base_api)
exception_aware_communicator = (
exception_decorator.ExceptionAwareApiCommunicator(communicator))
exception_aware_communicator.add_handler(exception_handler)
encoding_communicator = encoding_decorator.EncodingApiCommunicator(
exception_aware_communicator)
return encoding_communicator

View file

@ -10,13 +10,13 @@ class ApiCommunicatorBase(object):
self.response_buffor = {}
def call_async(self, path, command, arguments=None, queries=None,
additional_queries=(), binary=False, include_done=False):
additional_queries=(), include_done=False):
tag = self._get_next_tag()
command = self.get_command(path, command, arguments, queries, tag=tag,
additional_queries=additional_queries)
self.send_command(command)
self.response_buffor[tag] = AsynchronousResponse(
command, binary, include_done)
command, include_done)
return ResponsePromise(self, tag)
def get_command(self, path, command, arguments=None, queries=None,
@ -55,11 +55,11 @@ class ApiCommunicatorBase(object):
if response.type in asynchronous_response.get_meaningfull_responses():
attributes = response.attributes
asynchronous_response.attributes.append(attributes)
if response.type == 'done':
if response.type == b'done':
asynchronous_response.done = True
elif response.type == 'trap':
asynchronous_response.error = response.attributes['message']
elif response.type == 'fatal':
elif response.type == b'trap':
asynchronous_response.error = response.attributes[b'message']
elif response.type == b'fatal':
del(self.response_buffor[response.tag])
message = "Fatal error executing command {command}".format(
command=asynchronous_response.command)
@ -75,30 +75,22 @@ class ApiCommunicatorBase(object):
error=response.error.decode(), command=response.command)
raise exceptions.RouterOsApiCommunicationError(message)
else:
if not response.binary:
response.decode()
return response.attributes
class AsynchronousResponse(object):
def __init__(self, command, binary, include_done):
def __init__(self, command, include_done):
self.attributes = []
self.done = False
self.error = None
self.command = command
self.binary = binary
self.include_done = include_done
def decode(self):
for attribute in self.attributes:
for key in attribute:
attribute[key] = attribute[key].decode()
def get_meaningfull_responses(self):
if self.include_done:
save_responses = ['re', 'done']
save_responses = [b're', b'done']
else:
save_responses = ['re']
save_responses = [b're']
return save_responses

View file

@ -0,0 +1,47 @@
class EncodingApiCommunicator(object):
def __init__(self, inner):
self.inner = inner
def call_async(self, path, command, arguments=None, queries=None,
additional_queries=(), include_done=False, binary=False):
queries = queries or {}
path = path.encode()
command = command.encode()
arguments = self.encode_dictionary(arguments or {}, binary)
queries = self.encode_dictionary(queries or {}, binary)
promise = self.inner.call_async(
path, command, arguments, queries, additional_queries,
include_done)
return EncodedPromiseDecorator(promise, binary)
def encode_dictionary(self, dictionary, binary_values):
encoded_arguments = {}
for key, value in dictionary:
if binary_values:
encoded_arguments[key.encode()] = value
else:
encoded_arguments[key.encode()] = value.encode()
return encoded_arguments
class EncodedPromiseDecorator(object):
def __init__(self, inner, binary_values):
self.inner = inner
self.binary_values = binary_values
def get(self):
response = self.inner.get()
decoded_response = []
for row in response:
decoded_row = self.decode_dictionary(row)
decoded_response.append(decoded_row)
return decoded_response
def decode_dictionary(self, dictionary):
decoded_dictionary = {}
for key, value in dictionary:
if self.binary_values:
decoded_dictionary[key.decode()] = value
else:
decoded_dictionary[key.decode()] = value.decode()
return decoded_dictionary

View file

@ -1,7 +1,6 @@
import re
from routeros_api import exceptions
from routeros_api import utils
from routeros_api import query
@ -20,7 +19,7 @@ class ResponseSentence(object):
def parse(cls, sentence):
response_match = response_re.match(sentence[0])
if response_match:
response = cls(response_match.group(1).decode())
response = cls(response_match.group(1))
response.parse_attributes(sentence[1:])
else:
raise exceptions.RouterOsApiParsingError("Malformed sentence %s",
@ -34,9 +33,9 @@ class ResponseSentence(object):
tag_match = tag_re.match(serialized)
if attribute_match:
key, value = attribute_match.groups()
self.attributes[key.decode()] = self.process_value(value)
self.attributes[key] = self.process_value(value)
elif tag_match:
self.tag = tag_match.group(1).decode()
self.tag = tag_match.group(1)
else:
raise exceptions.RouterOsApiParsingError(
"Malformed attribute %s", serialized)
@ -47,12 +46,12 @@ class ResponseSentence(object):
class CommandSentence(object):
def __init__(self, path, command, tag=None):
self.path = utils.get_bytes(path)
self.command = utils.get_bytes(command)
self.path = path
self.command = command
self.attributes = {}
self.api_attributes = {}
self.queries = set()
self.tag = utils.get_bytes(tag)
self.tag = tag
def get_api_format(self):
formated = [self.path + self.command]
@ -65,7 +64,7 @@ class CommandSentence(object):
return formated
def set(self, key, value):
self.attributes[utils.get_bytes(key)] = utils.get_bytes(value)
self.attributes[key] = value
def filter(self, *args, **kwargs):
for arg in args: