script/lib/tweetstream/servercontext.py
author Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
Tue, 18 Jan 2011 18:25:18 +0100
changeset 12 4daf47fcf792
permissions -rw-r--r--
move lib and prepare tweetstream for modification
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     1
import threading
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     2
import contextlib
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     3
import time
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     4
import os
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     5
import socket
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     6
import random
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     7
from functools import partial
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     8
from inspect import isclass
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
     9
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    10
from SimpleHTTPServer import SimpleHTTPRequestHandler
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    11
from SocketServer import BaseRequestHandler
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    12
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    13
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    14
class ServerError(Exception):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    15
    pass
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    16
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    17
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    18
class ServerContext(object):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    19
    """Context object with information about a running test server."""
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    20
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    21
    def __init__(self, address, port):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    22
        self.address = address or "localhost"
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    23
        self.port = port
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    24
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    25
    @property
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    26
    def baseurl(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    27
        return "http://%s:%s" % (self.address, self.port)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    28
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    29
    def __str__(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    30
        return "<ServerContext %s >" % self.baseurl
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    31
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    32
    __repr__ = __str__
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    33
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    34
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    35
class _SilentSimpleHTTPRequestHandler(SimpleHTTPRequestHandler):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    36
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    37
    def __init__(self, *args, **kwargs):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    38
        self.logging = kwargs.get("logging", False)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    39
        SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    40
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    41
    def log_message(self, *args, **kwargs):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    42
        if self.logging:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    43
            SimpleHTTPRequestHandler.log_message(self, *args, **kwargs)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    44
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    45
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    46
class _TestHandler(BaseHTTPRequestHandler):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    47
    """RequestHandler class that handles requests that use a custom handler
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    48
    callable."""
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    49
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    50
    def __init__(self, handler, methods, *args, **kwargs):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    51
        self._handler = handler
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    52
        self._methods = methods
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    53
        self._response_sent = False
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    54
        self._headers_sent = False
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    55
        self.logging = kwargs.get("logging", False)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    56
        BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    57
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    58
    def log_message(self, *args, **kwargs):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    59
        if self.logging:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    60
            BaseHTTPRequestHandler.log_message(self, *args, **kwargs)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    61
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    62
    def send_response(self, *args, **kwargs):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    63
        self._response_sent = True
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    64
        BaseHTTPRequestHandler.send_response(self, *args, **kwargs)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    65
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    66
    def end_headers(self, *args, **kwargs):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    67
        self._headers_sent = True
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    68
        BaseHTTPRequestHandler.end_headers(self, *args, **kwargs)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    69
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    70
    def _do_whatever(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    71
        """Called in place of do_METHOD"""
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    72
        data = self._handler(self)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    73
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    74
        if hasattr(data, "next"):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    75
            # assume it's something supporting generator protocol
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    76
            self._handle_with_iterator(data)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    77
        else:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    78
            # Nothing more to do then.
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    79
            pass
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    80
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    81
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    82
    def __getattr__(self, name):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    83
        if name.startswith("do_") and name[3:].lower() in self._methods:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    84
            return self._do_whatever
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    85
        else:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    86
            # fixme instance or class?
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    87
            raise AttributeError(name)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    88
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    89
    def _handle_with_iterator(self, iterator):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    90
        self.connection.settimeout(0.1)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    91
        for data in iterator:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    92
            if not self.server.server_thread.running:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    93
                return
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    94
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    95
            if not self._response_sent:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    96
                self.send_response(200)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    97
            if not self._headers_sent:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    98
                self.end_headers()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
    99
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   100
            self.wfile.write(data)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   101
            # flush immediatly. We may want to do trickling writes
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   102
            # or something else tha trequires bypassing normal caching
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   103
            self.wfile.flush()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   104
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   105
class _TestServerThread(threading.Thread):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   106
    """Thread class for a running test server"""
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   107
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   108
    def __init__(self, handler, methods, cwd, port, address):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   109
        threading.Thread.__init__(self)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   110
        self.startup_finished = threading.Event()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   111
        self._methods = methods
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   112
        self._cwd = cwd
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   113
        self._orig_cwd = None
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   114
        self._handler = self._wrap_handler(handler, methods)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   115
        self._setup()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   116
        self.running = True
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   117
        self.serverloc = (address, port)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   118
        self.error = None
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   119
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   120
    def _wrap_handler(self, handler, methods):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   121
        if isclass(handler) and issubclass(handler, BaseRequestHandler):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   122
            return handler # It's OK. user passed in a proper handler
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   123
        elif callable(handler):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   124
            return partial(_TestHandler, handler, methods)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   125
            # it's a callable, so wrap in a req handler
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   126
        else:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   127
            raise ServerError("handler must be callable or RequestHandler")
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   128
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   129
    def _setup(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   130
        if self._cwd != "./":
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   131
            self._orig_cwd = os.getcwd()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   132
            os.chdir(self._cwd)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   133
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   134
    def _init_server(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   135
        """Hooks up the server socket"""
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   136
        try:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   137
            if self.serverloc[1] == "random":
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   138
                retries = 10 # try getting an available port max this many times
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   139
                while True:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   140
                    try:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   141
                        self.serverloc = (self.serverloc[0],
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   142
                                          random.randint(1025, 49151))
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   143
                        self._server = HTTPServer(self.serverloc, self._handler)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   144
                    except socket.error:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   145
                        retries -= 1
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   146
                        if not retries: # not able to get a port.
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   147
                            raise
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   148
                    else:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   149
                        break
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   150
            else: # use specific port. this might throw, that's expected
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   151
                self._server = HTTPServer(self.serverloc, self._handler)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   152
        except socket.error, e:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   153
            self.running = False
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   154
            self.error = e
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   155
            # set this here, since we'll never enter the serve loop where
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   156
            # it is usually set:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   157
            self.startup_finished.set()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   158
            return
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   159
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   160
        self._server.allow_reuse_address = True # lots of tests, same port
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   161
        self._server.timeout = 0.1
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   162
        self._server.server_thread = self
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   163
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   164
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   165
    def run(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   166
        self._init_server()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   167
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   168
        while self.running:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   169
            self._server.handle_request() # blocks for self.timeout secs
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   170
            # First time this falls through, signal the parent thread that
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   171
            # the server is ready for incomming connections
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   172
            if not self.startup_finished.is_set():
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   173
                self.startup_finished.set()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   174
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   175
        self._cleanup()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   176
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   177
    def stop(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   178
        """Stop the server and attempt to make the thread terminate.
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   179
        This happens async but the calling code can check periodically
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   180
        the isRunning flag on the thread object.
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   181
        """
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   182
        # actual stopping happens in the run method
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   183
        self.running = False
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   184
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   185
    def _cleanup(self):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   186
        """Do some rudimentary cleanup."""
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   187
        if self._orig_cwd:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   188
            os.chdir(self._orig_cwd)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   189
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   190
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   191
@contextlib.contextmanager
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   192
def test_server(handler=_SilentSimpleHTTPRequestHandler, port=8514,
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   193
                address="", methods=("get", "head"), cwd="./"):
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   194
    """Context that makes available a web server in a separate thread"""
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   195
    thread = _TestServerThread(handler=handler, methods=methods, cwd=cwd,
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   196
                               port=port, address=address)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   197
    thread.start()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   198
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   199
    # fixme: should this be daemonized? If it isn't it will block the entire
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   200
    # app, but that should never happen anyway..
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   201
    thread.startup_finished.wait()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   202
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   203
    if thread.error: # startup failed! Bail, throw whatever the server did
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   204
        raise thread.error
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   205
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   206
    exc = None
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   207
    try:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   208
        yield ServerContext(*thread.serverloc)
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   209
    except Exception, exc:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   210
        pass
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   211
    thread.stop()
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   212
    thread.join(5) # giving it a lot of leeway. should never happen
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   213
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   214
    if exc:
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   215
        raise exc
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   216
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   217
    # fixme: this takes second priorty after the internal exception but would
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   218
    # still be nice to signal back to calling code.
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   219
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   220
    if thread.isAlive():
4daf47fcf792 move lib and prepare tweetstream for modification
Yves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
parents:
diff changeset
   221
        raise Warning("Test server could not be stopped")