Repository: sphinx-contrib/spelling

Issue:
Allow multiple wordlists via command line parameter
I have a sphinx build that is embedded in a larger build process and adding/editing the conf.py that is generated is non-trivial.
We have been adding our custom word list via a `-D spelling_word_list_filename=my_words.txt` parameter on the sphinx command line.

The documentation says you can use multiple text files with words to be added to the dictionary, if you set the spelling_word_list_filename to a list.  This works if you set the list in the conf.py file, but using a -D parameter only allows the addition of a single word list.  We'd like to add several, but the way that command line parameter is handled, it is always given to sphinxcontrib-spelling as a string.

It would be nice if I could add a list of filenames via `-D spelling_word_list_filename=[my_words.txt,other_words.txt]` or some similar format.

Looking at the code, I think a small change in builder.py to check the incoming string and, if it starts and ends with square brackets, split it into a list would work.
i.e. just before Line 109 (https://github.com/sphinx-contrib/spelling/blob/master/sphinxcontrib/spelling/builder.py#L109).

Would you consider adding this?  If so, I can probably contribute a pull request to add it.  




Discussion:

Patch:
diff --git a/docs/source/customize.rst b/docs/source/customize.rst
index cb54061..cb2d982 100644
--- a/docs/source/customize.rst
+++ b/docs/source/customize.rst
@@ -27,10 +27,12 @@ Input Options
   String specifying a file containing a list of words known to be
   spelled correctly but that do not appear in the language dictionary
   selected by ``spelling_lang``.  The file should contain one word per
-  line. Refer to the `PyEnchant tutorial`_ for details. To add multiple
-  files use a list, or a comma separated string. This is useful when
-  calling sphinx with ``-D spelling_word_list_filename=...`` which will
-  not accept a list and will only accept a string parameter.
+  line. Refer to the `PyEnchant tutorial`_ for details.
+
+  To add multiple files use a list, or a comma separated string. This
+  is useful when calling sphinx with ``-D
+  spelling_word_list_filename=...`` which will not accept a list and
+  will only accept a string parameter.
 
 ``spelling_word_list_filename=['spelling_wordlist.txt','another_list.txt']``
 
diff --git a/docs/source/history.rst b/docs/source/history.rst
index 53b1b27..d6c0dac 100644
--- a/docs/source/history.rst
+++ b/docs/source/history.rst
@@ -20,7 +20,6 @@ Features
   Added configuration option to limit the number of suggestions
   output. See :doc:`/customize` for more details. Idea contributed by
   Trevor Gross.
-
 - `#169 <https://github.com/sphinx-contrib/spelling/issues/169>`__
   Adds the ability to pass in multiple wordlists via the sphinx
   command line as ``-D spelling_word_list_filename=file1,file2``.
diff --git a/sphinxcontrib/spelling/builder.py b/sphinxcontrib/spelling/builder.py
index e9e5f61..e2b147c 100644
--- a/sphinxcontrib/spelling/builder.py
+++ b/sphinxcontrib/spelling/builder.py
@@ -101,19 +101,27 @@ class SpellingBuilder(Builder):
             mod = importlib.import_module(module_name)
             yield getattr(mod, class_name)
 
-    def get_wordlist_filename(self):
+    def get_configured_wordlist_filenames(self):
+        "Returns the configured wordlist filenames."
         word_list = self.config.spelling_word_list_filename
         if word_list is None:
-            word_list = 'spelling_wordlist.txt'
+            word_list = ['spelling_wordlist.txt']
 
-        if isinstance(word_list, str) and word_list.find(',') > 0:
-            # Wordlist is a list, formatted as a str.
-            # Split it back into a list
+        if isinstance(word_list, str):
+            # Wordlist is a string. Split on comma in case it came
+            # from the command line, via -D, and has multiple values.
             word_list = word_list.split(',')
 
-        if not isinstance(word_list, list):
-            return os.path.join(self.srcdir, word_list)
+        return [
+            os.path.join(self.srcdir, p)
+            for p in word_list
+        ]
 
+    def get_wordlist_filename(self):
+        "Returns the filename of the wordlist to use when checking content."
+        filenames = self.get_configured_wordlist_filenames()
+        if len(filenames) == 1:
+            return filenames[0]
         # In case the user has multiple word lists, we combine them
         # into one large list that we pass on to the checker.
         return self._build_combined_wordlist()
@@ -126,10 +134,8 @@ class SpellingBuilder(Builder):
         combined_word_list = os.path.join(temp_dir,
                                           'spelling_wordlist.txt')
 
-        word_list = self.config.spelling_word_list_filename
-
         with open(combined_word_list, 'w', encoding='UTF-8') as outfile:
-            for word_file in word_list:
+            for word_file in self.get_configured_wordlist_filenames():
                 # Paths are relative
                 long_word_file = os.path.join(self.srcdir, word_file)
                 logger.info('Adding contents of %s to custom word list',


Test patch:
diff --git a/tests/test_builder.py b/tests/test_builder.py
index 8e59d1f..3518b90 100644
--- a/tests/test_builder.py
+++ b/tests/test_builder.py
@@ -13,14 +13,18 @@ import pytest
 from sphinx.application import Sphinx
 
 
-@pytest.fixture
-def sphinx_project(tmpdir):
+def _make_sphinx_project(tmpdir):
     srcdir = tmpdir.mkdir('src')
     outdir = tmpdir.mkdir('out')
     add_file(srcdir, 'conf.py', '''
     extensions = [ 'sphinxcontrib.spelling' ]
     ''')
-    yield (srcdir, outdir)
+    return (srcdir, outdir)
+
+
+@pytest.fixture
+def sphinx_project(tmpdir):
+    yield _make_sphinx_project(tmpdir)
 
 
 @contextlib.contextmanager
@@ -160,6 +164,75 @@ def test_several_word_lists(sphinx_project):
     assert '(tihs)' in output_text
 
 
+def _wordlist_sphinx_project(tmpdir, conf_contents):
+    srcdir, outdir = _make_sphinx_project(tmpdir)
+    add_file(srcdir, 'conf.py', conf_contents)
+    add_file(srcdir, 'test_wordlist.txt', '''
+    txt
+    ''')
+    add_file(srcdir, 'test_wordlist2.txt', '''
+    mispelled
+    ''')
+    stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents')
+    return (srcdir, outdir, stdout, stderr, app)
+
+
+def test_word_list_default(tmpdir):
+    srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project(
+        tmpdir,
+        '''
+        extensions = ['sphinxcontrib.spelling']
+        ''',
+    )
+    results = app.builder.get_configured_wordlist_filenames()
+    assert len(results) == 1
+    assert os.path.basename(results[0]) == 'spelling_wordlist.txt'
+
+
+def test_one_word_list_str(tmpdir):
+    srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project(
+        tmpdir,
+        '''
+        extensions = ['sphinxcontrib.spelling']
+        spelling_word_list_filename='test_wordlist.txt'
+        ''',
+    )
+    results = app.builder.get_configured_wordlist_filenames()
+    assert len(results) == 1
+    assert os.path.basename(results[0]) == 'test_wordlist.txt'
+
+
+def test_multiple_word_list_str(tmpdir):
+    # We don't expect anyone to set up their conf.py this way but it
+    # simulates passing the configuration option from the command line
+    # using -D.
+    srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project(
+        tmpdir,
+        '''
+        extensions = ['sphinxcontrib.spelling']
+        spelling_word_list_filename='test_wordlist.txt,test_wordlist2.txt'
+        ''',
+    )
+    results = app.builder.get_configured_wordlist_filenames()
+    assert len(results) == 2
+    assert os.path.basename(results[0]) == 'test_wordlist.txt'
+    assert os.path.basename(results[1]) == 'test_wordlist2.txt'
+
+
+def test_multiple_word_list_list(tmpdir):
+    srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project(
+        tmpdir,
+        '''
+        extensions = ['sphinxcontrib.spelling']
+        spelling_word_list_filename=['test_wordlist.txt', 'test_wordlist2.txt']
+        ''',
+    )
+    results = app.builder.get_configured_wordlist_filenames()
+    assert len(results) == 2
+    assert os.path.basename(results[0]) == 'test_wordlist.txt'
+    assert os.path.basename(results[1]) == 'test_wordlist2.txt'
+
+
 def test_ignore_file(sphinx_project):
     srcdir, outdir = sphinx_project
     add_file(srcdir, 'conf.py', '''