Skip to content

amended mkdocs missing message to allign with sphinx #12012

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions readthedocs/builds/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,12 @@ def get_conf_py_path(self):
conf_py_path = os.path.relpath(conf_py_path, checkout_prefix)
return conf_py_path

def get_mkdocs_yml_path(self):
mkdocs_yml_path = self.project.mkdocs_dir(self.slug)
checkout_prefix = self.project.checkout_path(self.slug)
mkdocs_yml_path = os.path.relpath(mkdocs_yml_path, checkout_prefix)
return mkdocs_yml_path

def get_storage_paths(self, version_slug=None):
"""
Return a list of all build artifact storage paths for this version.
Expand Down
9 changes: 6 additions & 3 deletions readthedocs/doc_builder/backends/mkdocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from readthedocs.core.utils.filesystem import safe_open
from readthedocs.doc_builder.base import BaseBuilder
from readthedocs.doc_builder.exceptions import MkDocsYAMLParseError
from readthedocs.projects.constants import MKDOCS, MKDOCS_HTML

log = structlog.get_logger(__name__)
Expand All @@ -33,7 +34,6 @@ def get_absolute_static_url():


class BaseMkdocs(BaseBuilder):

"""Mkdocs builder."""

# The default theme for mkdocs is the 'mkdocs' theme
Expand Down Expand Up @@ -80,6 +80,11 @@ def get_yaml_config(self):
def show_conf(self):
"""Show the current ``mkdocs.yaml`` being used."""
# Write the mkdocs.yml to the build logs
if not os.path.exists(self.yaml_file):
raise MkDocsYAMLParseError(
message_id=MkDocsYAMLParseError.NOT_FOUND,
)

self.run(
"cat",
os.path.relpath(self.yaml_file, self.project_path),
Expand Down Expand Up @@ -122,7 +127,6 @@ def __eq__(self, other):


class SafeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors

"""
Safe YAML loader.

Expand All @@ -141,7 +145,6 @@ def construct_python_name(self, suffix, node): # pylint: disable=unused-argumen


class SafeDumper(yaml.SafeDumper):

"""
Safe YAML dumper.

Expand Down
30 changes: 18 additions & 12 deletions readthedocs/projects/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Project models."""

import fnmatch
import hashlib
import hmac
Expand Down Expand Up @@ -34,6 +35,7 @@
from readthedocs.core.resolver import Resolver
from readthedocs.core.utils import extract_valid_attributes_for_model, slugify
from readthedocs.core.utils.url import unsafe_join_url_path
from readthedocs.doc_builder.exceptions import MkDocsYAMLParseError
from readthedocs.domains.querysets import DomainQueryset
from readthedocs.domains.validators import check_domains_limit
from readthedocs.notifications.models import Notification as NewNotification
Expand Down Expand Up @@ -80,7 +82,6 @@ def default_privacy_level():


class ProjectRelationship(models.Model):

"""
Project to project relationship.

Expand Down Expand Up @@ -135,7 +136,6 @@ def subproject_prefix(self):


class AddonsConfig(TimeStampedModel):

"""
Addons project configuration.

Expand Down Expand Up @@ -266,7 +266,6 @@ class AddonsConfig(TimeStampedModel):


class AddonSearchFilter(TimeStampedModel):

"""
Addon search user defined filter.

Expand All @@ -279,7 +278,6 @@ class AddonSearchFilter(TimeStampedModel):


class Project(models.Model):

"""Project model."""

# Auto fields
Expand Down Expand Up @@ -962,7 +960,6 @@ def conf_file(self, version=LATEST):
# contains the `doc` word in its path and return this one
if filename.find("doc", 70) != -1:
return filename

# If the project has more than one conf.py file but none of them have
# the `doc` word in the path, we raise an error informing this to the user
if len(files) > 1:
Expand All @@ -972,11 +969,27 @@ def conf_file(self, version=LATEST):

raise ProjectConfigurationError(ProjectConfigurationError.NOT_FOUND)

def yml_file(self, version=LATEST):
"""Find a Mkdocs ``mkdocs.yml`` file in the project checkout."""
files = self.find("mkdocs.yml", version)
if not files:
files = self.full_find("mkdocs.yml", version)
if len(files) == 1:
return files[0]
# TODO: handle for multiple mkdocs.yml files

raise MkDocsYAMLParseError(MkDocsYAMLParseError.NOT_FOUND)

def conf_dir(self, version=LATEST):
conf_file = self.conf_file(version)
if conf_file:
return os.path.dirname(conf_file)

def mkdocs_dir(self, version=LATEST):
yml_file = self.yml_file(version)
if yml_file:
return os.path.dirname(yml_file)

@property
def has_good_build(self):
# Check if there is `_good_build` annotation in the Queryset.
Expand Down Expand Up @@ -1432,7 +1445,6 @@ def organization(self):


class APIProject(Project):

"""
Project proxy model for API data deserialization.

Expand Down Expand Up @@ -1506,7 +1518,6 @@ def environment_variables(self, *, public_only=True):


class ImportedFile(models.Model):

"""
Imported files model.

Expand Down Expand Up @@ -1558,7 +1569,6 @@ def get_absolute_url(self):


class HTMLFile(ImportedFile):

"""
Imported HTML file Proxy model.

Expand All @@ -1580,7 +1590,6 @@ def processed_json(self):


class Notification(TimeStampedModel):

"""WebHook / Email notification attached to a Project."""

# TODO: Overridden from TimeStampedModel just to allow null values,
Expand Down Expand Up @@ -1745,7 +1754,6 @@ def sign_payload(self, payload):


class Domain(TimeStampedModel):

"""A custom domain name for a project."""

# TODO: Overridden from TimeStampedModel just to allow null values,
Expand Down Expand Up @@ -1869,7 +1877,6 @@ def save(self, *args, **kwargs):


class HTTPHeader(TimeStampedModel, models.Model):

"""
Define a HTTP header for a user Domain.

Expand Down Expand Up @@ -1912,7 +1919,6 @@ def __str__(self):


class Feature(models.Model):

"""
Project feature flags.

Expand Down
49 changes: 48 additions & 1 deletion readthedocs/rtd_tests/tests/test_doc_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
from django.test.utils import override_settings

from readthedocs.config.tests.test_config import get_build_config
from readthedocs.doc_builder.backends.mkdocs import BaseMkdocs
from readthedocs.doc_builder.backends.sphinx import BaseSphinx
from readthedocs.doc_builder.exceptions import MkDocsYAMLParseError
from readthedocs.doc_builder.python_environments import Virtualenv
from readthedocs.projects.exceptions import ProjectConfigurationError
from readthedocs.projects.models import Project


@override_settings(PRODUCTION_DOMAIN="readthedocs.org")
class SphinxBuilderTest(TestCase):
class BuilderTest(TestCase):
fixtures = ["test_data", "eric"]

def setUp(self):
Expand All @@ -33,6 +35,9 @@ def setUp(self):
BaseSphinx.type = "base"
BaseSphinx.sphinx_build_dir = tempfile.mkdtemp()
BaseSphinx.relative_output_dir = "_readthedocs/"
BaseMkdocs.type = "base"
BaseMkdocs.sphinx_build_dir = tempfile.mkdtemp()
BaseMkdocs.relative_output_dir = "_readthedocs/"

@patch("readthedocs.doc_builder.backends.sphinx.BaseSphinx.docs_dir")
@patch("readthedocs.doc_builder.backends.sphinx.BaseSphinx.run")
Expand Down Expand Up @@ -112,3 +117,45 @@ def test_multiple_conf_py(
with pytest.raises(ProjectConfigurationError):
with override_settings(DOCROOT=tmp_docs_dir):
base_sphinx.show_conf()

@patch("readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.docs_dir")
@patch("readthedocs.doc_builder.backends.mkdocs.BaseMkdocs.run")
@patch("readthedocs.builds.models.Version.get_mkdocs_yml_path")
@patch("readthedocs.projects.models.Project.checkout_path")
@patch("readthedocs.doc_builder.python_environments.load_yaml_config")
def test_project_without_mkdocs_yml(
self,
load_yaml_config,
checkout_path,
get_mkdocs_yml_path,
_,
docs_dir,
):
"""
Test for a project without ``mkdocs.yml`` file.

When this happen, the ``get_mkdocs_yml_path`` raises a
``MkDocsYAMLParseError`` which is captured by our own code.
"""
tmp_dir = tempfile.mkdtemp()
checkout_path.return_value = tmp_dir
docs_dir.return_value = tmp_dir
get_mkdocs_yml_path.side_effect = MkDocsYAMLParseError
python_env = Virtualenv(
version=self.version,
build_env=self.build_env,
config=get_build_config(
{"mkdocs": {"configuration": "mkdocs.yml"}}, validate=True
),
)
base_mkdocs = BaseMkdocs(
build_env=self.build_env,
python_env=python_env,
)
with self.assertRaises(MkDocsYAMLParseError) as e:
base_mkdocs.show_conf()

self.assertEqual(
e.exception.message_id,
MkDocsYAMLParseError.NOT_FOUND,
)