def start(self, mode):
        """
            In CLIENT_MODE:

                Establish a connection with the server before sending a new message.

            In SERVER_MODE:

                Start listening to the incoming messages from the clients.

        :param mode: (int) Either CLIENT_MODE or SERVER_MODE.
        :return: None
        """
        address = 'tcp://{}:{}'.format(self.ip, self.port)

        if mode == CLIENT_MODE:
            self.mode = mode
            self.logger.info(
                "Starting Scoreboard Client listening on {}:{} ...".format(
                    self.ip, self.port))
            self.instance = Proxy(address)

        elif mode == SERVER_MODE:
            self.mode = mode
            self.scoreboard = Scoreboard()
            server = Server(self, address)
            self.logger.info(
                "Starting Scoreboard Server listening on {}:{} ...".format(
                    self.ip, self.port))
            server.serve_forever()
Exemple #2
0
    def test_signal_two_proxies(self):

        address = 'tcp://127.0.0.1:6009'

        s = Server(Example(), rep_endpoint=address)

        proxy1 = Proxy(address)
        proxy2 = Proxy(address)

        class MemMethod(object):

            def __init__(self_):
                self_.called = 0

            def __call__(self_, value, old_value, others):
                self_.called += 1

        fun = MemMethod()

        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)
        proxy2.rw_prop_changed.connect(fun)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy1.p = 28

        proxy1._proxy_stop_server()
        proxy1._proxy_stop_me()
        proxy2._proxy_stop_me()
Exemple #3
0
    def test_signal(self):

        address = 'tcp://127.0.0.1:6008'

        s = Server(Example(), rep_endpoint=address)

        proxy = Proxy(address)

        class MemMethod(object):
            def __init__(self_):
                self_.called = 0

            def __call__(self_, value, old_value, others):
                self_.called += 1

        fun1 = MemMethod()
        self.assertEqual(fun1.called, 0)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)
        proxy.rw_prop_changed.connect(fun1)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop = 28
        time.sleep(SLEEP_SECS)
        self.assertEqual(proxy.rw_prop, 28)
        self.assertEqual(fun1.called, 1)

        fun2 = MemMethod()
        self.assertEqual(fun2.called, 0)
        proxy.rw_prop_changed.connect(fun2)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop = 29
        time.sleep(SLEEP_SECS)
        self.assertEqual(proxy.rw_prop, 29)
        self.assertEqual(fun1.called, 2)
        self.assertEqual(fun2.called, 1)

        proxy.rw_prop_changed.disconnect(fun1)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop = 30
        self.assertEqual(fun1.called, 2)

        proxy.rw_prop_changed.disconnect(fun2)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)

        proxy.rw_prop_changed.connect(fun1)
        proxy.rw_prop_changed.connect(fun2)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop_changed.disconnect(None)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)

        proxy._proxy_stop_server()
        proxy._proxy_stop_me()
Exemple #4
0
    def test_signal(self):

        address = 'tcp://127.0.0.1:6008'

        s = Server(Example(), rep_endpoint=address)

        proxy = Proxy(address)

        class MemMethod(object):

            def __init__(self_):
                self_.called = 0

            def __call__(self_, value, old_value, others):
                self_.called += 1


        fun1 = MemMethod()
        self.assertEqual(fun1.called, 0)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)
        proxy.rw_prop_changed.connect(fun1)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop = 28
        time.sleep(SLEEP_SECS)
        self.assertEqual(proxy.rw_prop, 28)
        self.assertEqual(fun1.called, 1)

        fun2 = MemMethod()
        self.assertEqual(fun2.called, 0)
        proxy.rw_prop_changed.connect(fun2)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop = 29
        time.sleep(SLEEP_SECS)
        self.assertEqual(proxy.rw_prop, 29)
        self.assertEqual(fun1.called, 2)
        self.assertEqual(fun2.called, 1)

        proxy.rw_prop_changed.disconnect(fun1)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop = 30
        self.assertEqual(fun1.called, 2)

        proxy.rw_prop_changed.disconnect(fun2)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)

        proxy.rw_prop_changed.connect(fun1)
        proxy.rw_prop_changed.connect(fun2)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy.rw_prop_changed.disconnect(None)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)

        proxy._proxy_stop_server()
        proxy._proxy_stop_me()
Exemple #5
0
def get_mmvt_object(subject):
    mmvt = None
    pizco_log_fname = op.join(get_mmvt_dir(), subject, 'logs', 'pizco.log')
    waits_for_file(pizco_log_fname)
    with open(pizco_log_fname, 'r') as log:
        pizco_address = log.read()
    try:
        from pizco import Proxy
        devnull = open(os.devnull, 'w')
        with RedirectStdStreams(stdout=devnull, stderr=devnull):
            mmvt = Proxy(pizco_address)
    except:
        pass
    return mmvt
Exemple #6
0
    def test_server_return_dict(self):

        s = ReturnDictsServer(Example())

        proxy = Proxy(s.rep_endpoint)

        self.assertEqual(s.served_object.dict_attribute[1], 2)
        self.assertEqual(s.served_object.dict_attribute, {1: 2})
        self.assertEqual(proxy.dict_attribute[1], 2)
        self.assertEqual(proxy.dict_attribute, {1: 2})

        # This should not work as the dictionary is not remotely linked
        proxy.dict_attribute[2] = 4
        self.assertEqual(s.served_object.dict_attribute, {1: 2})

        proxy._proxy_stop_server()
        proxy._proxy_stop_me()
Exemple #7
0
    def test_future(self):

        s = Server(Example())

        proxy = Proxy(s.rep_endpoint)

        fut = proxy.fut()
        self.assertEqual(fut.result(), 10)

        fut = proxy.fut_raise()
        self.assertIsInstance(fut.exception(), ValueError)

        fut = proxy.fut_raise()
        self.assertRaises(ValueError, fut.result)

        proxy._proxy_stop_me()
        s.stop()
Exemple #8
0
    def test_future(self):

        s = Server(Example())

        proxy = Proxy(s.rep_endpoint)

        fut = proxy.fut()
        self.assertEqual(fut.result(), 10)

        fut = proxy.fut_raise()
        self.assertIsInstance(fut.exception(), ValueError)

        fut = proxy.fut_raise()
        self.assertRaises(ValueError, fut.result)

        proxy._proxy_stop_me()
        s.stop()
Exemple #9
0
    def test_server_return_dict(self):

        s = ReturnDictsServer(Example())

        proxy = Proxy(s.rep_endpoint)

        self.assertEqual(s.served_object.dict_attribute[1], 2)
        self.assertEqual(s.served_object.dict_attribute, {1: 2})
        self.assertEqual(proxy.dict_attribute[1], 2)
        self.assertEqual(proxy.dict_attribute, {1: 2})

        # This should not work as the dictionary is not remotely linked
        proxy.dict_attribute[2] = 4
        self.assertEqual(s.served_object.dict_attribute, {1: 2})

        proxy._proxy_stop_server()
        proxy._proxy_stop_me()
Exemple #10
0
# -*- coding: utf-8 -*-

import sys
import time
import random

if sys.version_info < (3,0):
    input = raw_input

from pizco import Proxy

proxy = Proxy('tcp://127.0.0.1:8000')

colors = ('green', 'blue', 'white', 'yellow')

while True:
    input('Press enter to run ...\n')
    proxy.door_open = True
    proxy.lights_on = True
    time.sleep(.1)
    proxy.paint(random.choice(colors))
    proxy.lights_on = False
    proxy.door_open = False
Exemple #11
0
        self.layout3 = QHBoxLayout()
        self.label3 = QLabel()
        self.label3.setMinimumSize(QSize(100, 0))
        self.label3.setText('Color:')
        self.color = QLineEdit()
        self.color.setReadOnly(True)
        self.color.textChanged.connect(self.on_color_text_changed)
        self.color_box = QLabel()
        self.color_box.setText('  ')
        self.layout3.addWidget(self.label3)
        self.layout3.addWidget(self.color)
        self.layout3.addWidget(self.color_box)

        self.lights.stateChanged.connect(self.on_lights_on_changed)
        self.door_open.stateChanged.connect(self.on_door_open_changed)

        self.layout.addLayout(self.layout1)
        self.layout.addLayout(self.layout2)
        self.layout.addLayout(self.layout3)


if __name__ == "__main__":
    proxy = Proxy('tcp://127.0.0.1:8000')
    app = QtGui.QApplication(sys.argv)
    main = ControlForm(proxy)
    main.show()
    if sys.platform.startswith('darwin'):
        main.raise_()
    sys.exit(app.exec_())
Exemple #12
0
# -*- coding: utf-8 -*-

import sys
import time

if sys.version_info < (3, 0):
    input = raw_input

from pizco import Proxy

proxy = Proxy('tcp://127.0.0.1:8000')

while True:
    input('Press enter to run ...\n')
    fut = proxy.change_roof()
    print('I am doing something while changing the roof')
    print('The door is open?: {}'.format(proxy.door_open))
    print('The lights are on?: {}'.format(proxy.lights_on))
    print('I have finished doing this and now I will wait for the result')
    print(fut.result())
# -*- coding: utf-8 -*-
from __future__ import print_function

import sys
import time

if sys.version_info < (3,0):
    input = raw_input

from pizco import Proxy

proxy = Proxy('tcp://127.0.0.1:8000')

while True:
    try:
        proxy.paint(input('New color for the house: '))
    except ValueError as ex:
        print('Oops!')
        print(ex)
Exemple #14
0
# -*- coding: utf-8 -*-

import sys
import time

if sys.version_info < (3,0):
    input = raw_input

from pizco import Proxy

proxy = Proxy('tcp://127.0.0.1:8000')

while True:
    input('Press enter to run ...\n')
    fut = proxy.change_roof()
    print('I am doing something while changing the roof')
    print('The door is open?: {}'.format(proxy.door_open))
    print('The lights are on?: {}'.format(proxy.lights_on))
    print('I have finished doing this and now I will wait for the result')
    print(fut.result())

Exemple #15
0
    def test_server_no_inspect(self):

        s = NoInspectServer(Example())

        proxy = Proxy(s.rep_endpoint)
        self.assertEqual(s.served_object.simple_attribute, 12)
        self.assertEqual(proxy.simple_attribute, 12)
        proxy.simple_attribute = 24
        self.assertEqual(s.served_object.simple_attribute, 24)
        self.assertEqual(proxy.simple_attribute, 24)

        self.assertRaises(AttributeError, getattr, proxy, 'not_an_attribute')

        self.assertEqual(s.served_object.dict_attribute[1], 2)
        self.assertEqual(proxy.dict_attribute[1], 2)
        self.assertRaises(KeyError, operator.getitem, proxy.dict_attribute, 2)
        print(proxy.dict_attribute)
        proxy.dict_attribute[2] = 4
        self.assertEqual(s.served_object.dict_attribute[2], 4)
        self.assertEqual(proxy.dict_attribute[2], 4)

        self.assertEqual(s.served_object.rw_prop, 42)
        self.assertEqual(proxy.rw_prop, 42)
        proxy.rw_prop = 21
        self.assertEqual(s.served_object.rw_prop, 21)
        self.assertEqual(proxy.rw_prop, 21)

        self.assertEqual(proxy.fun_simple(), 46)
        self.assertEqual(proxy.fun_arg1(2), 4)
        self.assertEqual(proxy.fun_arg2(2, 3), 8)
        self.assertEqual(proxy.fun_arg2(y=2), 4)

        self.assertRaises(ValueError, proxy.fun_raise)

        proxy._proxy_stop_server()
        proxy._proxy_stop_me()
class ScoreboardWrapper():
    """
        Wraps the Scoreboard into two types of remotely accessible components:

            * Server: wraps a real in-memory instance of the Scoreboard and exposes it via a ZMQ socket.
            * Client: connects to a server, redirects attribute request to it, and collect the response.

        Using this kind of wrapper we can easily implement a multiprocess scoreboardwrapper in which multiple clients,
        each one in a different process, listen to a the HTTP RESTful API that the clients will use to access the
        scoreboard. Besides the multiple clients (as many as allowed by the underlying hardware) there will be a single
        server instance, that receives clients communications and keeps the unique and shared Scoreboard instance.

        This is the typical type of situation in which we have to make a commitment in terms of latency. The scalability
        of the final architecture is hindered by the need of keeping the Scoreboard Data Consistency (SDC). The more
        scalable the architecture the harder to keep the SDC. The proposed architecture is the straighforward initial
        approach, that gets rid of the SDC problem by having a single and centralized server that manages the shared
        scoreboard data. Obviously, this makes the server the critical piece of the architecture in terms of latency,
        since all requests must be attended by the same process.

        If the language allows simultaneous execution of multiple threads (Python does not due to the GIL, or Global
        Interpreter Lock), the next straightforward step towards increasing the scalability would be to make the server
        thread-safe and allow multiple read threads plus a single write thread, to simultaneously run on the same
        server. This is implemented using mutual exclusion (mutex) tools (e.g. semaphores) to protect the critical
        section (i.e., the shared data). Read operations, such as Top100, Top200, Top500, and At100/3, can be done
        simultaneously (one per thread). There will be as many simultaneous threads as allowed by the underlying
        hardware. However, whenever a user reported a new score, regardless of it was either absolute or relative, it
        must be assured that no other thread is within the critical section (unless we follow a policy that does not
        need to report 100% accurate scores on each read).

        The next step towards increasing the scalability of our architecture, that is to reduce the latency, would need
        some kind of partition of the single server to allow accessing it in less time. That kind of vertical
        scalability solution would require adding some kind of scheduling mechanism to properly orchestrate all the
        server partitions to keep SDC yielding better performance, in terms of lower latencies.

        In order not to end up with a overdesign situation, the steps towards the scalability of our architecture should
        be guided by a performance analysis, measuring the latency of one step before taking the decision to go for the
        next one. Take into account that the more steps taken the more complexity in our final design, and therefore
        the less maintainable.

    """
    def __init__(self, port=DEFAULT_PORT, ip=DEFAULT_IP, elogger=logger):
        self.ip = ip
        self.port = port
        self.logger = elogger
        self.mode = None
        self.instance = None  # Server or Proxy, according to mode
        self.scoreboard = None  # The in-memory scoreboard (only in the server)

    def is_valid_info(self, client_info):
        """
            True if the format of the specified client info is as expected.

        :param client_info: (dict) The client info to be checked. The Valid format is:

                    {"user": <client_id>, ("total": <total_score>|"score": <relative_score>)}

                where:
                        <client_id> : (int) Id of the client.
                        <total_score>: (int) Absolute score of the client.
                        <relative_score>: (int) Relative score of the client.

                Examples:

                            {"user": 123, "total": 250}
                            {"user": 456, "score": "+10"}
                            {"user": 789, "score": "-20"}
        :return:
        """
        result = False

        try:
            if isinstance(client_info,
                          dict) and len(client_info) == 2 and isinstance(
                              client_info["user"], int):
                try:
                    if isinstance(client_info["total"], int):
                        result = True

                except KeyError:
                    # There is no "total" (absolute). Try with "score" (relative)

                    if isinstance(client_info["score"],
                                  str) and (client_info["score"][0] == '+'
                                            or client_info["score"][0] == '-'):
                        value = int(client_info["score"][1:])
                        if value >= 0:
                            result = True

        except (TypeError, KeyError, ValueError):
            pass

        return result

    def start(self, mode):
        """
            In CLIENT_MODE:

                Establish a connection with the server before sending a new message.

            In SERVER_MODE:

                Start listening to the incoming messages from the clients.

        :param mode: (int) Either CLIENT_MODE or SERVER_MODE.
        :return: None
        """
        address = 'tcp://{}:{}'.format(self.ip, self.port)

        if mode == CLIENT_MODE:
            self.mode = mode
            self.logger.info(
                "Starting Scoreboard Client listening on {}:{} ...".format(
                    self.ip, self.port))
            self.instance = Proxy(address)

        elif mode == SERVER_MODE:
            self.mode = mode
            self.scoreboard = Scoreboard()
            server = Server(self, address)
            self.logger.info(
                "Starting Scoreboard Server listening on {}:{} ...".format(
                    self.ip, self.port))
            server.serve_forever()

    def reset(self):
        """

            Resets the info in the server.

        :return: None
        """
        if self.mode == SERVER_MODE:
            self.scoreboard.reset()
            self.logger.debug("Server Scoreboard reset")

        elif self.mode == CLIENT_MODE:
            self.instance.reset()
            self.logger.debug("Client Scoreboard reset (sent to server)")

    def update(self, client_info):
        """
            In CLIENT_MODE:

                Sends updated client score to the shared Scoreboard.

            In SERVER_MODE:

                Updates the client score and sends back the updated client score to the client.

        :param client_info: (dict) A JSON submitted by the client, as specified in the Code Challenge:

                Examples:

                            {"user": 123, "total": 250}
                            {"user": 456, "score": "+10"}
                            {"user": 789, "score": "-20"}

        :return: (dict) The updated client score.
        """
        if self.mode == SERVER_MODE:
            if isinstance(client_info, str):
                client_info = loads(client_info)
            self.scoreboard.update(client_info)
            client = self.scoreboard.get(client_info["user"])
            result = {"user": client.id, "total": client.score}
            self.logger.debug("Server Scoreboard updated : {}".format(result))
            result = dumps(result)

        elif self.mode == CLIENT_MODE and self.is_valid_info(client_info):
            result = self.instance.update(dumps(client_info))
            self.logger.debug(
                "Client Scoreboard obtained update response from server : {}".
                format(result))
            result = loads(result)

        else:
            result = {"error": "Invalid client info"}

        return result

    def top(self, top_size):
        """
            Asks the shared Scoreboard for the clients that occupy the specified number of top ranking positions
            (i.e., those with the higher score values), according to the absolute ranking.

        :param top_size: (int) Number of higher ranking positions to retrieve.
        :return: (list of dict) The clients that occupies the specified ranking positions.
        """
        if self.mode == SERVER_MODE:
            result = self.scoreboard.top(int(top_size))

            # Serialize to stringified JSON to be sent to the client
            # From list of tuples to list of dicts
            serial_result = []
            for client in result:
                serial_result.append(client.to_json())
            self.logger.debug("Server Scoreboard top ({}) : {}".format(
                top_size, result))
            result = dumps(serial_result)

        elif self.mode == CLIENT_MODE and isinstance(top_size, int):
            result = self.instance.top(str(top_size))
            self.logger.debug("Client Scoreboard top ({}) : {}".format(
                top_size, result))
            result = loads(result)

        else:
            result = {"error": "Invalid top size"}

        return result

    def relative_top(self, ranking_position, scope_size):
        """
            Asks the shared Scoreboard for the relative top (see Scoreboard.relative_top)

        :param ranking_position: (int) Ranking position to retrieve scope around. Must be a positive value, from 1 to N.
        :param scope_size: (int) Scope size (see explanation above). Must be a positive value.
        :return: (list of dict) The clients that occupies the specified ranking positions.
        """
        if self.mode == SERVER_MODE:
            result = self.scoreboard.relative_top(int(ranking_position),
                                                  int(scope_size))

            # Serialize to stringified JSON to be sent to the client
            # From list of tuples to list of dicts
            serial_result = []
            for client in result:
                serial_result.append(client.to_json())
            self.logger.debug(
                "Server Scoreboard relative top ({}, {}) : {}".format(
                    ranking_position, scope_size, result))
            result = dumps(serial_result)

        elif self.mode == CLIENT_MODE and isinstance(
                ranking_position, int) and isinstance(scope_size, int):
            result = self.instance.relative_top(str(ranking_position),
                                                str(scope_size))
            self.logger.debug(
                "Client Scoreboard relative top ({}, {}) : {}".format(
                    ranking_position, scope_size, result))
            result = loads(result)

        else:
            result = {"error": "Invalid ranking_position, scope_size values"}

        return result
Exemple #17
0
    def test_signal_two_proxies(self):

        address = 'tcp://127.0.0.1:6009'

        s = Server(Example(), rep_endpoint=address)

        proxy1 = Proxy(address)
        proxy2 = Proxy(address)

        class MemMethod(object):
            def __init__(self_):
                self_.called = 0

            def __call__(self_, value, old_value, others):
                self_.called += 1

        fun = MemMethod()

        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 0)
        proxy2.rw_prop_changed.connect(fun)
        time.sleep(SLEEP_SECS)
        self.assertEqual(len(s.served_object.rw_prop_changed.slots), 1)
        proxy1.p = 28

        proxy1._proxy_stop_server()
        proxy1._proxy_stop_me()
        proxy2._proxy_stop_me()
Exemple #18
0
import os
import os.path as op
from pizco import Proxy

os.chdir(os.environ['MMVT_CODE'])
from src.mmvt_addon.scripts import run_mmvt
from src.utils import utils

subject, atlas = 'DC', 'laus250'
run_mmvt.run(subject, atlas, run_in_background=False, debug=False)
mmvt = Proxy('tcp://127.0.0.1:8001')
meg_dir = utils.get_link_dir(utils.get_links_dir(), 'meg')
stc_fname = op.join(meg_dir, subject, 'left-MNE-1-15-lh.stc')
mmvt.plot_stc(stc_fname, 1270, threshold=0.1)
Exemple #19
0
    def test_server_no_inspect(self):

        s = NoInspectServer(Example())

        proxy = Proxy(s.rep_endpoint)
        self.assertEqual(s.served_object.simple_attribute, 12)
        self.assertEqual(proxy.simple_attribute, 12)
        proxy.simple_attribute = 24
        self.assertEqual(s.served_object.simple_attribute, 24)
        self.assertEqual(proxy.simple_attribute, 24)

        self.assertRaises(AttributeError, getattr, proxy, 'not_an_attribute')

        self.assertEqual(s.served_object.dict_attribute[1], 2)
        self.assertEqual(proxy.dict_attribute[1], 2)
        self.assertRaises(KeyError, operator.getitem, proxy.dict_attribute, 2)
        print(proxy.dict_attribute)
        proxy.dict_attribute[2] = 4
        self.assertEqual(s.served_object.dict_attribute[2], 4)
        self.assertEqual(proxy.dict_attribute[2], 4)

        self.assertEqual(s.served_object.rw_prop, 42)
        self.assertEqual(proxy.rw_prop, 42)
        proxy.rw_prop = 21
        self.assertEqual(s.served_object.rw_prop, 21)
        self.assertEqual(proxy.rw_prop, 21)

        self.assertEqual(proxy.fun_simple(), 46)
        self.assertEqual(proxy.fun_arg1(2), 4)
        self.assertEqual(proxy.fun_arg2(2, 3), 8)
        self.assertEqual(proxy.fun_arg2(y=2), 4)

        self.assertRaises(ValueError, proxy.fun_raise)

        proxy._proxy_stop_server()
        proxy._proxy_stop_me()
Exemple #20
0
# -*- coding: utf-8 -*-
from __future__ import print_function

import sys
import time

if sys.version_info < (3, 0):
    input = raw_input

from pizco import Proxy

proxy = Proxy('tcp://127.0.0.1:8000')

while True:
    try:
        proxy.paint(input('New color for the house: '))
    except ValueError as ex:
        print('Oops!')
        print(ex)