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)