Skip to content

Stop creating a conf.py automatically and doing magic around README handling #5609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions readthedocs/doc_builder/backends/mkdocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ def load_yaml_config(self):
try:
return yaml.safe_load(open(self.yaml_file, 'r'),)
except IOError:
return {
'site_name': self.version.project.name,
}
raise MkDocsYAMLParseError(MkDocsYAMLParseError.NOT_FOUND)
except yaml.YAMLError as exc:
note = ''
if hasattr(exc, 'problem_mark'):
Expand Down
25 changes: 7 additions & 18 deletions readthedocs/doc_builder/backends/sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from readthedocs.builds import utils as version_utils
from readthedocs.projects.exceptions import ProjectConfigurationError
from readthedocs.projects.models import Feature
from readthedocs.projects.utils import safe_write

from ..base import BaseBuilder, restoring_chdir
from ..constants import PDF_RE
Expand Down Expand Up @@ -53,20 +52,6 @@ def __init__(self, *args, **kwargs):
self.sphinx_build_dir,
)

def _write_config(self, master_doc='index'):
"""Create ``conf.py`` if it doesn't exist."""
docs_dir = self.docs_dir()
conf_template = render_to_string(
'sphinx/conf.py.conf',
{
'project': self.project,
'version': self.version,
'master_doc': master_doc,
},
)
conf_file = os.path.join(docs_dir, 'conf.py')
safe_write(conf_file, conf_template)

def get_config_params(self):
"""Get configuration parameters to be rendered into the conf file."""
# TODO this should be handled better in the theme
Expand Down Expand Up @@ -161,13 +146,14 @@ def get_config_params(self):

def append_conf(self, **__):
"""
Find or create a ``conf.py`` and appends default content.
Find a ``conf.py`` and appends default content.

The default content is rendered from ``doc_builder/conf.py.tmpl``.
"""
if self.config_file is None:
master_doc = self.create_index(extension='rst')
self._write_config(master_doc=master_doc)
raise ProjectConfigurationError(
ProjectConfigurationError.NOT_FOUND
)

try:
self.config_file = (
Expand All @@ -177,6 +163,9 @@ def append_conf(self, **__):
except IOError:
raise ProjectConfigurationError(ProjectConfigurationError.NOT_FOUND)

# Create an index file if there is None.
self.create_index(extension='rst')

# Append config to project conf file
tmpl = template_loader.get_template('doc_builder/conf.py.tmpl')
rendered = tmpl.render(self.get_config_params())
Expand Down
9 changes: 1 addition & 8 deletions readthedocs/doc_builder/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,6 @@ def create_index(self, extension='md', **__):
'index.{ext}'.format(ext=extension),
)
if not os.path.exists(index_filename):
readme_filename = os.path.join(
docs_dir,
'README.{ext}'.format(ext=extension),
)
if os.path.exists(readme_filename):
return 'README'

index_file = open(index_filename, 'w+')
index_text = """

Expand All @@ -118,7 +111,7 @@ def create_index(self, extension='md', **__):

This is an autogenerated index file.

Please create an ``index.{ext}`` or ``README.{ext}`` file with your own content
Please create an ``index.{ext}`` file with your own content
under the root (or ``/docs``) directory in your repository.

If you want to use another markup, choose a different builder in your settings.
Expand Down
4 changes: 4 additions & 0 deletions readthedocs/doc_builder/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ class MkDocsYAMLParseError(BuildEnvironmentError):
'The "{config}" config from your MkDocs YAML config file has to be a '
'a list of relative paths.',
)
NOT_FOUND = ugettext_noop(
'A configuration file was not found. '
'Make sure you have a "mkdocs.yaml" file in your repository.',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it matters, but official MkDocs uses mkdocs.yml to refer this file. I suppose it's better to follow their convention here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@humitos Fixed. :)

)
20 changes: 0 additions & 20 deletions readthedocs/projects/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,3 @@ def version_from_slug(slug, version):
else:
v = Version.objects.get(project__slug=slug, slug=version)
return v


def safe_write(filename, contents):
"""
Normalize and write to filename.

Write ``contents`` to the given ``filename``. If the filename's
directory does not exist, it is created. Contents are written as UTF-8,
ignoring any characters that cannot be encoded as UTF-8.

:param filename: Filename to write to
:param contents: File contents to write to file
"""
dirname = os.path.dirname(filename)
if not os.path.exists(dirname):
os.makedirs(dirname)

with open(filename, 'w', encoding='utf-8', errors='ignore') as fh:
fh.write(contents)
fh.close()
83 changes: 15 additions & 68 deletions readthedocs/rtd_tests/tests/test_doc_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,23 @@ def test_conf_py_path(self, checkout_path, docs_dir):
)

@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.docs_dir')
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.create_index')
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.get_config_params')
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.run')
@patch('readthedocs.builds.models.Version.get_conf_py_path')
@patch('readthedocs.projects.models.Project.checkout_path')
def test_create_conf_py(
def test_project_without_conf_py(
self, checkout_path, get_conf_py_path, _,
get_config_params, create_index, docs_dir,
get_config_params, docs_dir,
):
"""
Test for a project without ``conf.py`` file.

When this happen, the ``get_conf_py_path`` raises a
``ProjectConfigurationError`` which is captured by our own code and
generates a conf.py file based using our own template.

This template should be properly rendered in Python2 and Python3 without
any kind of exception raised by ``append_conf`` (we were originally
having a ``TypeError`` because of an encoding problem in Python3)
``ProjectConfigurationError`` which is captured by our own code.
"""
tmp_dir = tempfile.mkdtemp()
checkout_path.return_value = tmp_dir
docs_dir.return_value = tmp_dir
create_index.return_value = 'README.rst'
get_config_params.return_value = {}
get_conf_py_path.side_effect = ProjectConfigurationError
python_env = Virtualenv(
Expand All @@ -105,36 +98,20 @@ def test_create_conf_py(
build_env=self.build_env,
python_env=python_env,
)
try:
with pytest.raises(
ProjectConfigurationError,
match=ProjectConfigurationError.NOT_FOUND
):
base_sphinx.append_conf()
except Exception:
pytest.fail('Exception was generated when append_conf called.')

# Check the content generated by our method is the same than what we
# expects from a pre-generated file
generated_conf_py = os.path.join(base_sphinx.docs_dir(), 'conf.py')
expected_conf_py = os.path.join(
os.path.dirname(__file__),
'..',
'files',
'conf.py',
)
with open(generated_conf_py) as gf, open(expected_conf_py) as ef:
autogenerated_confpy_lines = 28
self.assertEqual(
gf.readlines()[:autogenerated_confpy_lines],
ef.readlines()[:autogenerated_confpy_lines],
)

@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.docs_dir')
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.create_index')
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.get_config_params')
@patch('readthedocs.doc_builder.backends.sphinx.BaseSphinx.run')
@patch('readthedocs.builds.models.Version.get_conf_py_path')
@patch('readthedocs.projects.models.Project.checkout_path')
def test_multiple_conf_py(
self, checkout_path, get_conf_py_path, _, get_config_params,
create_index, docs_dir,
self, checkout_path, get_conf_py_path,
_, get_config_params, docs_dir
):
"""
Test for a project with multiple ``conf.py`` files.
Expand All @@ -148,7 +125,6 @@ def test_multiple_conf_py(
tmp_docs_dir.join('test').mkdir().join('conf.py').write('')
docs_dir.return_value = str(tmp_docs_dir)
checkout_path.return_value = str(tmp_docs_dir)
create_index.return_value = 'README.rst'
get_config_params.return_value = {}
get_conf_py_path.side_effect = ProjectConfigurationError
python_env = Virtualenv(
Expand Down Expand Up @@ -281,7 +257,7 @@ def test_get_theme_name_with_feature_flag(self, checkout_path, run):

@patch('readthedocs.doc_builder.base.BaseBuilder.run')
@patch('readthedocs.projects.models.Project.checkout_path')
def test_append_conf_create_yaml(self, checkout_path, run):
def test_mkdocs_yaml_not_found(self, checkout_path, run):
tmpdir = tempfile.mkdtemp()
os.mkdir(os.path.join(tmpdir, 'docs'))
checkout_path.return_value = tmpdir
Expand All @@ -295,40 +271,11 @@ def test_append_conf_create_yaml(self, checkout_path, run):
build_env=self.build_env,
python_env=python_env,
)
self.searchbuilder.append_conf()

run.assert_called_with('cat', 'mkdocs.yml', cwd=mock.ANY)

# There is a mkdocs.yml file created
generated_yaml = os.path.join(tmpdir, 'mkdocs.yml')
self.assertTrue(os.path.exists(generated_yaml))
config = yaml.safe_load(open(generated_yaml))
self.assertEqual(
config['docs_dir'],
os.path.join(tmpdir, 'docs'),
)
self.assertEqual(
config['extra_css'],
[
'http://readthedocs.org/static/css/badge_only.css',
'http://readthedocs.org/static/css/readthedocs-doc-embed.css',
],
)
self.assertEqual(
config['extra_javascript'],
[
'readthedocs-data.js',
'http://readthedocs.org/static/core/js/readthedocs-doc-embed.js',
'http://readthedocs.org/static/javascript/readthedocs-analytics.js',
],
)
self.assertIsNone(
config['google_analytics'],
)
self.assertEqual(
config['site_name'],
'mkdocs',
)
with pytest.raises(
MkDocsYAMLParseError,
match=MkDocsYAMLParseError.NOT_FOUND
):
self.searchbuilder.append_conf()

@patch('readthedocs.doc_builder.base.BaseBuilder.run')
@patch('readthedocs.projects.models.Project.checkout_path')
Expand Down