From 2cf4949b99eb75ac9ee7850cf2c91310523d9048 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 15 Sep 2014 21:28:29 +0200 Subject: [PATCH 01/13] Test both reloader types --- tests/conftest.py | 9 ++++----- tests/test_serving.py | 7 ++++--- tox.ini | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 998e4a332..540f72192 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -49,9 +49,7 @@ def inner(environ, start_response): def _dev_server(): - appfile = sys.argv[1] - - sys.path.insert(0, os.path.dirname(appfile)) + sys.path.insert(0, sys.argv[1]) import testsuite_app app = _get_pid_middleware(testsuite_app.app) serving.run_simple(hostname='localhost', application=app, @@ -76,7 +74,8 @@ def dev_server(tmpdir, subprocess, request, monkeypatch): whose values will be passed to ``run_simple``. ''' def run_dev_server(application): - appfile = tmpdir.join('testsuite_app.py') + app_pkg = tmpdir.mkdir('testsuite_app') + appfile = app_pkg.join('__init__.py') appfile.write('\n\n'.join(( 'kwargs = dict(port=5001)', textwrap.dedent(application) @@ -103,7 +102,7 @@ def request_pid(): return False def preparefunc(cwd): - args = [sys.executable, __file__, str(appfile)] + args = [sys.executable, __file__, str(tmpdir)] return request_pid, args subprocess.ensure('dev_server', preparefunc, restart=True) diff --git a/tests/test_serving.py b/tests/test_serving.py index 2ed284616..3bc474c60 100644 --- a/tests/test_serving.py +++ b/tests/test_serving.py @@ -122,7 +122,8 @@ def test_make_ssl_devcert(tmpdir): assert os.path.isfile(private_key) -def test_reloader_broken_imports(tmpdir, dev_server): +@pytest.mark.parametrize('reloader_type', ['watchdog', 'stat']) +def test_reloader_broken_imports(tmpdir, dev_server, reloader_type): server = dev_server(''' trials = [] def app(environ, start_response): @@ -133,9 +134,9 @@ def app(environ, start_response): kwargs['use_reloader'] = True kwargs['reloader_interval'] = 0.1 - ''') + kwargs['reloader_type'] = %s + ''' % repr(reloader_type)) - assert any('app.py' in str(x) for x in tmpdir.listdir()) real_app = tmpdir.join('real_app.py') real_app.write("lol syntax error") time.sleep(2) # wait for stat reloader to pick up new file diff --git a/tox.ini b/tox.ini index d3ddf74fa..f0f5ad519 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,7 @@ deps= pytest pytest-xprocess redis + watchdog # Python 2 py26: python-memcached From 6ed5bb2341b191ebdf4fb428035daa78fc2d331d Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Wed, 17 Sep 2014 16:26:58 +0200 Subject: [PATCH 02/13] Add testcase --- tests/test_serving.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/test_serving.py b/tests/test_serving.py index 3bc474c60..5fa2aabcb 100644 --- a/tests/test_serving.py +++ b/tests/test_serving.py @@ -124,6 +124,9 @@ def test_make_ssl_devcert(tmpdir): @pytest.mark.parametrize('reloader_type', ['watchdog', 'stat']) def test_reloader_broken_imports(tmpdir, dev_server, reloader_type): + # We explicitly assert that the server reloads on change, even though in + # this case the import could've just been retried. This is to assert + # correct behavior for apps that catch and cache import errors. server = dev_server(''' trials = [] def app(environ, start_response): @@ -157,3 +160,39 @@ def real_app(environ, start_response): response = connection.getresponse() assert response.status == 200 assert response.read() == b'hello' + + +@pytest.mark.parametrize('reloader_type', ['watchdog', 'stat']) +def test_reloader_nested_broken_imports(tmpdir, dev_server, reloader_type): + server = dev_server(''' + def app(environ, start_response): + import real_app + return real_app.real_app(environ, start_response) + + kwargs['use_reloader'] = True + kwargs['reloader_interval'] = 0.1 + kwargs['reloader_type'] = %s + ''' % repr(reloader_type)) + + real_app = tmpdir.mkdir('real_app') + real_app.join('__init__.py').write('from real_app.sub import real_app') + sub = real_app.mkdir('sub').join('__init__.py') + sub.write("lol syntax error") + time.sleep(2) # wait for stat reloader to pick up new file + + connection = httplib.HTTPConnection(server.addr) + connection.request('GET', '/') + response = connection.getresponse() + assert response.status == 500 + + sub.write(textwrap.dedent(''' + def real_app(environ, start_response): + start_response('200 OK', [('Content-Type', 'text/html')]) + return [b'hello'] + ''')) + time.sleep(2) # wait for stat reloader to pick up changes + + connection.request('GET', '/') + response = connection.getresponse() + assert response.status == 200 + assert response.read() == b'hello' From 1bb94ce67eb0548c2d6c83a9650ef6af17ac9283 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Wed, 17 Sep 2014 17:18:17 +0200 Subject: [PATCH 03/13] Also scan sys.path --- werkzeug/_reloader.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/werkzeug/_reloader.py b/werkzeug/_reloader.py index c2bcb4f49..2ff9c2093 100644 --- a/werkzeug/_reloader.py +++ b/werkzeug/_reloader.py @@ -50,6 +50,10 @@ def _recursive_walk(path_entry): # The list call is necessary on Python 3 in case the module # dictionary modifies during iteration. + for path_entry in list(sys.path): + for filename in _recursive_walk(os.path.abspath(path_entry)): + yield filename + for module in list(sys.modules.values()): if module is None: continue @@ -65,7 +69,7 @@ def _recursive_walk(path_entry): def _find_observable_paths(extra_files=None): """Finds all paths that should be observed.""" - rv = set() + rv = set(os.path.abspath(x) for x in sys.path if os.path.isdir(x)) for filename in extra_files or (): rv.append(os.path.dirname(os.path.abspath(filename))) for module in list(sys.modules.values()): @@ -168,7 +172,8 @@ def __init__(self, *args, **kwargs): def _check_modification(filename): if filename in self.extra_files: self.trigger_reload(filename) - if os.path.dirname(filename) in self.observable_paths: + dirname = os.path.dirname(filename) + if dirname.startswith(tuple(self.observable_paths)): if filename.endswith(('.pyc', '.pyo')): self.trigger_reload(filename[:-1]) elif filename.endswith('.py'): From 0e327a123505661d6f423d933291079e9a5ea887 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Thu, 18 Sep 2014 18:04:29 +0200 Subject: [PATCH 04/13] Explicitly assert reload Also fails without this. --- tests/test_serving.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_serving.py b/tests/test_serving.py index 5fa2aabcb..7953ef186 100644 --- a/tests/test_serving.py +++ b/tests/test_serving.py @@ -165,7 +165,10 @@ def real_app(environ, start_response): @pytest.mark.parametrize('reloader_type', ['watchdog', 'stat']) def test_reloader_nested_broken_imports(tmpdir, dev_server, reloader_type): server = dev_server(''' + trials = [] def app(environ, start_response): + assert not trials, 'should have reloaded' + trials.append(1) import real_app return real_app.real_app(environ, start_response) From a0aff329fe6c9c798f8e6b78419110e3778fa706 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 20 Sep 2014 17:56:03 +0200 Subject: [PATCH 05/13] Make _recursive_walk actually recursive --- werkzeug/_reloader.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/werkzeug/_reloader.py b/werkzeug/_reloader.py index 2ff9c2093..f9f50bcc0 100644 --- a/werkzeug/_reloader.py +++ b/werkzeug/_reloader.py @@ -40,11 +40,16 @@ def _recursive_walk(path_entry): entered.add(path_entry) try: for filename in os.listdir(path_entry): - if not filename.endswith(('.py', '.pyc', '.pyo')): - continue - filename = _verify_file(os.path.join(path_entry, filename)) - if filename: - yield filename + path = os.path.join(path_entry, filename) + if os.path.isdir(path): + for filename in _recursive_walk(path): + yield filename + else: + if not filename.endswith(('.py', '.pyc', '.pyo')): + continue + filename = _verify_file(path) + if filename: + yield filename except OSError: pass From a9b17c865f16dff9094a63975f123a307e7b8aec Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 20 Sep 2014 18:13:18 +0200 Subject: [PATCH 06/13] Don't use simple sleep when waiting for reloader --- tests/conftest.py | 48 ++++++++++++++++++++++++++++--------------- tests/test_serving.py | 8 ++++---- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 540f72192..42fa1388b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -63,6 +63,30 @@ class _ServerInfo(object): addr = None url = None port = None + last_pid = None + + def __init__(self, addr, url, port): + self.addr = addr + self.url = url + self.port = port + + def request_pid(self): + for i in range(10): + try: + self.last_pid = int(urlopen(self.url + '/_getpid').read()) + return self.last_pid + except Exception as e: # urllib also raises socketerrors + print(self.url) + print(e) + time.sleep(0.1 * i) + return False + + def wait_for_reloader(self): + old_pid = self.last_pid + for i in range(10): + if self.request_pid() != old_pid: + break + time.sleep(0.1 * i) @pytest.fixture @@ -91,19 +115,15 @@ def run_dev_server(application): else: url_base = 'http://localhost:{0}'.format(port) - def request_pid(): - for i in range(10): - try: - return int(urlopen(url_base + '/_getpid').read()) - except Exception as e: # urllib also raises socketerrors - print(url_base) - print(e) - time.sleep(0.1 * i) - return False + info = _ServerInfo( + 'localhost:{0}'.format(port), + url_base, + port + ) def preparefunc(cwd): args = [sys.executable, __file__, str(tmpdir)] - return request_pid, args + return info.request_pid, args subprocess.ensure('dev_server', preparefunc, restart=True) @@ -111,14 +131,10 @@ def teardown(): # Killing the process group that runs the server, not just the # parent process attached. xprocess is confused about Werkzeug's # reloader and won't help here. - pid = request_pid() + pid = info.last_pid os.killpg(os.getpgid(pid), signal.SIGTERM) request.addfinalizer(teardown) - rv = _ServerInfo() - rv.addr = 'localhost:{0}'.format(port) - rv.url = url_base - rv.port = port - return rv + return info return run_dev_server diff --git a/tests/test_serving.py b/tests/test_serving.py index 7953ef186..5b3502e5c 100644 --- a/tests/test_serving.py +++ b/tests/test_serving.py @@ -142,7 +142,7 @@ def app(environ, start_response): real_app = tmpdir.join('real_app.py') real_app.write("lol syntax error") - time.sleep(2) # wait for stat reloader to pick up new file + server.wait_for_reloader() connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') @@ -154,7 +154,7 @@ def real_app(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'hello'] ''')) - time.sleep(2) # wait for stat reloader to pick up changes + server.wait_for_reloader() connection.request('GET', '/') response = connection.getresponse() @@ -181,7 +181,7 @@ def app(environ, start_response): real_app.join('__init__.py').write('from real_app.sub import real_app') sub = real_app.mkdir('sub').join('__init__.py') sub.write("lol syntax error") - time.sleep(2) # wait for stat reloader to pick up new file + server.wait_for_reloader() connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') @@ -193,7 +193,7 @@ def real_app(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'hello'] ''')) - time.sleep(2) # wait for stat reloader to pick up changes + server.wait_for_reloader() connection.request('GET', '/') response = connection.getresponse() From 3d52ee902b036819d9d00d8d5b03a4da4748ffd0 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 20 Sep 2014 18:29:37 +0200 Subject: [PATCH 07/13] Don't wait for reloader twice --- tests/conftest.py | 2 +- tests/test_serving.py | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 42fa1388b..ca1e03fa1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -83,7 +83,7 @@ def request_pid(self): def wait_for_reloader(self): old_pid = self.last_pid - for i in range(10): + for i in range(20): if self.request_pid() != old_pid: break time.sleep(0.1 * i) diff --git a/tests/test_serving.py b/tests/test_serving.py index 5b3502e5c..29fc09da8 100644 --- a/tests/test_serving.py +++ b/tests/test_serving.py @@ -127,6 +127,10 @@ def test_reloader_broken_imports(tmpdir, dev_server, reloader_type): # We explicitly assert that the server reloads on change, even though in # this case the import could've just been retried. This is to assert # correct behavior for apps that catch and cache import errors. + + real_app = tmpdir.join('real_app.py') + real_app.write("lol syntax error") + server = dev_server(''' trials = [] def app(environ, start_response): @@ -140,10 +144,6 @@ def app(environ, start_response): kwargs['reloader_type'] = %s ''' % repr(reloader_type)) - real_app = tmpdir.join('real_app.py') - real_app.write("lol syntax error") - server.wait_for_reloader() - connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') response = connection.getresponse() @@ -164,6 +164,11 @@ def real_app(environ, start_response): @pytest.mark.parametrize('reloader_type', ['watchdog', 'stat']) def test_reloader_nested_broken_imports(tmpdir, dev_server, reloader_type): + real_app = tmpdir.mkdir('real_app') + real_app.join('__init__.py').write('from real_app.sub import real_app') + sub = real_app.mkdir('sub').join('__init__.py') + sub.write("lol syntax error") + server = dev_server(''' trials = [] def app(environ, start_response): @@ -177,12 +182,6 @@ def app(environ, start_response): kwargs['reloader_type'] = %s ''' % repr(reloader_type)) - real_app = tmpdir.mkdir('real_app') - real_app.join('__init__.py').write('from real_app.sub import real_app') - sub = real_app.mkdir('sub').join('__init__.py') - sub.write("lol syntax error") - server.wait_for_reloader() - connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') response = connection.getresponse() From 78636ee56ffdc1363c4ac89cff6babe94de570d9 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 20 Sep 2014 18:29:44 +0200 Subject: [PATCH 08/13] Better dealing with invalid dirpaths --- werkzeug/_reloader.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/werkzeug/_reloader.py b/werkzeug/_reloader.py index f9f50bcc0..af096793d 100644 --- a/werkzeug/_reloader.py +++ b/werkzeug/_reloader.py @@ -74,7 +74,7 @@ def _recursive_walk(path_entry): def _find_observable_paths(extra_files=None): """Finds all paths that should be observed.""" - rv = set(os.path.abspath(x) for x in sys.path if os.path.isdir(x)) + rv = set(os.path.abspath(x) for x in sys.path) for filename in extra_files or (): rv.append(os.path.dirname(os.path.abspath(filename))) for module in list(sys.modules.values()): @@ -211,8 +211,14 @@ def monitor_update_thread(): common_roots = _find_common_roots(paths) for path in common_roots: if path not in watches: - watches[path] = observer.schedule( - self.event_handler, path, recursive=True) + try: + watches[path] = observer.schedule( + self.event_handler, path, recursive=True) + except OSError: + # "Path is not a directory". We could filter out + # those paths beforehand, but that would cause + # additional stat calls. + watches[path] = None to_delete.discard(path) for path in to_delete: watch = watches.pop(path, None) From 5b27d2e68991620e5a35e3a2f92b48ddc6304834 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 21 Sep 2014 12:45:08 +0200 Subject: [PATCH 09/13] Install less watches --- werkzeug/_reloader.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/werkzeug/_reloader.py b/werkzeug/_reloader.py index af096793d..55b45b558 100644 --- a/werkzeug/_reloader.py +++ b/werkzeug/_reloader.py @@ -207,9 +207,9 @@ def run(self): def monitor_update_thread(): while 1: to_delete = set(watches) - paths = _find_observable_paths(self.extra_files) - common_roots = _find_common_roots(paths) - for path in common_roots: + paths = _find_common_roots( + _find_observable_paths(self.extra_files)) + for path in paths: if path not in watches: try: watches[path] = observer.schedule( From 2cdbe40d014c524bb06f4b5bfed33b2f012c8669 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 20 Sep 2014 18:42:59 +0200 Subject: [PATCH 10/13] Parameter tuning and better error reporting --- tests/conftest.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index ca1e03fa1..518f15ff0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -72,21 +72,25 @@ def __init__(self, addr, url, port): def request_pid(self): for i in range(10): + time.sleep(0.1 * i) try: self.last_pid = int(urlopen(self.url + '/_getpid').read()) return self.last_pid except Exception as e: # urllib also raises socketerrors print(self.url) print(e) - time.sleep(0.1 * i) return False def wait_for_reloader(self): old_pid = self.last_pid - for i in range(20): - if self.request_pid() != old_pid: - break + for i in range(10): time.sleep(0.1 * i) + new_pid = self.request_pid() + if not new_pid: + raise RuntimeError('Server is down.') + if self.request_pid() != old_pid: + return + raise RuntimeError('Server did not reload.') @pytest.fixture From 058ee823fa77748004971de7d8bfac1e66ed0458 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 21 Sep 2014 13:07:00 +0200 Subject: [PATCH 11/13] Wait for one loop round of the observer thread --- tests/test_serving.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_serving.py b/tests/test_serving.py index 29fc09da8..e1f15607f 100644 --- a/tests/test_serving.py +++ b/tests/test_serving.py @@ -143,6 +143,7 @@ def app(environ, start_response): kwargs['reloader_interval'] = 0.1 kwargs['reloader_type'] = %s ''' % repr(reloader_type)) + time.sleep(5) connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') @@ -181,6 +182,7 @@ def app(environ, start_response): kwargs['reloader_interval'] = 0.1 kwargs['reloader_type'] = %s ''' % repr(reloader_type)) + time.sleep(5) connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') From b6ae58bbabb52ec5c2772053905d1b0c5c2eea1a Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 27 Sep 2014 14:28:12 +0200 Subject: [PATCH 12/13] More sophisticated waiting for reloader loop --- tests/conftest.py | 30 +++++++++++++++++++++++++++--- tests/test_serving.py | 4 ++-- werkzeug/_reloader.py | 5 +++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 518f15ff0..a5b718b33 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -20,10 +20,10 @@ except ImportError: # pragma: no cover from urllib.request import urlopen - import pytest -from werkzeug import serving +from werkzeug import serving +from werkzeug.utils import cached_property from werkzeug._compat import to_bytes @@ -39,6 +39,15 @@ def subprocess(xprocess): return xprocess +def _patch_reloader_loop(): + def f(x): + print('reloader loop finished') + return time.sleep(x) + + import werkzeug._reloader + werkzeug._reloader.ReloaderLoop._sleep = staticmethod(f) + + def _get_pid_middleware(f): def inner(environ, start_response): if environ['PATH_INFO'] == '/_getpid': @@ -49,6 +58,7 @@ def inner(environ, start_response): def _dev_server(): + _patch_reloader_loop() sys.path.insert(0, sys.argv[1]) import testsuite_app app = _get_pid_middleware(testsuite_app.app) @@ -60,16 +70,22 @@ def _dev_server(): class _ServerInfo(object): + xprocess = None addr = None url = None port = None last_pid = None - def __init__(self, addr, url, port): + def __init__(self, xprocess, addr, url, port): + self.xprocess = xprocess self.addr = addr self.url = url self.port = port + @cached_property + def logfile(self): + return self.xprocess.getinfo('dev_server').logpath.open() + def request_pid(self): for i in range(10): time.sleep(0.1 * i) @@ -92,6 +108,13 @@ def wait_for_reloader(self): return raise RuntimeError('Server did not reload.') + def wait_for_reloader_loop(self): + for i in range(60*3): + time.sleep(0.1 * i) + line = self.logfile.readline() + if 'reloader loop finished' in line: + return + @pytest.fixture def dev_server(tmpdir, subprocess, request, monkeypatch): @@ -120,6 +143,7 @@ def run_dev_server(application): url_base = 'http://localhost:{0}'.format(port) info = _ServerInfo( + subprocess, 'localhost:{0}'.format(port), url_base, port diff --git a/tests/test_serving.py b/tests/test_serving.py index e1f15607f..2e9d377d1 100644 --- a/tests/test_serving.py +++ b/tests/test_serving.py @@ -143,7 +143,7 @@ def app(environ, start_response): kwargs['reloader_interval'] = 0.1 kwargs['reloader_type'] = %s ''' % repr(reloader_type)) - time.sleep(5) + server.wait_for_reloader_loop() connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') @@ -182,7 +182,7 @@ def app(environ, start_response): kwargs['reloader_interval'] = 0.1 kwargs['reloader_type'] = %s ''' % repr(reloader_type)) - time.sleep(5) + server.wait_for_reloader_loop() connection = httplib.HTTPConnection(server.addr) connection.request('GET', '/') diff --git a/werkzeug/_reloader.py b/werkzeug/_reloader.py index 55b45b558..96308e22f 100644 --- a/werkzeug/_reloader.py +++ b/werkzeug/_reloader.py @@ -107,6 +107,7 @@ def _walk(node, path): class ReloaderLoop(object): + _sleep = time.sleep # monkeypatched by testsuite name = None def __init__(self, extra_files=None, interval=1): @@ -163,7 +164,7 @@ def run(self): continue elif mtime > old_time: self.trigger_reload(filename) - time.sleep(self.interval) + self._sleep(self.interval) class WatchdogReloaderLoop(ReloaderLoop): @@ -225,7 +226,7 @@ def monitor_update_thread(): if watch is not None: observer.unschedule(watch) self.observable_paths = paths - time.sleep(self.interval) + self._sleep(self.interval) t = threading.Thread(target=monitor_update_thread, args=()) t.setDaemon(True) From a00377315bbf02ec48fdad22c6bb08433fc1e9c1 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 27 Sep 2014 15:08:12 +0200 Subject: [PATCH 13/13] Fix timeouts again --- tests/conftest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a5b718b33..c3866a990 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -87,7 +87,7 @@ def logfile(self): return self.xprocess.getinfo('dev_server').logpath.open() def request_pid(self): - for i in range(10): + for i in range(20): time.sleep(0.1 * i) try: self.last_pid = int(urlopen(self.url + '/_getpid').read()) @@ -99,7 +99,7 @@ def request_pid(self): def wait_for_reloader(self): old_pid = self.last_pid - for i in range(10): + for i in range(20): time.sleep(0.1 * i) new_pid = self.request_pid() if not new_pid: @@ -109,7 +109,7 @@ def wait_for_reloader(self): raise RuntimeError('Server did not reload.') def wait_for_reloader_loop(self): - for i in range(60*3): + for i in range(20): time.sleep(0.1 * i) line = self.logfile.readline() if 'reloader loop finished' in line: