11#!/usr/bin/env python
2+ import functools
23import logging
34import multiprocessing
45import os
56import signal
67import socket
78import time
8- from urllib .error import URLError
9- from urllib .request import urlopen
9+ import warnings
1010
1111import pytest
1212from flask import _request_ctx_stack
1313
1414
15+ def deprecated (reason ):
16+ """Decorator which can be used to mark function or method as deprecated.
17+ It will result a warning being emmitted when the function is called.
18+ """
19+
20+ def decorator (func ):
21+ @functools .wraps (func )
22+ def deprecated_call (* args , ** kwargs ):
23+ warnings .simplefilter ("always" , DeprecationWarning )
24+ warnings .warn (reason , DeprecationWarning , stacklevel = 2 )
25+ warnings .simplefilter ("default" , DeprecationWarning )
26+ return func (* args , ** kwargs )
27+
28+ return deprecated_call
29+
30+ return decorator
31+
32+
1533@pytest .yield_fixture
1634def client (app ):
1735 """A Flask test client. An instance of :class:`flask.testing.TestClient`
@@ -47,12 +65,15 @@ class LiveServer:
4765 :param app: The application to run.
4866 :param host: The host where to listen (default localhost).
4967 :param port: The port to run application.
68+ :param wait: The timeout after which test case is aborted if
69+ application is not started.
5070 """
5171
52- def __init__ (self , app , host , port , clean_stop = False ):
72+ def __init__ (self , app , host , port , wait , clean_stop = False ):
5373 self .app = app
5474 self .port = port
5575 self .host = host
76+ self .wait = wait
5677 self .clean_stop = clean_stop
5778 self ._process = None
5879
@@ -65,22 +86,45 @@ def worker(app, host, port):
6586 self ._process = multiprocessing .Process (
6687 target = worker , args = (self .app , self .host , self .port )
6788 )
89+ self ._process .daemon = True
6890 self ._process .start ()
6991
70- # We must wait for the server to start listening with a maximum
71- # timeout of 5 seconds.
72- timeout = 5
73- while timeout > 0 :
74- time .sleep (1 )
75- try :
76- urlopen (self .url ())
77- timeout = 0
78- except URLError :
79- timeout -= 1
80-
92+ keep_trying = True
93+ start_time = time .time ()
94+ while keep_trying :
95+ elapsed_time = time .time () - start_time
96+ if elapsed_time > self .wait :
97+ pytest .fail (
98+ "Failed to start the server after {!s} "
99+ "seconds." .format (self .wait )
100+ )
101+ if self ._is_ready ():
102+ keep_trying = False
103+
104+ def _is_ready (self ):
105+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
106+ try :
107+ sock .connect ((self .host , self .port ))
108+ except socket .error :
109+ ret = False
110+ else :
111+ ret = True
112+ finally :
113+ sock .close ()
114+ return ret
115+
116+ @deprecated (
117+ reason = (
118+ 'The "live_server.url" method is deprecated and will '
119+ "be removed in the future. Please use "
120+ 'the "flask.url_for" function instead.' ,
121+ )
122+ )
81123 def url (self , url = "" ):
82124 """Returns the complete url based on server options."""
83- return "http://%s:%d%s" % (self .host , self .port , url )
125+ return "http://{host!s}:{port!s}{url!s}" .format (
126+ host = self .host , port = self .port , url = url
127+ )
84128
85129 def stop (self ):
86130 """Stop application process."""
@@ -155,8 +199,9 @@ def test_server_is_up_and_running(live_server):
155199 final_server_name = _rewrite_server_name (original_server_name , str (port ))
156200 app .config ["SERVER_NAME" ] = final_server_name
157201
202+ wait = request .config .getvalue ("live_server_wait" )
158203 clean_stop = request .config .getvalue ("live_server_clean_stop" )
159- server = LiveServer (app , host , port , clean_stop )
204+ server = LiveServer (app , host , port , wait , clean_stop )
160205 if request .config .getvalue ("start_live_server" ):
161206 server .start ()
162207
0 commit comments