import os
import zmq
import warnings
TIMEOUT = 1000  # milliseconds
VERBOSE = False
RETRY = True  # Should we try to get another server if we can't connect?
SERVERFILE = "serverlist.dat" # Base name of the file containing  server names
if __name__ == '__main__':
    VERBOSE = True
def printV(*args):
    if VERBOSE:
        for arg in args:
            print arg,
        print ''
def getBasePath(): # Get the base directory of this script
    return __file__[:__file__.rfind("clientBase.py")]
def getServerFile(): # Return the full path the the server list file
    return os.path.join(getBasePath(), SERVERFILE)
def generateConfig(): # generates the config and server files if not found
    serverFile = getServerFile()
    if os.path.isfile(serverFile):
        printV("Server List Found at %s" % serverFile)
    else:
        printV("No Server List Found")
        printV("Generating New Server List at %s" % serverFile)
        with open(serverFile,'wb') as f:
            f.write("echidna tcp://108.52.218.107:5001")
class SDSSError(Exception):  # custom SDSSError that relates to serverside issues
    def __init__(self, message, errors=None):
        super(SDSSError, self).__init__(message)
        self.errors = errors
class ServerList(dict):  # dictionary like class that manages the possible servers
    def __init__(self, *args, **kwargs):
        super(ServerList, self).__init__(*args, **kwargs)
        self.best = None
        self.priority = {}
    def addServer(self, name, address, priority):  # add a server to our list of servers
        server = {"address": address, "priority": priority}
        self[name] = server
        self.priority[priority] = name
    def addServersFromFile(self, filename):
        servers = []
        priority = 0
        with open(filename, 'rb') as f:
            for line in f:
                name, address = line.strip().split()
                self.addServer(name, address, priority)
                priority += 1
    def saveServersToFile(self, filename):
        lines = []
        for p in sorted(self.priority.keys()):
            name = self.priority[p]
            address = self[name]['address']
            lines.append(' '.join((name, address)))
        with open(filename, 'wb') as f:
            f.write('\n'.join(lines))
    def testServer(self, server):
        try:
            context = zmq.Context()
            socket = context.socket(zmq.REQ)
            socket.LINGER = False
            socket.connect(server['address'])
            socket.send(b"ping\n", flags=zmq.NOBLOCK)
            if socket.poll(timeout=1000, flags=zmq.POLLIN):
                return True
            else:
                return False
        except zmq.ZMQError as e:
            raise SDSSError(e.message, e.errno)
    def getBestServer(self):  # determine the best server
        for key, server in sorted(self.items(), key=lambda x: x[1]['priority']):
            isGood = self.testServer(server)
            if isGood:
                printV("Best Server is %s" % key)
                self.best = server['address']
                break
        else:
            self.best = None
            raise SDSSError("No good servers available at the moment", self.best)
    def setBestServer(self, server):  # manually override the best server
        printV("Testing Server %s" % server)
        isGood = self.testServer(self[server])
        if isGood:
            self.best = self[server]['address']
            printV("%s is now connected" % server)
        else:
            raise SDSSError("Bad Server: %s" % server, server)
generateConfig() # Setup the server list and config if needed
servers = ServerList() # Instantiate a new server list
servers.addServersFromFile(getServerFile()) # Add servers from our server list
servers.getBestServer() # Find the best server based on priority and availability
def getSocket():
    context = zmq.Context()
    socket = context.socket(zmq.REQ)
    socket.LINGER = False
    socket.connect(servers.best)
    return socket
def zmqSocketDecorator(func):  # a decorator that handles the zmq sockets and raises SDSS exceptions
    def wrapper(*args, **kwargs):
        try:
            socket = getSocket()
            return func(socket, *args, **kwargs)
        except zmq.ZMQError as e:
            raise SDSSError(e.message, e.errno)
    return wrapper
@zmqSocketDecorator
def getCommandResult(socket, cmd):  # send a command to the server and return the result
    global RETRY
    socket.send(cmd)
    if socket.poll(timeout=TIMEOUT, flags=zmq.POLLIN):
        result = socket.recv_pyobj(flags=zmq.NOBLOCK)
    else:
        if RETRY:
            printV("Server Disconnected.  Attempting to Connect to Another Server")
            servers.getBestServer()
            RETRY = False
            result = getCommandResult(cmd)
            RETRY = True
            return result
        else:
            raise SDSSError("Socket timed out", TIMEOUT)
    if isinstance(result, Exception):
        raise SDSSError(*result.args)
    return result
def createCommand(server_func, *args):  # get the command string for a function and it's arguments
    if len(args):
        args = " ".join(map(str, args))
    else:
        args = ''
    cmd = b"%s\n%s" % (server_func, args)
    return cmd
def isValid(server_func):  # checks if a server_func is valid
    cmd = createCommand('isValid', server_func)
    result = getCommandResult(cmd)
    return result
def commandArgCount(server_func):  # gets information about the server func
    cmd = createCommand('argCount', server_func)
    result = getCommandResult(cmd)
    return result
def _createFunction(server_func, docstr=None):
    # Create a function object that acts on a server side func with name 'server_func'
    if isValid(server_func):
        nargs = commandArgCount(server_func) - 1
    else:
        raise SDSSError("Invalid Function: %s" % server_func, server_func)
    def Func(*args):
        if len(args) != nargs:
            message = "%s takes exactly %i arguments (%i given)" % (server_func, nargs, len(args))
            raise TypeError(message)
        if docstr is not None:
            Func.__doc__ = docstr
        cmd = createCommand(server_func, *args)
        result = getCommandResult(cmd)
        return result
    return Func
def createFunction(server_func, docstr=None):
    def initialFunc(*args):
        initalFunc = _createFunction(server_func, docstr)
        return initalFunc(*args)
    return initialFunc
# define our client-side functions below
getRandLC = createFunction("randLC",
                           """
args: None
returns:
    filename, redshift, data (tuple):
        filename (str): name of the file on disk
        redshift (float): redshift of the object
        data (numpy structure array): structured array of the data from the LC file
""")
getLC = createFunction("getLC",
                       """
args:
    ID (str): SDSS J2000 name
returns:
    filename, redshift, data (tuple):
        filename (str): name of the file on disk
        redshift (float): redshift of the object
        data (numpy structure array): structured array of the data from the LC file
""")
getIDList = createFunction("IDList",
                           """
args: None
returns:
    IDList (list): List of strings of SDSS Objects names on disk
""")
getNearestLC = createFunction('getNearestLC',
                              """
args:
    ID (str): SDSS J200 name
    tol (float): matching tolerance in degrees
returns:
    filename, reshift, data (tuple):
        see above
""")
if __name__ == '__main__':
    import sys
    if len(sys.argv) == 1:
        print "Test"
    if sys.argv[1] == '--check':
        for name in sys.argv[2:]:
            try:
                getNearestLC(name, 2/60.0/60.0)
            except SDSSError as e:
                if 'No objects in list' in e.message:
                    print "LC does not exist in data base", 0, name
            except IndexError as e:
                print "No File Specified"
            else:
                print "LC does exist in database     ", 1, name
    elif sys.argv[1] == '--rand':
        print getRandLC()


Answer:     elif sys.argv[1] == '--list':