Skip to content

Commit 8705717

Browse files
stsewdagjohnson
authored andcommitted
Implement sphinx key from v2 config (#4482)
* Test conf.py default value * Fix conf.py path * Don't skip tests * Expose config object in builders * Use doctype from config * Pass python_env in tests * Fix old test * Implement sphinx key * Implement fail_on_warning * Skip tests for mkdocs * Fix raising wrong exception * Fix tests * Remove search from tests * Return the absolute path * Check for None * Use the config file * Fix test * Fix test * Remove repetition * Break and fix test
1 parent 51717ab commit 8705717

File tree

7 files changed

+166
-45
lines changed

7 files changed

+166
-45
lines changed

readthedocs/config/config.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,17 @@ def build(self):
526526
def doctype(self):
527527
return self.defaults['doctype']
528528

529+
@property
530+
def sphinx(self):
531+
config_file = self.defaults['sphinx_configuration']
532+
if config_file is not None:
533+
config_file = os.path.join(self.base_path, config_file)
534+
return Sphinx(
535+
builder=self.doctype,
536+
configuration=config_file,
537+
fail_on_warning=False,
538+
)
539+
529540

530541
class BuildConfigV2(BuildConfigBase):
531542

@@ -955,7 +966,8 @@ def get_configuration_class(version):
955966
version = int(version)
956967
return configurations_class[version]
957968
except (KeyError, ValueError):
958-
raise ConfigError(
959-
'Invalid version of the configuration file',
969+
raise InvalidConfig(
970+
'version',
960971
code=VERSION_INVALID,
972+
error_message='Invalid version of the configuration file',
961973
)

readthedocs/doc_builder/backends/sphinx.py

+21-11
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,14 @@ class BaseSphinx(BaseBuilder):
4141

4242
def __init__(self, *args, **kwargs):
4343
super(BaseSphinx, self).__init__(*args, **kwargs)
44+
self.config_file = self.config.sphinx.configuration
4445
try:
46+
if not self.config_file:
47+
self.config_file = self.project.conf_file(self.version.slug)
4548
self.old_artifact_path = os.path.join(
46-
self.project.conf_dir(self.version.slug), self.sphinx_build_dir)
49+
os.path.dirname(self.config_file),
50+
self.sphinx_build_dir
51+
)
4752
except ProjectConfigurationError:
4853
docs_dir = self.docs_dir()
4954
self.old_artifact_path = os.path.join(
@@ -69,7 +74,7 @@ def get_config_params(self):
6974
# TODO this should be handled better in the theme
7075
conf_py_path = os.path.join(
7176
os.path.sep,
72-
self.version.get_conf_py_path(),
77+
self.config_file,
7378
'',
7479
)
7580
remote_version = self.version.commit_name
@@ -151,15 +156,16 @@ def get_config_params(self):
151156

152157
def append_conf(self, **__):
153158
"""Find or create a ``conf.py`` with a rendered ``doc_builder/conf.py.tmpl`` appended"""
154-
try:
155-
self.version.get_conf_py_path()
156-
except ProjectConfigurationError:
159+
if self.config_file is None:
157160
master_doc = self.create_index(extension='rst')
158161
self._write_config(master_doc=master_doc)
159162

160163
try:
161-
outfile_path = self.project.conf_file(self.version.slug)
162-
outfile = codecs.open(outfile_path, encoding='utf-8', mode='a')
164+
self.config_file = (
165+
self.config_file or
166+
self.project.conf_file(self.version.slug)
167+
)
168+
outfile = codecs.open(self.config_file, encoding='utf-8', mode='a')
163169
except (ProjectConfigurationError, IOError):
164170
trace = sys.exc_info()[2]
165171
six.reraise(
@@ -183,7 +189,7 @@ def append_conf(self, **__):
183189
self.run(
184190
'cat',
185191
os.path.relpath(
186-
outfile_path,
192+
self.config_file,
187193
self.project.checkout_path(self.version.slug),
188194
),
189195
cwd=self.project.checkout_path(self.version.slug),
@@ -199,6 +205,8 @@ def build(self):
199205
]
200206
if self._force:
201207
build_command.append('-E')
208+
if self.config.sphinx.fail_on_warning:
209+
build_command.append('-W')
202210
build_command.extend([
203211
'-b',
204212
self.sphinx_builder,
@@ -210,8 +218,10 @@ def build(self):
210218
self.sphinx_build_dir,
211219
])
212220
cmd_ret = self.run(
213-
*build_command, cwd=project.conf_dir(self.version.slug),
214-
bin_path=self.python_env.venv_bin())
221+
*build_command,
222+
cwd=os.path.dirname(self.config_file),
223+
bin_path=self.python_env.venv_bin()
224+
)
215225
return cmd_ret.successful
216226

217227

@@ -353,7 +363,7 @@ class PdfBuilder(BaseSphinx):
353363

354364
def build(self):
355365
self.clean()
356-
cwd = self.project.conf_dir(self.version.slug)
366+
cwd = os.path.dirname(self.config_file)
357367

358368
# Default to this so we can return it always.
359369
self.run(

readthedocs/doc_builder/base.py

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def __init__(self, build_env, python_env, force=False):
4646
self.python_env = python_env
4747
self.version = build_env.version
4848
self.project = build_env.project
49+
self.config = python_env.config
4950
self._force = force
5051
self.target = self.project.artifact_path(
5152
version=self.version.slug, type_=self.type)

readthedocs/doc_builder/config.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ def load_yaml_config(version):
3131
python_version = 3 if project.python_interpreter == 'python3' else 2
3232
allow_v2 = project.has_feature(Feature.ALLOW_V2_CONFIG_FILE)
3333
try:
34-
sphinx_configuration = version.get_conf_py_path()
34+
sphinx_configuration = path.join(
35+
version.get_conf_py_path(),
36+
'conf.py'
37+
)
3538
except ProjectConfigurationError:
3639
sphinx_configuration = None
3740

readthedocs/projects/tasks.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ def build_docs(self):
701701

702702
def build_docs_html(self):
703703
"""Build HTML docs."""
704-
html_builder = get_builder_class(self.project.documentation_type)(
704+
html_builder = get_builder_class(self.config.doctype)(
705705
build_env=self.build_env,
706706
python_env=self.python_env,
707707
)

readthedocs/rtd_tests/tests/test_config_integration.py

+46-8
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ def test_requirements_file(self, load_config):
232232
self.assertEqual(config.python.requirements, '__init__.py')
233233

234234

235-
@pytest.mark.skip
236235
@pytest.mark.django_db
237236
@mock.patch('readthedocs.projects.models.Project.checkout_path')
238237
class TestLoadConfigV2(object):
@@ -290,12 +289,10 @@ def test_report_using_invalid_version(self, checkout_path, tmpdir):
290289

291290
@pytest.mark.parametrize('config', [{}, {'formats': []}])
292291
@patch('readthedocs.projects.models.Project.repo_nonblockinglock', new=MagicMock())
293-
@patch('readthedocs.doc_builder.backends.sphinx.SearchBuilder.build')
294292
@patch('readthedocs.doc_builder.backends.sphinx.HtmlBuilder.build')
295293
@patch('readthedocs.doc_builder.backends.sphinx.HtmlBuilder.append_conf')
296294
def test_build_formats_default_empty(
297-
self, append_conf, html_build, search_build,
298-
checkout_path, config, tmpdir):
295+
self, append_conf, html_build, checkout_path, config, tmpdir):
299296
"""
300297
The default value for formats is [], which means no extra
301298
formats are build.
@@ -304,22 +301,26 @@ def test_build_formats_default_empty(
304301
self.create_config_file(tmpdir, config)
305302

306303
update_docs = self.get_update_docs_task()
304+
python_env = Virtualenv(
305+
version=self.version,
306+
build_env=update_docs.build_env,
307+
config=update_docs.config
308+
)
309+
update_docs.python_env = python_env
307310
outcomes = update_docs.build_docs()
308311

309312
# No extra formats were triggered
310313
assert outcomes['html']
311-
assert outcomes['search']
312314
assert not outcomes['localmedia']
313315
assert not outcomes['pdf']
314316
assert not outcomes['epub']
315317

316318
@patch('readthedocs.projects.models.Project.repo_nonblockinglock', new=MagicMock())
317319
@patch('readthedocs.projects.tasks.UpdateDocsTaskStep.build_docs_class')
318-
@patch('readthedocs.doc_builder.backends.sphinx.SearchBuilder.build')
319320
@patch('readthedocs.doc_builder.backends.sphinx.HtmlBuilder.build')
320321
@patch('readthedocs.doc_builder.backends.sphinx.HtmlBuilder.append_conf')
321322
def test_build_formats_only_pdf(
322-
self, append_conf, html_build, search_build, build_docs_class,
323+
self, append_conf, html_build, build_docs_class,
323324
checkout_path, tmpdir):
324325
"""
325326
Only the pdf format is build.
@@ -328,11 +329,17 @@ def test_build_formats_only_pdf(
328329
self.create_config_file(tmpdir, {'formats': ['pdf']})
329330

330331
update_docs = self.get_update_docs_task()
332+
python_env = Virtualenv(
333+
version=self.version,
334+
build_env=update_docs.build_env,
335+
config=update_docs.config
336+
)
337+
update_docs.python_env = python_env
338+
331339
outcomes = update_docs.build_docs()
332340

333341
# Only pdf extra format was triggered
334342
assert outcomes['html']
335-
assert outcomes['search']
336343
build_docs_class.assert_called_with('sphinx_pdf')
337344
assert outcomes['pdf']
338345
assert not outcomes['localmedia']
@@ -642,6 +649,35 @@ def test_sphinx_configuration_default(
642649
append_conf.assert_called_once()
643650
move.assert_called_once()
644651

652+
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.move')
653+
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.append_conf')
654+
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.run')
655+
def test_sphinx_configuration_default(
656+
self, run, append_conf, move, checkout_path, tmpdir):
657+
"""Should be default to find a conf.py file."""
658+
checkout_path.return_value = str(tmpdir)
659+
660+
apply_fs(tmpdir, {'conf.py': ''})
661+
self.create_config_file(tmpdir, {})
662+
self.project.conf_py_file = ''
663+
self.project.save()
664+
665+
update_docs = self.get_update_docs_task()
666+
config = update_docs.config
667+
python_env = Virtualenv(
668+
version=self.version,
669+
build_env=update_docs.build_env,
670+
config=config
671+
)
672+
update_docs.python_env = python_env
673+
674+
update_docs.build_docs_html()
675+
676+
args, kwargs = run.call_args
677+
assert kwargs['cwd'] == str(tmpdir)
678+
append_conf.assert_called_once()
679+
move.assert_called_once()
680+
645681
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.move')
646682
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.append_conf')
647683
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.run')
@@ -716,6 +752,7 @@ def test_sphinx_fail_on_warning(
716752
append_conf.assert_called_once()
717753
move.assert_called_once()
718754

755+
@pytest.mark.skip
719756
@patch('readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.move')
720757
@patch('readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.append_conf')
721758
@patch('readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.run')
@@ -754,6 +791,7 @@ def test_mkdocs_configuration(
754791
append_conf.assert_called_once()
755792
move.assert_called_once()
756793

794+
@pytest.mark.skip
757795
@patch('readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.move')
758796
@patch('readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.append_conf')
759797
@patch('readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.run')

0 commit comments

Comments
 (0)