Flask update

This commit is contained in:
Ruud committed 2012-01-06 17:09:44 +01:00
1 parent 168a9a2f95
commit f7d72dd5a9
114 files changed
+1540 -3835

No files matched your search

Regular → Executable
+100 -35
View File
@@ -35,6 +35,8 @@
:copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import with_statement
import os
import socket
import sys
@@ -177,6 +179,7 @@ class WSGIRequestHandler(BaseHTTPRequestHandler, object):
def handle(self):
"""Handles a request ignoring dropped connections."""
rv = None
try:
rv = BaseHTTPRequestHandler.handle(self)
except (socket.error, socket.timeout), e:
@@ -192,9 +195,11 @@ class WSGIRequestHandler(BaseHTTPRequestHandler, object):
"""A horrible, horrible way to kill the server for Python 2.6 and
later. It's the best we can do.
"""
# Windows does not provide SIGKILL, go with SIGTERM then.
sig = getattr(signal, 'SIGKILL', signal.SIGTERM)
# reloader active
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
os.kill(os.getpid(), signal.SIGKILL)
os.kill(os.getpid(), sig)
# python 2.7
self.server._BaseServer__shutdown_request = True
# python 2.6
@@ -247,10 +252,13 @@ class WSGIRequestHandler(BaseHTTPRequestHandler, object):
BaseRequestHandler = WSGIRequestHandler
def generate_adhoc_ssl_context():
"""Generates an adhoc SSL context for the development server."""
def generate_adhoc_ssl_pair(cn=None):
from random import random
from OpenSSL import crypto, SSL
from OpenSSL import crypto
# pretty damn sure that this is not actually accepted by anyone
if cn is None:
cn = '*'
cert = crypto.X509()
cert.set_serial_number(int(random() * sys.maxint))
@@ -258,7 +266,7 @@ def generate_adhoc_ssl_context():
cert.gmtime_adj_notAfter(60 * 60 * 24 * 365)
subject = cert.get_subject()
subject.CN = '*'
subject.CN = cn
subject.O = 'Dummy Certificate'
issuer = cert.get_issuer()
@@ -270,10 +278,59 @@ def generate_adhoc_ssl_context():
cert.set_pubkey(pkey)
cert.sign(pkey, 'md5')
return cert, pkey
def make_ssl_devcert(base_path, host=None, cn=None):
"""Creates an SSL key for development. This should be used instead of
the ``'adhoc'`` key which generates a new cert on each server start.
It accepts a path for where it should store the key and cert and
either a host or CN. If a host is given it will use the CN
``*.host/CN=host``.
For more information see :func:`run_simple`.
.. versionadded:: 0.9
:param base_path: the path to the certificate and key. The extension
``.crt`` is added for the certificate, ``.key`` is
added for the key.
:param host: the name of the host. This can be used as an alternative
for the `cn`.
:param cn: the `CN` to use.
"""
from OpenSSL import crypto
if host is not None:
cn = '*.%s/CN=%s' % (host, host)
cert, pkey = generate_adhoc_ssl_pair(cn=cn)
cert_file = base_path + '.crt'
pkey_file = base_path + '.key'
with open(cert_file, 'w') as f:
f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
with open(pkey_file, 'w') as f:
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
return cert_file, pkey_file
def generate_adhoc_ssl_context():
"""Generates an adhoc SSL context for the development server."""
from OpenSSL import SSL
pkey, cert = generate_adhoc_ssl_pair()
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_privatekey(pkey)
ctx.use_certificate(cert)
return ctx
def load_ssl_context(cert_file, pkey_file):
"""Loads an SSL context from a certificate and private key file."""
from OpenSSL import SSL
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_certificate_file(cert_file)
ctx.use_privatekey_file(pkey_file)
return ctx
@@ -297,6 +354,9 @@ class _SSLConnectionFix(object):
def __getattr__(self, attrib):
return getattr(self._con, attrib)
def shutdown(self, arg=None):
self._con.shutdown()
def select_ip_version(host, port):
"""Returns AF_INET4 or AF_INET6 depending on where to connect to."""
@@ -339,6 +399,8 @@ class BaseWSGIServer(HTTPServer, object):
except ImportError:
raise TypeError('SSL is not available if the OpenSSL '
'library is not installed.')
if isinstance(ssl_context, tuple):
ssl_context = load_ssl_context(*ssl_context)
if ssl_context == 'adhoc':
ssl_context = generate_adhoc_ssl_context()
self.socket = tsafe.Connection(ssl_context, self.socket)
@@ -405,7 +467,23 @@ def make_server(host, port, app=None, threaded=False, processes=1,
passthrough_errors, ssl_context)
def reloader_loop(extra_files=None, interval=1):
def _iter_module_files():
for module in sys.modules.values():
filename = getattr(module, '__file__', None)
if filename:
old = None
while not os.path.isfile(filename):
old = filename
filename = os.path.dirname(filename)
if filename == old:
break
else:
if filename[-4:] in ('.pyc', '.pyo'):
filename = filename[:-1]
yield filename
def _reloader_stat_loop(extra_files=None, interval=1):
"""When this function is run from the main thread, it will force other
threads to exit when any modules currently loaded change.
@@ -414,32 +492,10 @@ def reloader_loop(extra_files=None, interval=1):
:param extra_files: a list of additional files it should watch.
"""
def iter_module_files():
for module in sys.modules.values():
filename = getattr(module, '__file__', None)
if filename:
old = None
while not os.path.isfile(filename):
old = filename
filename = os.path.dirname(filename)
if filename == old:
break
else:
if filename[-4:] in ('.pyc', '.pyo'):
filename = filename[:-1]
yield filename
fnames = []
fnames.extend(iter_module_files())
fnames.extend(extra_files or ())
reloader(fnames, interval=interval)
def _reloader_stat_loop(fnames, interval=1):
from itertools import chain
mtimes = {}
while 1:
for filename in fnames:
for filename in chain(_iter_module_files(), extra_files or ()):
try:
mtime = os.stat(filename).st_mtime
except OSError:
@@ -455,7 +511,7 @@ def _reloader_stat_loop(fnames, interval=1):
time.sleep(interval)
def _reloader_inotify(fnames, interval=None):
def _reloader_inotify(extra_files=None, interval=None):
# Mutated by inotify loop when changes occur.
changed = [False]
@@ -478,13 +534,16 @@ def _reloader_inotify(fnames, interval=None):
_log('info', ' * Detected change in %r, reloading' % event.path)
changed[:] = [True]
for fname in fnames:
for fname in extra_files or ():
wm.add_watch(fname, mask, signal_changed)
# ... And now we wait...
notif = Notifier(wm)
try:
while not changed[0]:
# always reiterate through sys.modules, adding them
for fname in _iter_module_files():
wm.add_watch(fname, mask, signal_changed)
notif.process_events()
if notif.check_events(timeout=interval):
notif.read_events()
@@ -497,7 +556,7 @@ def _reloader_inotify(fnames, interval=None):
# currently we always use the stat loop reloader for the simple reason
# that the inotify one does not respond to added files properly. Also
# it's quite buggy and the API is a mess.
reloader = _reloader_stat_loop
reloader_loop = _reloader_stat_loop
def restart_with_reloader():
@@ -555,6 +614,10 @@ def run_simple(hostname, port, application, use_reloader=False,
.. versionadded:: 0.6
support for SSL was added.
.. versionadded:: 0.8
Added support for automatically loading a SSL context from certificate
file and private key.
:param hostname: The host for the application. eg: ``'localhost'``
:param port: The port for the server. eg: ``8080``
:param application: the WSGI application to execute
@@ -582,7 +645,8 @@ def run_simple(hostname, port, application, use_reloader=False,
This means that the server will die on errors but
it can be useful to hook debuggers in (pdb etc.)
:param ssl_context: an SSL context for the connection. Either an OpenSSL
context, the string ``'adhoc'`` if the server should
context, a tuple in the form ``(cert_file, pkey_file)``,
the string ``'adhoc'`` if the server should
automatically create one, or `None` to disable SSL
(which is the default).
"""
@@ -607,7 +671,8 @@ def run_simple(hostname, port, application, use_reloader=False,
if use_reloader:
# Create and destroy a socket so that any exceptions are raised before
# we spawn a separate Python interpreter and lose this ability.
test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address_family = select_ip_version(hostname, port)
test_socket = socket.socket(address_family, socket.SOCK_STREAM)
test_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
test_socket.bind((hostname, port))
test_socket.close()