Source code for pipeLionServer.core.client
""" Module holds the Client class.
pythond-standard-includes:
:imports: socket
:imports: cPickle
:imports: time
pipeLion-includes:
:imports: pipeLion.core.configManager.ConfigManager
pipeLionServer-includes:
:imports: pipeLionServer.core.server.Server
:imports: pipeLionServer.core.error.PipeLionServerException
:imports: pipeLionServer.core.error.PipeLionServerWarning
"""
import socket
import time
import pickle
from pipeLionServer.core.server import Server
from pipeLionServer.core.error import PipeLionServerException
from pipeLionServer.core.error import PipeLionServerWarning
from pipeLionServer.utils import encode
from pipeLion.core.configManager import ConfigManager
[docs]class Client(object):
""" The Client-class is an interface, which automatically connects to the server set in the config.
The Client class should be used everywhere where ther is the need to connect to the data-base.
It is possible to access the database through the server by using predefined services.
example:
1 | c = Client()
2 | c.sendRequest('exampleService', 'exampleRequest', {'argName1': True, 'argName2': argValue})
3 | >>> resultFromServer
"""
__defaultHost = "localhost"
__defaultPort = "50007"
requestSeparator = '||REQTOCMD||'
# __config holds the current configuration information
__config = ConfigManager()
def __init__(self):
""" constructor
"""
self.__socket = None
self.__connected = False
# holds a list of former requests to the server
self.requests = []
@classmethod
[docs] def getHost(cls):
""" gets the host from the config or takes the default host, which is the local
:return: host
:rtype: string
"""
host = cls.__config.getPipeLionSocket()['host'] or cls.__defaultHost
return host
@classmethod
[docs] def getPort(cls):
""" gets the port from the config or takes the default port, which is 50007
:return: port
:rtype: int
"""
port = cls.__config.getPipeLionSocket()['port'] or cls.__defaultPort
return port
[docs] def connectToServer(self):
""" this method establishes a connection to the server. in case it wasn't possible to connect to the server, the result will be 0
:returns: success-value 1 if the connection was successful 0 if not
:rtype: int
"""
for res in socket.getaddrinfo(self.getHost(), self.getPort(), socket.AF_INET, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
self.__socket = socket.socket(af, socktype, proto)
self.__socket.setblocking(1)
self.__socket.settimeout(4.0)
break
try:
self.__socket.connect( (Server.getHost(), Server.getPort()) )
self.__connected = True
return 1
except:
self.__connected = False
return 0
[docs] def stopServer(self):
""" method will close the server
"""
self.connectToServer()
self.__socket.send('stopServer')
self.__socket.close()
self.__connected = False
[docs] def disconnectFromServer(self):
""" method will disconnect the client from the server
"""
self.__socket.send('closeSocket')
self.__socket.close()
self.__socket = None
self.__connected = False
[docs] def sendRequest(self, service, request='', args={}):
""" method will send a request to the server. argument-dictionary will be pickled and the server will send back
a pickled object as well.
:param service: name of the service, in which we can find the request
:type service: string
:param requests: name of the server-requests
:type requests: string
:param args: in case the request needs input arguments to work, these args can be given in here as keyword-args. If there are None,
the default value is an empty dictionary
:type args: dictionary:
:returns: the return of this method will be the returnValue of the Service-request-function, which ran on the server.
:rtype: unpickledObject
"""
request = self.requestSeparator.join([service, request, encode.encodeBinary(pickle.dumps(args, pickle.HIGHEST_PROTOCOL))])
response = ''
self.connectToServer()
self.__socket.setblocking(1)
self.__socket.sendall('%08d'%len(request))
self.__socket.sendall(request)
bits = ''
for i in xrange(8):
bits += self.__socket.recv(1)
for i in xrange(int(bits)):
response += self.__socket.recv(1)
self.disconnectFromServer()
returnValue = self.addRequestToHistory(request, response)
if isinstance(returnValue,Exception):
raise returnValue
return returnValue
[docs] def sendRequests(self, requests=None):
""" method is a wrapper around the sendRequest method, and takes a list of service-requests
instead of just one. return Value is a list of all server-replies
:param requests: a list of tuples which hold two strings and one dictionary
:type requests: list
:returns: list of all server-responses
:rtype: list
"""
if not requests:
requests = []
responses = []
for eachRequest in requests:
responses.append(self.sendRequest(*eachRequest))
return responses
[docs] def addRequestToHistory(self, request, response=None):
""" Each request a client does to the server the request and its response is stored in a dict.
this method will add an entry to this dictionary.
:param request: name of the server-request
:type request: string
:param response: pickled server-response
:type response: pickled object
:returns: unpickled response
:rtype: variant object
"""
msg = pickle.loads(encode.decodeBinary(response))
self.requests.append({
'request': request, 'response' : msg
})
return self.requests[-1]['response']
[docs] def queryRequestHistory(self, id=None, request=None, response=None, all=False):
""" method will query the request history by one of the given args: id, request, response
if id is given, the ids entry in the history is returned,
if request is given, all history-entries with the given request are returned
and if response is given, all history entries with the given response are returned
:param id: index number of request (last request is -1, first is 0)
:type id: int
:param request: name of the request
:type request: string
:param response: object which is searched for in the history
:type response: variant object
:returns: method will either return a list of dictionaries or a single dictionary.
:rtype: list or dictionary
"""
if all:
return self.requests
elif id != None:
return [self.requests[id]]
elif request:
return [eachRequest for eachRequest in self.requests if request in eachRequest['request']]
elif response:
return [eachRequest for eachRequest in self.requests if response in eachRequest['response']]
return []
[docs] def getRequestHistory(self):
""" method will return the full request-history dictionary
"""
return self.requests