From e2a3480735c2d74da7831edba5eaa126a5a3a213 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Thu, 13 May 2021 15:20:35 -0400 Subject: [PATCH] Remove hard dependency on lunr.py (#2402) Begin deprecation of 'python' option of 'plugins.search.prebuild_index'. --- docs/about/release-notes.md | 13 +++++++++++++ docs/user-guide/configuration.md | 22 +++++++++------------- mkdocs/contrib/search/__init__.py | 7 +++++++ mkdocs/contrib/search/search_index.py | 26 +++++++++++++++++++------- mkdocs/tests/search_tests.py | 12 ++++++++++++ setup.py | 1 - 6 files changed, 60 insertions(+), 21 deletions(-) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index d121b81c..c38e6ebe 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -138,6 +138,19 @@ The `mkdocs.utils.warning_filter` is deprecated and now does nothing. Plugins To ensure any warnings get counted, simply log them to the `mkdocs` log (i.e: `mkdocs.plugins.pluginname`). +The `python` method of the `plugins.search.prebuild_index` configuration option +is pending deprecation as of version 1.2. It is expected that in version 1.3 it +will raise a warning if used and in version 1.4 it will raise an error. Users +are encouraged to use an alternate method to generate a prebuilt index for +search. + +The `lunr` and `lunr[languages]` dependencies are no longer installed by +default. The dependencies are only needed for the rare user who prebuilds the +search index and uses the `python` option, which is now pending deprecation. If +you use this feature, then you will need to manually install `lunr` and +`lunr[languages]`. A warning is issued if the dependencies are needed but not +installed. + ### Other Changes and Additions to Version 1.2 * Bugfix: Properly process navigation child items in `_get_by_type` when diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index ef7384b0..4e5b6c29 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -607,22 +607,16 @@ You may [contribute additional languages]. ##### **prebuild_index** Optionally generates a pre-built index of all pages, which provides some -performance improvements for larger sites. Before enabling, check that the +performance improvements for larger sites. Before enabling, confirm that the theme you are using explicitly supports using a prebuilt index (the builtin -themes do). +themes do). Set to `true` to enable. -There are two options for prebuilding the index: +!!! warning -Using [Node.js] setting `prebuild_index` to `True` or `node`. This option -requires that Node.js be installed and the command `node` be on the system -path. If this feature is enabled and fails for any reason, a warning is issued. -You may use the `--strict` flag when building to cause such a failure to raise -an error instead. - -Using [Lunr.py] setting `prebuild_index` to `python`. Lunr.py is installed -as part of mkdocs and guarantees compatibility with Lunr.js even on languages -other than English. If you find substantial inconsistencies or problems please -report it on [Lunr.py's issues] and fall back to the Node.js version. + This option requires that [Node.js] be installed and the command `node` be + on the system path. If the call to `node` fails for any reason, a warning + is issued and the build continues uninterupted. You may use the `--strict` + flag when building to cause such a failure to raise an error instead. !!! Note @@ -634,6 +628,8 @@ report it on [Lunr.py's issues] and fall back to the Node.js version. **default**: `False` +[Node.js]: https://nodejs.org/ + ##### **indexing** Configures what strategy the search indexer will use when building the index diff --git a/mkdocs/contrib/search/__init__.py b/mkdocs/contrib/search/__init__.py index 5a56830a..1ca09863 100644 --- a/mkdocs/contrib/search/__init__.py +++ b/mkdocs/contrib/search/__init__.py @@ -54,6 +54,13 @@ class SearchPlugin(BasePlugin): # lang setting undefined. Set default based on theme locale validate = self.config_scheme[0][1].run_validation self.config['lang'] = validate(config['theme']['locale'].language) + # The `python` method of `prebuild_index` is pending deprecation as of version 1.2. + # TODO: Raise a deprecation warning in a future release (1.3?). + if self.config['prebuild_index'] == 'python': + log.info( + "The 'python' method of the search plugin's 'prebuild_index' config option " + "is pending deprecation and will not be supported in a future release." + ) return config def on_pre_build(self, config, **kwargs): diff --git a/mkdocs/contrib/search/search_index.py b/mkdocs/contrib/search/search_index.py index f6f7ceaa..bef81393 100644 --- a/mkdocs/contrib/search/search_index.py +++ b/mkdocs/contrib/search/search_index.py @@ -4,10 +4,14 @@ import json import logging import subprocess -from lunr import lunr - from html.parser import HTMLParser +try: + from lunr import lunr + haslunrpy = True +except ImportError: + haslunrpy = False + log = logging.getLogger(__name__) @@ -121,11 +125,19 @@ class SearchIndex: except (OSError, ValueError) as e: log.warning(f'Failed to pre-build search index. Error: {e}') elif self.config['prebuild_index'] == 'python': - idx = lunr( - ref='location', fields=('title', 'text'), documents=self._entries, - languages=self.config['lang']) - page_dicts['index'] = idx.serialize() - data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':')) + if haslunrpy: + idx = lunr( + ref='location', fields=('title', 'text'), documents=self._entries, + languages=self.config['lang']) + page_dicts['index'] = idx.serialize() + data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':')) + else: + log.warning( + "Failed to pre-build search index. The 'python' method was specified; " + "however, the 'lunr.py' library does not appear to be installed. Try " + "installing it with 'pip install lunr'. If you are using any language " + "other than English you will also need to install 'lunr[languages]'." + ) return data diff --git a/mkdocs/tests/search_tests.py b/mkdocs/tests/search_tests.py index 9d071a51..596da48e 100644 --- a/mkdocs/tests/search_tests.py +++ b/mkdocs/tests/search_tests.py @@ -563,6 +563,7 @@ class SearchIndexTests(unittest.TestCase): self.assertEqual(mock_popen_obj.communicate.call_count, 0) self.assertEqual(result, expected) + @unittest.skipUnless(search_index.haslunrpy, 'lunr.py is not installed') @mock.patch('mkdocs.contrib.search.search_index.lunr', autospec=True) def test_prebuild_index_python(self, mock_lunr): mock_lunr.return_value.serialize.return_value = {'mock': 'index'} @@ -576,6 +577,17 @@ class SearchIndexTests(unittest.TestCase): self.assertEqual(mock_lunr.call_count, 1) self.assertEqual(result, expected) + @unittest.skipIf(search_index.haslunrpy, 'lunr.py is installed') + def test_prebuild_index_python_missing_lunr(self): + # When the lunr.py dependencies are not installed no prebuilt index is created. + index = search_index.SearchIndex(prebuild_index='python', lang='en') + expected = { + 'docs': [], + 'config': {'prebuild_index': 'python', 'lang': 'en'} + } + result = json.loads(index.generate_search_index()) + self.assertEqual(result, expected) + @mock.patch('subprocess.Popen', autospec=True) def test_prebuild_index_node(self, mock_popen): # See https://stackoverflow.com/a/36501078/866026 diff --git a/setup.py b/setup.py index 1c43fe7c..43b6f4ab 100755 --- a/setup.py +++ b/setup.py @@ -61,7 +61,6 @@ setup( 'click>=3.3', 'Jinja2>=2.10.1', 'livereload>=2.5.1', - 'lunr[languages]==0.5.9', # must support lunr.js version included in search 'Markdown>=3.2.1', 'PyYAML>=3.10', 'tornado>=5.0',