##// END OF EJS Templates
Work around a bug in setting and getting the mtime in python 2...
Work around a bug in setting and getting the mtime in python 2 See http://bugs.python.org/issue12904. Basically, we can get the mtime in nanosecond precision, but only set it in microsecond precision. This means that the shutil.copy2 will not set the destination's mtime to exactly the same mtime as our source. The end result is that we can *always* end up copying the extension because the source always appears newer. We add a microsecond of fudge time when checking to see if the source is newer than the destination to get around this. This bug is fixed in Python 3.3+, I believe.

File last commit:

r19604:25165b0a
r20080:52d92404
Show More
launchnotebook.py
115 lines | 3.5 KiB | text/x-python | PythonLexer
"""Base class for notebook tests."""
from __future__ import print_function
import sys
import time
import requests
from contextlib import contextmanager
from threading import Thread, Event
from unittest import TestCase
from tornado.ioloop import IOLoop
from ..notebookapp import NotebookApp
from IPython.utils.tempdir import TemporaryDirectory
MAX_WAITTIME = 30 # seconds to wait for notebook server to start
POLL_INTERVAL = 0.1 # time between attempts
# TimeoutError is a builtin on Python 3. This can be removed when we stop
# supporting Python 2.
class TimeoutError(Exception):
pass
class NotebookTestBase(TestCase):
"""A base class for tests that need a running notebook.
This creates an empty profile in a temp ipython_dir
and then starts the notebook server with a separate temp notebook_dir.
"""
port = 12341
config = None
@classmethod
def wait_until_alive(cls):
"""Wait for the server to be alive"""
url = 'http://localhost:%i/api/contents' % cls.port
for _ in range(int(MAX_WAITTIME/POLL_INTERVAL)):
try:
requests.get(url)
except Exception as e:
if cls.notebook.poll() is not None:
raise RuntimeError("The notebook server exited with status %s" \
% cls.notebook.poll())
time.sleep(POLL_INTERVAL)
else:
return
raise TimeoutError("The notebook server didn't start up correctly.")
@classmethod
def wait_until_dead(cls):
"""Wait for the server process to terminate after shutdown"""
cls.notebook_thread.join(timeout=MAX_WAITTIME)
if cls.notebook_thread.is_alive():
raise TimeoutError("Undead notebook server")
@classmethod
def setup_class(cls):
cls.ipython_dir = TemporaryDirectory()
cls.notebook_dir = TemporaryDirectory()
app = cls.notebook = NotebookApp(
port=cls.port,
port_retries=0,
open_browser=False,
ipython_dir=cls.ipython_dir.name,
notebook_dir=cls.notebook_dir.name,
config=cls.config,
)
# clear log handlers and propagate to root for nose to capture it
# needs to be redone after initialize, which reconfigures logging
app.log.propagate = True
app.log.handlers = []
app.initialize(argv=[])
app.log.propagate = True
app.log.handlers = []
started = Event()
def start_thread():
loop = IOLoop.current()
loop.add_callback(started.set)
try:
app.start()
finally:
# set the event, so failure to start doesn't cause a hang
started.set()
cls.notebook_thread = Thread(target=start_thread)
cls.notebook_thread.start()
started.wait()
cls.wait_until_alive()
@classmethod
def teardown_class(cls):
cls.notebook.stop()
cls.wait_until_dead()
cls.ipython_dir.cleanup()
cls.notebook_dir.cleanup()
@classmethod
def base_url(cls):
return 'http://localhost:%i/' % cls.port
@contextmanager
def assert_http_error(status, msg=None):
try:
yield
except requests.HTTPError as e:
real_status = e.response.status_code
assert real_status == status, \
"Expected status %d, got %d" % (status, real_status)
if msg:
assert msg in str(e), e
else:
assert False, "Expected HTTP error status"