diff --git a/src/calibre/srv/http.py b/src/calibre/srv/http.py index 74d31aee59..41663062ae 100644 --- a/src/calibre/srv/http.py +++ b/src/calibre/srv/http.py @@ -260,7 +260,7 @@ class HTTPPair(object): ''' Represents a HTTP request/response pair ''' - def __init__(self, conn, handle_request): + def __init__(self, handle_request, conn): self.conn = conn self.server_loop = conn.server_loop self.max_header_line_size = self.server_loop.opts.max_header_line_size * 1024 @@ -522,3 +522,6 @@ class HTTPPair(object): def send_headers(self): self.sent_headers = True + +def create_http_handler(handle_request): + return partial(HTTPPair, handle_request) diff --git a/src/calibre/srv/loop.py b/src/calibre/srv/loop.py index d84102104f..aabac8034a 100644 --- a/src/calibre/srv/loop.py +++ b/src/calibre/srv/loop.py @@ -14,7 +14,7 @@ from io import DEFAULT_BUFFER_SIZE, BytesIO from calibre.srv.errors import NonHTTPConnRequest, MaxSizeExceeded from calibre.srv.http import http_communicate -from calibre.srv.opts import defaults +from calibre.srv.opts import Options from calibre.utils.socket_inheritance import set_socket_inherit from calibre.utils.logging import ThreadSafeLog @@ -337,7 +337,7 @@ class SocketFile(object): # {{{ # }}} -class Connection(object): +class Connection(object): # {{{ ' A thin wrapper around an active socket ' @@ -385,9 +385,9 @@ class Connection(object): def __exit__(self, *args): self.close() +# }}} - -class WorkerThread(Thread): +class WorkerThread(Thread): # {{{ daemon = True @@ -419,9 +419,9 @@ class WorkerThread(Thread): def __exit__(self, *args): self.serving = False +# }}} - -class ThreadPool(object): +class ThreadPool(object): # {{{ def __init__(self, server_loop, min_threads=10, max_threads=-1, accepted_queue_size=-1, accepted_queue_timeout=10): self.server_loop = server_loop @@ -514,7 +514,7 @@ class ThreadPool(object): @property def qsize(self): return self._queue.qsize() - +# }}} class ServerLoop(object): @@ -528,7 +528,7 @@ class ServerLoop(object): # stdout is used log=None ): - self.opts = opts or defaults + self.opts = opts or Options() if http_handler is None: def aborth(*args, **kwargs): raise NonHTTPConnRequest() @@ -546,6 +546,7 @@ class ServerLoop(object): # AI_PASSIVE does not work with host of '' or None ba = ('0.0.0.0', ba[1]) self.bind_address = ba + self.bound_address = None self.ssl_context = None if self.opts.ssl_certfile is not None and self.opts.ssl_keyfile is not None: self.ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) @@ -628,7 +629,7 @@ class ServerLoop(object): # Timeout so KeyboardInterrupt can be caught on Win32 self.socket.settimeout(1) self.socket.listen(self.opts.request_queue_size) - ba = self.bind_address + self.bound_address = ba = self.socket.getsockname() if isinstance(ba, tuple): ba = ':'.join(map(type(''), ba)) self.log('calibre server listening on', ba) diff --git a/src/calibre/srv/opts.py b/src/calibre/srv/opts.py index 034501f63a..38cfc8ed90 100644 --- a/src/calibre/srv/opts.py +++ b/src/calibre/srv/opts.py @@ -6,7 +6,8 @@ from __future__ import (unicode_literals, division, absolute_import, __license__ = 'GPL v3' __copyright__ = '2015, Kovid Goyal ' -from collections import namedtuple +from collections import namedtuple, OrderedDict +from operator import attrgetter Option = namedtuple('Option', 'name default longdoc shortdoc choices') @@ -76,7 +77,13 @@ while i + 3 < len(raw_options): choices = default default = default.default options.append(Option(name, default, doc, shortdoc, choices)) -options = tuple(options) +options = OrderedDict([(o.name, o) for o in sorted(options, key=attrgetter('name'))]) del raw_options -defaults = namedtuple('Defaults', ' '.join(o.name for o in options))(*tuple(o.default for o in options)) +class Options(object): + + __slots__ = tuple(name for name in options) + + def __init__(self, **kwargs): + for opt in options.itervalues(): + setattr(self, opt.name, kwargs.get(opt.name, opt.default))