mirror of
https://github.com/socialwifi/RouterOS-api.git
synced 2025-08-31 23:20:05 +02:00
Refactor.
This commit is contained in:
parent
fa9bb3542c
commit
43ae8ff4cb
5 changed files with 76 additions and 33 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
47
routeros_api/api_communicator/encoding_decorator.py
Normal file
47
routeros_api/api_communicator/encoding_decorator.py
Normal 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
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue