diff --git a/sphinx_autobuild/__init__.py b/sphinx_autobuild/__init__.py index fd4902c..f5e2d5b 100755 --- a/sphinx_autobuild/__init__.py +++ b/sphinx_autobuild/__init__.py @@ -21,6 +21,8 @@ from livereload import Server +from subprocess import call + from watchdog.observers import Observer from watchdog.observers.polling import PollingObserver from watchdog.events import FileSystemEventHandler @@ -129,12 +131,13 @@ class SphinxBuilder(object): """ Helper class to run sphinx-build command. """ - def __init__(self, outdir, args, ignored=None, regex_ignored=None): + def __init__(self, outdir, args, ignored=None, regex_ignored=None, exec_script=None): self._outdir = outdir self._args = args self._ignored = ignored or [] self._ignored.append(outdir) self._regex_ignored = [re.compile(r) for r in regex_ignored or []] + self._exec_script = exec_script def is_ignored(self, src_path): path = self.get_relative_path(src_path) @@ -159,10 +162,22 @@ def __call__(self, watcher, src_path): self.build(path) def build(self, path=None): + if self._exec_script: + self.execute_script() + + self._build(path) + + def execute_script(self): + code = call(self._exec_script, shell=True) + if code != 0: + sys.stdout.write("Warning: '{}' returned with status code {}\n".format(self._exec_script, code)) + + def _build(self, path): if path: pre = '+--------- {0} changed '.format(path) else: pre = '+--------- manually triggered build ' + sys.stdout.write('\n') sys.stdout.write(pre) sys.stdout.write('-' * (81 - len(pre))) @@ -230,6 +245,7 @@ def get_parser(): parser.add_argument('-H', '--host', type=str, default='127.0.0.1') parser.add_argument('-r', '--re-ignore', action='append', default=[]) parser.add_argument('-i', '--ignore', action='append', default=[]) + parser.add_argument('-x', '--exec_script', help='specify prebuild script') parser.add_argument('--poll', dest='use_polling', action='store_true', default=False) parser.add_argument('--no-initial', dest='initial_build', @@ -297,7 +313,7 @@ def main(): else: portn = port_for.select_random() - builder = SphinxBuilder(outdir, build_args, ignored, re_ignore) + builder = SphinxBuilder(outdir, build_args, ignored, re_ignore, args.exec_script) server = Server( watcher=LivereloadWatchdogWatcher(use_polling=args.use_polling), ) diff --git a/sphinx_autobuild/test/test_autobuild.py b/sphinx_autobuild/test/test_autobuild.py index 4368472..f047e2e 100644 --- a/sphinx_autobuild/test/test_autobuild.py +++ b/sphinx_autobuild/test/test_autobuild.py @@ -17,19 +17,27 @@ def patched_args(sys_args, monkeypatch): monkeypatch.setattr('sys.argv', sys_args) -@pytest.mark.parametrize('sys_args', ( - ['sphinx-autobuild', '/source', '/output'], +@pytest.mark.parametrize('sys_args, with_script', ( + (['sphinx-autobuild', '/source', '/output'], False), + (['sphinx-autobuild', '/source', '/output', + '--exec_script', '/script'], True), )) @mock.patch.object(observers.Observer, 'schedule') @mock.patch.object(livereload.Server, 'serve') -@mock.patch('sphinx_autobuild.SphinxBuilder.build') +@mock.patch('sphinx_autobuild.SphinxBuilder.execute_script') +@mock.patch('sphinx_autobuild.SphinxBuilder._build') @mock.patch('os.makedirs') -def test_autobuild(mock_makedirs, mock_builder, mock_serve, mock_schedule): +def test_autobuild(mock_makedirs, mock_builder, mock_execute_script, + mock_serve, mock_schedule, with_script): """ Test autobuild entry point. """ main() - mock_builder.assert_called_once_with() + mock_builder.assert_called_once_with(None) + if with_script: + mock_execute_script.assert_called_once_with() + else: + mock_execute_script.assert_not_called() mock_makedirs.assert_called_once_with('/output') mock_serve.assert_called_once_with( host='127.0.0.1', root='/output', port=8000) @@ -40,7 +48,8 @@ def test_autobuild(mock_makedirs, mock_builder, mock_serve, mock_schedule): '--port', '8888', '--host', 'example.org', '--ignore', '/ignored', - '--watch', '/external'], + '--watch', '/external', + '--exec_script', '/script'], )) @mock.patch.object(observers.Observer, 'schedule') @mock.patch.object(livereload.Server, 'serve') @@ -62,7 +71,8 @@ def test_autobuild_with_options(mock_makedirs, # --ignore mock_builder.assert_called_once_with( - '/output', ['/source', '/output'], ['/ignored'], DEFAULT_IGNORE_REGEX) + '/output', ['/source', '/output'], ['/ignored'], + DEFAULT_IGNORE_REGEX, '/script') # --watch calls = [call('/source', mock_builder.return_value),