diff --git a/IPython/frontend/html/notebook/notebookapp.py b/IPython/frontend/html/notebook/notebookapp.py
index 28e5fa854..344fd3c26 100644
--- a/IPython/frontend/html/notebook/notebookapp.py
+++ b/IPython/frontend/html/notebook/notebookapp.py
@@ -6,7 +6,7 @@ Authors:
* Brian Granger
"""
#-----------------------------------------------------------------------------
-# Copyright (C) 2008-2011 The IPython Development Team
+# Copyright (C) 2013 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
@@ -90,6 +90,7 @@ from IPython.kernel.zmq.kernelapp import (
)
from IPython.utils.importstring import import_item
from IPython.utils.localinterfaces import LOCALHOST
+from IPython.utils import submodule
from IPython.utils.traitlets import (
Dict, Unicode, Integer, List, Enum, Bool,
DottedObjectName
@@ -323,7 +324,7 @@ class NotebookApp(BaseIPythonApplication):
def _log_format_default(self):
"""override default log format to include time"""
- return u"%(asctime)s.%(msecs).03d [%(name)s] %(message)s"
+ return u"%(asctime)s.%(msecs).03d [%(name)s]%(highlevel)s %(message)s"
# create requested profiles by default, if they don't exist:
auto_create = Bool(True)
@@ -537,10 +538,6 @@ class NotebookApp(BaseIPythonApplication):
# and all of its ancenstors until propagate is set to False.
self.log.propagate = False
- # set the date format
- formatter = logging.Formatter(self.log_format, datefmt="%Y-%m-%d %H:%M:%S")
- self.log.handlers[0].setFormatter(formatter)
-
# hook up tornado 3's loggers to our app handlers
for name in ('access', 'application', 'general'):
logging.getLogger('tornado.%s' % name).handlers = self.log.handlers
@@ -673,11 +670,23 @@ class NotebookApp(BaseIPythonApplication):
def _signal_info(self, sig, frame):
print self.notebook_info()
+ def init_components(self):
+ """Check the components submodule, and warn if it's unclean"""
+ status = submodule.check_submodule_status()
+ if status == 'missing':
+ self.log.warn("components submodule missing, running `git submodule update`")
+ submodule.update_submodules(submodule.ipython_parent())
+ elif status == 'unclean':
+ self.log.warn("components submodule unclean, you may see 404s on static/components")
+ self.log.warn("run `setup.py submodule` or `git submodule update` to update")
+
+
@catch_config_error
def initialize(self, argv=None):
self.init_logging()
super(NotebookApp, self).initialize(argv)
self.init_configurables()
+ self.init_components()
self.init_webapp()
self.init_signal()
diff --git a/git-hooks/README.md b/git-hooks/README.md
new file mode 100644
index 000000000..51670b613
--- /dev/null
+++ b/git-hooks/README.md
@@ -0,0 +1,13 @@
+git hooks for IPython
+
+add these to your `.git/hooks`
+
+For now, we just have `post-checkout` and `post-merge`,
+both of which just update submodules,
+so make sure that you have a fully synced repo whenever you checkout or pull.
+
+To use these hooks, you can symlink or copy them to your `.git/hooks` directory.
+
+ ln -s ../../git-hooks/post-checkout .git/hooks/post-checkout
+ ln -s ../../git-hooks/post-merge .git/hooks/post-merge
+
diff --git a/git-hooks/post-checkout b/git-hooks/post-checkout
new file mode 100755
index 000000000..2e8348472
--- /dev/null
+++ b/git-hooks/post-checkout
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+git submodule init
+git submodule update
diff --git a/git-hooks/post-merge b/git-hooks/post-merge
new file mode 100755
index 000000000..2e8348472
--- /dev/null
+++ b/git-hooks/post-merge
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+git submodule init
+git submodule update
diff --git a/setup.py b/setup.py
index d69e66ce7..44991bf41 100755
--- a/setup.py
+++ b/setup.py
@@ -68,7 +68,7 @@ from setupbase import (
find_data_files,
check_for_dependencies,
git_prebuild,
- check_for_submodules,
+ check_submodule_status,
update_submodules,
require_submodules,
UpdateSubmodules,
@@ -112,21 +112,37 @@ if os_name == 'windows' and 'sdist' in sys.argv:
#-------------------------------------------------------------------------------
# Make sure we aren't trying to run without submodules
#-------------------------------------------------------------------------------
+here = os.path.abspath(os.path.dirname(__file__))
-def ensure_submodules_exist():
- """Check out git submodules before distutils can do anything
-
- Because distutils cannot be trusted to update the tree
- after everything has been set in motion.
+def require_clean_submodules():
+ """Check on git submodules before distutils can do anything
+
+ Since distutils cannot be trusted to update the tree
+ after everything has been set in motion,
+ this is not a distutils command.
"""
# don't do anything if nothing is actually supposed to happen
- for do_nothing in ('-h', '--help', '--help-commands', 'clean'):
+ for do_nothing in ('-h', '--help', '--help-commands', 'clean', 'submodule'):
if do_nothing in sys.argv:
return
- if not check_for_submodules():
- update_submodules()
-ensure_submodules_exist()
+ status = check_submodule_status(here)
+
+ if status == "missing":
+ print("checking out submodules for the first time")
+ update_submodules(here)
+ elif status == "unclean":
+ print('\n'.join([
+ "Cannot build / install IPython with unclean submodules",
+ "Please update submodules with",
+ " python setup.py submodule",
+ "or",
+ " git submodule update",
+ "or commit any submodule changes you have made."
+ ]))
+ sys.exit(1)
+
+require_clean_submodules()
#-------------------------------------------------------------------------------
# Things related to the IPython documentation
diff --git a/setupbase.py b/setupbase.py
index d024def3f..4a28694a8 100644
--- a/setupbase.py
+++ b/setupbase.py
@@ -373,27 +373,10 @@ def check_for_dependencies():
# VCS related
#---------------------------------------------------------------------------
-def check_for_submodules():
- """return False if there are any submodules that need to be checked out,
- True otherwise.
-
- This doesn't check if they are up to date, only existence.
- """
- here = os.path.dirname(__file__)
- submodules = [
- os.path.join(here, 'IPython', 'frontend', 'html', 'notebook', 'static', 'components')
- ]
- for submodule in submodules:
- if not os.path.exists(submodule):
- return False
- return True
+here = os.path.abspath(os.path.dirname(__file__))
-def update_submodules():
- """update git submodules"""
- import subprocess
- print("updating git submodules")
- subprocess.check_call('git submodule init'.split())
- subprocess.check_call('git submodule update --recursive'.split())
+# utils.submodule has checks for submodule status
+execfile(pjoin('IPython','utils','submodule.py'), globals())
class UpdateSubmodules(Command):
"""Update git submodules
@@ -418,12 +401,10 @@ class UpdateSubmodules(Command):
failure = e
print(e)
- if not check_for_submodules():
+ if not check_submodule_status(here) == 'clean':
print("submodules could not be checked out")
sys.exit(1)
-
- # re-scan package data after update
- self.distribution.package_data = find_package_data()
+
def git_prebuild(pkg_dir, build_cmd=build_py):
"""Return extended build or sdist command class for recording commit
@@ -438,10 +419,6 @@ def git_prebuild(pkg_dir, build_cmd=build_py):
class MyBuildPy(build_cmd):
''' Subclass to write commit data into installation tree '''
def run(self):
- if not check_for_submodules():
- print("submodules missing! Run `setup.py submodule` and try again")
- sys.exit(1)
-
build_cmd.run(self)
# this one will only fire for build commands
if hasattr(self, 'build_lib'):
@@ -478,14 +455,14 @@ def git_prebuild(pkg_dir, build_cmd=build_py):
'# GENERATED BY setup.py\n',
'commit = "%s"\n' % repo_commit,
])
- return MyBuildPy
+ return require_submodules(MyBuildPy)
def require_submodules(command):
"""decorator for instructing a command to check for submodules before running"""
class DecoratedCommand(command):
def run(self):
- if not check_for_submodules():
+ if not check_submodule_status(here) == 'clean':
print("submodules missing! Run `setup.py submodule` and try again")
sys.exit(1)
command.run(self)