diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml
index 51d25ba6..468fb14a 100644
--- a/.github/workflows/tox.yml
+++ b/.github/workflows/tox.yml
@@ -66,6 +66,9 @@ jobs:
- name: Install Node dependencies
run: |
npm install -g markdownlint-cli jshint csslint
+ - name: Check with black
+ if: always()
+ run: python -m tox -e black && git diff --exit-code
- name: Check with flake8
if: always()
run: python -m tox -e flake8
diff --git a/mkdocs/__main__.py b/mkdocs/__main__.py
index b4d77304..7e603e33 100644
--- a/mkdocs/__main__.py
+++ b/mkdocs/__main__.py
@@ -51,7 +51,7 @@ class ColorFormatter(logging.Formatter):
'CRITICAL': 'red',
'ERROR': 'red',
'WARNING': 'yellow',
- 'DEBUG': 'blue'
+ 'DEBUG': 'blue',
}
text_wrapper = textwrap.TextWrapper(
@@ -59,8 +59,8 @@ class ColorFormatter(logging.Formatter):
replace_whitespace=False,
break_long_words=False,
break_on_hyphens=False,
- initial_indent=' '*12,
- subsequent_indent=' '*12
+ initial_indent=' ' * 12,
+ subsequent_indent=' ' * 12,
)
def format(self, record):
@@ -70,17 +70,14 @@ class ColorFormatter(logging.Formatter):
prefix = click.style(prefix, fg=self.colors[record.levelname])
if self.text_wrapper.width:
# Only wrap text if a terminal width was detected
- msg = '\n'.join(
- self.text_wrapper.fill(line)
- for line in message.splitlines()
- )
+ msg = '\n'.join(self.text_wrapper.fill(line) for line in message.splitlines())
# Prepend prefix after wrapping so that color codes don't affect length
return prefix + msg[12:]
return prefix + message
class State:
- ''' Maintain logging level.'''
+ """Maintain logging level."""
def __init__(self, log_name='mkdocs', level=logging.INFO):
self.logger = logging.getLogger(log_name)
@@ -99,34 +96,42 @@ pass_state = click.make_pass_decorator(State, ensure=True)
clean_help = "Remove old files from the site_dir before building (the default)."
config_help = "Provide a specific MkDocs config"
-dev_addr_help = ("IP address and port to serve documentation locally (default: "
- "localhost:8000)")
-strict_help = ("Enable strict mode. This will cause MkDocs to abort the build "
- "on any warnings.")
+dev_addr_help = "IP address and port to serve documentation locally (default: localhost:8000)"
+strict_help = "Enable strict mode. This will cause MkDocs to abort the build on any warnings."
theme_help = "The theme to use when building your documentation."
theme_choices = utils.get_theme_names()
site_dir_help = "The directory to output the result of the documentation build."
use_directory_urls_help = "Use directory URLs when building pages (the default)."
reload_help = "Enable the live reloading in the development server (this is the default)"
no_reload_help = "Disable the live reloading in the development server."
-dirty_reload_help = "Enable the live reloading in the development server, but only re-build files that have changed"
-commit_message_help = ("A commit message to use when committing to the "
- "GitHub Pages remote branch. Commit {sha} and MkDocs {version} are available as expansions")
-remote_branch_help = ("The remote branch to commit to for GitHub Pages. This "
- "overrides the value specified in config")
-remote_name_help = ("The remote name to commit to for GitHub Pages. This "
- "overrides the value specified in config")
+dirty_reload_help = (
+ "Enable the live reloading in the development server, but only re-build files that have changed"
+)
+commit_message_help = (
+ "A commit message to use when committing to the "
+ "GitHub Pages remote branch. Commit {sha} and MkDocs {version} are available as expansions"
+)
+remote_branch_help = (
+ "The remote branch to commit to for GitHub Pages. This "
+ "overrides the value specified in config"
+)
+remote_name_help = (
+ "The remote name to commit to for GitHub Pages. This overrides the value specified in config"
+)
force_help = "Force the push to the repository."
no_history_help = "Replace the whole Git history with one new commit."
-ignore_version_help = "Ignore check that build is not being deployed with an older version of MkDocs."
-watch_theme_help = ("Include the theme in list of files to watch for live reloading. "
- "Ignored when live reload is not used.")
+ignore_version_help = (
+ "Ignore check that build is not being deployed with an older version of MkDocs."
+)
+watch_theme_help = (
+ "Include the theme in list of files to watch for live reloading. "
+ "Ignored when live reload is not used."
+)
shell_help = "Use the shell when invoking Git."
-watch_help = ("A directory or file to watch for live reloading. "
- "Can be supplied multiple times.")
+watch_help = "A directory or file to watch for live reloading. Can be supplied multiple times."
-def add_options(opts):
+def add_options(*opts):
def inner(f):
for i in reversed(opts):
f = i(f)
@@ -140,11 +145,15 @@ def verbose_option(f):
state = ctx.ensure_object(State)
if value:
state.stream.setLevel(logging.DEBUG)
- return click.option('-v', '--verbose',
- is_flag=True,
- expose_value=False,
- help='Enable verbose output',
- callback=callback)(f)
+
+ return click.option(
+ '-v',
+ '--verbose',
+ is_flag=True,
+ expose_value=False,
+ help='Enable verbose output',
+ callback=callback,
+ )(f)
def quiet_option(f):
@@ -152,15 +161,19 @@ def quiet_option(f):
state = ctx.ensure_object(State)
if value:
state.stream.setLevel(logging.ERROR)
- return click.option('-q', '--quiet',
- is_flag=True,
- expose_value=False,
- help='Silence warnings',
- callback=callback)(f)
+
+ return click.option(
+ '-q',
+ '--quiet',
+ is_flag=True,
+ expose_value=False,
+ help='Silence warnings',
+ callback=callback,
+ )(f)
-common_options = add_options([quiet_option, verbose_option])
-common_config_options = add_options([
+common_options = add_options(quiet_option, verbose_option)
+common_config_options = add_options(
click.option('-f', '--config-file', type=click.File('rb'), help=config_help),
# Don't override config value if user did not specify --strict flag
# Conveniently, load_config drops None values
@@ -168,8 +181,13 @@ common_config_options = add_options([
click.option('-t', '--theme', type=click.Choice(theme_choices), help=theme_help),
# As with --strict, set the default to None so that this doesn't incorrectly
# override the config file
- click.option('--use-directory-urls/--no-directory-urls', is_flag=True, default=None, help=use_directory_urls_help)
-])
+ click.option(
+ '--use-directory-urls/--no-directory-urls',
+ is_flag=True,
+ default=None,
+ help=use_directory_urls_help,
+ ),
+)
PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}"
@@ -179,8 +197,9 @@ PKG_DIR = os.path.dirname(os.path.abspath(__file__))
@click.group(context_settings={'help_option_names': ['-h', '--help']})
@click.version_option(
__version__,
- '-V', '--version',
- message=f'%(prog)s, version %(version)s from { PKG_DIR } (Python { PYTHON_VERSION })'
+ '-V',
+ '--version',
+ message=f'%(prog)s, version %(version)s from { PKG_DIR } (Python { PYTHON_VERSION })',
)
@common_options
def cli():
@@ -195,12 +214,15 @@ def cli():
@click.option('--no-livereload', 'livereload', flag_value='no-livereload', help=no_reload_help)
@click.option('--dirtyreload', 'livereload', flag_value='dirty', help=dirty_reload_help)
@click.option('--watch-theme', help=watch_theme_help, is_flag=True)
-@click.option('-w', '--watch', help=watch_help, type=click.Path(exists=True), multiple=True, default=[])
+@click.option(
+ '-w', '--watch', help=watch_help, type=click.Path(exists=True), multiple=True, default=[]
+)
@common_config_options
@common_options
def serve_command(dev_addr, livereload, watch, **kwargs):
"""Run the builtin development server"""
from mkdocs.commands import serve
+
_enable_warnings()
serve.serve(dev_addr=dev_addr, livereload=livereload, watch=watch, **kwargs)
@@ -213,6 +235,7 @@ def serve_command(dev_addr, livereload, watch, **kwargs):
def build_command(clean, **kwargs):
"""Build the MkDocs documentation"""
from mkdocs.commands import build
+
_enable_warnings()
build.build(config.load_config(**kwargs), dirty=not clean)
@@ -229,15 +252,14 @@ def build_command(clean, **kwargs):
@common_config_options
@click.option('-d', '--site-dir', type=click.Path(), help=site_dir_help)
@common_options
-def gh_deploy_command(clean, message, remote_branch, remote_name, force, no_history, ignore_version, shell, **kwargs):
+def gh_deploy_command(
+ clean, message, remote_branch, remote_name, force, no_history, ignore_version, shell, **kwargs
+):
"""Deploy your documentation to GitHub Pages"""
from mkdocs.commands import build, gh_deploy
+
_enable_warnings()
- cfg = config.load_config(
- remote_branch=remote_branch,
- remote_name=remote_name,
- **kwargs
- )
+ cfg = config.load_config(remote_branch=remote_branch, remote_name=remote_name, **kwargs)
build.build(cfg, dirty=not clean)
gh_deploy.gh_deploy(
cfg,
@@ -245,7 +267,7 @@ def gh_deploy_command(clean, message, remote_branch, remote_name, force, no_hist
force=force,
no_history=no_history,
ignore_version=ignore_version,
- shell=shell
+ shell=shell,
)
@@ -255,6 +277,7 @@ def gh_deploy_command(clean, message, remote_branch, remote_name, force, no_hist
def new_command(project_directory):
"""Create a new MkDocs project"""
from mkdocs.commands import new
+
new.new(project_directory)
diff --git a/mkdocs/commands/babel.py b/mkdocs/commands/babel.py
index bbfa9e82..0cdbbada 100644
--- a/mkdocs/commands/babel.py
+++ b/mkdocs/commands/babel.py
@@ -4,14 +4,14 @@ from pkg_resources import EntryPoint
from babel.messages import frontend as babel
-DEFAULT_MAPPING_FILE = path.normpath(path.join(
- path.abspath(path.dirname(__file__)), '../themes/babel.cfg'
-))
+DEFAULT_MAPPING_FILE = path.normpath(
+ path.join(path.abspath(path.dirname(__file__)), '../themes/babel.cfg')
+)
class ThemeMixin:
def get_theme_dir(self):
- ''' Validate theme option and return path to theme's root obtained from entry point. '''
+ """Validate theme option and return path to theme's root obtained from entry point."""
entry_points = EntryPoint.parse_map(self.distribution.entry_points, self.distribution)
if 'mkdocs.themes' not in entry_points:
raise DistutilsOptionError("no mkdocs.themes are defined in entry_points")
diff --git a/mkdocs/commands/build.py b/mkdocs/commands/build.py
index 144c6230..b191aac2 100644
--- a/mkdocs/commands/build.py
+++ b/mkdocs/commands/build.py
@@ -14,7 +14,8 @@ import mkdocs
class DuplicateFilter:
- ''' Avoid logging duplicate messages. '''
+ """Avoid logging duplicate messages."""
+
def __init__(self):
self.msgs = set()
@@ -46,15 +47,11 @@ def get_context(nav, files, config, page=None, base_url=''):
return {
'nav': nav,
'pages': files,
-
'base_url': base_url,
-
'extra_css': extra_css,
'extra_javascript': extra_javascript,
-
'mkdocs_version': mkdocs.__version__,
'build_date_utc': utils.get_build_datetime(),
-
'config': config,
'page': page,
}
@@ -90,15 +87,13 @@ def _build_template(name, template, files, config, nav):
output = template.render(context)
# Run `post_template` plugin events.
- output = config['plugins'].run_event(
- 'post_template', output, template_name=name, config=config
- )
+ output = config['plugins'].run_event('post_template', output, template_name=name, config=config)
return output
def _build_theme_template(template_name, env, files, config, nav):
- """ Build a template using the theme environment. """
+ """Build a template using the theme environment."""
log.debug(f"Building theme template: {template_name}")
@@ -119,14 +114,16 @@ def _build_theme_template(template_name, env, files, config, nav):
gz_filename = f'{output_path}.gz'
with open(gz_filename, 'wb') as f:
timestamp = utils.get_build_timestamp()
- with gzip.GzipFile(fileobj=f, filename=gz_filename, mode='wb', mtime=timestamp) as gz_buf:
+ with gzip.GzipFile(
+ fileobj=f, filename=gz_filename, mode='wb', mtime=timestamp
+ ) as gz_buf:
gz_buf.write(output.encode('utf-8'))
else:
log.info(f"Template skipped: '{template_name}' generated empty output.")
def _build_extra_template(template_name, files, config, nav):
- """ Build user templates which are not part of the theme. """
+ """Build user templates which are not part of the theme."""
log.debug(f"Building extra template: {template_name}")
@@ -151,7 +148,7 @@ def _build_extra_template(template_name, files, config, nav):
def _populate_page(page, config, files, dirty=False):
- """ Read page content from docs_dir and render Markdown. """
+ """Read page content from docs_dir and render Markdown."""
try:
# When --dirty is used, only read the page if the file has been modified since the
@@ -160,9 +157,7 @@ def _populate_page(page, config, files, dirty=False):
return
# Run the `pre_page` plugin event
- page = config['plugins'].run_event(
- 'pre_page', page, config=config, files=files
- )
+ page = config['plugins'].run_event('pre_page', page, config=config, files=files)
page.read_source(config)
@@ -187,7 +182,7 @@ def _populate_page(page, config, files, dirty=False):
def _build_page(page, config, doc_files, nav, env, dirty=False):
- """ Pass a Page to theme template and write output to site_dir. """
+ """Pass a Page to theme template and write output to site_dir."""
try:
# When --dirty is used, only build the page if the file has been modified since the
@@ -217,13 +212,13 @@ def _build_page(page, config, doc_files, nav, env, dirty=False):
output = template.render(context)
# Run `post_page` plugin events.
- output = config['plugins'].run_event(
- 'post_page', output, page=page, config=config
- )
+ output = config['plugins'].run_event('post_page', output, page=page, config=config)
# Write the output file.
if output.strip():
- utils.write_file(output.encode('utf-8', errors='xmlcharrefreplace'), page.file.abs_dest_path)
+ utils.write_file(
+ output.encode('utf-8', errors='xmlcharrefreplace'), page.file.abs_dest_path
+ )
else:
log.info(f"Page skipped: '{page.file.src_path}'. Generated empty output.")
@@ -239,7 +234,7 @@ def _build_page(page, config, doc_files, nav, env, dirty=False):
def build(config, live_server=False, dirty=False):
- """ Perform a full site build. """
+ """Perform a full site build."""
logger = logging.getLogger('mkdocs')
@@ -251,6 +246,7 @@ def build(config, live_server=False, dirty=False):
try:
from time import time
+
start = time()
# Run `config` plugin events.
@@ -264,8 +260,10 @@ def build(config, live_server=False, dirty=False):
utils.clean_directory(config['site_dir'])
else: # pragma: no cover
# Warn user about problems that may occur with --dirty option
- log.warning("A 'dirty' build is being performed, this will likely lead to inaccurate navigation and other"
- " links within your site. This option is designed for site development purposes only.")
+ log.warning(
+ "A 'dirty' build is being performed, this will likely lead to inaccurate navigation and other"
+ " links within your site. This option is designed for site development purposes only."
+ )
if not live_server: # pragma: no cover
log.info(f"Building documentation to directory: {config['site_dir']}")
@@ -292,9 +290,7 @@ def build(config, live_server=False, dirty=False):
_populate_page(file.page, config, files, dirty)
# Run `env` plugin events.
- env = config['plugins'].run_event(
- 'env', env, config=config, files=files
- )
+ env = config['plugins'].run_event('env', env, config=config, files=files)
# Start writing files to site_dir now that all data is gathered. Note that order matters. Files
# with lower precedence get written first so that files with higher precedence can overwrite them.
@@ -336,6 +332,6 @@ def build(config, live_server=False, dirty=False):
def site_directory_contains_stale_files(site_directory):
- """ Check if the site directory contains stale files from a previous build. """
+ """Check if the site directory contains stale files from a previous build."""
return True if os.path.exists(site_directory) and os.listdir(site_directory) else False
diff --git a/mkdocs/commands/gh_deploy.py b/mkdocs/commands/gh_deploy.py
index 2748447e..4b754e43 100644
--- a/mkdocs/commands/gh_deploy.py
+++ b/mkdocs/commands/gh_deploy.py
@@ -18,7 +18,7 @@ def _is_cwd_git_repo():
proc = subprocess.Popen(
['git', 'rev-parse', '--is-inside-work-tree'],
stdout=subprocess.PIPE,
- stderr=subprocess.PIPE
+ stderr=subprocess.PIPE,
)
except FileNotFoundError:
log.error("Could not find git - is it installed and on your path?")
@@ -29,8 +29,12 @@ def _is_cwd_git_repo():
def _get_current_sha(repo_path):
- proc = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], cwd=repo_path or None,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ proc = subprocess.Popen(
+ ['git', 'rev-parse', '--short', 'HEAD'],
+ cwd=repo_path or None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
stdout, _ = proc.communicate()
sha = stdout.decode('utf-8').strip()
@@ -42,8 +46,11 @@ def _get_remote_url(remote_name):
# No CNAME found. We will use the origin URL to determine the GitHub
# pages location.
remote = f"remote.{remote_name}.url"
- proc = subprocess.Popen(["git", "config", "--get", remote],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ proc = subprocess.Popen(
+ ["git", "config", "--get", remote],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
stdout, _ = proc.communicate()
url = stdout.decode('utf-8').strip()
@@ -60,8 +67,11 @@ def _get_remote_url(remote_name):
def _check_version(branch):
- proc = subprocess.Popen(['git', 'show', '-s', '--format=%s', f'refs/heads/{branch}'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ proc = subprocess.Popen(
+ ['git', 'show', '-s', '--format=%s', f'refs/heads/{branch}'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
stdout, _ = proc.communicate()
msg = stdout.decode('utf-8').strip()
@@ -84,11 +94,12 @@ def _check_version(branch):
raise Abort('Deployment Aborted!')
-def gh_deploy(config, message=None, force=False, no_history=False, ignore_version=False, shell=False):
+def gh_deploy(
+ config, message=None, force=False, no_history=False, ignore_version=False, shell=False
+):
if not _is_cwd_git_repo():
- log.error('Cannot deploy - this directory does not appear to be a git '
- 'repository')
+ log.error('Cannot deploy - this directory does not appear to be a git repository')
remote_branch = config['remote_branch']
remote_name = config['remote_name']
@@ -101,8 +112,11 @@ def gh_deploy(config, message=None, force=False, no_history=False, ignore_versio
sha = _get_current_sha(os.path.dirname(config.config_file_path))
message = message.format(version=mkdocs.__version__, sha=sha)
- log.info("Copying '%s' to '%s' branch and pushing to GitHub.",
- config['site_dir'], config['remote_branch'])
+ log.info(
+ "Copying '%s' to '%s' branch and pushing to GitHub.",
+ config['site_dir'],
+ config['remote_branch'],
+ )
try:
ghp_import.ghp_import(
@@ -114,7 +128,7 @@ def gh_deploy(config, message=None, force=False, no_history=False, ignore_versio
force=force,
use_shell=shell,
no_history=no_history,
- nojekyll=True
+ nojekyll=True,
)
except ghp_import.GhpError as e:
log.error(f"Failed to deploy to GitHub with error: \n{e.message}")
@@ -126,10 +140,13 @@ def gh_deploy(config, message=None, force=False, no_history=False, ignore_versio
# This GitHub pages repository has a CNAME configured.
with open(cname_file) as f:
cname_host = f.read().strip()
- log.info(f'Based on your CNAME file, your documentation should be '
- f'available shortly at: http://{cname_host}')
- log.info('NOTE: Your DNS records must be configured appropriately for '
- 'your CNAME URL to work.')
+ log.info(
+ f'Based on your CNAME file, your documentation should be '
+ f'available shortly at: http://{cname_host}'
+ )
+ log.info(
+ 'NOTE: Your DNS records must be configured appropriately for your CNAME URL to work.'
+ )
return
host, path = _get_remote_url(remote_name)
@@ -140,6 +157,6 @@ def gh_deploy(config, message=None, force=False, no_history=False, ignore_versio
else:
username, repo = path.split('/', 1)
if repo.endswith('.git'):
- repo = repo[:-len('.git')]
+ repo = repo[: -len('.git')]
url = f'https://{username}.github.io/{repo}/'
log.info(f"Your documentation should shortly be available at: {url}")
diff --git a/mkdocs/commands/serve.py b/mkdocs/commands/serve.py
index fec06fa2..b5cf1d58 100644
--- a/mkdocs/commands/serve.py
+++ b/mkdocs/commands/serve.py
@@ -14,8 +14,17 @@ from mkdocs.livereload import LiveReloadServer
log = logging.getLogger(__name__)
-def serve(config_file=None, dev_addr=None, strict=None, theme=None,
- theme_dir=None, livereload='livereload', watch_theme=False, watch=[], **kwargs):
+def serve(
+ config_file=None,
+ dev_addr=None,
+ strict=None,
+ theme=None,
+ theme_dir=None,
+ livereload='livereload',
+ watch_theme=False,
+ watch=[],
+ **kwargs,
+):
"""
Start the MkDocs development server
@@ -41,7 +50,7 @@ def serve(config_file=None, dev_addr=None, strict=None, theme=None,
theme=theme,
theme_dir=theme_dir,
site_dir=site_dir,
- **kwargs
+ **kwargs,
)
# combine CLI watch arguments with config file values
@@ -63,7 +72,9 @@ def serve(config_file=None, dev_addr=None, strict=None, theme=None,
config = builder()
host, port = config['dev_addr']
- server = LiveReloadServer(builder=builder, host=host, port=port, root=site_dir, mount_path=mount_path(config))
+ server = LiveReloadServer(
+ builder=builder, host=host, port=port, root=site_dir, mount_path=mount_path(config)
+ )
def error_handler(code):
if code in (404, 500):
diff --git a/mkdocs/commands/setup.py b/mkdocs/commands/setup.py
index b0512d0d..f68e3683 100644
--- a/mkdocs/commands/setup.py
+++ b/mkdocs/commands/setup.py
@@ -3,8 +3,9 @@ try:
compile_catalog,
extract_messages,
init_catalog,
- update_catalog
+ update_catalog,
)
+
babel_cmdclass = {
'compile_catalog': compile_catalog,
'extract_messages': extract_messages,
diff --git a/mkdocs/config/__init__.py b/mkdocs/config/__init__.py
index b9780de6..02827893 100644
--- a/mkdocs/config/__init__.py
+++ b/mkdocs/config/__init__.py
@@ -1,4 +1,3 @@
from mkdocs.config.base import load_config, Config
-__all__ = [load_config.__name__,
- Config.__name__]
+__all__ = [load_config.__name__, Config.__name__]
diff --git a/mkdocs/config/base.py b/mkdocs/config/base.py
index 8f7f8bef..74c23573 100644
--- a/mkdocs/config/base.py
+++ b/mkdocs/config/base.py
@@ -66,10 +66,8 @@ class Config(UserDict):
except ValidationError as e:
failed.append((key, e))
- for key in (set(self.keys()) - self._schema_keys):
- warnings.append((
- key, f"Unrecognised configuration name: {key}"
- ))
+ for key in set(self.keys()) - self._schema_keys:
+ warnings.append((key, f"Unrecognised configuration name: {key}"))
return failed, warnings
@@ -120,19 +118,20 @@ class Config(UserDict):
return failed, warnings
def load_dict(self, patch):
- """ Load config options from a dictionary. """
+ """Load config options from a dictionary."""
if not isinstance(patch, dict):
raise exceptions.ConfigurationError(
"The configuration is invalid. The expected type was a key "
"value mapping (a python dict) but we got an object of type: "
- f"{type(patch)}")
+ f"{type(patch)}"
+ )
self.user_configs.append(patch)
self.data.update(patch)
def load_file(self, config_file):
- """ Load config options from the open file descriptor of a YAML file. """
+ """Load config options from the open file descriptor of a YAML file."""
try:
return self.load_dict(utils.yaml_load(config_file))
except YAMLError as e:
@@ -177,8 +176,7 @@ def _open_config_file(config_file):
except FileNotFoundError:
continue
else:
- raise exceptions.ConfigurationError(
- f"Config file '{paths_to_try[0]}' does not exist.")
+ raise exceptions.ConfigurationError(f"Config file '{paths_to_try[0]}' does not exist.")
else:
log.debug(f"Loading configuration file: {config_file}")
# Ensure file descriptor is at beginning
@@ -214,6 +212,7 @@ def load_config(config_file=None, **kwargs):
# Initialize the config with the default schema.
from mkdocs.config.defaults import get_schema
+
cfg = Config(schema=get_schema(), config_file_path=options['config_file_path'])
# load the config file
cfg.load_file(fd)
@@ -233,9 +232,7 @@ def load_config(config_file=None, **kwargs):
log.debug(f"Config value: '{key}' = {value!r}")
if len(errors) > 0:
- raise exceptions.Abort(
- f"Aborted with {len(errors)} Configuration Errors!"
- )
+ raise exceptions.Abort(f"Aborted with {len(errors)} Configuration Errors!")
elif cfg['strict'] and len(warnings) > 0:
raise exceptions.Abort(
f"Aborted with {len(warnings)} Configuration Warnings in 'strict' mode!"
diff --git a/mkdocs/config/config_options.py b/mkdocs/config/config_options.py
index 2074c7c0..5e654295 100644
--- a/mkdocs/config/config_options.py
+++ b/mkdocs/config/config_options.py
@@ -12,7 +12,6 @@ from mkdocs.config.base import Config, ValidationError
class BaseConfigOption:
-
def __init__(self):
self.warnings = []
self.default = None
@@ -72,6 +71,7 @@ class ConfigItems(BaseConfigOption):
Validates a list of mappings that all must match the same set of
options.
"""
+
def __init__(self, *config_options, **kwargs):
BaseConfigOption.__init__(self)
self.item_config = SubConfig(*config_options)
@@ -88,8 +88,9 @@ class ConfigItems(BaseConfigOption):
return ()
if not isinstance(value, Sequence):
- raise ValidationError(f'Expected a sequence of mappings, but a '
- f'{type(value)} was given.')
+ raise ValidationError(
+ f'Expected a sequence of mappings, but a ' f'{type(value)} was given.'
+ )
return [self.item_config.validate(item) for item in value]
@@ -149,8 +150,10 @@ class Type(OptionallyRequired):
if not isinstance(value, self._type):
msg = f"Expected type: {self._type} but received: {type(value)}"
elif self.length is not None and len(value) != self.length:
- msg = (f"Expected type: {self._type} with length {self.length}"
- f" but received: {value} with length {len(value)}")
+ msg = (
+ f"Expected type: {self._type} with length {self.length}"
+ f" but received: {value} with length {len(value)}"
+ )
else:
return value
@@ -287,10 +290,10 @@ class IpAddress(OptionallyRequired):
host = config[key_name].host
if key_name == 'dev_addr' and host in ['0.0.0.0', '::']:
self.warnings.append(
- (f"The use of the IP address '{host}' suggests a production environment "
- "or the use of a proxy to connect to the MkDocs server. However, "
- "the MkDocs' server is intended for local development purposes only. "
- "Please use a third party production-ready server instead.")
+ f"The use of the IP address '{host}' suggests a production environment "
+ "or the use of a proxy to connect to the MkDocs server. However, "
+ "the MkDocs' server is intended for local development purposes only. "
+ "Please use a third party production-ready server instead."
)
@@ -319,8 +322,7 @@ class URL(OptionallyRequired):
parsed_url = parsed_url._replace(path=f'{parsed_url.path}/')
return urlunsplit(parsed_url)
- raise ValidationError(
- "The URL isn't valid, it should include the http:// (scheme)")
+ raise ValidationError("The URL isn't valid, it should include the http:// (scheme)")
class RepoURL(URL):
@@ -373,7 +375,9 @@ class FilesystemObject(Type):
self.config_dir = None
def pre_validation(self, config, key_name):
- self.config_dir = os.path.dirname(config.config_file_path) if config.config_file_path else None
+ self.config_dir = (
+ os.path.dirname(config.config_file_path) if config.config_file_path else None
+ )
def run_validation(self, value):
value = super().run_validation(value)
@@ -390,6 +394,7 @@ class Dir(FilesystemObject):
Validate a path to a directory, optionally verifying that it exists.
"""
+
existence_test = staticmethod(os.path.isdir)
name = 'directory'
@@ -400,9 +405,10 @@ class Dir(FilesystemObject):
# Validate that the dir is not the parent dir of the config file.
if os.path.dirname(config.config_file_path) == config[key_name]:
raise ValidationError(
- (f"The '{key_name}' should not be the parent directory of the"
- " config file. Use a child directory instead so that the"
- f" '{key_name}' is a sibling of the config file."))
+ f"The '{key_name}' should not be the parent directory of the"
+ f" config file. Use a child directory instead so that the"
+ f" '{key_name}' is a sibling of the config file."
+ )
class File(FilesystemObject):
@@ -411,6 +417,7 @@ class File(FilesystemObject):
Validate a path to a file, optionally verifying that it exists.
"""
+
existence_test = staticmethod(os.path.isfile)
name = 'file'
@@ -427,7 +434,9 @@ class ListOfPaths(OptionallyRequired):
super().__init__(default, required)
def pre_validation(self, config, key_name):
- self.config_dir = os.path.dirname(config.config_file_path) if config.config_file_path else None
+ self.config_dir = (
+ os.path.dirname(config.config_file_path) if config.config_file_path else None
+ )
def run_validation(self, value):
if not isinstance(value, list):
@@ -455,24 +464,26 @@ class SiteDir(Dir):
def post_validation(self, config, key_name):
super().post_validation(config, key_name)
+ docs_dir = config['docs_dir']
+ site_dir = config['site_dir']
# Validate that the docs_dir and site_dir don't contain the
# other as this will lead to copying back and forth on each
# and eventually make a deep nested mess.
- if (config['docs_dir'] + os.sep).startswith(config['site_dir'].rstrip(os.sep) + os.sep):
+ if (docs_dir + os.sep).startswith(site_dir.rstrip(os.sep) + os.sep):
raise ValidationError(
- ("The 'docs_dir' should not be within the 'site_dir' as this "
- "can mean the source files are overwritten by the output or "
- "it will be deleted if --clean is passed to mkdocs build."
- "(site_dir: '{}', docs_dir: '{}')"
- ).format(config['site_dir'], config['docs_dir']))
- elif (config['site_dir'] + os.sep).startswith(config['docs_dir'].rstrip(os.sep) + os.sep):
+ f"The 'docs_dir' should not be within the 'site_dir' as this "
+ f"can mean the source files are overwritten by the output or "
+ f"it will be deleted if --clean is passed to mkdocs build."
+ f"(site_dir: '{site_dir}', docs_dir: '{docs_dir}')"
+ )
+ elif (site_dir + os.sep).startswith(docs_dir.rstrip(os.sep) + os.sep):
raise ValidationError(
- ("The 'site_dir' should not be within the 'docs_dir' as this "
- "leads to the build directory being copied into itself and "
- "duplicate nested files in the 'site_dir'."
- "(site_dir: '{}', docs_dir: '{}')"
- ).format(config['site_dir'], config['docs_dir']))
+ f"The 'site_dir' should not be within the 'docs_dir' as this "
+ f"leads to the build directory being copied into itself and "
+ f"duplicate nested files in the 'site_dir'."
+ f"(site_dir: '{site_dir}', docs_dir: '{docs_dir}')"
+ )
class Theme(BaseConfigOption):
@@ -507,13 +518,17 @@ class Theme(BaseConfigOption):
raise ValidationError("No theme name set.")
- raise ValidationError(f'Invalid type "{type(value)}". Expected a string or key/value pairs.')
+ raise ValidationError(
+ f'Invalid type "{type(value)}". Expected a string or key/value pairs.'
+ )
def post_validation(self, config, key_name):
theme_config = config[key_name]
if not theme_config['name'] and 'custom_dir' not in theme_config:
- raise ValidationError("At least one of 'theme.name' or 'theme.custom_dir' must be defined.")
+ raise ValidationError(
+ "At least one of 'theme.name' or 'theme.custom_dir' must be defined."
+ )
# Ensure custom_dir is an absolute path
if 'custom_dir' in theme_config and not os.path.isabs(theme_config['custom_dir']):
@@ -521,8 +536,11 @@ class Theme(BaseConfigOption):
theme_config['custom_dir'] = os.path.join(config_dir, theme_config['custom_dir'])
if 'custom_dir' in theme_config and not os.path.isdir(theme_config['custom_dir']):
- raise ValidationError("The path set in {name}.custom_dir ('{path}') does not exist.".
- format(path=theme_config['custom_dir'], name=key_name))
+ raise ValidationError(
+ "The path set in {name}.custom_dir ('{path}') does not exist.".format(
+ path=theme_config['custom_dir'], name=key_name
+ )
+ )
if 'locale' in theme_config and not isinstance(theme_config['locale'], str):
raise ValidationError(f"'{theme_config['name']}.locale' must be a string.")
@@ -559,11 +577,15 @@ class Nav(OptionallyRequired):
pass
elif isinstance(value, dict):
if len(value) != 1:
- raise ValidationError(f"Expected nav item to be a dict of size 1, got {self._repr_item(value)}")
+ raise ValidationError(
+ f"Expected nav item to be a dict of size 1, got {self._repr_item(value)}"
+ )
for subnav in value.values():
self.run_validation(subnav, top=False)
else:
- raise ValidationError(f"Expected nav item to be a string or dict, got {self._repr_item(value)}")
+ raise ValidationError(
+ f"Expected nav item to be a string or dict, got {self._repr_item(value)}"
+ )
@classmethod
def _repr_item(cls, value):
@@ -595,7 +617,8 @@ class MarkdownExtensions(OptionallyRequired):
a dict item must be a valid Markdown extension name and the value must be a dict of config
options for that extension. Extension configs are set on the private setting passed to
`configkey`. The `builtins` keyword accepts a list of extensions which cannot be overridden by
- the user. However, builtins can be duplicated to define config options for them if desired. """
+ the user. However, builtins can be duplicated to define config options for them if desired."""
+
def __init__(self, builtins=None, configkey='mdx_configs', **kwargs):
super().__init__(**kwargs)
self.builtins = builtins or []
@@ -647,7 +670,9 @@ class MarkdownExtensions(OptionallyRequired):
stack.insert(0, frame)
tb = ''.join(traceback.format_list(stack))
- raise ValidationError(f"Failed to load extension '{ext}'.\n{tb}{type(e).__name__}: {e}")
+ raise ValidationError(
+ f"Failed to load extension '{ext}'.\n{tb}{type(e).__name__}: {e}"
+ )
return extensions
@@ -705,15 +730,13 @@ class Plugins(OptionallyRequired):
if not issubclass(Plugin, plugins.BasePlugin):
raise ValidationError(
f'{Plugin.__module__}.{Plugin.__name__} must be a subclass of'
- f' {plugins.BasePlugin.__module__}.{plugins.BasePlugin.__name__}')
+ f' {plugins.BasePlugin.__module__}.{plugins.BasePlugin.__name__}'
+ )
plugin = Plugin()
errors, warnings = plugin.load_config(config, self.config_file_path)
self.warnings.extend(warnings)
- errors_message = '\n'.join(
- f"Plugin '{name}' value: '{x}'. Error: {y}"
- for x, y in errors
- )
+ errors_message = '\n'.join(f"Plugin '{name}' value: '{x}'. Error: {y}" for x, y in errors)
if errors_message:
raise ValidationError(errors_message)
return plugin
diff --git a/mkdocs/config/defaults.py b/mkdocs/config/defaults.py
index 95d3c440..79f346d0 100644
--- a/mkdocs/config/defaults.py
+++ b/mkdocs/config/defaults.py
@@ -10,116 +10,91 @@ from mkdocs.config import config_options
def get_schema():
- return (
-
+ schema = {
# Reserved for internal use, stores the mkdocs.yml config file.
- ('config_file_path', config_options.Type(str)),
-
+ 'config_file_path': config_options.Type(str),
# The title to use for the documentation
- ('site_name', config_options.Type(str, required=True)),
-
+ 'site_name': config_options.Type(str, required=True),
# Defines the structure of the navigation.
- ('nav', config_options.Nav()),
- ('pages', config_options.Deprecated(removed=True, moved_to='nav')),
-
+ 'nav': config_options.Nav(),
+ 'pages': config_options.Deprecated(removed=True, moved_to='nav'),
# The full URL to where the documentation will be hosted
- ('site_url', config_options.URL(is_dir=True)),
-
+ 'site_url': config_options.URL(is_dir=True),
# A description for the documentation project that will be added to the
# HTML meta tags.
- ('site_description', config_options.Type(str)),
+ 'site_description': config_options.Type(str),
# The name of the author to add to the HTML meta tags
- ('site_author', config_options.Type(str)),
-
+ 'site_author': config_options.Type(str),
# The MkDocs theme for the documentation.
- ('theme', config_options.Theme(default='mkdocs')),
-
+ 'theme': config_options.Theme(default='mkdocs'),
# The directory containing the documentation markdown.
- ('docs_dir', config_options.Dir(default='docs', exists=True)),
-
+ 'docs_dir': config_options.Dir(default='docs', exists=True),
# The directory where the site will be built to
- ('site_dir', config_options.SiteDir(default='site')),
-
+ 'site_dir': config_options.SiteDir(default='site'),
# A copyright notice to add to the footer of documentation.
- ('copyright', config_options.Type(str)),
-
+ 'copyright': config_options.Type(str),
# set of values for Google analytics containing the account IO and domain,
# this should look like, ['UA-27795084-5', 'mkdocs.org']
- ('google_analytics', config_options.Deprecated(
+ 'google_analytics': config_options.Deprecated(
message=(
'The configuration option {} has been deprecated and '
'will be removed in a future release of MkDocs. See the '
'options available on your theme for an alternative.'
),
- option_type=config_options.Type(list, length=2)
- )),
-
+ option_type=config_options.Type(list, length=2),
+ ),
# The address on which to serve the live reloading docs server.
- ('dev_addr', config_options.IpAddress(default='127.0.0.1:8000')),
-
+ 'dev_addr': config_options.IpAddress(default='127.0.0.1:8000'),
# If `True`, use `/index.hmtl` style files with hyperlinks to
# the directory.If `False`, use `.html style file with
# hyperlinks to the file.
# True generates nicer URLs, but False is useful if browsing the output on
# a filesystem.
- ('use_directory_urls', config_options.Type(bool, default=True)),
-
+ 'use_directory_urls': config_options.Type(bool, default=True),
# Specify a link to the project source repo to be included
# in the documentation pages.
- ('repo_url', config_options.RepoURL()),
-
+ 'repo_url': config_options.RepoURL(),
# A name to use for the link to the project source repo.
# Default, If repo_url is unset then None, otherwise
# "GitHub", "Bitbucket" or "GitLab" for known url or Hostname
# for unknown urls.
- ('repo_name', config_options.Type(str)),
-
+ 'repo_name': config_options.Type(str),
# Specify a URI to the docs dir in the project source repo, relative to the
# repo_url. When set, a link directly to the page in the source repo will
# be added to the generated HTML. If repo_url is not set also, this option
# is ignored.
- ('edit_uri', config_options.Type(str)),
-
+ 'edit_uri': config_options.Type(str),
# Specify which css or javascript files from the docs directory should be
# additionally included in the site.
- ('extra_css', config_options.Type(list, default=[])),
- ('extra_javascript', config_options.Type(list, default=[])),
-
+ 'extra_css': config_options.Type(list, default=[]),
+ 'extra_javascript': config_options.Type(list, default=[]),
# Similar to the above, but each template (HTML or XML) will be build with
# Jinja2 and the global context.
- ('extra_templates', config_options.Type(list, default=[])),
-
+ 'extra_templates': config_options.Type(list, default=[]),
# PyMarkdown extension names.
- ('markdown_extensions', config_options.MarkdownExtensions(
- builtins=['toc', 'tables', 'fenced_code'],
- configkey='mdx_configs', default=[])),
-
+ 'markdown_extensions': config_options.MarkdownExtensions(
+ builtins=['toc', 'tables', 'fenced_code'], configkey='mdx_configs', default=[]
+ ),
# PyMarkdown Extension Configs. For internal use only.
- ('mdx_configs', config_options.Private()),
-
+ 'mdx_configs': config_options.Private(),
# enabling strict mode causes MkDocs to stop the build when a problem is
# encountered rather than display an error.
- ('strict', config_options.Type(bool, default=False)),
-
+ 'strict': config_options.Type(bool, default=False),
# the remote branch to commit to when using gh-deploy
- ('remote_branch', config_options.Type(
- str, default='gh-pages')),
-
+ 'remote_branch': config_options.Type(str, default='gh-pages'),
# the remote name to push to when using gh-deploy
- ('remote_name', config_options.Type(str, default='origin')),
-
+ 'remote_name': config_options.Type(str, default='origin'),
# extra is a mapping/dictionary of data that is passed to the template.
# This allows template authors to require extra configuration that not
# relevant to all themes and doesn't need to be explicitly supported by
# MkDocs itself. A good example here would be including the current
# project version.
- ('extra', config_options.SubConfig()),
-
+ 'extra': config_options.SubConfig(),
# a list of plugins. Each item may contain a string name or a key value pair.
# A key value pair should be the string name (as the key) and a dict of config
# options (as the value).
- ('plugins', config_options.Plugins(default=['search'])),
-
+ 'plugins': config_options.Plugins(default=['search']),
# a list of extra paths to watch while running `mkdocs serve`
- ('watch', config_options.ListOfPaths(default=[]))
- )
+ 'watch': config_options.ListOfPaths(default=[]),
+ }
+ return tuple(schema.items())
diff --git a/mkdocs/contrib/search/__init__.py b/mkdocs/contrib/search/__init__.py
index 66eb92d8..a5549f8d 100644
--- a/mkdocs/contrib/search/__init__.py
+++ b/mkdocs/contrib/search/__init__.py
@@ -11,7 +11,7 @@ base_path = os.path.dirname(os.path.abspath(__file__))
class LangOption(config_options.OptionallyRequired):
- """ Validate Language(s) provided in config are known languages. """
+ """Validate Language(s) provided in config are known languages."""
def get_lunr_supported_lang(self, lang):
for lang_part in lang.split("_"):
@@ -40,14 +40,14 @@ class LangOption(config_options.OptionallyRequired):
class SearchPlugin(BasePlugin):
- """ Add a search feature to MkDocs. """
+ """Add a search feature to MkDocs."""
config_scheme = (
('lang', LangOption()),
('separator', config_options.Type(str, default=r'[\s\-]+')),
('min_search_length', config_options.Type(int, default=3)),
('prebuild_index', config_options.Choice((False, True, 'node', 'python'), default=False)),
- ('indexing', config_options.Choice(('full', 'sections', 'titles'), default='full'))
+ ('indexing', config_options.Choice(('full', 'sections', 'titles'), default='full')),
)
def on_config(self, config, **kwargs):
@@ -95,10 +95,10 @@ class SearchPlugin(BasePlugin):
files.append('lunr.stemmer.support.js')
if len(self.config['lang']) > 1:
files.append('lunr.multi.js')
- if ('ja' in self.config['lang'] or 'jp' in self.config['lang']):
+ if 'ja' in self.config['lang'] or 'jp' in self.config['lang']:
files.append('tinyseg.js')
for lang in self.config['lang']:
- if (lang != 'en'):
+ if lang != 'en':
files.append(f'lunr.{lang}.js')
for filename in files:
diff --git a/mkdocs/contrib/search/search_index.py b/mkdocs/contrib/search/search_index.py
index bef81393..e610bb82 100644
--- a/mkdocs/contrib/search/search_index.py
+++ b/mkdocs/contrib/search/search_index.py
@@ -8,6 +8,7 @@ from html.parser import HTMLParser
try:
from lunr import lunr
+
haslunrpy = True
except ImportError:
haslunrpy = False
@@ -44,11 +45,7 @@ class SearchIndex:
text = text.replace('\u00a0', ' ')
text = re.sub(r'[ \t\n\r\f\v]+', ' ', text.strip())
- self._entries.append({
- 'title': title,
- 'text': text,
- 'location': loc
- })
+ self._entries.append({'title': title, 'text': text, 'location': loc})
def add_entry_from_context(self, page):
"""
@@ -70,11 +67,7 @@ class SearchIndex:
# Create an entry for the full page.
text = parser.stripped_html.rstrip('\n') if self.config['indexing'] == 'full' else ''
- self._add_entry(
- title=page.title,
- text=text,
- loc=url
- )
+ self._add_entry(title=page.title, text=text, loc=url)
if self.config['indexing'] in ['full', 'sections']:
for section in parser.data:
@@ -91,28 +84,23 @@ class SearchIndex:
text = ' '.join(section.text) if self.config['indexing'] == 'full' else ''
if toc_item is not None:
- self._add_entry(
- title=toc_item.title,
- text=text,
- loc=abs_url + toc_item.url
- )
+ self._add_entry(title=toc_item.title, text=text, loc=abs_url + toc_item.url)
def generate_search_index(self):
"""python to json conversion"""
- page_dicts = {
- 'docs': self._entries,
- 'config': self.config
- }
+ page_dicts = {'docs': self._entries, 'config': self.config}
data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':'), default=str)
if self.config['prebuild_index'] in (True, 'node'):
try:
- script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'prebuild-index.js')
+ script_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), 'prebuild-index.js'
+ )
p = subprocess.Popen(
['node', script_path],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
- stderr=subprocess.PIPE
+ stderr=subprocess.PIPE,
)
idx, err = p.communicate(data.encode('utf-8'))
if not err:
@@ -127,8 +115,11 @@ class SearchIndex:
elif self.config['prebuild_index'] == 'python':
if haslunrpy:
idx = lunr(
- ref='location', fields=('title', 'text'), documents=self._entries,
- languages=self.config['lang'])
+ 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:
@@ -154,11 +145,7 @@ class ContentSection:
self.title = title
def __eq__(self, other):
- return (
- self.text == other.text and
- self.id == other.id and
- self.title == other.title
- )
+ return self.text == other.text and self.id == other.id and self.title == other.title
class ContentParser(HTMLParser):
diff --git a/mkdocs/exceptions.py b/mkdocs/exceptions.py
index c72175df..4ce39ba2 100644
--- a/mkdocs/exceptions.py
+++ b/mkdocs/exceptions.py
@@ -7,6 +7,7 @@ class MkDocsException(ClickException):
class Abort(MkDocsException):
"""Abort the build"""
+
def show(self, **kwargs):
echo(self.format_message())
diff --git a/mkdocs/livereload/__init__.py b/mkdocs/livereload/__init__.py
index 9feb27f7..8f9b7bff 100644
--- a/mkdocs/livereload/__init__.py
+++ b/mkdocs/livereload/__init__.py
@@ -219,7 +219,7 @@ class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGISe
return [b"%d" % self._visible_epoch]
if path.startswith(self.mount_path):
- rel_file_path = path[len(self.mount_path):]
+ rel_file_path = path[len(self.mount_path) :]
if path.endswith("/"):
rel_file_path += "index.html"
diff --git a/mkdocs/localization.py b/mkdocs/localization.py
index 6f772ec3..54a711df 100644
--- a/mkdocs/localization.py
+++ b/mkdocs/localization.py
@@ -7,9 +7,11 @@ from mkdocs.config.base import ValidationError
try:
from babel.core import Locale, UnknownLocaleError
from babel.support import Translations, NullTranslations
+
has_babel = True
except ImportError: # pragma: no cover
from mkdocs.utils.babel_stub import Locale, UnknownLocaleError
+
has_babel = False
diff --git a/mkdocs/plugins.py b/mkdocs/plugins.py
index 4cc978b9..4ea25ab6 100644
--- a/mkdocs/plugins.py
+++ b/mkdocs/plugins.py
@@ -15,14 +15,28 @@ log = logging.getLogger('mkdocs.plugins')
EVENTS = (
- 'config', 'pre_build', 'files', 'nav', 'env', 'pre_template', 'template_context',
- 'post_template', 'pre_page', 'page_read_source', 'page_markdown',
- 'page_content', 'page_context', 'post_page', 'post_build', 'serve', 'build_error'
+ 'config',
+ 'pre_build',
+ 'files',
+ 'nav',
+ 'env',
+ 'pre_template',
+ 'template_context',
+ 'post_template',
+ 'pre_page',
+ 'page_read_source',
+ 'page_markdown',
+ 'page_content',
+ 'page_context',
+ 'post_page',
+ 'post_build',
+ 'serve',
+ 'build_error',
)
def get_plugins():
- """ Return a dict of all installed Plugins as {name: EntryPoint}. """
+ """Return a dict of all installed Plugins as {name: EntryPoint}."""
plugins = importlib_metadata.entry_points(group='mkdocs.plugins')
@@ -48,7 +62,7 @@ class BasePlugin:
config = {}
def load_config(self, options, config_file_path=None):
- """ Load config from a dict of options. Returns a tuple of (errors, warnings)."""
+ """Load config from a dict of options. Returns a tuple of (errors, warnings)."""
self.config = Config(schema=self.config_scheme, config_file_path=config_file_path)
self.config.load_dict(options)
@@ -70,7 +84,7 @@ class PluginCollection(OrderedDict):
self.events = {x: [] for x in EVENTS}
def _register_event(self, event_name, method):
- """ Register a method for an event. """
+ """Register a method for an event."""
self.events[event_name].append(method)
def __setitem__(self, key, value, **kwargs):
@@ -78,7 +92,8 @@ class PluginCollection(OrderedDict):
raise TypeError(
f'{self.__module__}.{self.__name__} only accepts values which'
f' are instances of {BasePlugin.__module__}.{BasePlugin.__name__}'
- ' subclasses')
+ ' subclasses'
+ )
super().__setitem__(key, value, **kwargs)
# Register all of the event methods defined for this Plugin.
for event_name in (x for x in dir(value) if x.startswith('on_')):
diff --git a/mkdocs/structure/files.py b/mkdocs/structure/files.py
index 4ab26988..39a68d80 100644
--- a/mkdocs/structure/files.py
+++ b/mkdocs/structure/files.py
@@ -10,7 +10,8 @@ log = logging.getLogger(__name__)
class Files:
- """ A collection of File objects. """
+ """A collection of File objects."""
+
def __init__(self, files):
self._files = files
@@ -28,45 +29,46 @@ class Files:
return {file.src_path: file for file in self._files}
def get_file_from_path(self, path):
- """ Return a File instance with File.src_path equal to path. """
+ """Return a File instance with File.src_path equal to path."""
return self.src_paths.get(os.path.normpath(path))
def append(self, file):
- """ Append file to Files collection. """
+ """Append file to Files collection."""
self._files.append(file)
def remove(self, file):
- """ Remove file from Files collection. """
+ """Remove file from Files collection."""
self._files.remove(file)
def copy_static_files(self, dirty=False):
- """ Copy static files from source to destination. """
+ """Copy static files from source to destination."""
for file in self:
if not file.is_documentation_page():
file.copy_file(dirty)
def documentation_pages(self):
- """ Return iterable of all Markdown page file objects. """
+ """Return iterable of all Markdown page file objects."""
return [file for file in self if file.is_documentation_page()]
def static_pages(self):
- """ Return iterable of all static page file objects. """
+ """Return iterable of all static page file objects."""
return [file for file in self if file.is_static_page()]
def media_files(self):
- """ Return iterable of all file objects which are not documentation or static pages. """
+ """Return iterable of all file objects which are not documentation or static pages."""
return [file for file in self if file.is_media_file()]
def javascript_files(self):
- """ Return iterable of all javascript file objects. """
+ """Return iterable of all javascript file objects."""
return [file for file in self if file.is_javascript()]
def css_files(self):
- """ Return iterable of all CSS file objects. """
+ """Return iterable of all CSS file objects."""
return [file for file in self if file.is_css()]
def add_files_from_theme(self, env, config):
- """ Retrieve static files from Jinja environment and add to collection. """
+ """Retrieve static files from Jinja environment and add to collection."""
+
def filter(name):
# '.*' filters dot files/dirs at root level whereas '*/.*' filters nested levels
patterns = ['.*', '*/.*', '*.py', '*.pyc', '*.html', '*readme*', 'mkdocs_theme.yml']
@@ -78,6 +80,7 @@ class Files:
if fnmatch.fnmatch(name.lower(), pattern):
return False
return True
+
for path in env.list_templates(filter_func=filter):
# Theme files do not override docs_dir files
path = os.path.normpath(path)
@@ -85,7 +88,9 @@ class Files:
for dir in config['theme'].dirs:
# Find the first theme dir which contains path
if os.path.isfile(os.path.join(dir, path)):
- self.append(File(path, dir, config['site_dir'], config['use_directory_urls']))
+ self.append(
+ File(path, dir, config['site_dir'], config['use_directory_urls'])
+ )
break
@@ -121,6 +126,7 @@ class File:
File.url
The url of the destination file relative to the destination directory as a string.
"""
+
def __init__(self, path, src_dir, dest_dir, use_directory_urls):
self.page = None
self.src_path = os.path.normpath(path)
@@ -132,10 +138,10 @@ class File:
def __eq__(self, other):
return (
- isinstance(other, self.__class__) and
- self.src_path == other.src_path and
- self.abs_src_path == other.abs_src_path and
- self.url == other.url
+ isinstance(other, self.__class__)
+ and self.src_path == other.src_path
+ and self.abs_src_path == other.abs_src_path
+ and self.url == other.url
)
def __repr__(self):
@@ -145,13 +151,13 @@ class File:
)
def _get_stem(self):
- """ Return the name of the file without it's extension. """
+ """Return the name of the file without it's extension."""
filename = os.path.basename(self.src_path)
stem, ext = os.path.splitext(filename)
return 'index' if stem in ('index', 'README') else stem
def _get_dest_path(self, use_directory_urls):
- """ Return destination path based on source path. """
+ """Return destination path based on source path."""
if self.is_documentation_page():
parent, filename = os.path.split(self.src_path)
if not use_directory_urls or self.name == 'index':
@@ -164,7 +170,7 @@ class File:
return self.src_path
def _get_url(self, use_directory_urls):
- """ Return url based in destination path. """
+ """Return url based in destination path."""
url = self.dest_path.replace(os.path.sep, '/')
dirname, filename = os.path.split(url)
if use_directory_urls and filename == 'index.html':
@@ -175,11 +181,11 @@ class File:
return urlquote(url)
def url_relative_to(self, other):
- """ Return url for file relative to other file. """
+ """Return url for file relative to other file."""
return utils.get_relative_url(self.url, other.url if isinstance(other, File) else other)
def copy_file(self, dirty=False):
- """ Copy source file to destination, ensuring parent directories exist. """
+ """Copy source file to destination, ensuring parent directories exist."""
if dirty and not self.is_modified():
log.debug(f"Skip copying unmodified file: '{self.src_path}'")
else:
@@ -192,28 +198,28 @@ class File:
return True
def is_documentation_page(self):
- """ Return True if file is a Markdown page. """
+ """Return True if file is a Markdown page."""
return utils.is_markdown_file(self.src_path)
def is_static_page(self):
- """ Return True if file is a static page (html, xml, json). """
+ """Return True if file is a static page (html, xml, json)."""
return self.src_path.endswith(('.html', '.htm', '.xml', '.json'))
def is_media_file(self):
- """ Return True if file is not a documentation or static page. """
+ """Return True if file is not a documentation or static page."""
return not (self.is_documentation_page() or self.is_static_page())
def is_javascript(self):
- """ Return True if file is a JavaScript file. """
+ """Return True if file is a JavaScript file."""
return self.src_path.endswith(('.js', '.javascript'))
def is_css(self):
- """ Return True if file is a CSS file. """
+ """Return True if file is a CSS file."""
return self.src_path.endswith('.css')
def get_files(config):
- """ Walk the `docs_dir` and return a Files collection. """
+ """Walk the `docs_dir` and return a Files collection."""
files = []
exclude = ['.*', '/templates']
@@ -234,15 +240,19 @@ def get_files(config):
continue
# Skip README.md if an index file also exists in dir
if filename == 'README.md' and 'index.md' in filenames:
- log.warning(f"Both index.md and README.md found. Skipping README.md from {source_dir}")
+ log.warning(
+ f"Both index.md and README.md found. Skipping README.md from {source_dir}"
+ )
continue
- files.append(File(path, config['docs_dir'], config['site_dir'], config['use_directory_urls']))
+ files.append(
+ File(path, config['docs_dir'], config['site_dir'], config['use_directory_urls'])
+ )
return Files(files)
def _sort_files(filenames):
- """ Always sort `index` or `README` as first filename in list. """
+ """Always sort `index` or `README` as first filename in list."""
def key(f):
if os.path.splitext(f)[0] in ['index', 'README']:
@@ -253,7 +263,7 @@ def _sort_files(filenames):
def _filter_paths(basename, path, is_dir, exclude):
- """ .gitignore style file filtering. """
+ """.gitignore style file filtering."""
for item in exclude:
# Items ending in '/' apply only to directories.
if item.endswith('/') and not is_dir:
diff --git a/mkdocs/structure/nav.py b/mkdocs/structure/nav.py
index b8883773..e5433868 100644
--- a/mkdocs/structure/nav.py
+++ b/mkdocs/structure/nav.py
@@ -44,11 +44,11 @@ class Section:
return f"Section(title='{self.title}')"
def _get_active(self):
- """ Return active status of section. """
+ """Return active status of section."""
return self.__active
def _set_active(self, value):
- """ Set active status of section and ancestors. """
+ """Set active status of section and ancestors."""
self.__active = bool(value)
if self.parent is not None:
self.parent.active = bool(value)
@@ -96,7 +96,7 @@ class Link:
def get_navigation(files, config):
- """ Build site navigation from config and files."""
+ """Build site navigation from config and files."""
nav_config = config['nav'] or nest_paths(f.src_path for f in files.documentation_pages())
items = _data_to_navigation(nav_config, files, config)
if not isinstance(items, list):
@@ -114,7 +114,8 @@ def get_navigation(files, config):
log.info(
'The following pages exist in the docs directory, but are not '
'included in the "nav" configuration:\n - {}'.format(
- '\n - '.join([file.src_path for file in missing_from_config]))
+ '\n - '.join([file.src_path for file in missing_from_config])
+ )
)
# Any documentation files not found in the nav should still have an associated page, so we
# create them here. The Page object will automatically be assigned to `file.page` during
@@ -126,9 +127,7 @@ def get_navigation(files, config):
for link in links:
scheme, netloc, path, query, fragment = urlsplit(link.url)
if scheme or netloc:
- log.debug(
- f"An external link to '{link.url}' is included in the 'nav' configuration."
- )
+ log.debug(f"An external link to '{link.url}' is included in the 'nav' configuration.")
elif link.url.startswith('/'):
log.debug(
f"An absolute path to '{link.url}' is included in the 'nav' "
@@ -147,15 +146,15 @@ def _data_to_navigation(data, files, config):
if isinstance(data, dict):
return [
_data_to_navigation((key, value), files, config)
- if isinstance(value, str) else
- Section(title=key, children=_data_to_navigation(value, files, config))
+ if isinstance(value, str)
+ else Section(title=key, children=_data_to_navigation(value, files, config))
for key, value in data.items()
]
elif isinstance(data, list):
return [
_data_to_navigation(item, files, config)[0]
- if isinstance(item, dict) and len(item) == 1 else
- _data_to_navigation(item, files, config)
+ if isinstance(item, dict) and len(item) == 1
+ else _data_to_navigation(item, files, config)
for item in data
]
title, path = data if isinstance(data, tuple) else (None, data)
diff --git a/mkdocs/structure/pages.py b/mkdocs/structure/pages.py
index db50ddb2..a1a68ae7 100644
--- a/mkdocs/structure/pages.py
+++ b/mkdocs/structure/pages.py
@@ -44,9 +44,9 @@ class Page:
def __eq__(self, other):
return (
- isinstance(other, self.__class__) and
- self.title == other.title and
- self.file == other.file
+ isinstance(other, self.__class__)
+ and self.title == other.title
+ and self.file == other.file
)
def __repr__(self):
@@ -58,11 +58,11 @@ class Page:
return '{}{}'.format(' ' * depth, repr(self))
def _get_active(self):
- """ Return active status of page. """
+ """Return active status of page."""
return self.__active
def _set_active(self, value):
- """ Set active status of page and ancestors. """
+ """Set active status of page and ancestors."""
self.__active = bool(value)
if self.parent is not None:
self.parent.active = bool(value)
@@ -112,9 +112,7 @@ class Page:
self.edit_url = None
def read_source(self, config):
- source = config['plugins'].run_event(
- 'page_read_source', page=self, config=config
- )
+ source = config['plugins'].run_event('page_read_source', page=self, config=config)
if source is None:
try:
with open(self.file.abs_src_path, encoding='utf-8-sig', errors='strict') as f:
@@ -164,13 +162,11 @@ class Page:
Convert the Markdown source file to HTML as per the config.
"""
- extensions = [
- _RelativePathExtension(self.file, files)
- ] + config['markdown_extensions']
+ extensions = [_RelativePathExtension(self.file, files)] + config['markdown_extensions']
md = markdown.Markdown(
extensions=extensions,
- extension_configs=config['mdx_configs'] or {}
+ extension_configs=config['mdx_configs'] or {},
)
self.content = md.convert(self.markdown)
self.toc = get_toc(getattr(md, 'toc_tokens', []))
@@ -205,8 +201,15 @@ class _RelativePathTreeprocessor(Treeprocessor):
def path_to_url(self, url):
scheme, netloc, path, query, fragment = urlsplit(url)
- if (scheme or netloc or not path or url.startswith('/') or url.startswith('\\')
- or AMP_SUBSTITUTE in url or '.' not in os.path.split(path)[-1]):
+ if (
+ scheme
+ or netloc
+ or not path
+ or url.startswith('/')
+ or url.startswith('\\')
+ or AMP_SUBSTITUTE in url
+ or '.' not in os.path.split(path)[-1]
+ ):
# Ignore URLs unless they are a relative link to a source file.
# AMP_SUBSTITUTE is used internally by Markdown only for email.
# No '.' in the last part of a path indicates path does not point to a file.
diff --git a/mkdocs/structure/toc.py b/mkdocs/structure/toc.py
index 72250ffe..9541b036 100644
--- a/mkdocs/structure/toc.py
+++ b/mkdocs/structure/toc.py
@@ -19,6 +19,7 @@ class TableOfContents:
"""
Represents the table of contents for a given page.
"""
+
def __init__(self, items):
self.items = items
@@ -36,6 +37,7 @@ class AnchorLink:
"""
A single entry in the table of contents.
"""
+
def __init__(self, title, id, level):
self.title, self.id, self.level = title, id, level
self.children = []
diff --git a/mkdocs/tests/babel_cmd_tests.py b/mkdocs/tests/babel_cmd_tests.py
index 1a47738a..59dfa6c8 100644
--- a/mkdocs/tests/babel_cmd_tests.py
+++ b/mkdocs/tests/babel_cmd_tests.py
@@ -9,14 +9,13 @@ BASE_DIR = path.normpath(path.join(path.abspath(path.dirname(__file__)), '../../
class ThemeMixinTests(unittest.TestCase):
-
def test_dict_entry_point(self):
inst = babel.ThemeMixin()
inst.distribution = Distribution()
inst.distribution.entry_points = {
'mkdocs.themes': [
- 'mkdocs = mkdocs.themes.mkdocs'
- ]
+ 'mkdocs = mkdocs.themes.mkdocs',
+ ],
}
inst.theme = 'mkdocs'
self.assertEqual(inst.get_theme_dir(), path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs'))
@@ -36,8 +35,8 @@ class ThemeMixinTests(unittest.TestCase):
inst.distribution = Distribution()
inst.distribution.entry_points = {
'mkdocs.themes': [
- 'mkdocs = mkdocs.themes.mkdocs'
- ]
+ 'mkdocs = mkdocs.themes.mkdocs',
+ ],
}
inst.theme = None
self.assertEqual(inst.get_theme_dir(), path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs'))
@@ -49,10 +48,12 @@ class ThemeMixinTests(unittest.TestCase):
'mkdocs.themes': [
'mkdocs = mkdocs.themes.mkdocs',
'readthedocs = mkdocs.themes.readthedocs',
- ]
+ ],
}
inst.theme = 'readthedocs'
- self.assertEqual(inst.get_theme_dir(), path.join(BASE_DIR, 'mkdocs', 'themes', 'readthedocs'))
+ self.assertEqual(
+ inst.get_theme_dir(), path.join(BASE_DIR, 'mkdocs', 'themes', 'readthedocs')
+ )
def test_multiple_entry_points_no_default(self):
inst = babel.ThemeMixin()
@@ -61,7 +62,7 @@ class ThemeMixinTests(unittest.TestCase):
'mkdocs.themes': [
'mkdocs = mkdocs.themes.mkdocs',
'readthedocs = mkdocs.themes.readthedocs',
- ]
+ ],
}
inst.theme = None
self.assertRaises(DistutilsOptionError, inst.get_theme_dir)
@@ -78,15 +79,14 @@ class ThemeMixinTests(unittest.TestCase):
inst.distribution = Distribution()
inst.distribution.entry_points = {
'mkdocs.themes': [
- 'mkdocs = mkdocs.themes.mkdocs'
- ]
+ 'mkdocs = mkdocs.themes.mkdocs',
+ ],
}
inst.theme = 'undefined'
self.assertRaises(DistutilsOptionError, inst.get_theme_dir)
class CommandTests(unittest.TestCase):
-
def test_compile_catalog(self):
dist = Distribution()
dist.entry_points = '''
@@ -136,7 +136,9 @@ class CommandTests(unittest.TestCase):
cmd.theme = 'mkdocs'
cmd.finalize_options()
self.assertEqual(cmd.input_paths, [path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs')])
- self.assertEqual(cmd.output_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.output_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
self.assertEqual(cmd.mapping_file, babel.DEFAULT_MAPPING_FILE)
self.assertEqual(cmd.project, 'foo')
self.assertEqual(cmd.version, '1.2')
@@ -153,7 +155,9 @@ class CommandTests(unittest.TestCase):
cmd.finalize_options()
self.assertEqual(cmd.theme, 'mkdocs')
self.assertEqual(cmd.input_paths, [path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs')])
- self.assertEqual(cmd.output_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.output_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
def test_extract_messages_ingore_theme(self):
dist = Distribution(dict(name='foo', version='1.2'))
@@ -182,7 +186,9 @@ class CommandTests(unittest.TestCase):
cmd.input_paths = 'mkdocs/tests'
cmd.finalize_options()
self.assertEqual(cmd.input_paths, ['mkdocs/tests'])
- self.assertEqual(cmd.output_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.output_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
def test_extract_messages_ingore_theme_for_output(self):
dist = Distribution(dict(name='foo', version='1.2'))
@@ -209,7 +215,9 @@ class CommandTests(unittest.TestCase):
cmd.theme = 'mkdocs'
cmd.locale = 'en'
cmd.finalize_options()
- self.assertEqual(cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
self.assertEqual(cmd.output_dir, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/locales'))
def test_init_catalog_default_theme(self):
@@ -224,7 +232,9 @@ class CommandTests(unittest.TestCase):
self.assertIsNone(cmd.theme)
cmd.finalize_options()
self.assertEqual(cmd.theme, 'mkdocs')
- self.assertEqual(cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
self.assertEqual(cmd.output_dir, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/locales'))
def test_init_catalog_ignore_theme(self):
@@ -270,7 +280,9 @@ class CommandTests(unittest.TestCase):
cmd.locale = 'en'
cmd.output_dir = 'foo/bar'
cmd.finalize_options()
- self.assertEqual(cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
self.assertEqual(cmd.output_dir, 'foo/bar')
def test_update_catalog(self):
@@ -283,7 +295,9 @@ class CommandTests(unittest.TestCase):
cmd.initialize_options()
cmd.theme = 'mkdocs'
cmd.finalize_options()
- self.assertEqual(cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
self.assertEqual(cmd.output_dir, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/locales'))
def test_update_catalog_default_theme(self):
@@ -298,7 +312,9 @@ class CommandTests(unittest.TestCase):
self.assertIsNone(cmd.theme)
cmd.finalize_options()
self.assertEqual(cmd.theme, 'mkdocs')
- self.assertEqual(cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
self.assertEqual(cmd.output_dir, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/locales'))
def test_update_catalog_ignore_theme(self):
@@ -344,5 +360,7 @@ class CommandTests(unittest.TestCase):
cmd.locale = 'en'
cmd.output_dir = 'foo/bar'
cmd.finalize_options()
- self.assertEqual(cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot'))
+ self.assertEqual(
+ cmd.input_file, path.join(BASE_DIR, 'mkdocs', 'themes', 'mkdocs/messages.pot')
+ )
self.assertEqual(cmd.output_dir, 'foo/bar')
diff --git a/mkdocs/tests/base.py b/mkdocs/tests/base.py
index 1270db3a..3fbb4943 100644
--- a/mkdocs/tests/base.py
+++ b/mkdocs/tests/base.py
@@ -14,17 +14,15 @@ def dedent(text):
def get_markdown_toc(markdown_source):
- """ Return TOC generated by Markdown parser from Markdown source text. """
+ """Return TOC generated by Markdown parser from Markdown source text."""
md = markdown.Markdown(extensions=['toc'])
md.convert(markdown_source)
return md.toc_tokens
def load_config(**cfg):
- """ Helper to build a simple config for testing. """
- path_base = os.path.join(
- os.path.abspath(os.path.dirname(__file__)), 'integration', 'minimal'
- )
+ """Helper to build a simple config for testing."""
+ path_base = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'integration', 'minimal')
cfg = cfg or {}
if 'site_name' not in cfg:
cfg['site_name'] = 'Example'
@@ -33,7 +31,9 @@ def load_config(**cfg):
if 'docs_dir' not in cfg:
# Point to an actual dir to avoid a 'does not exist' error on validation.
cfg['docs_dir'] = os.path.join(path_base, 'docs')
- conf = config.Config(schema=config_defaults.get_schema(), config_file_path=cfg['config_file_path'])
+ conf = config.Config(
+ schema=config_defaults.get_schema(), config_file_path=cfg['config_file_path']
+ )
conf.load_dict(cfg)
errors_warnings = conf.validate()
@@ -78,7 +78,9 @@ def tempdir(files=None, **kw):
pth = os.path.join(td, path)
utils.write_file(content.encode(encoding='utf-8'), pth)
return fn(self, td, *args)
+
return wrapper
+
return decorator
diff --git a/mkdocs/tests/build_tests.py b/mkdocs/tests/build_tests.py
index 266309d5..c99c7e44 100644
--- a/mkdocs/tests/build_tests.py
+++ b/mkdocs/tests/build_tests.py
@@ -13,9 +13,11 @@ from mkdocs.utils import meta
def build_page(title, path, config, md_src=''):
- """ Helper which returns a Page object. """
+ """Helper which returns a Page object."""
- files = Files([File(path, config['docs_dir'], config['site_dir'], config['use_directory_urls'])])
+ files = Files(
+ [File(path, config['docs_dir'], config['site_dir'], config['use_directory_urls'])]
+ )
page = Page(title, list(files)[0], config)
# Fake page.read_source()
page.markdown, page.meta = meta.get_data(md_src)
@@ -23,7 +25,6 @@ def build_page(title, path, config, md_src=''):
class BuildTests(PathAssertionMixin, unittest.TestCase):
-
def _get_env_with_null_translations(self, config):
env = config['theme'].get_env()
env.add_extension('jinja2.ext.i18n')
@@ -34,24 +35,26 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
def test_context_base_url_homepage(self):
nav_cfg = [
- {'Home': 'index.md'}
+ {'Home': 'index.md'},
]
cfg = load_config(nav=nav_cfg, use_directory_urls=False)
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ ]
+ files = Files(fs)
nav = get_navigation(files, cfg)
context = build.get_context(nav, files, cfg, nav.pages[0])
self.assertEqual(context['base_url'], '.')
def test_context_base_url_homepage_use_directory_urls(self):
nav_cfg = [
- {'Home': 'index.md'}
+ {'Home': 'index.md'},
]
cfg = load_config(nav=nav_cfg)
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ ]
+ files = Files(fs)
nav = get_navigation(files, cfg)
context = build.get_context(nav, files, cfg, nav.pages[0])
self.assertEqual(context['base_url'], '.')
@@ -59,13 +62,14 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
def test_context_base_url_nested_page(self):
nav_cfg = [
{'Home': 'index.md'},
- {'Nested': 'foo/bar.md'}
+ {'Nested': 'foo/bar.md'},
]
cfg = load_config(nav=nav_cfg, use_directory_urls=False)
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ ]
+ files = Files(fs)
nav = get_navigation(files, cfg)
context = build.get_context(nav, files, cfg, nav.pages[1])
self.assertEqual(context['base_url'], '..')
@@ -73,13 +77,14 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
def test_context_base_url_nested_page_use_directory_urls(self):
nav_cfg = [
{'Home': 'index.md'},
- {'Nested': 'foo/bar.md'}
+ {'Nested': 'foo/bar.md'},
]
cfg = load_config(nav=nav_cfg)
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ ]
+ files = Files(fs)
nav = get_navigation(files, cfg)
context = build.get_context(nav, files, cfg, nav.pages[1])
self.assertEqual(context['base_url'], '../..')
@@ -116,17 +121,18 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
def test_context_extra_css_js_from_homepage(self):
nav_cfg = [
- {'Home': 'index.md'}
+ {'Home': 'index.md'},
]
cfg = load_config(
nav=nav_cfg,
extra_css=['style.css'],
extra_javascript=['script.js'],
- use_directory_urls=False
+ use_directory_urls=False,
)
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ ]
+ files = Files(fs)
nav = get_navigation(files, cfg)
context = build.get_context(nav, files, cfg, nav.pages[0])
self.assertEqual(context['extra_css'], ['style.css'])
@@ -135,18 +141,19 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
def test_context_extra_css_js_from_nested_page(self):
nav_cfg = [
{'Home': 'index.md'},
- {'Nested': 'foo/bar.md'}
+ {'Nested': 'foo/bar.md'},
]
cfg = load_config(
nav=nav_cfg,
extra_css=['style.css'],
extra_javascript=['script.js'],
- use_directory_urls=False
+ use_directory_urls=False,
)
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ ]
+ files = Files(fs)
nav = get_navigation(files, cfg)
context = build.get_context(nav, files, cfg, nav.pages[1])
self.assertEqual(context['extra_css'], ['../style.css'])
@@ -155,17 +162,18 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
def test_context_extra_css_js_from_nested_page_use_directory_urls(self):
nav_cfg = [
{'Home': 'index.md'},
- {'Nested': 'foo/bar.md'}
+ {'Nested': 'foo/bar.md'},
]
cfg = load_config(
nav=nav_cfg,
extra_css=['style.css'],
- extra_javascript=['script.js']
+ extra_javascript=['script.js'],
)
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ ]
+ files = Files(fs)
nav = get_navigation(files, cfg)
context = build.get_context(nav, files, cfg, nav.pages[1])
self.assertEqual(context['extra_css'], ['../../style.css'])
@@ -213,7 +221,9 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
build._build_theme_template('missing.html', env, mock.Mock(), cfg, mock.Mock())
self.assertEqual(
cm.output,
- ["WARNING:mkdocs.commands.build:Template skipped: 'missing.html' not found in theme directories."]
+ [
+ "WARNING:mkdocs.commands.build:Template skipped: 'missing.html' not found in theme directories."
+ ],
)
mock_write_file.assert_not_called()
mock_build_template.assert_not_called()
@@ -227,7 +237,7 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
build._build_theme_template('main.html', env, mock.Mock(), cfg, mock.Mock())
self.assertEqual(
cm.output,
- ["INFO:mkdocs.commands.build:Template skipped: 'main.html' generated empty output."]
+ ["INFO:mkdocs.commands.build:Template skipped: 'main.html' generated empty output."],
)
mock_write_file.assert_not_called()
mock_build_template.assert_called_once()
@@ -237,48 +247,54 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
@mock.patch('mkdocs.commands.build.open', mock.mock_open(read_data='template content'))
def test_build_extra_template(self):
cfg = load_config()
- files = Files([
+ fs = [
File('foo.html', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ ]
+ files = Files(fs)
build._build_extra_template('foo.html', files, cfg, mock.Mock())
@mock.patch('mkdocs.commands.build.open', mock.mock_open(read_data='template content'))
def test_skip_missing_extra_template(self):
cfg = load_config()
- files = Files([
+ fs = [
File('foo.html', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ ]
+ files = Files(fs)
with self.assertLogs('mkdocs', level='INFO') as cm:
build._build_extra_template('missing.html', files, cfg, mock.Mock())
self.assertEqual(
cm.output,
- ["WARNING:mkdocs.commands.build:Template skipped: 'missing.html' not found in docs_dir."]
+ [
+ "WARNING:mkdocs.commands.build:Template skipped: 'missing.html' not found in docs_dir."
+ ],
)
@mock.patch('mkdocs.commands.build.open', side_effect=OSError('Error message.'))
def test_skip_ioerror_extra_template(self, mock_open):
cfg = load_config()
- files = Files([
+ fs = [
File('foo.html', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ ]
+ files = Files(fs)
with self.assertLogs('mkdocs', level='INFO') as cm:
build._build_extra_template('foo.html', files, cfg, mock.Mock())
self.assertEqual(
cm.output,
- ["WARNING:mkdocs.commands.build:Error reading template 'foo.html': Error message."]
+ ["WARNING:mkdocs.commands.build:Error reading template 'foo.html': Error message."],
)
@mock.patch('mkdocs.commands.build.open', mock.mock_open(read_data=''))
def test_skip_extra_template_empty_output(self):
cfg = load_config()
- files = Files([
+ fs = [
File('foo.html', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ ]
+ files = Files(fs)
with self.assertLogs('mkdocs', level='INFO') as cm:
build._build_extra_template('foo.html', files, cfg, mock.Mock())
self.assertEqual(
cm.output,
- ["INFO:mkdocs.commands.build:Template skipped: 'foo.html' generated empty output."]
+ ["INFO:mkdocs.commands.build:Template skipped: 'foo.html' generated empty output."],
)
# Test build._populate_page
@@ -298,7 +314,9 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
page = Page('Foo', file, cfg)
build._populate_page(page, cfg, Files([file]), dirty=True)
self.assertTrue(page.markdown.startswith('# Welcome to MkDocs'))
- self.assertTrue(page.content.startswith('Welcome to MkDocs
'))
+ self.assertTrue(
+ page.content.startswith('Welcome to MkDocs
')
+ )
@tempdir(files={'index.md': 'page content'})
@tempdir(files={'index.html': 'page content
'})
@@ -321,15 +339,18 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
with self.assertRaises(OSError):
build._populate_page(page, cfg, Files([file]))
self.assertEqual(
- cm.output, [
+ cm.output,
+ [
'ERROR:mkdocs.structure.pages:File not found: missing.md',
- "ERROR:mkdocs.commands.build:Error reading page 'missing.md': Error message."
- ]
+ "ERROR:mkdocs.commands.build:Error reading page 'missing.md': Error message.",
+ ],
)
mock_open.assert_called_once()
@tempdir(files={'index.md': 'page content'})
- @mock.patch('mkdocs.plugins.PluginCollection.run_event', side_effect=PluginError('Error message.'))
+ @mock.patch(
+ 'mkdocs.plugins.PluginCollection.run_event', side_effect=PluginError('Error message.')
+ )
def test_populate_page_read_plugin_error(self, docs_dir, mock_open):
cfg = load_config(docs_dir=docs_dir)
file = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
@@ -338,9 +359,8 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
with self.assertRaises(PluginError):
build._populate_page(page, cfg, Files([file]))
self.assertEqual(
- cm.output, [
- "ERROR:mkdocs.commands.build:Error reading page 'index.md':"
- ]
+ cm.output,
+ ["ERROR:mkdocs.commands.build:Error reading page 'index.md':"],
)
mock_open.assert_called_once()
@@ -349,7 +369,8 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
@tempdir()
def test_build_page(self, site_dir):
cfg = load_config(site_dir=site_dir, nav=['index.md'], plugins=[])
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
nav = get_navigation(files, cfg)
page = files.documentation_pages()[0].page
# Fake populate page
@@ -363,13 +384,16 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
@mock.patch('jinja2.environment.Template.render', return_value='')
def test_build_page_empty(self, site_dir, render_mock):
cfg = load_config(site_dir=site_dir, nav=['index.md'], plugins=[])
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
nav = get_navigation(files, cfg)
with self.assertLogs('mkdocs', level='INFO') as cm:
- build._build_page(files.documentation_pages()[0].page, cfg, files, nav, cfg['theme'].get_env())
+ build._build_page(
+ files.documentation_pages()[0].page, cfg, files, nav, cfg['theme'].get_env()
+ )
self.assertEqual(
cm.output,
- ["INFO:mkdocs.commands.build:Page skipped: 'index.md'. Generated empty output."]
+ ["INFO:mkdocs.commands.build:Page skipped: 'index.md'. Generated empty output."],
)
self.assertPathNotFile(site_dir, 'index.html')
render_mock.assert_called_once()
@@ -379,34 +403,41 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
@mock.patch('mkdocs.utils.write_file')
def test_build_page_dirty_modified(self, site_dir, docs_dir, mock_write_file):
cfg = load_config(docs_dir=docs_dir, site_dir=site_dir, nav=['index.md'], plugins=[])
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
nav = get_navigation(files, cfg)
page = files.documentation_pages()[0].page
# Fake populate page
page.title = 'Title'
page.markdown = 'new page content'
page.content = 'new page content
'
- build._build_page(page, cfg, files, nav, self._get_env_with_null_translations(cfg), dirty=True)
+ build._build_page(
+ page, cfg, files, nav, self._get_env_with_null_translations(cfg), dirty=True
+ )
mock_write_file.assert_not_called()
@tempdir(files={'testing.html': 'page content
'})
@mock.patch('mkdocs.utils.write_file')
def test_build_page_dirty_not_modified(self, site_dir, mock_write_file):
cfg = load_config(site_dir=site_dir, nav=['testing.md'], plugins=[])
- files = Files([File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
nav = get_navigation(files, cfg)
page = files.documentation_pages()[0].page
# Fake populate page
page.title = 'Title'
page.markdown = 'page content'
page.content = 'page content
'
- build._build_page(page, cfg, files, nav, self._get_env_with_null_translations(cfg), dirty=True)
+ build._build_page(
+ page, cfg, files, nav, self._get_env_with_null_translations(cfg), dirty=True
+ )
mock_write_file.assert_called_once()
@tempdir()
def test_build_page_custom_template(self, site_dir):
cfg = load_config(site_dir=site_dir, nav=['index.md'], plugins=[])
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
nav = get_navigation(files, cfg)
page = files.documentation_pages()[0].page
# Fake populate page
@@ -421,7 +452,8 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
@mock.patch('mkdocs.utils.write_file', side_effect=OSError('Error message.'))
def test_build_page_error(self, site_dir, mock_write_file):
cfg = load_config(site_dir=site_dir, nav=['index.md'], plugins=[])
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
nav = get_navigation(files, cfg)
page = files.documentation_pages()[0].page
# Fake populate page
@@ -430,24 +462,21 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
page.content = 'page content
'
with self.assertLogs('mkdocs', level='ERROR') as cm:
with self.assertRaises(OSError):
- build._build_page(
- page,
- cfg,
- files,
- nav,
- self._get_env_with_null_translations(cfg)
- )
+ build._build_page(page, cfg, files, nav, self._get_env_with_null_translations(cfg))
self.assertEqual(
cm.output,
- ["ERROR:mkdocs.commands.build:Error building page 'index.md': Error message."]
+ ["ERROR:mkdocs.commands.build:Error building page 'index.md': Error message."],
)
mock_write_file.assert_called_once()
@tempdir()
- @mock.patch('mkdocs.plugins.PluginCollection.run_event', side_effect=PluginError('Error message.'))
+ @mock.patch(
+ 'mkdocs.plugins.PluginCollection.run_event', side_effect=PluginError('Error message.')
+ )
def test_build_page_plugin_error(self, site_dir, mock_write_file):
cfg = load_config(site_dir=site_dir, nav=['index.md'], plugins=[])
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
nav = get_navigation(files, cfg)
page = files.documentation_pages()[0].page
# Fake populate page
@@ -459,20 +488,22 @@ class BuildTests(PathAssertionMixin, unittest.TestCase):
build._build_page(page, cfg, files, nav, cfg['theme'].get_env())
self.assertEqual(
cm.output,
- ["ERROR:mkdocs.commands.build:Error building page 'index.md':"]
+ ["ERROR:mkdocs.commands.build:Error building page 'index.md':"],
)
mock_write_file.assert_called_once()
# Test build.build
- @tempdir(files={
- 'index.md': 'page content',
- 'empty.md': '',
- 'img.jpg': '',
- 'static.html': 'content',
- '.hidden': 'content',
- '.git/hidden': 'content'
- })
+ @tempdir(
+ files={
+ 'index.md': 'page content',
+ 'empty.md': '',
+ 'img.jpg': '',
+ 'static.html': 'content',
+ '.hidden': 'content',
+ '.git/hidden': 'content',
+ }
+ )
@tempdir()
def test_copying_media(self, site_dir, docs_dir):
cfg = load_config(docs_dir=docs_dir, site_dir=site_dir)
diff --git a/mkdocs/tests/cli_tests.py b/mkdocs/tests/cli_tests.py
index 40397d72..b84f127c 100644
--- a/mkdocs/tests/cli_tests.py
+++ b/mkdocs/tests/cli_tests.py
@@ -11,15 +11,13 @@ from mkdocs import __main__ as cli
class CLITests(unittest.TestCase):
-
def setUp(self):
self.runner = CliRunner()
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_default(self, mock_serve):
- result = self.runner.invoke(
- cli.cli, ["serve"], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ["serve"], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -30,14 +28,15 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=None,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_config_file(self, mock_serve):
result = self.runner.invoke(
- cli.cli, ["serve", "--config-file", "mkdocs.yml"], catch_exceptions=False)
+ cli.cli, ["serve", "--config-file", "mkdocs.yml"], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_serve.call_count, 1)
@@ -50,7 +49,8 @@ class CLITests(unittest.TestCase):
def test_serve_dev_addr(self, mock_serve):
result = self.runner.invoke(
- cli.cli, ["serve", '--dev-addr', '0.0.0.0:80'], catch_exceptions=False)
+ cli.cli, ["serve", '--dev-addr', '0.0.0.0:80'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -61,14 +61,13 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=None,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_strict(self, mock_serve):
- result = self.runner.invoke(
- cli.cli, ["serve", '--strict'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ["serve", '--strict'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -79,14 +78,15 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=None,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_theme(self, mock_serve):
result = self.runner.invoke(
- cli.cli, ["serve", '--theme', 'readthedocs'], catch_exceptions=False)
+ cli.cli, ["serve", '--theme', 'readthedocs'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -97,14 +97,15 @@ class CLITests(unittest.TestCase):
theme='readthedocs',
use_directory_urls=None,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_use_directory_urls(self, mock_serve):
result = self.runner.invoke(
- cli.cli, ["serve", '--use-directory-urls'], catch_exceptions=False)
+ cli.cli, ["serve", '--use-directory-urls'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -115,14 +116,15 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=True,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_no_directory_urls(self, mock_serve):
result = self.runner.invoke(
- cli.cli, ["serve", '--no-directory-urls'], catch_exceptions=False)
+ cli.cli, ["serve", '--no-directory-urls'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -133,14 +135,13 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=False,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_livereload(self, mock_serve):
- result = self.runner.invoke(
- cli.cli, ["serve", '--livereload'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ["serve", '--livereload'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -151,14 +152,13 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=None,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_no_livereload(self, mock_serve):
- result = self.runner.invoke(
- cli.cli, ["serve", '--no-livereload'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ["serve", '--no-livereload'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -169,14 +169,13 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=None,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_dirtyreload(self, mock_serve):
- result = self.runner.invoke(
- cli.cli, ["serve", '--dirtyreload'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ["serve", '--dirtyreload'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -187,14 +186,13 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=None,
watch_theme=False,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.commands.serve.serve', autospec=True)
def test_serve_watch_theme(self, mock_serve):
- result = self.runner.invoke(
- cli.cli, ["serve", '--watch-theme'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ["serve", '--watch-theme'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
mock_serve.assert_called_once_with(
@@ -205,15 +203,14 @@ class CLITests(unittest.TestCase):
theme=None,
use_directory_urls=None,
watch_theme=True,
- watch=()
+ watch=(),
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@mock.patch('mkdocs.commands.build.build', autospec=True)
def test_build_defaults(self, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['build'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['build'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -225,7 +222,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
handler = logging._handlers.get('MkDocsStreamHandler')
self.assertEqual(handler.level, logging.INFO)
@@ -234,8 +231,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.build.build', autospec=True)
def test_build_clean(self, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['build', '--clean'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['build', '--clean'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -247,8 +243,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.build.build', autospec=True)
def test_build_dirty(self, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['build', '--dirty'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['build', '--dirty'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -261,7 +256,8 @@ class CLITests(unittest.TestCase):
def test_build_config_file(self, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['build', '--config-file', 'mkdocs.yml'], catch_exceptions=False)
+ cli.cli, ['build', '--config-file', 'mkdocs.yml'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -275,8 +271,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.build.build', autospec=True)
def test_build_strict(self, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['build', '--strict'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['build', '--strict'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -285,7 +280,7 @@ class CLITests(unittest.TestCase):
strict=True,
theme=None,
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -293,7 +288,8 @@ class CLITests(unittest.TestCase):
def test_build_theme(self, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['build', '--theme', 'readthedocs'], catch_exceptions=False)
+ cli.cli, ['build', '--theme', 'readthedocs'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -302,7 +298,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme='readthedocs',
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -310,7 +306,8 @@ class CLITests(unittest.TestCase):
def test_build_use_directory_urls(self, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['build', '--use-directory-urls'], catch_exceptions=False)
+ cli.cli, ['build', '--use-directory-urls'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -319,7 +316,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=True,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -327,7 +324,8 @@ class CLITests(unittest.TestCase):
def test_build_no_directory_urls(self, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['build', '--no-directory-urls'], catch_exceptions=False)
+ cli.cli, ['build', '--no-directory-urls'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -336,7 +334,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=False,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -344,7 +342,8 @@ class CLITests(unittest.TestCase):
def test_build_site_dir(self, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['build', '--site-dir', 'custom'], catch_exceptions=False)
+ cli.cli, ['build', '--site-dir', 'custom'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -360,8 +359,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.build.build', autospec=True)
def test_build_verbose(self, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['build', '--verbose'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['build', '--verbose'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -372,8 +370,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.build.build', autospec=True)
def test_build_quiet(self, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['build', '--quiet'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['build', '--quiet'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_build.call_count, 1)
@@ -383,8 +380,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.new.new', autospec=True)
def test_new(self, mock_new):
- result = self.runner.invoke(
- cli.cli, ["new", "project"], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ["new", "project"], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
mock_new.assert_called_once_with('project')
@@ -394,8 +390,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
def test_gh_deploy_defaults(self, mock_gh_deploy, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['gh-deploy'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['gh-deploy'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -417,7 +412,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -425,8 +420,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
def test_gh_deploy_clean(self, mock_gh_deploy, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--clean'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['gh-deploy', '--clean'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -440,8 +434,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
def test_gh_deploy_dirty(self, mock_gh_deploy, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--dirty'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['gh-deploy', '--dirty'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -456,7 +449,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_config_file(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--config-file', 'mkdocs.yml'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--config-file', 'mkdocs.yml'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -473,7 +467,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_message(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--message', 'A commit message'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--message', 'A commit message'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -489,7 +484,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_remote_branch(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--remote-branch', 'foo'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--remote-branch', 'foo'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -501,7 +497,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -510,7 +506,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_remote_name(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--remote-name', 'foo'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--remote-name', 'foo'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -522,7 +519,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -530,8 +527,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
def test_gh_deploy_force(self, mock_gh_deploy, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--force'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['gh-deploy', '--force'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -547,7 +543,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_ignore_version(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--ignore-version'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--ignore-version'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -562,8 +559,7 @@ class CLITests(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy.gh_deploy', autospec=True)
def test_gh_deploy_strict(self, mock_gh_deploy, mock_build, mock_load_config):
- result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--strict'], catch_exceptions=False)
+ result = self.runner.invoke(cli.cli, ['gh-deploy', '--strict'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -575,7 +571,7 @@ class CLITests(unittest.TestCase):
strict=True,
theme=None,
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -584,7 +580,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_theme(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--theme', 'readthedocs'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--theme', 'readthedocs'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -596,7 +593,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme='readthedocs',
use_directory_urls=None,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -605,7 +602,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_use_directory_urls(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--use-directory-urls'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--use-directory-urls'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -617,7 +615,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=True,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -626,7 +624,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_no_directory_urls(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--no-directory-urls'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--no-directory-urls'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -638,7 +637,7 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=False,
- site_dir=None
+ site_dir=None,
)
@mock.patch('mkdocs.config.load_config', autospec=True)
@@ -647,7 +646,8 @@ class CLITests(unittest.TestCase):
def test_gh_deploy_site_dir(self, mock_gh_deploy, mock_build, mock_load_config):
result = self.runner.invoke(
- cli.cli, ['gh-deploy', '--site-dir', 'custom'], catch_exceptions=False)
+ cli.cli, ['gh-deploy', '--site-dir', 'custom'], catch_exceptions=False
+ )
self.assertEqual(result.exit_code, 0)
self.assertEqual(mock_gh_deploy.call_count, 1)
@@ -659,5 +659,5 @@ class CLITests(unittest.TestCase):
strict=None,
theme=None,
use_directory_urls=None,
- site_dir='custom'
+ site_dir='custom',
)
diff --git a/mkdocs/tests/config/base_tests.py b/mkdocs/tests/config/base_tests.py
index 0f1f8d54..b9a37822 100644
--- a/mkdocs/tests/config/base_tests.py
+++ b/mkdocs/tests/config/base_tests.py
@@ -9,20 +9,26 @@ from mkdocs.config.config_options import BaseConfigOption
class ConfigBaseTests(unittest.TestCase):
-
def test_unrecognised_keys(self):
c = base.Config(schema=defaults.get_schema())
- c.load_dict({
- 'not_a_valid_config_option': "test"
- })
+ c.load_dict(
+ {
+ 'not_a_valid_config_option': "test",
+ }
+ )
failed, warnings = c.validate()
- self.assertEqual(warnings, [
- ('not_a_valid_config_option',
- 'Unrecognised configuration name: not_a_valid_config_option')
- ])
+ self.assertEqual(
+ warnings,
+ [
+ (
+ 'not_a_valid_config_option',
+ 'Unrecognised configuration name: not_a_valid_config_option',
+ )
+ ],
+ )
def test_missing_required(self):
@@ -197,8 +203,7 @@ class ConfigBaseTests(unittest.TestCase):
config_file = tempfile.NamedTemporaryFile('w', delete=False)
try:
- config_file.write(
- "site_dir: output\nsite_uri: https://www.mkdocs.org\n")
+ config_file.write("site_dir: output\nsite_uri: https://www.mkdocs.org\n")
config_file.flush()
config_file.close()
@@ -212,7 +217,7 @@ class ConfigBaseTests(unittest.TestCase):
def pre_validation(self, config, key_name):
raise base.ValidationError('pre_validation error')
- c = base.Config(schema=(('invalid_option', InvalidConfigOption()), ))
+ c = base.Config(schema=(('invalid_option', InvalidConfigOption()),))
errors, warnings = c.validate()
@@ -227,7 +232,7 @@ class ConfigBaseTests(unittest.TestCase):
def run_validation(self, value):
raise base.ValidationError('run_validation error')
- c = base.Config(schema=(('invalid_option', InvalidConfigOption()), ))
+ c = base.Config(schema=(('invalid_option', InvalidConfigOption()),))
errors, warnings = c.validate()
@@ -242,7 +247,7 @@ class ConfigBaseTests(unittest.TestCase):
def post_validation(self, config, key_name):
raise base.ValidationError('post_validation error')
- c = base.Config(schema=(('invalid_option', InvalidConfigOption()), ))
+ c = base.Config(schema=(('invalid_option', InvalidConfigOption()),))
errors, warnings = c.validate()
@@ -253,7 +258,8 @@ class ConfigBaseTests(unittest.TestCase):
self.assertEqual(len(warnings), 0)
def test_pre_and_run_validation_errors(self):
- """ A pre_validation error does not stop run_validation from running. """
+ """A pre_validation error does not stop run_validation from running."""
+
class InvalidConfigOption(BaseConfigOption):
def pre_validation(self, config, key_name):
raise base.ValidationError('pre_validation error')
@@ -261,7 +267,7 @@ class ConfigBaseTests(unittest.TestCase):
def run_validation(self, value):
raise base.ValidationError('run_validation error')
- c = base.Config(schema=(('invalid_option', InvalidConfigOption()), ))
+ c = base.Config(schema=(('invalid_option', InvalidConfigOption()),))
errors, warnings = c.validate()
@@ -275,7 +281,8 @@ class ConfigBaseTests(unittest.TestCase):
self.assertEqual(len(warnings), 0)
def test_run_and_post_validation_errors(self):
- """ A run_validation error stops post_validation from running. """
+ """A run_validation error stops post_validation from running."""
+
class InvalidConfigOption(BaseConfigOption):
def run_validation(self, value):
raise base.ValidationError('run_validation error')
@@ -283,7 +290,7 @@ class ConfigBaseTests(unittest.TestCase):
def post_validation(self, config, key_name):
raise base.ValidationError('post_validation error')
- c = base.Config(schema=(('invalid_option', InvalidConfigOption()), ))
+ c = base.Config(schema=(('invalid_option', InvalidConfigOption()),))
errors, warnings = c.validate()
@@ -304,16 +311,19 @@ class ConfigBaseTests(unittest.TestCase):
def post_validation(self, config, key_name):
self.warnings.append('post_validation warning')
- c = base.Config(schema=(('invalid_option', InvalidConfigOption()), ))
+ c = base.Config(schema=(('invalid_option', InvalidConfigOption()),))
errors, warnings = c.validate()
self.assertEqual(len(errors), 0)
- self.assertEqual(warnings, [
- ('invalid_option', 'pre_validation warning'),
- ('invalid_option', 'run_validation warning'),
- ('invalid_option', 'post_validation warning'),
- ])
+ self.assertEqual(
+ warnings,
+ [
+ ('invalid_option', 'pre_validation warning'),
+ ('invalid_option', 'run_validation warning'),
+ ('invalid_option', 'post_validation warning'),
+ ],
+ )
def test_load_from_file_with_relative_paths(self):
"""
diff --git a/mkdocs/tests/config/config_options_tests.py b/mkdocs/tests/config/config_options_tests.py
index e344aec3..fd605545 100644
--- a/mkdocs/tests/config/config_options_tests.py
+++ b/mkdocs/tests/config/config_options_tests.py
@@ -12,7 +12,6 @@ from mkdocs.utils import yaml_load
class OptionallyRequiredTest(unittest.TestCase):
-
def test_empty(self):
option = config_options.OptionallyRequired()
@@ -49,7 +48,6 @@ class OptionallyRequiredTest(unittest.TestCase):
class TypeTest(unittest.TestCase):
-
def test_single_type(self):
option = config_options.Type(str)
@@ -79,7 +77,6 @@ class TypeTest(unittest.TestCase):
class ChoiceTest(unittest.TestCase):
-
def test_valid_choice(self):
option = config_options.Choice(('python', 'node'))
value = option.validate('python')
@@ -97,7 +94,6 @@ class ChoiceTest(unittest.TestCase):
class DeprecatedTest(unittest.TestCase):
-
def test_deprecated_option_simple(self):
option = config_options.Deprecated()
option.pre_validation({'d': 'value'}, 'd')
@@ -164,7 +160,6 @@ class DeprecatedTest(unittest.TestCase):
class IpAddressTest(unittest.TestCase):
-
def test_valid_address(self):
addr = '127.0.0.1:8000'
@@ -256,7 +251,6 @@ class IpAddressTest(unittest.TestCase):
class URLTest(unittest.TestCase):
-
def test_valid_url(self):
option = config_options.URL()
@@ -288,7 +282,6 @@ class URLTest(unittest.TestCase):
class RepoURLTest(unittest.TestCase):
-
def test_repo_name_github(self):
option = config_options.RepoURL()
@@ -351,14 +344,12 @@ class RepoURLTest(unittest.TestCase):
def test_repo_name_custom_and_empty_edit_uri(self):
option = config_options.RepoURL()
- config = {'repo_url': "https://github.com/mkdocs/mkdocs",
- 'repo_name': 'mkdocs'}
+ config = {'repo_url': "https://github.com/mkdocs/mkdocs", 'repo_name': 'mkdocs'}
option.post_validation(config, 'repo_url')
self.assertEqual(config.get('edit_uri'), 'edit/master/docs/')
class DirTest(unittest.TestCase):
-
def test_valid_dir(self):
d = os.path.dirname(__file__)
@@ -403,7 +394,7 @@ class DirTest(unittest.TestCase):
)
test_config = {
- 'dir': 'юникод'
+ 'dir': 'юникод',
}
cfg.load_dict(test_config)
@@ -421,7 +412,7 @@ class DirTest(unittest.TestCase):
)
test_config = {
- 'dir': 'Übersicht'.encode(encoding=sys.getfilesystemencoding())
+ 'dir': 'Übersicht'.encode(encoding=sys.getfilesystemencoding()),
}
cfg.load_dict(test_config)
@@ -439,7 +430,7 @@ class DirTest(unittest.TestCase):
)
test_config = {
- 'dir': 'юникод'.encode(encoding='ISO 8859-5')
+ 'dir': 'юникод'.encode(encoding='ISO 8859-5'),
}
cfg.load_dict(test_config)
@@ -457,7 +448,7 @@ class DirTest(unittest.TestCase):
)
test_config = {
- 'dir': 'foo'
+ 'dir': 'foo',
}
cfg.load_dict(test_config)
@@ -476,7 +467,7 @@ class DirTest(unittest.TestCase):
)
test_config = {
- 'dir': '.'
+ 'dir': '.',
}
cfg.load_dict(test_config)
@@ -488,7 +479,6 @@ class DirTest(unittest.TestCase):
class ListOfPathsTest(unittest.TestCase):
-
def test_valid_path(self):
paths = [os.path.dirname(__file__)]
option = config_options.ListOfPaths()
@@ -523,7 +513,7 @@ class ListOfPathsTest(unittest.TestCase):
config_file_path=os.path.join(base_path, 'mkdocs.yml'),
)
test_config = {
- 'watch': ['foo']
+ 'watch': ['foo'],
}
cfg.load_dict(test_config)
fails, warns = cfg.validate()
@@ -534,9 +524,8 @@ class ListOfPathsTest(unittest.TestCase):
class SiteDirTest(unittest.TestCase):
-
def validate_config(self, config):
- """ Given a config with values for site_dir and doc_dir, run site_dir post_validation. """
+ """Given a config with values for site_dir and doc_dir, run site_dir post_validation."""
site_dir = config_options.SiteDir()
docs_dir = config_options.Dir()
@@ -571,7 +560,7 @@ class SiteDirTest(unittest.TestCase):
{'docs_dir': 'docs', 'site_dir': ''},
{'docs_dir': '', 'site_dir': ''},
{'docs_dir': j('..', parent_dir, 'docs'), 'site_dir': 'docs'},
- {'docs_dir': 'docs', 'site_dir': '/'}
+ {'docs_dir': 'docs', 'site_dir': '/'},
)
for test_config in test_configs:
@@ -594,7 +583,7 @@ class SiteDirTest(unittest.TestCase):
self.validate_config(test_config)
def test_common_prefix(self):
- """ Legitimate settings with common prefixes should not fail validation. """
+ """Legitimate settings with common prefixes should not fail validation."""
test_configs = (
{'docs_dir': 'docs', 'site_dir': 'docs-site'},
@@ -606,7 +595,6 @@ class SiteDirTest(unittest.TestCase):
class ThemeTest(unittest.TestCase):
-
def test_theme_as_string(self):
option = config_options.Theme()
@@ -627,7 +615,7 @@ class ThemeTest(unittest.TestCase):
def test_theme_as_simple_config(self):
config = {
- 'name': 'mkdocs'
+ 'name': 'mkdocs',
}
option = config_options.Theme()
value = option.validate(config)
@@ -639,7 +627,7 @@ class ThemeTest(unittest.TestCase):
'name': 'mkdocs',
'custom_dir': 'custom',
'static_templates': ['sitemap.html'],
- 'show_sidebar': False
+ 'show_sidebar': False,
}
option = config_options.Theme()
value = option.validate(config)
@@ -648,7 +636,7 @@ class ThemeTest(unittest.TestCase):
def test_theme_name_is_none(self):
config = {
- 'name': None
+ 'name': None,
}
option = config_options.Theme()
value = option.validate(config)
@@ -666,7 +654,7 @@ class ThemeTest(unittest.TestCase):
def test_uninstalled_theme_as_config(self):
config = {
- 'name': 'mkdocs2'
+ 'name': 'mkdocs2',
}
option = config_options.Theme()
with self.assertRaises(config_options.ValidationError):
@@ -683,8 +671,8 @@ class ThemeTest(unittest.TestCase):
config = {
'theme': {
- 'name': None
- }
+ 'name': None,
+ },
}
option = config_options.Theme()
with self.assertRaises(config_options.ValidationError):
@@ -697,7 +685,7 @@ class ThemeTest(unittest.TestCase):
'theme': {
'name': None,
'custom_dir': abs_base_path + '/inexisting_custom_dir',
- }
+ },
}
option = config_options.Theme()
with self.assertRaises(config_options.ValidationError):
@@ -708,8 +696,8 @@ class ThemeTest(unittest.TestCase):
config = {
'theme': {
'name': 'mkdocs',
- 'locale': None
- }
+ 'locale': None,
+ },
}
option = config_options.Theme()
with self.assertRaises(config_options.ValidationError):
@@ -720,8 +708,8 @@ class ThemeTest(unittest.TestCase):
config = {
'theme': {
'name': 'mkdocs',
- 'locale': 0
- }
+ 'locale': 0,
+ },
}
option = config_options.Theme()
with self.assertRaises(config_options.ValidationError):
@@ -732,8 +720,8 @@ class ThemeTest(unittest.TestCase):
config = {
'theme': {
'name': 'mkdocs',
- 'locale': 'fr'
- }
+ 'locale': 'fr',
+ },
}
option = config_options.Theme()
option.post_validation(config, 'theme')
@@ -741,19 +729,17 @@ class ThemeTest(unittest.TestCase):
class NavTest(unittest.TestCase):
-
def test_old_format(self):
option = config_options.Nav()
with self.assertRaises(config_options.ValidationError) as cm:
option.validate([['index.md']])
- self.assertEqual(str(cm.exception), "Expected nav item to be a string or dict, got a list: ['index.md']")
+ self.assertEqual(
+ str(cm.exception), "Expected nav item to be a string or dict, got a list: ['index.md']"
+ )
def test_provided_dict(self):
option = config_options.Nav()
- value = option.validate([
- 'index.md',
- {"Page": "page.md"}
- ])
+ value = option.validate(['index.md', {"Page": "page.md"}])
self.assertEqual(['index.md', {'Page': 'page.md'}], value)
option.post_validation({'extra_stuff': []}, 'extra_stuff')
@@ -768,13 +754,17 @@ class NavTest(unittest.TestCase):
self.assertEqual(option.warnings, [])
def test_normal_nav(self):
- nav = yaml_load(textwrap.dedent('''\
- - Home: index.md
- - getting-started.md
- - User Guide:
- - Overview: user-guide/index.md
- - Installation: user-guide/installation.md
- ''').encode())
+ nav = yaml_load(
+ textwrap.dedent(
+ '''\
+ - Home: index.md
+ - getting-started.md
+ - User Guide:
+ - Overview: user-guide/index.md
+ - Installation: user-guide/installation.md
+ '''
+ ).encode()
+ )
option = config_options.Nav()
self.assertEqual(option.validate(nav), nav)
@@ -796,7 +786,9 @@ class NavTest(unittest.TestCase):
option = config_options.Nav()
with self.assertRaises(config_options.ValidationError) as cm:
option.validate([1])
- self.assertEqual(str(cm.exception), "Expected nav item to be a string or dict, got a int: 1")
+ self.assertEqual(
+ str(cm.exception), "Expected nav item to be a string or dict, got a int: 1"
+ )
def test_invalid_item_none(self):
option = config_options.Nav()
@@ -821,14 +813,18 @@ class NavTest(unittest.TestCase):
nav = ['foo', {}]
with self.assertRaises(config_options.ValidationError) as cm:
option.validate(nav)
- self.assertEqual(str(cm.exception), "Expected nav item to be a dict of size 1, got a dict: {}")
+ self.assertEqual(
+ str(cm.exception), "Expected nav item to be a dict of size 1, got a dict: {}"
+ )
def test_invalid_nested_list(self):
option = config_options.Nav()
nav = [{'aaa': [[{"bbb": "user-guide/index.md"}]]}]
with self.assertRaises(config_options.ValidationError) as cm:
option.validate(nav)
- msg = "Expected nav item to be a string or dict, got a list: [{'bbb': 'user-guide/index.md'}]"
+ msg = (
+ "Expected nav item to be a string or dict, got a list: [{'bbb': 'user-guide/index.md'}]"
+ )
self.assertEqual(str(cm.exception), msg)
def test_invalid_children_oversized_dict(self):
@@ -842,11 +838,12 @@ class NavTest(unittest.TestCase):
def test_warns_for_dict(self):
option = config_options.Nav()
option.validate([{"a": {"b": "c.md", "d": "e.md"}}])
- self.assertEqual(option.warnings, ["Expected nav to be a list, got dict with keys ('b', 'd')"])
+ self.assertEqual(
+ option.warnings, ["Expected nav to be a list, got dict with keys ('b', 'd')"]
+ )
class PrivateTest(unittest.TestCase):
-
def test_defined(self):
option = config_options.Private()
@@ -855,19 +852,21 @@ class PrivateTest(unittest.TestCase):
class MarkdownExtensionsTest(unittest.TestCase):
-
@patch('markdown.Markdown')
def test_simple_list(self, mockMd):
option = config_options.MarkdownExtensions()
config = {
- 'markdown_extensions': ['foo', 'bar']
+ 'markdown_extensions': ['foo', 'bar'],
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['foo', 'bar'],
- 'mdx_configs': {}
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['foo', 'bar'],
+ 'mdx_configs': {},
+ },
+ config,
+ )
@patch('markdown.Markdown')
def test_list_dicts(self, mockMd):
@@ -876,18 +875,21 @@ class MarkdownExtensionsTest(unittest.TestCase):
'markdown_extensions': [
{'foo': {'foo_option': 'foo value'}},
{'bar': {'bar_option': 'bar value'}},
- {'baz': None}
+ {'baz': None},
]
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['foo', 'bar', 'baz'],
- 'mdx_configs': {
- 'foo': {'foo_option': 'foo value'},
- 'bar': {'bar_option': 'bar value'}
- }
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['foo', 'bar', 'baz'],
+ 'mdx_configs': {
+ 'foo': {'foo_option': 'foo value'},
+ 'bar': {'bar_option': 'bar value'},
+ },
+ },
+ config,
+ )
@patch('markdown.Markdown')
def test_mixed_list(self, mockMd):
@@ -895,17 +897,20 @@ class MarkdownExtensionsTest(unittest.TestCase):
config = {
'markdown_extensions': [
'foo',
- {'bar': {'bar_option': 'bar value'}}
+ {'bar': {'bar_option': 'bar value'}},
]
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['foo', 'bar'],
- 'mdx_configs': {
- 'bar': {'bar_option': 'bar value'}
- }
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['foo', 'bar'],
+ 'mdx_configs': {
+ 'bar': {'bar_option': 'bar value'},
+ },
+ },
+ config,
+ )
@patch('markdown.Markdown')
def test_dict_of_dicts(self, mockMd):
@@ -914,86 +919,104 @@ class MarkdownExtensionsTest(unittest.TestCase):
'markdown_extensions': {
'foo': {'foo_option': 'foo value'},
'bar': {'bar_option': 'bar value'},
- 'baz': {}
+ 'baz': {},
}
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['foo', 'bar', 'baz'],
- 'mdx_configs': {
- 'foo': {'foo_option': 'foo value'},
- 'bar': {'bar_option': 'bar value'}
- }
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['foo', 'bar', 'baz'],
+ 'mdx_configs': {
+ 'foo': {'foo_option': 'foo value'},
+ 'bar': {'bar_option': 'bar value'},
+ },
+ },
+ config,
+ )
@patch('markdown.Markdown')
def test_builtins(self, mockMd):
option = config_options.MarkdownExtensions(builtins=['meta', 'toc'])
config = {
- 'markdown_extensions': ['foo', 'bar']
+ 'markdown_extensions': ['foo', 'bar'],
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['meta', 'toc', 'foo', 'bar'],
- 'mdx_configs': {}
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['meta', 'toc', 'foo', 'bar'],
+ 'mdx_configs': {},
+ },
+ config,
+ )
def test_duplicates(self):
option = config_options.MarkdownExtensions(builtins=['meta', 'toc'])
config = {
- 'markdown_extensions': ['meta', 'toc']
+ 'markdown_extensions': ['meta', 'toc'],
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['meta', 'toc'],
- 'mdx_configs': {}
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['meta', 'toc'],
+ 'mdx_configs': {},
+ },
+ config,
+ )
def test_builtins_config(self):
option = config_options.MarkdownExtensions(builtins=['meta', 'toc'])
config = {
'markdown_extensions': [
- {'toc': {'permalink': True}}
- ]
+ {'toc': {'permalink': True}},
+ ],
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['meta', 'toc'],
- 'mdx_configs': {'toc': {'permalink': True}}
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['meta', 'toc'],
+ 'mdx_configs': {'toc': {'permalink': True}},
+ },
+ config,
+ )
@patch('markdown.Markdown')
def test_configkey(self, mockMd):
option = config_options.MarkdownExtensions(configkey='bar')
config = {
'markdown_extensions': [
- {'foo': {'foo_option': 'foo value'}}
+ {'foo': {'foo_option': 'foo value'}},
]
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': ['foo'],
- 'bar': {
- 'foo': {'foo_option': 'foo value'}
- }
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': ['foo'],
+ 'bar': {
+ 'foo': {'foo_option': 'foo value'},
+ },
+ },
+ config,
+ )
def test_none(self):
option = config_options.MarkdownExtensions(default=[])
config = {
- 'markdown_extensions': None
+ 'markdown_extensions': None,
}
config['markdown_extensions'] = option.validate(config['markdown_extensions'])
option.post_validation(config, 'markdown_extensions')
- self.assertEqual({
- 'markdown_extensions': [],
- 'mdx_configs': {}
- }, config)
+ self.assertEqual(
+ {
+ 'markdown_extensions': [],
+ 'mdx_configs': {},
+ },
+ config,
+ )
@patch('markdown.Markdown')
def test_not_list(self, mockMd):
@@ -1006,8 +1029,8 @@ class MarkdownExtensionsTest(unittest.TestCase):
option = config_options.MarkdownExtensions()
config = {
'markdown_extensions': [
- {'foo': 'not a dict'}
- ]
+ {'foo': 'not a dict'},
+ ],
}
with self.assertRaises(config_options.ValidationError):
option.validate(config['markdown_extensions'])
@@ -1017,8 +1040,8 @@ class MarkdownExtensionsTest(unittest.TestCase):
option = config_options.MarkdownExtensions()
config = {
'markdown_extensions': [
- ['not a dict']
- ]
+ ['not a dict'],
+ ],
}
with self.assertRaises(config_options.ValidationError):
option.validate(config['markdown_extensions'])
@@ -1028,8 +1051,8 @@ class MarkdownExtensionsTest(unittest.TestCase):
option = config_options.MarkdownExtensions()
config = {
'markdown_extensions': [
- {'key1': 'value', 'key2': 'too many keys'}
- ]
+ {'key1': 'value', 'key2': 'too many keys'},
+ ],
}
with self.assertRaises(config_options.ValidationError):
option.validate(config['markdown_extensions'])
@@ -1037,7 +1060,7 @@ class MarkdownExtensionsTest(unittest.TestCase):
def test_unknown_extension(self):
option = config_options.MarkdownExtensions()
config = {
- 'markdown_extensions': ['unknown']
+ 'markdown_extensions': ['unknown'],
}
with self.assertRaises(config_options.ValidationError):
option.validate(config['markdown_extensions'])
diff --git a/mkdocs/tests/config/config_tests.py b/mkdocs/tests/config/config_tests.py
index 295a9bd4..fe24fd3a 100644
--- a/mkdocs/tests/config/config_tests.py
+++ b/mkdocs/tests/config/config_tests.py
@@ -38,11 +38,13 @@ class ConfigTests(unittest.TestCase):
config.load_config(config_file='/path/that/is/not/real')
def test_invalid_config(self):
- file_contents = dedent("""
- - ['index.md', 'Introduction']
- - ['index.md', 'Introduction']
- - ['index.md', 'Introduction']
- """)
+ file_contents = dedent(
+ """
+ - ['index.md', 'Introduction']
+ - ['index.md', 'Introduction']
+ - ['index.md', 'Introduction']
+ """
+ )
config_file = tempfile.NamedTemporaryFile('w', delete=False)
try:
config_file.write(file_contents)
@@ -61,15 +63,15 @@ class ConfigTests(unittest.TestCase):
"""
expected_result = {
'site_name': 'Example',
- 'nav': [
- {'Introduction': 'index.md'}
- ],
+ 'nav': [{'Introduction': 'index.md'}],
}
- file_contents = dedent("""
- site_name: Example
- nav:
- - 'Introduction': 'index.md'
- """)
+ file_contents = dedent(
+ """
+ site_name: Example
+ nav:
+ - 'Introduction': 'index.md'
+ """
+ )
with TemporaryDirectory() as temp_path:
os.mkdir(os.path.join(temp_path, 'docs'))
config_path = os.path.join(temp_path, 'mkdocs.yml')
@@ -90,16 +92,18 @@ class ConfigTests(unittest.TestCase):
{"theme": "readthedocs"}, # builtin theme
{"theme": {'name': 'readthedocs'}}, # builtin as complex
{"theme": {'name': None, 'custom_dir': mytheme}}, # custom only as complex
- {"theme": {'name': 'readthedocs', 'custom_dir': custom}}, # builtin and custom as complex
+ {
+ "theme": {'name': 'readthedocs', 'custom_dir': custom}
+ }, # builtin and custom as complex
{ # user defined variables
'theme': {
'name': 'mkdocs',
'locale': 'fr',
'static_templates': ['foo.html'],
'show_sidebar': False,
- 'some_var': 'bar'
+ 'some_var': 'bar',
}
- }
+ },
]
mkdocs_dir = os.path.abspath(os.path.dirname(mkdocs.__file__))
@@ -120,9 +124,10 @@ class ConfigTests(unittest.TestCase):
'hljs_languages': [],
'navigation_depth': 2,
'nav_style': 'primary',
- 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83}
- }
- }, {
+ 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83},
+ },
+ },
+ {
'dirs': [os.path.join(theme_dir, 'readthedocs'), mkdocs_templates_dir],
'static_templates': ['404.html', 'sitemap.xml'],
'vars': {
@@ -138,9 +143,10 @@ class ConfigTests(unittest.TestCase):
'sticky_navigation': True,
'logo': None,
'titles_only': False,
- 'collapse_navigation': True
- }
- }, {
+ 'collapse_navigation': True,
+ },
+ },
+ {
'dirs': [os.path.join(theme_dir, 'readthedocs'), mkdocs_templates_dir],
'static_templates': ['404.html', 'sitemap.xml'],
'vars': {
@@ -156,13 +162,15 @@ class ConfigTests(unittest.TestCase):
'sticky_navigation': True,
'logo': None,
'titles_only': False,
- 'collapse_navigation': True
- }
- }, {
+ 'collapse_navigation': True,
+ },
+ },
+ {
'dirs': [mytheme, mkdocs_templates_dir],
'static_templates': ['sitemap.xml'],
- 'vars': {'locale': parse_locale('en')}
- }, {
+ 'vars': {'locale': parse_locale('en')},
+ },
+ {
'dirs': [custom, os.path.join(theme_dir, 'readthedocs'), mkdocs_templates_dir],
'static_templates': ['404.html', 'sitemap.xml'],
'vars': {
@@ -178,9 +186,10 @@ class ConfigTests(unittest.TestCase):
'sticky_navigation': True,
'logo': None,
'titles_only': False,
- 'collapse_navigation': True
- }
- }, {
+ 'collapse_navigation': True,
+ },
+ },
+ {
'dirs': [os.path.join(theme_dir, 'mkdocs'), mkdocs_templates_dir],
'static_templates': ['404.html', 'sitemap.xml', 'foo.html'],
'vars': {
@@ -195,9 +204,9 @@ class ConfigTests(unittest.TestCase):
'hljs_languages': [],
'navigation_depth': 2,
'nav_style': 'primary',
- 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83}
- }
- }
+ 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83},
+ },
+ },
)
for config_contents, result in zip(configs, results):
@@ -212,25 +221,29 @@ class ConfigTests(unittest.TestCase):
def test_empty_nav(self):
conf = config.Config(schema=defaults.get_schema())
- conf.load_dict({
- 'site_name': 'Example',
- 'config_file_path': os.path.join(os.path.abspath('.'), 'mkdocs.yml')
- })
+ conf.load_dict(
+ {
+ 'site_name': 'Example',
+ 'config_file_path': os.path.join(os.path.abspath('.'), 'mkdocs.yml'),
+ }
+ )
conf.validate()
self.assertEqual(conf['nav'], None)
def test_error_on_pages(self):
conf = config.Config(schema=defaults.get_schema())
- conf.load_dict({
- 'site_name': 'Example',
- 'pages': ['index.md', 'about.md'],
- })
+ conf.load_dict(
+ {
+ 'site_name': 'Example',
+ 'pages': ['index.md', 'about.md'],
+ }
+ )
errors, warnings = conf.validate()
self.assertEqual(warnings, [])
self.assertEqual(len(errors), 1)
self.assertEqual(
str(errors[0][1]),
- "The configuration option 'pages' was removed from MkDocs. Use 'nav' instead."
+ "The configuration option 'pages' was removed from MkDocs. Use 'nav' instead.",
)
def test_doc_dir_in_site_dir(self):
@@ -247,7 +260,7 @@ class ConfigTests(unittest.TestCase):
)
conf = {
- 'config_file_path': j(os.path.abspath('..'), 'mkdocs.yml')
+ 'config_file_path': j(os.path.abspath('..'), 'mkdocs.yml'),
}
for test_config in test_configs:
@@ -256,11 +269,13 @@ class ConfigTests(unittest.TestCase):
patch.update(test_config)
# Same as the default schema, but don't verify the docs_dir exists.
- c = config.Config(schema=(
- ('docs_dir', config_options.Dir(default='docs')),
- ('site_dir', config_options.SiteDir(default='site')),
- ('config_file_path', config_options.Type(str))
- ))
+ c = config.Config(
+ schema=(
+ ('docs_dir', config_options.Dir(default='docs')),
+ ('site_dir', config_options.SiteDir(default='site')),
+ ('config_file_path', config_options.Type(str)),
+ )
+ )
c.load_dict(patch)
errors, warnings = c.validate()
diff --git a/mkdocs/tests/gh_deploy_tests.py b/mkdocs/tests/gh_deploy_tests.py
index 4670e21a..45acd044 100644
--- a/mkdocs/tests/gh_deploy_tests.py
+++ b/mkdocs/tests/gh_deploy_tests.py
@@ -9,7 +9,6 @@ from mkdocs import __version__
class TestGitHubDeploy(unittest.TestCase):
-
@mock.patch('subprocess.Popen')
def test_is_cwd_git_repo(self, mock_popeno):
@@ -36,7 +35,7 @@ class TestGitHubDeploy(unittest.TestCase):
mock_popeno().communicate.return_value = (
b'git@github.com:mkdocs/mkdocs.git\n',
- b''
+ b'',
)
expected = ('git@', 'mkdocs/mkdocs.git')
@@ -47,7 +46,7 @@ class TestGitHubDeploy(unittest.TestCase):
mock_popeno().communicate.return_value = (
b'https://github.com/mkdocs/mkdocs.git\n',
- b''
+ b'',
)
expected = ('https://', 'mkdocs/mkdocs.git')
@@ -58,7 +57,7 @@ class TestGitHubDeploy(unittest.TestCase):
mock_popeno().communicate.return_value = (
b'https://notgh.com/mkdocs/mkdocs.git\n',
- b''
+ b'',
)
expected = (None, None)
@@ -82,8 +81,9 @@ class TestGitHubDeploy(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy._check_version')
@mock.patch('ghp_import.ghp_import')
@mock.patch('os.path.isfile', return_value=False)
- def test_deploy_no_cname(self, mock_isfile, mock_import, check_version, get_remote,
- get_sha, is_repo):
+ def test_deploy_no_cname(
+ self, mock_isfile, mock_import, check_version, get_remote, get_sha, is_repo
+ ):
config = load_config(
remote_branch='test',
@@ -92,8 +92,9 @@ class TestGitHubDeploy(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy._is_cwd_git_repo', return_value=True)
@mock.patch('mkdocs.commands.gh_deploy._get_current_sha', return_value='shashas')
- @mock.patch('mkdocs.commands.gh_deploy._get_remote_url', return_value=(
- 'git@', 'mkdocs/mkdocs.git'))
+ @mock.patch(
+ 'mkdocs.commands.gh_deploy._get_remote_url', return_value=('git@', 'mkdocs/mkdocs.git')
+ )
@mock.patch('mkdocs.commands.gh_deploy._check_version')
@mock.patch('ghp_import.ghp_import')
def test_deploy_hostname(self, mock_import, check_version, get_remote, get_sha, is_repo):
@@ -108,7 +109,9 @@ class TestGitHubDeploy(unittest.TestCase):
@mock.patch('mkdocs.commands.gh_deploy._get_remote_url', return_value=(None, None))
@mock.patch('mkdocs.commands.gh_deploy._check_version')
@mock.patch('ghp_import.ghp_import')
- def test_deploy_ignore_version_default(self, mock_import, check_version, get_remote, get_sha, is_repo):
+ def test_deploy_ignore_version_default(
+ self, mock_import, check_version, get_remote, get_sha, is_repo
+ ):
config = load_config(
remote_branch='test',
@@ -150,31 +153,42 @@ class TestGitHubDeploy(unittest.TestCase):
class TestGitHubDeployLogs(unittest.TestCase):
-
@mock.patch('subprocess.Popen')
def test_mkdocs_newer(self, mock_popeno):
- mock_popeno().communicate.return_value = (b'Deployed 12345678 with MkDocs version: 0.1.2\n', b'')
+ mock_popeno().communicate.return_value = (
+ b'Deployed 12345678 with MkDocs version: 0.1.2\n',
+ b'',
+ )
with self.assertLogs('mkdocs', level='INFO') as cm:
gh_deploy._check_version('gh-pages')
self.assertEqual(
- cm.output, ['INFO:mkdocs.commands.gh_deploy:Previous deployment was done with MkDocs '
- f'version 0.1.2; you are deploying with a newer version ({__version__})']
+ cm.output,
+ [
+ 'INFO:mkdocs.commands.gh_deploy:Previous deployment was done with MkDocs '
+ f'version 0.1.2; you are deploying with a newer version ({__version__})'
+ ],
)
@mock.patch('subprocess.Popen')
def test_mkdocs_older(self, mock_popeno):
- mock_popeno().communicate.return_value = (b'Deployed 12345678 with MkDocs version: 10.1.2\n', b'')
+ mock_popeno().communicate.return_value = (
+ b'Deployed 12345678 with MkDocs version: 10.1.2\n',
+ b'',
+ )
with self.assertLogs('mkdocs', level='ERROR') as cm:
with self.assertRaises(Abort):
gh_deploy._check_version('gh-pages')
self.assertEqual(
- cm.output, ['ERROR:mkdocs.commands.gh_deploy:Deployment terminated: Previous deployment was made with '
- f'MkDocs version 10.1.2; you are attempting to deploy with an older version ({__version__}).'
- ' Use --ignore-version to deploy anyway.']
+ cm.output,
+ [
+ 'ERROR:mkdocs.commands.gh_deploy:Deployment terminated: Previous deployment was made with '
+ f'MkDocs version 10.1.2; you are attempting to deploy with an older version ({__version__}).'
+ ' Use --ignore-version to deploy anyway.'
+ ],
)
@mock.patch('subprocess.Popen')
@@ -186,5 +200,7 @@ class TestGitHubDeployLogs(unittest.TestCase):
gh_deploy._check_version('gh-pages')
self.assertEqual(
cm.output,
- ['WARNING:mkdocs.commands.gh_deploy:Version check skipped: No version specified in previous deployment.']
+ [
+ 'WARNING:mkdocs.commands.gh_deploy:Version check skipped: No version specified in previous deployment.'
+ ],
)
diff --git a/mkdocs/tests/integration.py b/mkdocs/tests/integration.py
index ebbe8897..4b594f1c 100644
--- a/mkdocs/tests/integration.py
+++ b/mkdocs/tests/integration.py
@@ -31,21 +31,22 @@ TEST_PROJECTS = os.path.abspath(os.path.join(DIR, 'integration'))
@click.command()
-@click.option('--output',
- help="The output directory to use when building themes",
- type=click.Path(file_okay=False, writable=True),
- required=True)
+@click.option(
+ '--output',
+ help="The output directory to use when building themes",
+ type=click.Path(file_okay=False, writable=True),
+ required=True,
+)
def main(output=None):
log.propagate = False
stream = logging.StreamHandler()
- formatter = logging.Formatter(
- "\033[1m\033[1;32m *** %(message)s *** \033[0m")
+ formatter = logging.Formatter("\033[1m\033[1;32m *** %(message)s *** \033[0m")
stream.setFormatter(formatter)
log.addHandler(stream)
log.setLevel(logging.DEBUG)
- base_cmd = ['mkdocs', 'build', '-s', '-v', '--site-dir', ]
+ base_cmd = ['mkdocs', 'build', '-s', '-v', '--site-dir']
log.debug("Building installed themes.")
for theme in sorted(MKDOCS_THEMES):
@@ -60,7 +61,7 @@ def main(output=None):
log.debug(f"Building test project: {project}")
project_dir = os.path.join(TEST_PROJECTS, project)
out = os.path.join(output, project)
- command = base_cmd + [out, ]
+ command = base_cmd + [out]
subprocess.check_call(command, cwd=project_dir)
log.debug(f"Theme and integration builds are in {output}")
diff --git a/mkdocs/tests/livereload_tests.py b/mkdocs/tests/livereload_tests.py
index ecbbaecc..6d838c14 100644
--- a/mkdocs/tests/livereload_tests.py
+++ b/mkdocs/tests/livereload_tests.py
@@ -64,9 +64,7 @@ def do_request(server, content):
return headers, content.decode()
-SCRIPT_REGEX = (
- r''
-)
+SCRIPT_REGEX = r''
class BuildTests(unittest.TestCase):
diff --git a/mkdocs/tests/localization_tests.py b/mkdocs/tests/localization_tests.py
index a7ceff96..d7312c6c 100644
--- a/mkdocs/tests/localization_tests.py
+++ b/mkdocs/tests/localization_tests.py
@@ -9,7 +9,6 @@ from mkdocs.config.base import ValidationError
class LocalizationTests(unittest.TestCase):
-
def setUp(self):
self.env = unittest.mock.Mock()
@@ -42,7 +41,9 @@ class LocalizationTests(unittest.TestCase):
def test_translations_found(self, tdir):
translations = unittest.mock.Mock()
- with unittest.mock.patch('mkdocs.localization.Translations.load', return_value=translations):
+ with unittest.mock.patch(
+ 'mkdocs.localization.Translations.load', return_value=translations
+ ):
install_translations(self.env, parse_locale('en'), [tdir])
self.env.install_gettext_translations.assert_called_once_with(translations)
diff --git a/mkdocs/tests/new_tests.py b/mkdocs/tests/new_tests.py
index 735fdf5d..3406c296 100644
--- a/mkdocs/tests/new_tests.py
+++ b/mkdocs/tests/new_tests.py
@@ -8,7 +8,6 @@ from mkdocs.commands import new
class NewTests(unittest.TestCase):
-
def test_new(self):
tempdir = tempfile.mkdtemp()
diff --git a/mkdocs/tests/plugin_tests.py b/mkdocs/tests/plugin_tests.py
index fa0e3d08..e204c91f 100644
--- a/mkdocs/tests/plugin_tests.py
+++ b/mkdocs/tests/plugin_tests.py
@@ -21,24 +21,23 @@ class DummyPlugin(plugins.BasePlugin):
)
def on_pre_page(self, content, **kwargs):
- """ modify page content by prepending `foo` config value. """
+ """modify page content by prepending `foo` config value."""
return f'{self.config["foo"]} {content}'
def on_nav(self, item, **kwargs):
- """ do nothing (return None) to not modify item. """
+ """do nothing (return None) to not modify item."""
return None
def on_page_read_source(self, **kwargs):
- """ create new source by prepending `foo` config value to 'source'. """
+ """create new source by prepending `foo` config value to 'source'."""
return f'{self.config["foo"]} source'
def on_pre_build(self, **kwargs):
- """ do nothing (return None). """
+ """do nothing (return None)."""
return None
class TestPluginClass(unittest.TestCase):
-
def test_valid_plugin_options(self):
test_dir = 'test'
@@ -85,7 +84,6 @@ class TestPluginClass(unittest.TestCase):
class TestPluginCollection(unittest.TestCase):
-
def test_set_plugin_on_collection(self):
collection = plugins.PluginCollection()
plugin = DummyPlugin()
@@ -98,7 +96,9 @@ class TestPluginCollection(unittest.TestCase):
collection['foo'] = plugin1
plugin2 = DummyPlugin()
collection['bar'] = plugin2
- self.assertEqual([(k, v) for k, v in collection.items()], [('foo', plugin1), ('bar', plugin2)])
+ self.assertEqual(
+ [(k, v) for k, v in collection.items()], [('foo', plugin1), ('bar', plugin2)]
+ )
def test_run_event_on_collection(self):
collection = plugins.PluginCollection()
@@ -115,8 +115,9 @@ class TestPluginCollection(unittest.TestCase):
plugin2 = DummyPlugin()
plugin2.load_config({'foo': 'second'})
collection['bar'] = plugin2
- self.assertEqual(collection.run_event('pre_page', 'page content'),
- 'second new page content')
+ self.assertEqual(
+ collection.run_event('pre_page', 'page content'), 'second new page content'
+ )
def test_event_returns_None(self):
collection = plugins.PluginCollection()
@@ -214,7 +215,6 @@ MockEntryPoint.configure_mock(**{'name': 'sample', 'load.return_value': DummyPlu
@mock.patch('importlib_metadata.entry_points', return_value=[MockEntryPoint])
class TestPluginConfig(unittest.TestCase):
-
def test_plugin_config_without_options(self, mock_class):
cfg = {'plugins': ['sample']}
@@ -234,12 +234,14 @@ class TestPluginConfig(unittest.TestCase):
def test_plugin_config_with_options(self, mock_class):
cfg = {
- 'plugins': [{
- 'sample': {
- 'foo': 'foo value',
- 'bar': 42
+ 'plugins': [
+ {
+ 'sample': {
+ 'foo': 'foo value',
+ 'bar': 42,
+ },
}
- }]
+ ],
}
option = config.config_options.Plugins()
cfg['plugins'] = option.validate(cfg['plugins'])
@@ -260,9 +262,9 @@ class TestPluginConfig(unittest.TestCase):
'plugins': {
'sample': {
'foo': 'foo value',
- 'bar': 42
- }
- }
+ 'bar': 42,
+ },
+ },
}
option = config.config_options.Plugins()
cfg['plugins'] = option.validate(cfg['plugins'])
@@ -335,13 +337,15 @@ class TestPluginConfig(unittest.TestCase):
def test_plugin_config_multivalue_dict(self, mock_class):
cfg = {
- 'plugins': [{
- 'sample': {
- 'foo': 'foo value',
- 'bar': 42
- },
- 'extra_key': 'baz'
- }]
+ 'plugins': [
+ {
+ 'sample': {
+ 'foo': 'foo value',
+ 'bar': 42,
+ },
+ 'extra_key': 'baz',
+ }
+ ],
}
option = config.config_options.Plugins()
with self.assertRaises(config.base.ValidationError):
@@ -350,7 +354,7 @@ class TestPluginConfig(unittest.TestCase):
def test_plugin_config_not_string_or_dict(self, mock_class):
cfg = {
- 'plugins': [('not a string or dict',)]
+ 'plugins': [('not a string or dict',)],
}
option = config.config_options.Plugins()
with self.assertRaises(config.base.ValidationError):
@@ -359,9 +363,11 @@ class TestPluginConfig(unittest.TestCase):
def test_plugin_config_options_not_dict(self, mock_class):
cfg = {
- 'plugins': [{
- 'sample': 'not a dict'
- }]
+ 'plugins': [
+ {
+ 'sample': 'not a dict',
+ }
+ ],
}
option = config.config_options.Plugins()
with self.assertRaises(config.base.ValidationError):
diff --git a/mkdocs/tests/search_tests.py b/mkdocs/tests/search_tests.py
index a7a33917..654a4cae 100644
--- a/mkdocs/tests/search_tests.py
+++ b/mkdocs/tests/search_tests.py
@@ -18,7 +18,6 @@ def strip_whitespace(string):
class SearchConfigTests(unittest.TestCase):
-
def test_lang_default(self):
option = search.LangOption(default=['en'])
value = option.validate(None)
@@ -76,14 +75,13 @@ class SearchConfigTests(unittest.TestCase):
class SearchPluginTests(unittest.TestCase):
-
def test_plugin_config_defaults(self):
expected = {
'lang': None,
'separator': r'[\s\-]+',
'min_search_length': 3,
'prebuild_index': False,
- 'indexing': 'full'
+ 'indexing': 'full',
}
plugin = search.SearchPlugin()
errors, warnings = plugin.load_config({})
@@ -97,7 +95,7 @@ class SearchPluginTests(unittest.TestCase):
'separator': r'[\s\-]+',
'min_search_length': 3,
'prebuild_index': False,
- 'indexing': 'full'
+ 'indexing': 'full',
}
plugin = search.SearchPlugin()
errors, warnings = plugin.load_config({'lang': 'es'})
@@ -111,7 +109,7 @@ class SearchPluginTests(unittest.TestCase):
'separator': r'[\s\-\.]+',
'min_search_length': 3,
'prebuild_index': False,
- 'indexing': 'full'
+ 'indexing': 'full',
}
plugin = search.SearchPlugin()
errors, warnings = plugin.load_config({'separator': r'[\s\-\.]+'})
@@ -125,7 +123,7 @@ class SearchPluginTests(unittest.TestCase):
'separator': r'[\s\-]+',
'min_search_length': 2,
'prebuild_index': False,
- 'indexing': 'full'
+ 'indexing': 'full',
}
plugin = search.SearchPlugin()
errors, warnings = plugin.load_config({'min_search_length': 2})
@@ -139,7 +137,7 @@ class SearchPluginTests(unittest.TestCase):
'separator': r'[\s\-]+',
'min_search_length': 3,
'prebuild_index': True,
- 'indexing': 'full'
+ 'indexing': 'full',
}
plugin = search.SearchPlugin()
errors, warnings = plugin.load_config({'prebuild_index': True})
@@ -153,7 +151,7 @@ class SearchPluginTests(unittest.TestCase):
'separator': r'[\s\-]+',
'min_search_length': 3,
'prebuild_index': False,
- 'indexing': 'titles'
+ 'indexing': 'titles',
}
plugin = search.SearchPlugin()
errors, warnings = plugin.load_config({'indexing': 'titles'})
@@ -186,7 +184,9 @@ class SearchPluginTests(unittest.TestCase):
def test_event_on_config_theme_locale(self):
plugin = search.SearchPlugin()
plugin.load_config({})
- result = plugin.on_config(load_config(theme={'name': 'mkdocs', 'locale': 'fr'}, extra_javascript=[]))
+ result = plugin.on_config(
+ load_config(theme={'name': 'mkdocs', 'locale': 'fr'}, extra_javascript=[])
+ )
self.assertFalse(result['theme']['search_index_only'])
self.assertFalse(result['theme']['include_search_page'])
self.assertEqual(result['theme'].static_templates, {'404.html', 'sitemap.xml'})
@@ -197,18 +197,24 @@ class SearchPluginTests(unittest.TestCase):
def test_event_on_config_include_search_page(self):
plugin = search.SearchPlugin()
plugin.load_config({})
- config = load_config(theme={'name': 'mkdocs', 'include_search_page': True}, extra_javascript=[])
+ config = load_config(
+ theme={'name': 'mkdocs', 'include_search_page': True}, extra_javascript=[]
+ )
result = plugin.on_config(config)
self.assertFalse(result['theme']['search_index_only'])
self.assertTrue(result['theme']['include_search_page'])
- self.assertEqual(result['theme'].static_templates, {'404.html', 'sitemap.xml', 'search.html'})
+ self.assertEqual(
+ result['theme'].static_templates, {'404.html', 'sitemap.xml', 'search.html'}
+ )
self.assertEqual(len(result['theme'].dirs), 3)
self.assertEqual(result['extra_javascript'], ['search/main.js'])
def test_event_on_config_search_index_only(self):
plugin = search.SearchPlugin()
plugin.load_config({})
- config = load_config(theme={'name': 'mkdocs', 'search_index_only': True}, extra_javascript=[])
+ config = load_config(
+ theme={'name': 'mkdocs', 'search_index_only': True}, extra_javascript=[]
+ )
result = plugin.on_config(config)
self.assertTrue(result['theme']['search_index_only'])
self.assertFalse(result['theme']['include_search_page'])
@@ -263,7 +269,6 @@ class SearchPluginTests(unittest.TestCase):
class SearchIndexTests(unittest.TestCase):
-
def test_html_stripping(self):
stripper = search_index.ContentParser()
@@ -279,11 +284,9 @@ class SearchIndexTests(unittest.TestCase):
parser.feed('Title
TEST')
parser.close()
- self.assertEqual(parser.data, [search_index.ContentSection(
- text=["TEST"],
- id_="title",
- title="Title"
- )])
+ self.assertEqual(
+ parser.data, [search_index.ContentSection(text=["TEST"], id_="title", title="Title")]
+ )
def test_content_parser_no_id(self):
@@ -292,11 +295,9 @@ class SearchIndexTests(unittest.TestCase):
parser.feed("Title
TEST")
parser.close()
- self.assertEqual(parser.data, [search_index.ContentSection(
- text=["TEST"],
- id_=None,
- title="Title"
- )])
+ self.assertEqual(
+ parser.data, [search_index.ContentSection(text=["TEST"], id_=None, title="Title")]
+ )
def test_content_parser_content_before_header(self):
@@ -305,11 +306,9 @@ class SearchIndexTests(unittest.TestCase):
parser.feed("Content Before H1 Title
TEST")
parser.close()
- self.assertEqual(parser.data, [search_index.ContentSection(
- text=["TEST"],
- id_=None,
- title="Title"
- )])
+ self.assertEqual(
+ parser.data, [search_index.ContentSection(text=["TEST"], id_=None, title="Title")]
+ )
def test_content_parser_no_sections(self):
@@ -326,11 +325,13 @@ class SearchIndexTests(unittest.TestCase):
index = search_index.SearchIndex()
- md = dedent("""
- # Heading 1
- ## Heading 2
- ### Heading 3
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 2
+ ### Heading 3
+ """
+ )
toc = get_toc(get_markdown_toc(md))
toc_item = index._find_toc_by_id(toc, "heading-1")
@@ -364,23 +365,29 @@ class SearchIndexTests(unittest.TestCase):
'index.md',
base_cfg['docs_dir'],
base_cfg['site_dir'],
- base_cfg['use_directory_urls']),
- base_cfg),
+ base_cfg['use_directory_urls'],
+ ),
+ base_cfg,
+ ),
Page(
'About',
File(
'about.md',
base_cfg['docs_dir'],
base_cfg['site_dir'],
- base_cfg['use_directory_urls']),
- base_cfg)
+ base_cfg['use_directory_urls'],
+ ),
+ base_cfg,
+ ),
]
- md = dedent("""
- # Heading 1
- ## Heading 2
- ### Heading 3
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 2
+ ### Heading 3
+ """
+ )
toc = get_toc(get_markdown_toc(md))
full_content = ''.join(f"Heading{i}Content{i}" for i in range(1, 4))
@@ -420,12 +427,12 @@ class SearchIndexTests(unittest.TestCase):
def test_search_indexing_options(self):
def test_page(title, filename, config):
test_page = Page(
- title, File(
- filename,
- config['docs_dir'],
- config['site_dir'],
- config['use_directory_urls']),
- config)
+ title,
+ File(
+ filename, config['docs_dir'], config['site_dir'], config['use_directory_urls']
+ ),
+ config,
+ )
test_page.content = """
Heading 1
Content 1
@@ -433,29 +440,40 @@ class SearchIndexTests(unittest.TestCase):
Content 2
Heading 3
Content 3
"""
- test_page.markdown = dedent("""
+ test_page.markdown = dedent(
+ """
# Heading 1
## Heading 2
- ### Heading 3""")
+ ### Heading 3"""
+ )
test_page.toc = get_toc(get_markdown_toc(test_page.markdown))
return test_page
validate = {
- 'full': (lambda data:
- self.assertEqual(len(data[0]), 4) and
- self.assertTrue([x for x in data[0][0] if x['title'] and x['text']])),
- 'sections': (lambda data:
- # Sanity
- self.assertEqual(len(data[0]), 4) and
- # Page
- (self.assertEqual(data[0][0]['title'], data[1].title) and
- self.assertTrue(data[0][0]['text'])) and
- # Headings
- self.assertTrue([x for x in data[0][1:] if x['title'] and not x['text']])),
- 'titles': (lambda data:
- # Sanity
- self.assertEqual(len(data[0]), 1) and
- self.assertFalse([x for x in data[0] if x['text']]))
+ 'full': (
+ lambda data: self.assertEqual(len(data[0]), 4)
+ and self.assertTrue([x for x in data[0][0] if x['title'] and x['text']])
+ ),
+ 'sections': (
+ lambda data:
+ # Sanity
+ self.assertEqual(len(data[0]), 4)
+ and
+ # Page
+ (
+ self.assertEqual(data[0][0]['title'], data[1].title)
+ and self.assertTrue(data[0][0]['text'])
+ )
+ and
+ # Headings
+ self.assertTrue([x for x in data[0][1:] if x['title'] and not x['text']])
+ ),
+ 'titles': (
+ lambda data:
+ # Sanity
+ self.assertEqual(len(data[0]), 1)
+ and self.assertFalse([x for x in data[0] if x['text']])
+ ),
}
for option in ['full', 'sections', 'titles']:
@@ -471,7 +489,7 @@ class SearchIndexTests(unittest.TestCase):
pages = [
test_page('Home', 'index.md', base_cfg),
- test_page('About', 'about.md', base_cfg)
+ test_page('About', 'about.md', base_cfg),
]
for page in pages:
@@ -492,7 +510,7 @@ class SearchIndexTests(unittest.TestCase):
expected = {
'docs': [],
'config': {'prebuild_index': True},
- 'index': {'mock': 'index'}
+ 'index': {'mock': 'index'},
}
result = json.loads(index.generate_search_index())
self.assertEqual(mock_popen.call_count, 1)
@@ -510,7 +528,7 @@ class SearchIndexTests(unittest.TestCase):
index = search_index.SearchIndex(prebuild_index=True)
expected = {
'docs': [],
- 'config': {'prebuild_index': True}
+ 'config': {'prebuild_index': True},
}
result = json.loads(index.generate_search_index())
self.assertEqual(mock_popen.call_count, 1)
@@ -528,7 +546,7 @@ class SearchIndexTests(unittest.TestCase):
index = search_index.SearchIndex(prebuild_index=True)
expected = {
'docs': [],
- 'config': {'prebuild_index': True}
+ 'config': {'prebuild_index': True},
}
result = json.loads(index.generate_search_index())
self.assertEqual(mock_popen.call_count, 1)
@@ -546,7 +564,7 @@ class SearchIndexTests(unittest.TestCase):
index = search_index.SearchIndex(prebuild_index=True)
expected = {
'docs': [],
- 'config': {'prebuild_index': True}
+ 'config': {'prebuild_index': True},
}
result = json.loads(index.generate_search_index())
self.assertEqual(mock_popen.call_count, 1)
@@ -564,7 +582,7 @@ class SearchIndexTests(unittest.TestCase):
index = search_index.SearchIndex(prebuild_index=False)
expected = {
'docs': [],
- 'config': {'prebuild_index': False}
+ 'config': {'prebuild_index': False},
}
result = json.loads(index.generate_search_index())
self.assertEqual(mock_popen.call_count, 0)
@@ -579,7 +597,7 @@ class SearchIndexTests(unittest.TestCase):
expected = {
'docs': [],
'config': {'prebuild_index': 'python', 'lang': 'en'},
- 'index': {'mock': 'index'}
+ 'index': {'mock': 'index'},
}
result = json.loads(index.generate_search_index())
self.assertEqual(mock_lunr.call_count, 1)
@@ -591,7 +609,7 @@ class SearchIndexTests(unittest.TestCase):
index = search_index.SearchIndex(prebuild_index='python', lang='en')
expected = {
'docs': [],
- 'config': {'prebuild_index': 'python', 'lang': 'en'}
+ 'config': {'prebuild_index': 'python', 'lang': 'en'},
}
result = json.loads(index.generate_search_index())
self.assertEqual(result, expected)
@@ -608,7 +626,7 @@ class SearchIndexTests(unittest.TestCase):
expected = {
'docs': [],
'config': {'prebuild_index': 'node'},
- 'index': {'mock': 'index'}
+ 'index': {'mock': 'index'},
}
result = json.loads(index.generate_search_index())
self.assertEqual(mock_popen.call_count, 1)
diff --git a/mkdocs/tests/structure/file_tests.py b/mkdocs/tests/structure/file_tests.py
index d3d3cfad..b3076007 100644
--- a/mkdocs/tests/structure/file_tests.py
+++ b/mkdocs/tests/structure/file_tests.py
@@ -7,49 +7,56 @@ from mkdocs.tests.base import load_config, tempdir, PathAssertionMixin
class TestFiles(PathAssertionMixin, unittest.TestCase):
-
def test_file_eq(self):
file = File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=False)
- self.assertTrue(file == File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=False))
+ self.assertTrue(
+ file == File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=False)
+ )
def test_file_ne(self):
file = File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=False)
# Different filename
- self.assertTrue(file != File('b.md', '/path/to/docs', '/path/to/site', use_directory_urls=False))
+ self.assertTrue(
+ file != File('b.md', '/path/to/docs', '/path/to/site', use_directory_urls=False)
+ )
# Different src_path
- self.assertTrue(file != File('a.md', '/path/to/other', '/path/to/site', use_directory_urls=False))
+ self.assertTrue(
+ file != File('a.md', '/path/to/other', '/path/to/site', use_directory_urls=False)
+ )
# Different URL
- self.assertTrue(file != File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=True))
+ self.assertTrue(
+ file != File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=True)
+ )
def test_sort_files(self):
self.assertEqual(
_sort_files(['b.md', 'bb.md', 'a.md', 'index.md', 'aa.md']),
- ['index.md', 'a.md', 'aa.md', 'b.md', 'bb.md']
+ ['index.md', 'a.md', 'aa.md', 'b.md', 'bb.md'],
)
self.assertEqual(
_sort_files(['b.md', 'index.html', 'a.md', 'index.md']),
- ['index.html', 'index.md', 'a.md', 'b.md']
+ ['index.html', 'index.md', 'a.md', 'b.md'],
)
self.assertEqual(
_sort_files(['a.md', 'index.md', 'b.md', 'index.html']),
- ['index.md', 'index.html', 'a.md', 'b.md']
+ ['index.md', 'index.html', 'a.md', 'b.md'],
)
self.assertEqual(
_sort_files(['.md', '_.md', 'a.md', 'index.md', '1.md']),
- ['index.md', '.md', '1.md', '_.md', 'a.md']
+ ['index.md', '.md', '1.md', '_.md', 'a.md'],
)
self.assertEqual(
_sort_files(['a.md', 'b.md', 'a.md']),
- ['a.md', 'a.md', 'b.md']
+ ['a.md', 'a.md', 'b.md'],
)
self.assertEqual(
_sort_files(['A.md', 'B.md', 'README.md']),
- ['README.md', 'A.md', 'B.md']
+ ['README.md', 'A.md', 'B.md'],
)
def test_md_file(self):
@@ -320,7 +327,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
File('foo/bar.html', '/path/to/docs', '/path/to/site', use_directory_urls=True),
File('foo/bar.jpg', '/path/to/docs', '/path/to/site', use_directory_urls=True),
File('foo/bar.js', '/path/to/docs', '/path/to/site', use_directory_urls=True),
- File('foo/bar.css', '/path/to/docs', '/path/to/site', use_directory_urls=True)
+ File('foo/bar.css', '/path/to/docs', '/path/to/site', use_directory_urls=True),
]
files = Files(fs)
self.assertEqual([f for f in files], fs)
@@ -342,38 +349,42 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
self.assertTrue(extra_file.src_path in files)
self.assertEqual(files.documentation_pages(), [fs[0], fs[1], extra_file])
- @tempdir(files=[
- 'favicon.ico',
- 'index.md'
- ])
- @tempdir(files=[
- 'base.html',
- 'favicon.ico',
- 'style.css',
- 'foo.md',
- 'README',
- '.ignore.txt',
- '.ignore/file.txt',
- 'foo/.ignore.txt',
- 'foo/.ignore/file.txt'
- ])
+ @tempdir(
+ files=[
+ 'favicon.ico',
+ 'index.md',
+ ]
+ )
+ @tempdir(
+ files=[
+ 'base.html',
+ 'favicon.ico',
+ 'style.css',
+ 'foo.md',
+ 'README',
+ '.ignore.txt',
+ '.ignore/file.txt',
+ 'foo/.ignore.txt',
+ 'foo/.ignore/file.txt',
+ ]
+ )
def test_add_files_from_theme(self, tdir, ddir):
config = load_config(docs_dir=ddir, theme={'name': None, 'custom_dir': tdir})
env = config['theme'].get_env()
files = get_files(config)
self.assertEqual(
[file.src_path for file in files],
- ['index.md', 'favicon.ico']
+ ['index.md', 'favicon.ico'],
)
files.add_files_from_theme(env, config)
self.assertEqual(
[file.src_path for file in files],
- ['index.md', 'favicon.ico', 'style.css']
+ ['index.md', 'favicon.ico', 'style.css'],
)
# Ensure theme file does not override docs_dir file
self.assertEqual(
files.get_file_from_path('favicon.ico').abs_src_path,
- os.path.normpath(os.path.join(ddir, 'favicon.ico'))
+ os.path.normpath(os.path.join(ddir, 'favicon.ico')),
)
def test_filter_paths(self):
@@ -412,7 +423,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
'foo/bar/baz/index.md',
'foo.md',
'foo/bar.md',
- 'foo/bar/baz.md'
+ 'foo/bar/baz.md',
]
to_file_urls = [
@@ -422,18 +433,18 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
'foo/bar/baz/',
'foo/',
'foo/bar/',
- 'foo/bar/baz/'
+ 'foo/bar/baz/',
]
from_file = File('img.jpg', '/path/to/docs', '/path/to/site', use_directory_urls=True)
expected = [
- 'img.jpg', # img.jpg relative to .
- '../img.jpg', # img.jpg relative to foo/
- '../../img.jpg', # img.jpg relative to foo/bar/
+ 'img.jpg', # img.jpg relative to .
+ '../img.jpg', # img.jpg relative to foo/
+ '../../img.jpg', # img.jpg relative to foo/bar/
'../../../img.jpg', # img.jpg relative to foo/bar/baz/
- '../img.jpg', # img.jpg relative to foo
- '../../img.jpg', # img.jpg relative to foo/bar
- '../../../img.jpg' # img.jpg relative to foo/bar/baz
+ '../img.jpg', # img.jpg relative to foo
+ '../../img.jpg', # img.jpg relative to foo/bar
+ '../../../img.jpg', # img.jpg relative to foo/bar/baz
]
for i, filename in enumerate(to_files):
@@ -445,13 +456,13 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
from_file = File('foo/img.jpg', '/path/to/docs', '/path/to/site', use_directory_urls=True)
expected = [
- 'foo/img.jpg', # foo/img.jpg relative to .
- 'img.jpg', # foo/img.jpg relative to foo/
- '../img.jpg', # foo/img.jpg relative to foo/bar/
+ 'foo/img.jpg', # foo/img.jpg relative to .
+ 'img.jpg', # foo/img.jpg relative to foo/
+ '../img.jpg', # foo/img.jpg relative to foo/bar/
'../../img.jpg', # foo/img.jpg relative to foo/bar/baz/
- 'img.jpg', # foo/img.jpg relative to foo
- '../img.jpg', # foo/img.jpg relative to foo/bar
- '../../img.jpg' # foo/img.jpg relative to foo/bar/baz
+ 'img.jpg', # foo/img.jpg relative to foo
+ '../img.jpg', # foo/img.jpg relative to foo/bar
+ '../../img.jpg', # foo/img.jpg relative to foo/bar/baz
]
for i, filename in enumerate(to_files):
@@ -463,13 +474,13 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
from_file = File('index.html', '/path/to/docs', '/path/to/site', use_directory_urls=True)
expected = [
- '.', # . relative to .
- '..', # . relative to foo/
- '../..', # . relative to foo/bar/
+ '.', # . relative to .
+ '..', # . relative to foo/
+ '../..', # . relative to foo/bar/
'../../..', # . relative to foo/bar/baz/
- '..', # . relative to foo
- '../..', # . relative to foo/bar
- '../../..' # . relative to foo/bar/baz
+ '..', # . relative to foo
+ '../..', # . relative to foo/bar
+ '../../..', # . relative to foo/bar/baz
]
for i, filename in enumerate(to_files):
@@ -481,13 +492,13 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
from_file = File('file.md', '/path/to/docs', '/path/to/site', use_directory_urls=True)
expected = [
- 'file/', # file relative to .
- '../file/', # file relative to foo/
- '../../file/', # file relative to foo/bar/
+ 'file/', # file relative to .
+ '../file/', # file relative to foo/
+ '../../file/', # file relative to foo/bar/
'../../../file/', # file relative to foo/bar/baz/
- '../file/', # file relative to foo
- '../../file/', # file relative to foo/bar
- '../../../file/' # file relative to foo/bar/baz
+ '../file/', # file relative to foo
+ '../../file/', # file relative to foo/bar
+ '../../../file/', # file relative to foo/bar/baz
]
for i, filename in enumerate(to_files):
@@ -505,7 +516,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
'foo/bar/baz/index.md',
'foo.md',
'foo/bar.md',
- 'foo/bar/baz.md'
+ 'foo/bar/baz.md',
]
to_file_urls = [
@@ -515,18 +526,18 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
'foo/bar/baz/index.html',
'foo.html',
'foo/bar.html',
- 'foo/bar/baz.html'
+ 'foo/bar/baz.html',
]
from_file = File('img.jpg', '/path/to/docs', '/path/to/site', use_directory_urls=False)
expected = [
- 'img.jpg', # img.jpg relative to .
- '../img.jpg', # img.jpg relative to foo/
- '../../img.jpg', # img.jpg relative to foo/bar/
+ 'img.jpg', # img.jpg relative to .
+ '../img.jpg', # img.jpg relative to foo/
+ '../../img.jpg', # img.jpg relative to foo/bar/
'../../../img.jpg', # img.jpg relative to foo/bar/baz/
- 'img.jpg', # img.jpg relative to foo.html
- '../img.jpg', # img.jpg relative to foo/bar.html
- '../../img.jpg' # img.jpg relative to foo/bar/baz.html
+ 'img.jpg', # img.jpg relative to foo.html
+ '../img.jpg', # img.jpg relative to foo/bar.html
+ '../../img.jpg', # img.jpg relative to foo/bar/baz.html
]
for i, filename in enumerate(to_files):
@@ -538,13 +549,13 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
from_file = File('foo/img.jpg', '/path/to/docs', '/path/to/site', use_directory_urls=False)
expected = [
- 'foo/img.jpg', # foo/img.jpg relative to .
- 'img.jpg', # foo/img.jpg relative to foo/
- '../img.jpg', # foo/img.jpg relative to foo/bar/
+ 'foo/img.jpg', # foo/img.jpg relative to .
+ 'img.jpg', # foo/img.jpg relative to foo/
+ '../img.jpg', # foo/img.jpg relative to foo/bar/
'../../img.jpg', # foo/img.jpg relative to foo/bar/baz/
- 'foo/img.jpg', # foo/img.jpg relative to foo.html
- 'img.jpg', # foo/img.jpg relative to foo/bar.html
- '../img.jpg' # foo/img.jpg relative to foo/bar/baz.html
+ 'foo/img.jpg', # foo/img.jpg relative to foo.html
+ 'img.jpg', # foo/img.jpg relative to foo/bar.html
+ '../img.jpg', # foo/img.jpg relative to foo/bar/baz.html
]
for i, filename in enumerate(to_files):
@@ -556,13 +567,13 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
from_file = File('index.html', '/path/to/docs', '/path/to/site', use_directory_urls=False)
expected = [
- 'index.html', # index.html relative to .
- '../index.html', # index.html relative to foo/
- '../../index.html', # index.html relative to foo/bar/
+ 'index.html', # index.html relative to .
+ '../index.html', # index.html relative to foo/
+ '../../index.html', # index.html relative to foo/bar/
'../../../index.html', # index.html relative to foo/bar/baz/
- 'index.html', # index.html relative to foo.html
- '../index.html', # index.html relative to foo/bar.html
- '../../index.html' # index.html relative to foo/bar/baz.html
+ 'index.html', # index.html relative to foo.html
+ '../index.html', # index.html relative to foo/bar.html
+ '../../index.html', # index.html relative to foo/bar/baz.html
]
for i, filename in enumerate(to_files):
@@ -574,13 +585,13 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
from_file = File('file.html', '/path/to/docs', '/path/to/site', use_directory_urls=False)
expected = [
- 'file.html', # file.html relative to .
- '../file.html', # file.html relative to foo/
- '../../file.html', # file.html relative to foo/bar/
+ 'file.html', # file.html relative to .
+ '../file.html', # file.html relative to foo/
+ '../../file.html', # file.html relative to foo/bar/
'../../../file.html', # file.html relative to foo/bar/baz/
- 'file.html', # file.html relative to foo.html
- '../file.html', # file.html relative to foo/bar.html
- '../../file.html' # file.html relative to foo/bar/baz.html
+ 'file.html', # file.html relative to foo.html
+ '../file.html', # file.html relative to foo/bar.html
+ '../../file.html', # file.html relative to foo/bar/baz.html
]
for i, filename in enumerate(to_files):
@@ -590,17 +601,19 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
self.assertEqual(from_file.url_relative_to(file.url), expected[i])
self.assertEqual(from_file.url_relative_to(file), expected[i])
- @tempdir(files=[
- 'index.md',
- 'readme.md',
- 'bar.css',
- 'bar.html',
- 'bar.jpg',
- 'bar.js',
- 'bar.md',
- '.dotfile',
- 'templates/foo.html'
- ])
+ @tempdir(
+ files=[
+ 'index.md',
+ 'readme.md',
+ 'bar.css',
+ 'bar.html',
+ 'bar.jpg',
+ 'bar.js',
+ 'bar.md',
+ '.dotfile',
+ 'templates/foo.html',
+ ]
+ )
def test_get_files(self, tdir):
config = load_config(docs_dir=tdir, extra_css=['bar.css'], extra_javascript=['bar.js'])
files = get_files(config)
@@ -609,10 +622,12 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
self.assertEqual(len(files), len(expected))
self.assertEqual([f.src_path for f in files], expected)
- @tempdir(files=[
- 'README.md',
- 'foo.md'
- ])
+ @tempdir(
+ files=[
+ 'README.md',
+ 'foo.md',
+ ]
+ )
def test_get_files_include_readme_without_index(self, tdir):
config = load_config(docs_dir=tdir)
files = get_files(config)
@@ -621,11 +636,13 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
self.assertEqual(len(files), len(expected))
self.assertEqual([f.src_path for f in files], expected)
- @tempdir(files=[
- 'index.md',
- 'README.md',
- 'foo.md'
- ])
+ @tempdir(
+ files=[
+ 'index.md',
+ 'README.md',
+ 'foo.md',
+ ]
+ )
def test_get_files_exclude_readme_with_index(self, tdir):
config = load_config(docs_dir=tdir)
files = get_files(config)
@@ -683,7 +700,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
File('foo/bar.html', '/path/to/docs', '/path/to/site', use_directory_urls=True),
File('foo/bar.jpg', '/path/to/docs', '/path/to/site', use_directory_urls=True),
File('foo/bar.js', '/path/to/docs', '/path/to/site', use_directory_urls=True),
- File('foo/bar.css', '/path/to/docs', '/path/to/site', use_directory_urls=True)
+ File('foo/bar.css', '/path/to/docs', '/path/to/site', use_directory_urls=True),
]
files = Files(fs)
self.assertEqual(len(files), 6)
diff --git a/mkdocs/tests/structure/nav_tests.py b/mkdocs/tests/structure/nav_tests.py
index 81849236..de9141ea 100644
--- a/mkdocs/tests/structure/nav_tests.py
+++ b/mkdocs/tests/structure/nav_tests.py
@@ -16,17 +16,22 @@ class SiteNavigationTests(unittest.TestCase):
def test_simple_nav(self):
nav_cfg = [
{'Home': 'index.md'},
- {'About': 'about.md'}
+ {'About': 'about.md'},
]
- expected = dedent("""
- Page(title='Home', url='/')
- Page(title='About', url='/about/')
- """)
- cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files(
- [File(list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- for item in nav_cfg]
+ expected = dedent(
+ """
+ Page(title='Home', url='/')
+ Page(title='About', url='/about/')
+ """
)
+ cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
+ fs = [
+ File(
+ list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']
+ )
+ for item in nav_cfg
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 2)
@@ -36,17 +41,22 @@ class SiteNavigationTests(unittest.TestCase):
def test_nav_no_directory_urls(self):
nav_cfg = [
{'Home': 'index.md'},
- {'About': 'about.md'}
+ {'About': 'about.md'},
]
- expected = dedent("""
- Page(title='Home', url='/index.html')
- Page(title='About', url='/about.html')
- """)
- cfg = load_config(nav=nav_cfg, use_directory_urls=False, site_url='http://example.com/')
- files = Files(
- [File(list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- for item in nav_cfg]
+ expected = dedent(
+ """
+ Page(title='Home', url='/index.html')
+ Page(title='About', url='/about.html')
+ """
)
+ cfg = load_config(nav=nav_cfg, use_directory_urls=False, site_url='http://example.com/')
+ fs = [
+ File(
+ list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']
+ )
+ for item in nav_cfg
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 2)
@@ -55,16 +65,19 @@ class SiteNavigationTests(unittest.TestCase):
def test_nav_missing_page(self):
nav_cfg = [
- {'Home': 'index.md'}
+ {'Home': 'index.md'},
]
- expected = dedent("""
- Page(title='Home', url='/')
- """)
+ expected = dedent(
+ """
+ Page(title='Home', url='/')
+ """
+ )
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('page_not_in_nav.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ File('page_not_in_nav.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 1)
@@ -75,17 +88,20 @@ class SiteNavigationTests(unittest.TestCase):
def test_nav_no_title(self):
nav_cfg = [
'index.md',
- {'About': 'about.md'}
+ {'About': 'about.md'},
]
- expected = dedent("""
- Page(title=[blank], url='/')
- Page(title='About', url='/about/')
- """)
+ expected = dedent(
+ """
+ Page(title=[blank], url='/')
+ Page(title='About', url='/about/')
+ """
+ )
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files([
+ fs = [
File(nav_cfg[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File(nav_cfg[1]['About'], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ File(nav_cfg[1]['About'], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 2)
@@ -95,15 +111,18 @@ class SiteNavigationTests(unittest.TestCase):
nav_cfg = [
{'Home': 'index.md'},
{'Local': '/local.html'},
- {'External': 'http://example.com/external.html'}
+ {'External': 'http://example.com/external.html'},
]
- expected = dedent("""
- Page(title='Home', url='/')
- Link(title='Local', url='/local.html')
- Link(title='External', url='http://example.com/external.html')
- """)
+ expected = dedent(
+ """
+ Page(title='Home', url='/')
+ Link(title='Local', url='/local.html')
+ Link(title='External', url='http://example.com/external.html')
+ """
+ )
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
with self.assertLogs('mkdocs', level='DEBUG') as cm:
site_navigation = get_navigation(files, cfg)
self.assertEqual(
@@ -112,8 +131,8 @@ class SiteNavigationTests(unittest.TestCase):
"DEBUG:mkdocs.structure.nav:An absolute path to '/local.html' is included in the "
"'nav' configuration, which presumably points to an external resource.",
"DEBUG:mkdocs.structure.nav:An external link to 'http://example.com/external.html' "
- "is included in the 'nav' configuration."
- ]
+ "is included in the 'nav' configuration.",
+ ],
)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 3)
@@ -123,15 +142,18 @@ class SiteNavigationTests(unittest.TestCase):
nav_cfg = [
{'Home': 'index.md'},
{'Missing': 'missing.html'},
- {'Bad External': 'example.com'}
+ {'Bad External': 'example.com'},
]
- expected = dedent("""
- Page(title='Home', url='/')
- Link(title='Missing', url='missing.html')
- Link(title='Bad External', url='example.com')
- """)
+ expected = dedent(
+ """
+ Page(title='Home', url='/')
+ Link(title='Missing', url='missing.html')
+ Link(title='Bad External', url='example.com')
+ """
+ )
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files([File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])])
+ fs = [File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
with self.assertLogs('mkdocs', level='WARNING') as cm:
site_navigation = get_navigation(files, cfg)
self.assertEqual(
@@ -140,8 +162,8 @@ class SiteNavigationTests(unittest.TestCase):
"WARNING:mkdocs.structure.nav:A relative path to 'missing.html' is included "
"in the 'nav' configuration, which is not found in the documentation files",
"WARNING:mkdocs.structure.nav:A relative path to 'example.com' is included "
- "in the 'nav' configuration, which is not found in the documentation files"
- ]
+ "in the 'nav' configuration, which is not found in the documentation files",
+ ],
)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 3)
@@ -150,42 +172,53 @@ class SiteNavigationTests(unittest.TestCase):
def test_indented_nav(self):
nav_cfg = [
{'Home': 'index.md'},
- {'API Guide': [
- {'Running': 'api-guide/running.md'},
- {'Testing': 'api-guide/testing.md'},
- {'Debugging': 'api-guide/debugging.md'},
- {'Advanced': [
- {'Part 1': 'api-guide/advanced/part-1.md'},
- ]},
- ]},
- {'About': [
- {'Release notes': 'about/release-notes.md'},
- {'License': '/license.html'}
- ]},
- {'External': 'https://example.com/'}
+ {
+ 'API Guide': [
+ {'Running': 'api-guide/running.md'},
+ {'Testing': 'api-guide/testing.md'},
+ {'Debugging': 'api-guide/debugging.md'},
+ {
+ 'Advanced': [
+ {'Part 1': 'api-guide/advanced/part-1.md'},
+ ]
+ },
+ ]
+ },
+ {
+ 'About': [
+ {'Release notes': 'about/release-notes.md'},
+ {'License': '/license.html'},
+ ]
+ },
+ {'External': 'https://example.com/'},
]
- expected = dedent("""
- Page(title='Home', url='/')
- Section(title='API Guide')
- Page(title='Running', url='/api-guide/running/')
- Page(title='Testing', url='/api-guide/testing/')
- Page(title='Debugging', url='/api-guide/debugging/')
- Section(title='Advanced')
- Page(title='Part 1', url='/api-guide/advanced/part-1/')
- Section(title='About')
- Page(title='Release notes', url='/about/release-notes/')
- Link(title='License', url='/license.html')
- Link(title='External', url='https://example.com/')
- """)
+ expected = dedent(
+ """
+ Page(title='Home', url='/')
+ Section(title='API Guide')
+ Page(title='Running', url='/api-guide/running/')
+ Page(title='Testing', url='/api-guide/testing/')
+ Page(title='Debugging', url='/api-guide/debugging/')
+ Section(title='Advanced')
+ Page(title='Part 1', url='/api-guide/advanced/part-1/')
+ Section(title='About')
+ Page(title='Release notes', url='/about/release-notes/')
+ Link(title='License', url='/license.html')
+ Link(title='External', url='https://example.com/')
+ """
+ )
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files([
- File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/running.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/debugging.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/advanced/part-1.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('about/release-notes.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ fs = [
+ 'index.md',
+ 'api-guide/running.md',
+ 'api-guide/testing.md',
+ 'api-guide/debugging.md',
+ 'api-guide/advanced/part-1.md',
+ 'about/release-notes.md',
+ ]
+ files = Files(
+ [File(s, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for s in fs]
+ )
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 4)
@@ -196,23 +229,40 @@ class SiteNavigationTests(unittest.TestCase):
self.assertIsNone(site_navigation.items[1].parent)
self.assertEqual(site_navigation.items[1].ancestors, [])
self.assertEqual(len(site_navigation.items[1].children), 4)
- self.assertEqual(repr(site_navigation.items[1].children[0].parent), "Section(title='API Guide')")
+ self.assertEqual(
+ repr(site_navigation.items[1].children[0].parent), "Section(title='API Guide')"
+ )
self.assertEqual(site_navigation.items[1].children[0].ancestors, [site_navigation.items[1]])
- self.assertEqual(repr(site_navigation.items[1].children[1].parent), "Section(title='API Guide')")
+ self.assertEqual(
+ repr(site_navigation.items[1].children[1].parent), "Section(title='API Guide')"
+ )
self.assertEqual(site_navigation.items[1].children[1].ancestors, [site_navigation.items[1]])
- self.assertEqual(repr(site_navigation.items[1].children[2].parent), "Section(title='API Guide')")
+ self.assertEqual(
+ repr(site_navigation.items[1].children[2].parent), "Section(title='API Guide')"
+ )
self.assertEqual(site_navigation.items[1].children[2].ancestors, [site_navigation.items[1]])
- self.assertEqual(repr(site_navigation.items[1].children[3].parent), "Section(title='API Guide')")
+ self.assertEqual(
+ repr(site_navigation.items[1].children[3].parent), "Section(title='API Guide')"
+ )
self.assertEqual(site_navigation.items[1].children[3].ancestors, [site_navigation.items[1]])
self.assertEqual(len(site_navigation.items[1].children[3].children), 1)
- self.assertEqual(repr(site_navigation.items[1].children[3].children[0].parent), "Section(title='Advanced')")
- self.assertEqual(site_navigation.items[1].children[3].children[0].ancestors,
- [site_navigation.items[1].children[3], site_navigation.items[1]])
+ self.assertEqual(
+ repr(site_navigation.items[1].children[3].children[0].parent),
+ "Section(title='Advanced')",
+ )
+ self.assertEqual(
+ site_navigation.items[1].children[3].children[0].ancestors,
+ [site_navigation.items[1].children[3], site_navigation.items[1]],
+ )
self.assertIsNone(site_navigation.items[2].parent)
self.assertEqual(len(site_navigation.items[2].children), 2)
- self.assertEqual(repr(site_navigation.items[2].children[0].parent), "Section(title='About')")
+ self.assertEqual(
+ repr(site_navigation.items[2].children[0].parent), "Section(title='About')"
+ )
self.assertEqual(site_navigation.items[2].children[0].ancestors, [site_navigation.items[2]])
- self.assertEqual(repr(site_navigation.items[2].children[1].parent), "Section(title='About')")
+ self.assertEqual(
+ repr(site_navigation.items[2].children[1].parent), "Section(title='About')"
+ )
self.assertEqual(site_navigation.items[2].children[1].ancestors, [site_navigation.items[2]])
self.assertIsNone(site_navigation.items[3].parent)
self.assertEqual(site_navigation.items[3].ancestors, [])
@@ -224,16 +274,21 @@ class SiteNavigationTests(unittest.TestCase):
{'Contact': 'about/contact.md'},
{'License Title': 'about/sub/license.md'},
]
- expected = dedent("""
- Page(title='Home', url='/')
- Page(title='Contact', url='/about/contact/')
- Page(title='License Title', url='/about/sub/license/')
- """)
- cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files(
- [File(list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- for item in nav_cfg]
+ expected = dedent(
+ """
+ Page(title='Home', url='/')
+ Page(title='Contact', url='/about/contact/')
+ Page(title='License Title', url='/about/sub/license/')
+ """
)
+ cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
+ fs = [
+ File(
+ list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']
+ )
+ for item in nav_cfg
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 3)
@@ -243,18 +298,22 @@ class SiteNavigationTests(unittest.TestCase):
nav_cfg = [
'index.md',
'about/contact.md',
- 'about/sub/license.md'
+ 'about/sub/license.md',
]
- expected = dedent("""
- Page(title=[blank], url='/')
- Page(title=[blank], url='/about/contact/')
- Page(title=[blank], url='/about/sub/license/')
- """)
+ expected = dedent(
+ """
+ Page(title=[blank], url='/')
+ Page(title=[blank], url='/about/contact/')
+ Page(title=[blank], url='/about/sub/license/')
+ """
+ )
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files(
- [File(item, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for item in nav_cfg]
- )
+ fs = [
+ File(item, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
+ for item in nav_cfg
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 3)
@@ -268,31 +327,38 @@ class SiteNavigationTests(unittest.TestCase):
'about\\contact.md',
'about\\sub\\license.md',
]
- expected = dedent("""
- Page(title=[blank], url='/')
- Page(title=[blank], url='/about/contact/')
- Page(title=[blank], url='/about/sub/license/')
- """)
+ expected = dedent(
+ """
+ Page(title=[blank], url='/')
+ Page(title=[blank], url='/about/contact/')
+ Page(title=[blank], url='/about/sub/license/')
+ """
+ )
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files(
- [File(item, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for item in nav_cfg]
- )
+ fs = [
+ File(item, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
+ for item in nav_cfg
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 3)
self.assertEqual(len(site_navigation.pages), 3)
def test_nav_from_files(self):
- expected = dedent("""
- Page(title=[blank], url='/')
- Page(title=[blank], url='/about/')
- """)
+ expected = dedent(
+ """
+ Page(title=[blank], url='/')
+ Page(title=[blank], url='/about/')
+ """
+ )
cfg = load_config(site_url='http://example.com/')
- files = Files([
+ fs = [
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ ]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 2)
@@ -300,28 +366,33 @@ class SiteNavigationTests(unittest.TestCase):
self.assertEqual(repr(site_navigation.homepage), "Page(title=[blank], url='/')")
def test_nav_from_nested_files(self):
- expected = dedent("""
- Page(title=[blank], url='/')
- Section(title='About')
- Page(title=[blank], url='/about/license/')
- Page(title=[blank], url='/about/release-notes/')
- Section(title='Api guide')
- Page(title=[blank], url='/api-guide/debugging/')
- Page(title=[blank], url='/api-guide/running/')
- Page(title=[blank], url='/api-guide/testing/')
- Section(title='Advanced')
- Page(title=[blank], url='/api-guide/advanced/part-1/')
- """)
+ expected = dedent(
+ """
+ Page(title=[blank], url='/')
+ Section(title='About')
+ Page(title=[blank], url='/about/license/')
+ Page(title=[blank], url='/about/release-notes/')
+ Section(title='Api guide')
+ Page(title=[blank], url='/api-guide/debugging/')
+ Page(title=[blank], url='/api-guide/running/')
+ Page(title=[blank], url='/api-guide/testing/')
+ Section(title='Advanced')
+ Page(title=[blank], url='/api-guide/advanced/part-1/')
+ """
+ )
cfg = load_config(site_url='http://example.com/')
- files = Files([
- File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('about/license.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('about/release-notes.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/debugging.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/running.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/advanced/part-1.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ fs = [
+ 'index.md',
+ 'about/license.md',
+ 'about/release-notes.md',
+ 'api-guide/debugging.md',
+ 'api-guide/running.md',
+ 'api-guide/testing.md',
+ 'api-guide/advanced/part-1.md',
+ ]
+ files = Files(
+ [File(s, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for s in fs]
+ )
site_navigation = get_navigation(files, cfg)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 3)
@@ -331,29 +402,38 @@ class SiteNavigationTests(unittest.TestCase):
def test_active(self):
nav_cfg = [
{'Home': 'index.md'},
- {'API Guide': [
- {'Running': 'api-guide/running.md'},
- {'Testing': 'api-guide/testing.md'},
- {'Debugging': 'api-guide/debugging.md'},
- {'Advanced': [
- {'Part 1': 'api-guide/advanced/part-1.md'},
- ]},
- ]},
- {'About': [
- {'Release notes': 'about/release-notes.md'},
- {'License': 'about/license.md'}
- ]}
+ {
+ 'API Guide': [
+ {'Running': 'api-guide/running.md'},
+ {'Testing': 'api-guide/testing.md'},
+ {'Debugging': 'api-guide/debugging.md'},
+ {
+ 'Advanced': [
+ {'Part 1': 'api-guide/advanced/part-1.md'},
+ ]
+ },
+ ]
+ },
+ {
+ 'About': [
+ {'Release notes': 'about/release-notes.md'},
+ {'License': 'about/license.md'},
+ ]
+ },
]
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files([
- File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/running.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/debugging.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('api-guide/advanced/part-1.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('about/release-notes.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- File('about/license.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
- ])
+ fs = [
+ 'index.md',
+ 'api-guide/running.md',
+ 'api-guide/testing.md',
+ 'api-guide/debugging.md',
+ 'api-guide/advanced/part-1.md',
+ 'about/release-notes.md',
+ 'about/license.md',
+ ]
+ files = Files(
+ [File(s, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for s in fs]
+ )
site_navigation = get_navigation(files, cfg)
# Confirm nothing is active
self.assertTrue(all(page.active is False for page in site_navigation.pages))
@@ -381,15 +461,18 @@ class SiteNavigationTests(unittest.TestCase):
def test_get_by_type_nested_sections(self):
nav_cfg = [
- {'Section 1': [
- {'Section 2': [
- {'Page': 'page.md'}
- ]}
- ]}
+ {
+ 'Section 1': [
+ {
+ 'Section 2': [
+ {'Page': 'page.md'},
+ ]
+ },
+ ]
+ },
]
cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
- files = Files([
- File('page.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
- ])
+ fs = [File('page.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])]
+ files = Files(fs)
site_navigation = get_navigation(files, cfg)
self.assertEqual(len(_get_by_type(site_navigation, Section)), 2)
diff --git a/mkdocs/tests/structure/page_tests.py b/mkdocs/tests/structure/page_tests.py
index 35c1886b..af666b11 100644
--- a/mkdocs/tests/structure/page_tests.py
+++ b/mkdocs/tests/structure/page_tests.py
@@ -11,7 +11,9 @@ from mkdocs.tests.base import load_config, dedent
class PageTests(unittest.TestCase):
- DOCS_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../integration/subpages/docs')
+ DOCS_DIR = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)), '../integration/subpages/docs'
+ )
def test_homepage(self):
cfg = load_config(docs_dir=self.DOCS_DIR)
@@ -429,52 +431,24 @@ class PageTests(unittest.TestCase):
def test_page_edit_url(self):
configs = [
+ {'repo_url': 'http://github.com/mkdocs/mkdocs'},
+ {'repo_url': 'https://github.com/mkdocs/mkdocs/'},
+ {'repo_url': 'http://example.com'},
+ {'repo_url': 'http://example.com', 'edit_uri': 'edit/master'},
+ {'repo_url': 'http://example.com', 'edit_uri': '/edit/master'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': '/edit/master/'},
+ {'repo_url': 'http://example.com/foo', 'edit_uri': '/edit/master/'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': '/edit/master'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': 'edit/master/'},
+ {'repo_url': 'http://example.com/foo', 'edit_uri': 'edit/master/'},
+ {'repo_url': 'http://example.com', 'edit_uri': '?query=edit/master'},
+ {'repo_url': 'http://example.com/', 'edit_uri': '?query=edit/master/'},
+ {'repo_url': 'http://example.com', 'edit_uri': '#edit/master'},
+ {'repo_url': 'http://example.com/', 'edit_uri': '#edit/master/'},
+ {'repo_url': 'http://example.com', 'edit_uri': ''}, # Set to blank value
{
- 'repo_url': 'http://github.com/mkdocs/mkdocs'
- },
- {
- 'repo_url': 'https://github.com/mkdocs/mkdocs/'
- }, {
- 'repo_url': 'http://example.com'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': 'edit/master'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '/edit/master'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': '/edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo',
- 'edit_uri': '/edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': '/edit/master'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': 'edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo',
- 'edit_uri': 'edit/master/'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '?query=edit/master'
- }, {
- 'repo_url': 'http://example.com/',
- 'edit_uri': '?query=edit/master/'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '#edit/master'
- }, {
- 'repo_url': 'http://example.com/',
- 'edit_uri': '#edit/master/'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '' # Set to blank value
- }, {
# Nothing defined
- }
+ },
]
expected = [
@@ -493,7 +467,7 @@ class PageTests(unittest.TestCase):
'http://example.com#edit/master/testing.md',
'http://example.com/#edit/master/testing.md',
None,
- None
+ None,
]
for i, c in enumerate(configs):
@@ -505,47 +479,20 @@ class PageTests(unittest.TestCase):
def test_nested_page_edit_url(self):
configs = [
- {
- 'repo_url': 'http://github.com/mkdocs/mkdocs'
- },
- {
- 'repo_url': 'https://github.com/mkdocs/mkdocs/'
- }, {
- 'repo_url': 'http://example.com'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': 'edit/master'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '/edit/master'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': '/edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo',
- 'edit_uri': '/edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': '/edit/master'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': 'edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo',
- 'edit_uri': 'edit/master/'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '?query=edit/master'
- }, {
- 'repo_url': 'http://example.com/',
- 'edit_uri': '?query=edit/master/'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '#edit/master'
- }, {
- 'repo_url': 'http://example.com/',
- 'edit_uri': '#edit/master/'
- }
+ {'repo_url': 'http://github.com/mkdocs/mkdocs'},
+ {'repo_url': 'https://github.com/mkdocs/mkdocs/'},
+ {'repo_url': 'http://example.com'},
+ {'repo_url': 'http://example.com', 'edit_uri': 'edit/master'},
+ {'repo_url': 'http://example.com', 'edit_uri': '/edit/master'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': '/edit/master/'},
+ {'repo_url': 'http://example.com/foo', 'edit_uri': '/edit/master/'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': '/edit/master'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': 'edit/master/'},
+ {'repo_url': 'http://example.com/foo', 'edit_uri': 'edit/master/'},
+ {'repo_url': 'http://example.com', 'edit_uri': '?query=edit/master'},
+ {'repo_url': 'http://example.com/', 'edit_uri': '?query=edit/master/'},
+ {'repo_url': 'http://example.com', 'edit_uri': '#edit/master'},
+ {'repo_url': 'http://example.com/', 'edit_uri': '#edit/master/'},
]
expected = [
@@ -562,13 +509,15 @@ class PageTests(unittest.TestCase):
'http://example.com?query=edit/master/sub1/non-index.md',
'http://example.com/?query=edit/master/sub1/non-index.md',
'http://example.com#edit/master/sub1/non-index.md',
- 'http://example.com/#edit/master/sub1/non-index.md'
+ 'http://example.com/#edit/master/sub1/non-index.md',
]
for i, c in enumerate(configs):
c['docs_dir'] = self.DOCS_DIR
cfg = load_config(**c)
- fl = File('sub1/non-index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
+ fl = File(
+ 'sub1/non-index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']
+ )
pg = Page('Foo', fl, cfg)
self.assertEqual(pg.url, 'sub1/non-index/')
self.assertEqual(pg.edit_url, expected[i])
@@ -576,47 +525,20 @@ class PageTests(unittest.TestCase):
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_nested_page_edit_url_windows(self):
configs = [
- {
- 'repo_url': 'http://github.com/mkdocs/mkdocs'
- },
- {
- 'repo_url': 'https://github.com/mkdocs/mkdocs/'
- }, {
- 'repo_url': 'http://example.com'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': 'edit/master'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '/edit/master'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': '/edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo',
- 'edit_uri': '/edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': '/edit/master'
- }, {
- 'repo_url': 'http://example.com/foo/',
- 'edit_uri': 'edit/master/'
- }, {
- 'repo_url': 'http://example.com/foo',
- 'edit_uri': 'edit/master/'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '?query=edit/master'
- }, {
- 'repo_url': 'http://example.com/',
- 'edit_uri': '?query=edit/master/'
- }, {
- 'repo_url': 'http://example.com',
- 'edit_uri': '#edit/master'
- }, {
- 'repo_url': 'http://example.com/',
- 'edit_uri': '#edit/master/'
- }
+ {'repo_url': 'http://github.com/mkdocs/mkdocs'},
+ {'repo_url': 'https://github.com/mkdocs/mkdocs/'},
+ {'repo_url': 'http://example.com'},
+ {'repo_url': 'http://example.com', 'edit_uri': 'edit/master'},
+ {'repo_url': 'http://example.com', 'edit_uri': '/edit/master'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': '/edit/master/'},
+ {'repo_url': 'http://example.com/foo', 'edit_uri': '/edit/master/'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': '/edit/master'},
+ {'repo_url': 'http://example.com/foo/', 'edit_uri': 'edit/master/'},
+ {'repo_url': 'http://example.com/foo', 'edit_uri': 'edit/master/'},
+ {'repo_url': 'http://example.com', 'edit_uri': '?query=edit/master'},
+ {'repo_url': 'http://example.com/', 'edit_uri': '?query=edit/master/'},
+ {'repo_url': 'http://example.com', 'edit_uri': '#edit/master'},
+ {'repo_url': 'http://example.com/', 'edit_uri': '#edit/master/'},
]
expected = [
@@ -633,13 +555,15 @@ class PageTests(unittest.TestCase):
'http://example.com?query=edit/master/sub1/non-index.md',
'http://example.com/?query=edit/master/sub1/non-index.md',
'http://example.com#edit/master/sub1/non-index.md',
- 'http://example.com/#edit/master/sub1/non-index.md'
+ 'http://example.com/#edit/master/sub1/non-index.md',
]
for i, c in enumerate(configs):
c['docs_dir'] = self.DOCS_DIR
cfg = load_config(**c)
- fl = File('sub1\\non-index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])
+ fl = File(
+ 'sub1\\non-index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']
+ )
pg = Page('Foo', fl, cfg)
self.assertEqual(pg.url, 'sub1/non-index/')
self.assertEqual(pg.edit_url, expected[i])
@@ -652,14 +576,19 @@ class PageTests(unittest.TestCase):
self.assertEqual(pg.content, None)
self.assertEqual(pg.toc, [])
pg.render(cfg, [fl])
- self.assertTrue(pg.content.startswith(
- 'Welcome to MkDocs
\n'
- ))
- self.assertEqual(str(pg.toc).strip(), dedent("""
- Welcome to MkDocs - #welcome-to-mkdocs
- Commands - #commands
- Project layout - #project-layout
- """))
+ self.assertTrue(
+ pg.content.startswith('Welcome to MkDocs
\n')
+ )
+ self.assertEqual(
+ str(pg.toc).strip(),
+ dedent(
+ """
+ Welcome to MkDocs - #welcome-to-mkdocs
+ Commands - #commands
+ Project layout - #project-layout
+ """
+ ),
+ )
def test_missing_page(self):
cfg = load_config()
@@ -670,7 +599,6 @@ class PageTests(unittest.TestCase):
class SourceDateEpochTests(unittest.TestCase):
-
def setUp(self):
self.default = os.environ.get('SOURCE_DATE_EPOCH', None)
os.environ['SOURCE_DATE_EPOCH'] = '0'
@@ -690,13 +618,18 @@ class SourceDateEpochTests(unittest.TestCase):
class RelativePathExtensionTests(unittest.TestCase):
- DOCS_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../integration/subpages/docs')
+ DOCS_DIR = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)), '../integration/subpages/docs'
+ )
def get_rendered_result(self, files):
cfg = load_config(docs_dir=self.DOCS_DIR)
- fs = []
- for f in files:
- fs.append(File(f.replace('/', os.sep), cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']))
+ fs = [
+ File(
+ f.replace('/', os.sep), cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']
+ )
+ for f in files
+ ]
pg = Page('Foo', fs[0], cfg)
pg.read_source(cfg)
pg.render(cfg, Files(fs))
@@ -706,105 +639,113 @@ class RelativePathExtensionTests(unittest.TestCase):
def test_relative_html_link(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'non-index.md']),
- 'link
' # No trailing /
+ 'link
', # No trailing /
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](index.md)'))
def test_relative_html_link_index(self):
self.assertEqual(
self.get_rendered_result(['non-index.md', 'index.md']),
- 'link
'
+ 'link
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/index.md)'))
def test_relative_html_link_sub_index(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'sub2/index.md']),
- 'link
' # No trailing /
+ 'link
', # No trailing /
)
- @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/non-index.md)'))
+ @mock.patch(
+ 'mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/non-index.md)')
+ )
def test_relative_html_link_sub_page(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'sub2/non-index.md']),
- 'link
' # No trailing /
+ 'link
', # No trailing /
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](file%20name.md)'))
def test_relative_html_link_with_encoded_space(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'file name.md']),
- 'link
'
+ 'link
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](file name.md)'))
def test_relative_html_link_with_unencoded_space(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'file name.md']),
- 'link
'
+ 'link
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](../index.md)'))
def test_relative_html_link_parent_index(self):
self.assertEqual(
self.get_rendered_result(['sub2/non-index.md', 'index.md']),
- 'link
'
+ 'link
',
)
- @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](non-index.md#hash)'))
+ @mock.patch(
+ 'mkdocs.structure.pages.open', mock.mock_open(read_data='[link](non-index.md#hash)')
+ )
def test_relative_html_link_hash(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'non-index.md']),
- 'link
'
+ 'link
',
)
- @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/index.md#hash)'))
+ @mock.patch(
+ 'mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/index.md#hash)')
+ )
def test_relative_html_link_sub_index_hash(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'sub2/index.md']),
- 'link
'
+ 'link
',
)
- @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/non-index.md#hash)'))
+ @mock.patch(
+ 'mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/non-index.md#hash)')
+ )
def test_relative_html_link_sub_page_hash(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'sub2/non-index.md']),
- 'link
'
+ 'link
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](#hash)'))
def test_relative_html_link_hash_only(self):
self.assertEqual(
self.get_rendered_result(['index.md']),
- 'link
'
+ 'link
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data=''))
def test_relative_image_link_from_homepage(self):
self.assertEqual(
self.get_rendered_result(['index.md', 'image.png']),
- '
' # no opening ./
+ '
', # no opening ./
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data=''))
def test_relative_image_link_from_subpage(self):
self.assertEqual(
self.get_rendered_result(['sub2/non-index.md', 'image.png']),
- '
'
+ '
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data=''))
def test_relative_image_link_from_sibling(self):
self.assertEqual(
self.get_rendered_result(['non-index.md', 'image.png']),
- '
'
+ '
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='*__not__ a link*.'))
def test_no_links(self):
self.assertEqual(
self.get_rendered_result(['index.md']),
- 'not a link.
'
+ 'not a link.
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](non-existent.md)'))
@@ -812,33 +753,43 @@ class RelativePathExtensionTests(unittest.TestCase):
with self.assertLogs('mkdocs', level='WARNING') as cm:
self.assertEqual(
self.get_rendered_result(['index.md']),
- 'link
'
+ 'link
',
)
self.assertEqual(
cm.output,
- ["WARNING:mkdocs.structure.pages:Documentation file 'index.md' contains a link "
- "to 'non-existent.md' which is not found in the documentation files."]
+ [
+ "WARNING:mkdocs.structure.pages:Documentation file 'index.md' contains a link "
+ "to 'non-existent.md' which is not found in the documentation files."
+ ],
)
- @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[external](http://example.com/index.md)'))
+ @mock.patch(
+ 'mkdocs.structure.pages.open',
+ mock.mock_open(read_data='[external](http://example.com/index.md)'),
+ )
def test_external_link(self):
self.assertEqual(
self.get_rendered_result(['index.md']),
- 'external
'
+ 'external
',
)
- @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[absolute link](/path/to/file.md)'))
+ @mock.patch(
+ 'mkdocs.structure.pages.open', mock.mock_open(read_data='[absolute link](/path/to/file.md)')
+ )
def test_absolute_link(self):
self.assertEqual(
self.get_rendered_result(['index.md']),
- 'absolute link
'
+ 'absolute link
',
)
- @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[absolute local path](\\image.png)'))
+ @mock.patch(
+ 'mkdocs.structure.pages.open',
+ mock.mock_open(read_data='[absolute local path](\\image.png)'),
+ )
def test_absolute_win_local_path(self):
self.assertEqual(
self.get_rendered_result(['index.md']),
- 'absolute local path
'
+ 'absolute local path
',
)
@mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data=''))
@@ -849,5 +800,5 @@ class RelativePathExtensionTests(unittest.TestCase):
# The following is equivalent to: 'mail@example.com
'
'mail@'
- 'example.com
'
+ 'example.com
',
)
diff --git a/mkdocs/tests/structure/toc_tests.py b/mkdocs/tests/structure/toc_tests.py
index 591d4f7b..44c9a4b8 100644
--- a/mkdocs/tests/structure/toc_tests.py
+++ b/mkdocs/tests/structure/toc_tests.py
@@ -6,135 +6,166 @@ from mkdocs.tests.base import dedent, get_markdown_toc
class TableOfContentsTests(unittest.TestCase):
-
def test_indented_toc(self):
- md = dedent("""
- # Heading 1
- ## Heading 2
- ### Heading 3
- """)
- expected = dedent("""
- Heading 1 - #heading-1
- Heading 2 - #heading-2
- Heading 3 - #heading-3
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 2
+ ### Heading 3
+ """
+ )
+ expected = dedent(
+ """
+ Heading 1 - #heading-1
+ Heading 2 - #heading-2
+ Heading 3 - #heading-3
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 1)
def test_indented_toc_html(self):
- md = dedent("""
- # Heading 1
- ## Heading 2
- ## Heading 3
- """)
- expected = dedent("""
- Heading 1 - #heading-1
- Heading 2 - #heading-2
- Heading 3 - #heading-3
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 2
+ ## Heading 3
+ """
+ )
+ expected = dedent(
+ """
+ Heading 1 - #heading-1
+ Heading 2 - #heading-2
+ Heading 3 - #heading-3
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 1)
def test_flat_toc(self):
- md = dedent("""
- # Heading 1
- # Heading 2
- # Heading 3
- """)
- expected = dedent("""
- Heading 1 - #heading-1
- Heading 2 - #heading-2
- Heading 3 - #heading-3
- """)
+ md = dedent(
+ """
+ # Heading 1
+ # Heading 2
+ # Heading 3
+ """
+ )
+ expected = dedent(
+ """
+ Heading 1 - #heading-1
+ Heading 2 - #heading-2
+ Heading 3 - #heading-3
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 3)
def test_flat_h2_toc(self):
- md = dedent("""
- ## Heading 1
- ## Heading 2
- ## Heading 3
- """)
- expected = dedent("""
- Heading 1 - #heading-1
- Heading 2 - #heading-2
- Heading 3 - #heading-3
- """)
+ md = dedent(
+ """
+ ## Heading 1
+ ## Heading 2
+ ## Heading 3
+ """
+ )
+ expected = dedent(
+ """
+ Heading 1 - #heading-1
+ Heading 2 - #heading-2
+ Heading 3 - #heading-3
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 3)
def test_mixed_toc(self):
- md = dedent("""
- # Heading 1
- ## Heading 2
- # Heading 3
- ### Heading 4
- ### Heading 5
- """)
- expected = dedent("""
- Heading 1 - #heading-1
- Heading 2 - #heading-2
- Heading 3 - #heading-3
- Heading 4 - #heading-4
- Heading 5 - #heading-5
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 2
+ # Heading 3
+ ### Heading 4
+ ### Heading 5
+ """
+ )
+ expected = dedent(
+ """
+ Heading 1 - #heading-1
+ Heading 2 - #heading-2
+ Heading 3 - #heading-3
+ Heading 4 - #heading-4
+ Heading 5 - #heading-5
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 2)
def test_mixed_html(self):
- md = dedent("""
- # Heading 1
- ## Heading 2
- # Heading 3
- ### Heading 4
- ### Heading 5
- """)
- expected = dedent("""
- Heading 1 - #heading-1
- Heading 2 - #heading-2
- Heading 3 - #heading-3
- Heading 4 - #heading-4
- Heading 5 - #heading-5
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 2
+ # Heading 3
+ ### Heading 4
+ ### Heading 5
+ """
+ )
+ expected = dedent(
+ """
+ Heading 1 - #heading-1
+ Heading 2 - #heading-2
+ Heading 3 - #heading-3
+ Heading 4 - #heading-4
+ Heading 5 - #heading-5
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 2)
def test_nested_anchor(self):
- md = dedent("""
- # Heading 1
- ## Heading 2
- # Heading 3
- ### Heading 4
- ### Heading 5
- """)
- expected = dedent("""
- Heading 1 - #heading-1
- Heading 2 - #heading-2
- Heading 3 - #heading-3
- Heading 4 - #heading-4
- Heading 5 - #heading-5
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 2
+ # Heading 3
+ ### Heading 4
+ ### Heading 5
+ """
+ )
+ expected = dedent(
+ """
+ Heading 1 - #heading-1
+ Heading 2 - #heading-2
+ Heading 3 - #heading-3
+ Heading 4 - #heading-4
+ Heading 5 - #heading-5
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 2)
def test_entityref(self):
- md = dedent("""
- # Heading & 1
- ## Heading > 2
- ### Heading < 3
- """)
- expected = dedent("""
- Heading & 1 - #heading-1
- Heading > 2 - #heading-2
- Heading < 3 - #heading-3
- """)
+ md = dedent(
+ """
+ # Heading & 1
+ ## Heading > 2
+ ### Heading < 3
+ """
+ )
+ expected = dedent(
+ """
+ Heading & 1 - #heading-1
+ Heading > 2 - #heading-2
+ Heading < 3 - #heading-3
+ """
+ )
toc = get_toc(get_markdown_toc(md))
self.assertEqual(str(toc).strip(), expected)
self.assertEqual(len(toc), 1)
@@ -147,13 +178,15 @@ class TableOfContentsTests(unittest.TestCase):
self.assertEqual(len(toc), 1)
def test_level(self):
- md = dedent("""
- # Heading 1
- ## Heading 1.1
- ### Heading 1.1.1
- ### Heading 1.1.2
- ## Heading 1.2
- """)
+ md = dedent(
+ """
+ # Heading 1
+ ## Heading 1.1
+ ### Heading 1.1.1
+ ### Heading 1.1.2
+ ## Heading 1.2
+ """
+ )
toc = get_toc(get_markdown_toc(md))
def get_level_sequence(items):
diff --git a/mkdocs/tests/theme_tests.py b/mkdocs/tests/theme_tests.py
index 296540af..b4c71553 100644
--- a/mkdocs/tests/theme_tests.py
+++ b/mkdocs/tests/theme_tests.py
@@ -14,31 +14,33 @@ theme_dir = os.path.abspath(os.path.join(mkdocs_dir, 'themes'))
def get_vars(theme):
- """ Return dict of theme vars. """
+ """Return dict of theme vars."""
return {k: theme[k] for k in iter(theme)}
class ThemeTests(unittest.TestCase):
-
def test_simple_theme(self):
theme = Theme(name='mkdocs')
self.assertEqual(
theme.dirs,
- [os.path.join(theme_dir, 'mkdocs'), mkdocs_templates_dir]
+ [os.path.join(theme_dir, 'mkdocs'), mkdocs_templates_dir],
)
self.assertEqual(theme.static_templates, {'404.html', 'sitemap.xml'})
- self.assertEqual(get_vars(theme), {
- 'locale': parse_locale('en'),
- 'include_search_page': False,
- 'search_index_only': False,
- 'analytics': {'gtag': None},
- 'highlightjs': True,
- 'hljs_style': 'github',
- 'hljs_languages': [],
- 'navigation_depth': 2,
- 'nav_style': 'primary',
- 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83}
- })
+ self.assertEqual(
+ get_vars(theme),
+ {
+ 'locale': parse_locale('en'),
+ 'include_search_page': False,
+ 'search_index_only': False,
+ 'analytics': {'gtag': None},
+ 'highlightjs': True,
+ 'hljs_style': 'github',
+ 'hljs_languages': [],
+ 'navigation_depth': 2,
+ 'nav_style': 'primary',
+ 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83},
+ },
+ )
def test_custom_dir(self):
custom = tempfile.mkdtemp()
@@ -48,8 +50,8 @@ class ThemeTests(unittest.TestCase):
[
custom,
os.path.join(theme_dir, 'mkdocs'),
- mkdocs_templates_dir
- ]
+ mkdocs_templates_dir,
+ ],
)
def test_custom_dir_only(self):
@@ -57,14 +59,14 @@ class ThemeTests(unittest.TestCase):
theme = Theme(name=None, custom_dir=custom)
self.assertEqual(
theme.dirs,
- [custom, mkdocs_templates_dir]
+ [custom, mkdocs_templates_dir],
)
def static_templates(self):
theme = Theme(name='mkdocs', static_templates='foo.html')
self.assertEqual(
theme.static_templates,
- {'404.html', 'sitemap.xml', 'foo.html'}
+ {'404.html', 'sitemap.xml', 'foo.html'},
)
def test_vars(self):
@@ -85,10 +87,12 @@ class ThemeTests(unittest.TestCase):
self.assertEqual(theme.static_templates, {'sitemap.xml'})
def test_inherited_theme(self):
- m = mock.Mock(side_effect=[
- {'extends': 'readthedocs', 'static_templates': ['child.html']},
- {'static_templates': ['parent.html']}
- ])
+ m = mock.Mock(
+ side_effect=[
+ {'extends': 'readthedocs', 'static_templates': ['child.html']},
+ {'static_templates': ['parent.html']},
+ ]
+ )
with mock.patch('mkdocs.utils.yaml_load', m) as m:
theme = Theme(name='mkdocs')
self.assertEqual(m.call_count, 2)
@@ -97,9 +101,7 @@ class ThemeTests(unittest.TestCase):
[
os.path.join(theme_dir, 'mkdocs'),
os.path.join(theme_dir, 'readthedocs'),
- mkdocs_templates_dir
- ]
- )
- self.assertEqual(
- theme.static_templates, {'sitemap.xml', 'child.html', 'parent.html'}
+ mkdocs_templates_dir,
+ ],
)
+ self.assertEqual(theme.static_templates, {'sitemap.xml', 'child.html', 'parent.html'})
diff --git a/mkdocs/tests/utils/babel_stub_tests.py b/mkdocs/tests/utils/babel_stub_tests.py
index 59cb35f0..722d3b32 100644
--- a/mkdocs/tests/utils/babel_stub_tests.py
+++ b/mkdocs/tests/utils/babel_stub_tests.py
@@ -3,7 +3,6 @@ from mkdocs.utils.babel_stub import Locale, UnknownLocaleError
class BabelStubTests(unittest.TestCase):
-
def test_locale_language_only(self):
locale = Locale('es')
self.assertEqual(locale.language, 'es')
diff --git a/mkdocs/tests/utils/utils_tests.py b/mkdocs/tests/utils/utils_tests.py
index 1a79fcf0..0cb8142f 100644
--- a/mkdocs/tests/utils/utils_tests.py
+++ b/mkdocs/tests/utils/utils_tests.py
@@ -45,7 +45,7 @@ class UtilsTests(unittest.TestCase):
'index.markdown': True,
'index.MARKDOWN': False,
'index.txt': False,
- 'indexmd': False
+ 'indexmd': False,
}
for path, expected_result in expected_results.items():
is_markdown = utils.is_markdown_file(path)
@@ -85,7 +85,8 @@ class UtilsTests(unittest.TestCase):
('a', ''): 'a',
('a', '..'): 'a',
('a', 'b'): '../a',
- ('a', 'b/..'): '../a', # The dots are considered a file. Documenting a long-standing bug.
+ # The dots are considered a file. Documenting a long-standing bug:
+ ('a', 'b/..'): '../a',
('a', 'b/../..'): 'a',
('a/..../b', 'a/../b'): '../a/..../b',
('a/я/b', 'a/я/c'): '../b',
@@ -114,55 +115,67 @@ class UtilsTests(unittest.TestCase):
'https://media.cdn.org/jq.js': [
'https://media.cdn.org/jq.js',
'https://media.cdn.org/jq.js',
- 'https://media.cdn.org/jq.js'
+ 'https://media.cdn.org/jq.js',
],
'http://media.cdn.org/jquery.js': [
'http://media.cdn.org/jquery.js',
'http://media.cdn.org/jquery.js',
- 'http://media.cdn.org/jquery.js'
+ 'http://media.cdn.org/jquery.js',
],
'//media.cdn.org/jquery.js': [
'//media.cdn.org/jquery.js',
'//media.cdn.org/jquery.js',
- '//media.cdn.org/jquery.js'
+ '//media.cdn.org/jquery.js',
],
'media.cdn.org/jquery.js': [
'media.cdn.org/jquery.js',
'media.cdn.org/jquery.js',
- '../media.cdn.org/jquery.js'
+ '../media.cdn.org/jquery.js',
],
'local/file/jquery.js': [
'local/file/jquery.js',
'local/file/jquery.js',
- '../local/file/jquery.js'
+ '../local/file/jquery.js',
],
'local\\windows\\file\\jquery.js': [
'local/windows/file/jquery.js',
'local/windows/file/jquery.js',
- '../local/windows/file/jquery.js'
+ '../local/windows/file/jquery.js',
],
'image.png': [
'image.png',
'image.png',
- '../image.png'
+ '../image.png',
],
'style.css?v=20180308c': [
'style.css?v=20180308c',
'style.css?v=20180308c',
- '../style.css?v=20180308c'
+ '../style.css?v=20180308c',
],
'#some_id': [
'#some_id',
'#some_id',
- '#some_id'
- ]
+ '#some_id',
+ ],
}
cfg = load_config(use_directory_urls=False)
pages = [
- Page('Home', File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg),
- Page('About', File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg),
- Page('FooBar', File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg)
+ Page(
+ 'Home',
+ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ cfg,
+ ),
+ Page(
+ 'About',
+ File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ cfg,
+ ),
+ Page(
+ 'FooBar',
+ File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ cfg,
+ ),
]
for i, page in enumerate(pages):
@@ -175,55 +188,67 @@ class UtilsTests(unittest.TestCase):
'https://media.cdn.org/jq.js': [
'https://media.cdn.org/jq.js',
'https://media.cdn.org/jq.js',
- 'https://media.cdn.org/jq.js'
+ 'https://media.cdn.org/jq.js',
],
'http://media.cdn.org/jquery.js': [
'http://media.cdn.org/jquery.js',
'http://media.cdn.org/jquery.js',
- 'http://media.cdn.org/jquery.js'
+ 'http://media.cdn.org/jquery.js',
],
'//media.cdn.org/jquery.js': [
'//media.cdn.org/jquery.js',
'//media.cdn.org/jquery.js',
- '//media.cdn.org/jquery.js'
+ '//media.cdn.org/jquery.js',
],
'media.cdn.org/jquery.js': [
'media.cdn.org/jquery.js',
'../media.cdn.org/jquery.js',
- '../../media.cdn.org/jquery.js'
+ '../../media.cdn.org/jquery.js',
],
'local/file/jquery.js': [
'local/file/jquery.js',
'../local/file/jquery.js',
- '../../local/file/jquery.js'
+ '../../local/file/jquery.js',
],
'local\\windows\\file\\jquery.js': [
'local/windows/file/jquery.js',
'../local/windows/file/jquery.js',
- '../../local/windows/file/jquery.js'
+ '../../local/windows/file/jquery.js',
],
'image.png': [
'image.png',
'../image.png',
- '../../image.png'
+ '../../image.png',
],
'style.css?v=20180308c': [
'style.css?v=20180308c',
'../style.css?v=20180308c',
- '../../style.css?v=20180308c'
+ '../../style.css?v=20180308c',
],
'#some_id': [
'#some_id',
'#some_id',
- '#some_id'
- ]
+ '#some_id',
+ ],
}
cfg = load_config(use_directory_urls=True)
pages = [
- Page('Home', File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg),
- Page('About', File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg),
- Page('FooBar', File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg)
+ Page(
+ 'Home',
+ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ cfg,
+ ),
+ Page(
+ 'About',
+ File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ cfg,
+ ),
+ Page(
+ 'FooBar',
+ File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
+ cfg,
+ ),
]
for i, page in enumerate(pages):
@@ -233,14 +258,12 @@ class UtilsTests(unittest.TestCase):
def test_reduce_list(self):
self.assertEqual(
utils.reduce_list([1, 2, 3, 4, 5, 5, 2, 4, 6, 7, 8]),
- [1, 2, 3, 4, 5, 6, 7, 8]
+ [1, 2, 3, 4, 5, 6, 7, 8],
)
def test_get_themes(self):
- self.assertEqual(
- sorted(utils.get_theme_names()),
- ['mkdocs', 'readthedocs'])
+ self.assertEqual(sorted(utils.get_theme_names()), ['mkdocs', 'readthedocs'])
@mock.patch('importlib_metadata.entry_points', autospec=True)
def test_get_theme_dir(self, mock_iter):
@@ -289,9 +312,7 @@ class UtilsTests(unittest.TestCase):
mock_iter.return_value = [theme1, theme2]
- self.assertEqual(
- sorted(utils.get_theme_names()),
- sorted(['mkdocs2', ]))
+ self.assertEqual(sorted(utils.get_theme_names()), sorted(['mkdocs2']))
@mock.patch('importlib_metadata.entry_points', autospec=True)
def test_get_themes_error(self, mock_iter):
@@ -315,29 +336,37 @@ class UtilsTests(unittest.TestCase):
j = os.path.join
- result = utils.nest_paths([
- 'index.md',
- j('user-guide', 'configuration.md'),
- j('user-guide', 'styling-your-docs.md'),
- j('user-guide', 'writing-your-docs.md'),
- j('about', 'contributing.md'),
- j('about', 'license.md'),
- j('about', 'release-notes.md'),
- ])
+ result = utils.nest_paths(
+ [
+ 'index.md',
+ j('user-guide', 'configuration.md'),
+ j('user-guide', 'styling-your-docs.md'),
+ j('user-guide', 'writing-your-docs.md'),
+ j('about', 'contributing.md'),
+ j('about', 'license.md'),
+ j('about', 'release-notes.md'),
+ ]
+ )
self.assertEqual(
result,
[
'index.md',
- {'User guide': [
- j('user-guide', 'configuration.md'),
- j('user-guide', 'styling-your-docs.md'),
- j('user-guide', 'writing-your-docs.md')]},
- {'About': [
- j('about', 'contributing.md'),
- j('about', 'license.md'),
- j('about', 'release-notes.md')]}
- ]
+ {
+ 'User guide': [
+ j('user-guide', 'configuration.md'),
+ j('user-guide', 'styling-your-docs.md'),
+ j('user-guide', 'writing-your-docs.md'),
+ ]
+ },
+ {
+ 'About': [
+ j('about', 'contributing.md'),
+ j('about', 'license.md'),
+ j('about', 'release-notes.md'),
+ ]
+ },
+ ],
)
def test_unicode_yaml(self):
@@ -383,15 +412,15 @@ class UtilsTests(unittest.TestCase):
'baz': {
'sub1': 'replaced',
'sub2': 2,
- 'sub3': 'new'
+ 'sub3': 'new',
},
'deep1': {
'deep2-1': {
'deep3-1': 'replaced',
- 'deep3-2': 'bar'
+ 'deep3-2': 'bar',
},
- 'deep2-2': 'baz'
- }
+ 'deep2-2': 'baz',
+ },
}
with open(os.path.join(tdir, 'base.yml')) as fd:
result = utils.yaml_load(fd)
@@ -411,8 +440,8 @@ class UtilsTests(unittest.TestCase):
]
dst_paths = [
'foo.txt',
- 'foo/', # ensure src filename is appended
- 'foo/bar/baz.txt' # ensure missing dirs are created
+ 'foo/', # ensure src filename is appended
+ 'foo/bar/baz.txt', # ensure missing dirs are created
]
expected = [
'foo.txt',
@@ -459,7 +488,9 @@ class UtilsTests(unittest.TestCase):
os.chmod(src, stat.S_IRUSR)
utils.copy_file(src, dst_dir)
self.assertTrue(os.path.isfile(os.path.join(dst_dir, expected[i])))
- self.assertNotEqual(os.stat(src).st_mode, os.stat(os.path.join(dst_dir, expected[i])).st_mode)
+ self.assertNotEqual(
+ os.stat(src).st_mode, os.stat(os.path.join(dst_dir, expected[i])).st_mode
+ )
# While src was read-only, dst must remain writable
self.assertTrue(os.access(os.path.join(dst_dir, expected[i]), os.W_OK))
finally:
@@ -492,9 +523,9 @@ class UtilsTests(unittest.TestCase):
'title': 'Foo Bar',
'date': '2018-07-10',
'summary': 'Line one Line two',
- 'tags': 'foo bar'
- }
- )
+ 'tags': 'foo bar',
+ },
+ ),
)
def test_mm_meta_data_blank_first_line(self):
@@ -524,9 +555,9 @@ class UtilsTests(unittest.TestCase):
'Title': 'Foo Bar',
'Date': datetime.date(2018, 7, 10),
'Summary': 'Line one Line two',
- 'Tags': ['foo', 'bar']
- }
- )
+ 'Tags': ['foo', 'bar'],
+ },
+ ),
)
def test_yaml_meta_data_not_dict(self):
diff --git a/mkdocs/theme.py b/mkdocs/theme.py
index 04ae3c4d..a83ac27a 100644
--- a/mkdocs/theme.py
+++ b/mkdocs/theme.py
@@ -56,8 +56,11 @@ class Theme:
def __repr__(self):
return "{}(name='{}', dirs={}, static_templates={}, {})".format(
- self.__class__.__name__, self.name, self.dirs, list(self.static_templates),
- ', '.join(f'{k}={v!r}' for k, v in self._vars.items())
+ self.__class__.__name__,
+ self.name,
+ self.dirs,
+ list(self.static_templates),
+ ', '.join(f'{k}={v!r}' for k, v in self._vars.items()),
)
def __getitem__(self, key):
@@ -73,7 +76,7 @@ class Theme:
return iter(self._vars)
def _load_theme_config(self, name):
- """ Recursively load theme and any parent themes. """
+ """Recursively load theme and any parent themes."""
theme_dir = utils.get_theme_dir(name)
self.dirs.append(theme_dir)
@@ -107,7 +110,7 @@ class Theme:
self._vars.update(theme_config)
def get_env(self):
- """ Return a Jinja environment for the theme. """
+ """Return a Jinja environment for the theme."""
loader = jinja2.FileSystemLoader(self.dirs)
# No autoreload because editing a template in the middle of a build is not useful.
diff --git a/mkdocs/utils/__init__.py b/mkdocs/utils/__init__.py
index 4006d1b7..17e52d19 100644
--- a/mkdocs/utils/__init__.py
+++ b/mkdocs/utils/__init__.py
@@ -30,12 +30,12 @@ markdown_extensions = (
'.mdown',
'.mkdn',
'.mkd',
- '.md'
+ '.md',
)
def get_yaml_loader(loader=yaml.Loader):
- """ Wrap PyYaml's loader so we can extend it to suit our needs. """
+ """Wrap PyYaml's loader so we can extend it to suit our needs."""
class Loader(loader):
"""
@@ -51,7 +51,7 @@ def get_yaml_loader(loader=yaml.Loader):
def yaml_load(source, loader=None):
- """ Return dict of source YAML file using loader, recursively deep merging inherited parent. """
+ """Return dict of source YAML file using loader, recursively deep merging inherited parent."""
Loader = loader or get_yaml_loader()
result = yaml.load(source, Loader=Loader)
if result is not None and 'INHERIT' in result:
@@ -59,7 +59,8 @@ def yaml_load(source, loader=None):
abspath = os.path.normpath(os.path.join(os.path.dirname(source.name), relpath))
if not os.path.exists(abspath):
raise exceptions.ConfigurationError(
- f"Inherited config file '{relpath}' does not exist at '{abspath}'.")
+ f"Inherited config file '{relpath}' does not exist at '{abspath}'."
+ )
log.debug(f"Loading inherited configuration file: {abspath}")
with open(abspath, 'rb') as fd:
parent = yaml_load(fd, Loader)
@@ -116,7 +117,7 @@ def get_build_date():
def reduce_list(data_set):
- """ Reduce duplicate items in a list and preserve order """
+ """Reduce duplicate items in a list and preserve order"""
return list(dict.fromkeys(data_set))
@@ -181,7 +182,7 @@ def get_url_path(path, use_directory_urls=True):
path = get_html_path(path)
url = '/' + path.replace(os.path.sep, '/')
if use_directory_urls:
- return url[:-len('index.html')]
+ return url[: -len('index.html')]
return url
@@ -255,7 +256,7 @@ def get_relative_url(url, other):
def normalize_url(path, page=None, base=''):
- """ Return a URL relative to the given page or using the base. """
+ """Return a URL relative to the given page or using the base."""
path, is_abs = _get_norm_url(path)
if is_abs:
return path
@@ -288,14 +289,14 @@ def path_to_url(path):
def get_theme_dir(name):
- """ Return the directory of an installed theme by name. """
+ """Return the directory of an installed theme by name."""
theme = get_themes()[name]
return os.path.dirname(os.path.abspath(theme.load().__file__))
def get_themes():
- """ Return a dict of all installed themes as {name: EntryPoint}. """
+ """Return a dict of all installed themes as {name: EntryPoint}."""
themes = {}
eps = set(importlib_metadata.entry_points(group='mkdocs.themes'))
@@ -326,7 +327,7 @@ def get_theme_names():
def dirname_to_title(dirname):
- """ Return a page tile obtained from a directory name. """
+ """Return a page tile obtained from a directory name."""
title = dirname
title = title.replace('-', ' ').replace('_', ' ')
# Capitalize if the dirname was all lowercase, otherwise leave it as-is.
@@ -402,7 +403,7 @@ def nest_paths(paths):
class CountHandler(logging.NullHandler):
- """ Counts all logged messages >= level. """
+ """Counts all logged messages >= level."""
def __init__(self, **kwargs):
self.counts = defaultdict(int)
diff --git a/mkdocs/utils/filters.py b/mkdocs/utils/filters.py
index c3049db9..d959784c 100644
--- a/mkdocs/utils/filters.py
+++ b/mkdocs/utils/filters.py
@@ -8,5 +8,5 @@ from mkdocs.utils import normalize_url
@contextfilter
def url_filter(context, value):
- """ A Template filter to normalize URLs. """
+ """A Template filter to normalize URLs."""
return normalize_url(value, page=context['page'], base=context['base_url'])
diff --git a/mkdocs/utils/meta.py b/mkdocs/utils/meta.py
index d208589d..714fb184 100644
--- a/mkdocs/utils/meta.py
+++ b/mkdocs/utils/meta.py
@@ -36,6 +36,7 @@ Extracts, parses and transforms MultiMarkdown style data from documents.
import re
import yaml
+
try:
from yaml import CSafeLoader as SafeLoader
except ImportError: # pragma: no cover
@@ -64,7 +65,7 @@ def get_data(doc):
try:
data = yaml.load(m.group(1), SafeLoader)
if isinstance(data, dict):
- doc = doc[m.end():].lstrip('\n')
+ doc = doc[m.end() :].lstrip('\n')
else:
data = {}
except Exception:
diff --git a/requirements/project-min.txt b/requirements/project-min.txt
index 00719753..7dc9825c 100644
--- a/requirements/project-min.txt
+++ b/requirements/project-min.txt
@@ -1,5 +1,5 @@
babel==2.9.0
-click==3.3
+click==8.0
Jinja2==2.10.2
markupsafe<=2.0.1
Markdown==3.3
diff --git a/requirements/project.txt b/requirements/project.txt
index 2e1be0c8..bcf8e8d3 100644
--- a/requirements/project.txt
+++ b/requirements/project.txt
@@ -1,5 +1,5 @@
babel>=2.9.0
-click>=7.0
+click>=8.0
Jinja2>=2.10.2
Markdown>=3.3,<3.4
PyYAML>=5.2
diff --git a/requirements/test.txt b/requirements/test.txt
index 9c4e8691..d38598f9 100644
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -1,2 +1,3 @@
coverage
+black
flake8
diff --git a/setup.cfg b/setup.cfg
index 1e6ff981..41194d3a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,10 @@
[metadata]
license_file = LICENSE
+[flake8]
+max-line-length = 119
+extend-ignore = E203
+
[compile_catalog]
statistics = True
domain = messages
diff --git a/tox.ini b/tox.ini
index e36af039..62799a82 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
[tox]
envlist =
py{36,37,38,39,310,py3}-{unittests,min-req,integration,integration-no-babel},
- flake8, markdown-lint, linkchecker, jshint, csslint, nobabel, codespell
+ black, flake8, markdown-lint, linkchecker, jshint, csslint, nobabel, codespell
[testenv]
passenv = LANG
@@ -16,9 +16,13 @@ commands=
py{36,37,38,39,310,py3}-unittests: {envbindir}/coverage report --show-missing
py{36,37,38,39,310,py3}-integration: {envpython} -m mkdocs.tests.integration --output={envtmpdir}/builds
+[testenv:black]
+deps=-rrequirements/test.txt
+commands={envbindir}/black -l100 -tpy36 --skip-string-normalization mkdocs
+
[testenv:flake8]
deps=-rrequirements/test.txt
-commands={envbindir}/flake8 mkdocs --max-line-length=119
+commands={envbindir}/flake8 mkdocs
[testenv:markdown-lint]
whitelist_externals=