class BuildTest(TestCase):
    def setUp(self):
        self.t = Translator()

    def test_no_arguments(self):
        output = self.t.build_hit()
        self.assertEqual(b'HIT\n', output)

    def test_single_argument(self):
        output = self.t.build_hit(method="GET")
        self.assertEqual(b'HIT "method"="GET"\n', output)

    def test_multiple_arguments(self):
        output = self.t.build_hit(path="/cookies", method="GET")
        self.assertEqual(b'HIT "method"="GET" "path"="/cookies"\n', output)

    def test_coerced_arguments(self):
        output = self.t.build_hit(b=True, f=3.1416, i=-65535)
        self.assertEqual(b'HIT "b"="True" "f"="3.1416" "i"="-65535"\n', output)

    def test_special_keys(self):
        kwargs = {'Arg+1': 1, 'arg-*': '*'}
        output = self.t.build_hit(**kwargs)
        self.assertEqual(b'HIT "Arg+1"="1" "arg-*"="*"\n', output)

    def test_encoding(self):
        output = self.t.build_hit(happy_face=u'\U0001f604')
        self.assertEqual(b'HIT "happy_face"="\xf0\x9f\x98\x84"\n', output)

    def test_invalid_key(self):
        kwargs = {'Arg 3': 3}
        self.assertRaises(InputError, self.t.build_hit, **kwargs)

    def test_invalid_value(self):
        self.assertRaises(InputError, self.t.build_hit, method="GET PUT")
Ejemplo n.º 2
0
class DivvyClient(object):
    def __init__(self,
                 host='localhost',
                 port=8321,
                 socket_timeout=1,
                 socket_connect_timeout=1,
                 socket_keepalive=False,
                 socket_keepalive_options=None,
                 socket_type=0,
                 retry_on_timeout=False,
                 encoding='utf-8'):
        self.host = host
        self.port = port
        self.translator = Translator(encoding=encoding)
        self.connection = Connection(
            host=host,
            port=port,
            socket_timeout=socket_timeout,
            socket_connect_timeout=socket_connect_timeout,
            socket_keepalive=socket_keepalive,
            socket_keepalive_options=socket_keepalive_options,
            socket_type=socket_type,
            retry_on_timeout=retry_on_timeout)

    def check_rate_limit(self, **kwargs):
        """Perform a check-and-decrement of quota. Zero or more key-value pairs
        specify the operation being performed, and will be evaluated by the
        server against its configuration.

        Args:
             **kwargs: Zero or more key-value pairs to specify the operation
                being performed, which will be evaluated by the server against
                its configuration.

        Returns:
            divvy.Response, a namedtuple with these fields:
                is_allowed: one of true, false, indicating whether quota was
                    available.
                current_credit: number of credit(s) available at the end of
                    this command.
                next_reset_seconds: time, in seconds, until credit next resets.
        """
        cmd = self.translator.build_hit(**kwargs)
        self.connection.send(cmd)

        reply = self.connection.recv()
        response = self.translator.parse_reply(reply)
        return response
Ejemplo n.º 3
0
class DivvyProtocol(LineOnlyReceiver, TimeoutMixin, object):
    """
    Twisted handler for network communication with a Divvy server.
    """

    delimiter = "\n"

    def __init__(self, timeout=1.0, encoding='utf-8'):
        super(DivvyProtocol, self).__init__()
        self.timeout = timeout
        self.translator = Translator(encoding)
        self.deferred = None

    def timeoutConnection(self):
        TimeoutMixin.timeoutConnection(self)
        # self.deferred should be present whenever this method is
        # called, but let's program defensively and double-check.
        if self.deferred:
            self.deferred.errback(TimeoutError())

    def checkRateLimit(self, **kwargs):
        assert self.connected
        assert self.deferred is None
        self.deferred = Deferred()
        line = self.translator.build_hit(**kwargs).strip()
        self.sendLine(line)
        self.setTimeout(self.timeout)

        return self.deferred

    def lineReceived(self, line):
        self.setTimeout(None)

        # we should never receive a line if there's no outstanding request
        assert self.deferred is not None

        try:
            response = self.translator.parse_reply(line)
            self.deferred.callback(response)
        except Exception as e:
            self.deferred.errback(e)
        finally:
            self.transport.loseConnection()
            self.deferred = None