From b5cfce7bd17213ee455ece6ec5589b3052544ee7 Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Wed, 10 Feb 2021 20:58:10 +0100 Subject: [PATCH] Skip duplicated error message when omitting the traceback The new BuildError exception is good for skipping the traceback, but if it's skipped, now the two copies of the error mesage (one from logging, one from reaching SystemExit) immediately follow each other, which looks strange. So, skip logging the exception's message when encountering a BuildError in _populate_page and _build_page. --- mkdocs/commands/build.py | 12 ++++++++++-- mkdocs/tests/build_tests.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/mkdocs/commands/build.py b/mkdocs/commands/build.py index 643fec3f..5e8991e5 100644 --- a/mkdocs/commands/build.py +++ b/mkdocs/commands/build.py @@ -179,7 +179,11 @@ def _populate_page(page, config, files, dirty=False): 'page_content', page.content, page=page, config=config, files=files ) except Exception as e: - log.error("Error reading page '{}': {}".format(page.file.src_path, e)) + message = f"Error reading page '{page.file.src_path}':" + # Prevent duplicated the error message because it will be printed immediately afterwards. + if not isinstance(e, BuildError): + message += f" {e}" + log.error(message) raise @@ -227,7 +231,11 @@ def _build_page(page, config, doc_files, nav, env, dirty=False): # Deactivate page page.active = False except Exception as e: - log.error("Error building page '{}': {}".format(page.file.src_path, e)) + message = f"Error building page '{page.file.src_path}':" + # Prevent duplicated the error message because it will be printed immediately afterwards. + if not isinstance(e, BuildError): + message += f" {e}" + log.error(message) raise diff --git a/mkdocs/tests/build_tests.py b/mkdocs/tests/build_tests.py index 4a8bb4ba..2fb01f0a 100644 --- a/mkdocs/tests/build_tests.py +++ b/mkdocs/tests/build_tests.py @@ -3,6 +3,7 @@ from unittest import mock import unittest +from mkdocs.exceptions import PluginError from mkdocs.structure.pages import Page from mkdocs.structure.files import File, Files from mkdocs.structure.nav import get_navigation @@ -334,6 +335,21 @@ class BuildTests(PathAssertionMixin, unittest.TestCase): ) self.assert_mock_called_once(mock_open) + @tempdir(files={'index.md': 'page content'}) + @mock.patch('mkdocs.plugins.PluginCollection.run_event', side_effect=PluginError('Error message.')) + def test_populate_page_read_plugin_error(self, docs_dir, mock_open): + cfg = load_config(docs_dir=docs_dir) + file = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) + page = Page('Foo', file, cfg) + with self.assertLogs('mkdocs', level='ERROR') as cm: + self.assertRaises(PluginError, build._populate_page, page, cfg, Files([file])) + self.assertEqual( + cm.output, [ + "ERROR:mkdocs.commands.build:Error reading page 'index.md':" + ] + ) + self.assert_mock_called_once(mock_open) + # Test build._build_page @tempdir() @@ -433,6 +449,25 @@ class BuildTests(PathAssertionMixin, unittest.TestCase): ) self.assert_mock_called_once(mock_write_file) + @tempdir() + @mock.patch('mkdocs.plugins.PluginCollection.run_event', side_effect=PluginError('Error message.')) + def test_build_page_plugin_error(self, site_dir, mock_write_file): + cfg = load_config(site_dir=site_dir, nav=['index.md'], plugins=[]) + files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]) + nav = get_navigation(files, cfg) + page = files.documentation_pages()[0].page + # Fake populate page + page.title = 'Title' + page.markdown = 'page content' + page.content = '

page content

' + with self.assertLogs('mkdocs', level='ERROR') as cm: + self.assertRaises(PluginError, build._build_page, page, cfg, files, nav, cfg['theme'].get_env()) + self.assertEqual( + cm.output, + ["ERROR:mkdocs.commands.build:Error building page 'index.md':"] + ) + self.assert_mock_called_once(mock_write_file) + # Test build.build @tempdir(files={