Merge pull request #1393 from ashleysommer/pickleable-app-blueprint

Fix pickling blueprints Fixes #1392
This commit is contained in:
Stephen Sadowski 2018-11-05 07:24:15 -06:00 committed by GitHub
commit df0e3de911
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 5 deletions

View File

@ -5,7 +5,7 @@ from sanic.views import CompositionView
FutureRoute = namedtuple( FutureRoute = namedtuple(
"Route", "FutureRoute",
[ [
"handler", "handler",
"uri", "uri",
@ -17,11 +17,15 @@ FutureRoute = namedtuple(
"name", "name",
], ],
) )
FutureListener = namedtuple("Listener", ["handler", "uri", "methods", "host"]) FutureListener = namedtuple(
FutureMiddleware = namedtuple("Route", ["middleware", "args", "kwargs"]) "FutureListener", ["handler", "uri", "methods", "host"]
FutureException = namedtuple("Route", ["handler", "args", "kwargs"]) )
FutureMiddleware = namedtuple(
"FutureMiddleware", ["middleware", "args", "kwargs"]
)
FutureException = namedtuple("FutureException", ["handler", "args", "kwargs"])
FutureStatic = namedtuple( FutureStatic = namedtuple(
"Route", ["uri", "file_or_directory", "args", "kwargs"] "FutureStatic", ["uri", "file_or_directory", "args", "kwargs"]
) )

View File

@ -1,9 +1,11 @@
import multiprocessing import multiprocessing
import random import random
import signal import signal
import pickle
import pytest import pytest
from sanic.testing import HOST, PORT from sanic.testing import HOST, PORT
from sanic.response import text
@pytest.mark.skipif( @pytest.mark.skipif(
@ -27,3 +29,54 @@ def test_multiprocessing(app):
app.run(HOST, PORT, workers=num_workers) app.run(HOST, PORT, workers=num_workers)
assert len(process_list) == num_workers assert len(process_list) == num_workers
def test_multiprocessing_with_blueprint(app):
from sanic import Blueprint
# Selects a number at random so we can spot check
num_workers = random.choice(range(2, multiprocessing.cpu_count() * 2 + 1))
process_list = set()
def stop_on_alarm(*args):
for process in multiprocessing.active_children():
process_list.add(process.pid)
process.terminate()
signal.signal(signal.SIGALRM, stop_on_alarm)
signal.alarm(3)
bp = Blueprint('test_text')
app.blueprint(bp)
app.run(HOST, PORT, workers=num_workers)
assert len(process_list) == num_workers
# this function must be outside a test function so that it can be
# able to be pickled (local functions cannot be pickled).
def handler(request):
return text('Hello')
# Muliprocessing on Windows requires app to be able to be pickled
@pytest.mark.parametrize('protocol', [3, 4])
def test_pickle_app(app, protocol):
app.route('/')(handler)
p_app = pickle.dumps(app, protocol=protocol)
up_p_app = pickle.loads(p_app)
assert up_p_app
request, response = app.test_client.get('/')
assert response.text == 'Hello'
@pytest.mark.parametrize('protocol', [3, 4])
def test_pickle_app_with_bp(app, protocol):
from sanic import Blueprint
bp = Blueprint('test_text')
bp.route('/')(handler)
app.blueprint(bp)
p_app = pickle.dumps(app, protocol=protocol)
up_p_app = pickle.loads(p_app)
assert up_p_app
request, response = app.test_client.get('/')
assert app.is_request_stream is False
assert response.text == 'Hello'