Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sphinx/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ def __init__(
else:
self.confdir = _StrPath(confdir).resolve()
self.config = Config.read(self.confdir, confoverrides or {}, self.tags)
self.config._verbosity = -1 if self.quiet else self.verbosity

# set up translation infrastructure
self._init_i18n()
Expand Down
3 changes: 2 additions & 1 deletion sphinx/builders/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ def __init__(self, app: Sphinx, env: BuildEnvironment) -> None:

@property
def app(self) -> Sphinx:
cls_module = self.__class__.__module__
cls_name = self.__class__.__qualname__
_deprecation_warning(__name__, f'{cls_name}.app', remove=(10, 0))
_deprecation_warning(cls_module, f'{cls_name}.app', remove=(10, 0))
return self._app

@property
Expand Down
2 changes: 1 addition & 1 deletion sphinx/builders/_epub_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ def copy_image_files_pil(self) -> None:
__('copying images... '),
'brown',
len(self.images),
self.app.verbosity,
self.config.verbosity,
):
dest = self.images[src]
try:
Expand Down
7 changes: 6 additions & 1 deletion sphinx/builders/changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ class ChangesBuilder(Builder):

def init(self) -> None:
self.create_template_bridge()
theme_factory = HTMLThemeFactory(self.app)
theme_factory = HTMLThemeFactory(
confdir=self.confdir,
app=self._app,
config=self.config,
registry=self.env._registry,
)
self.theme = theme_factory.create('default')
self.templates.init(self, self.theme)

Expand Down
14 changes: 9 additions & 5 deletions sphinx/builders/gettext.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class I18nBuilder(Builder):
def init(self) -> None:
super().init()
self.env.set_versioning_method(self.versioning_method, self.config.gettext_uuid)
self.tags = self.app.tags = I18nTags()
self.tags = self._app.tags = I18nTags()
self.catalogs: defaultdict[str, Catalog] = defaultdict(Catalog)

def get_target_uri(self, docname: str, typ: str | None = None) -> str:
Expand Down Expand Up @@ -251,7 +251,7 @@ def init(self) -> None:
def _collect_templates(self) -> set[str]:
template_files = set()
for template_path in self.config.templates_path:
tmpl_abs_path = self.app.srcdir / template_path
tmpl_abs_path = self.srcdir / template_path
for dirpath, _dirs, files in walk(tmpl_abs_path):
for fn in files:
if fn.endswith('.html'):
Expand All @@ -268,7 +268,11 @@ def _extract_from_template(self) -> None:
extract_translations = self.templates.environment.extract_translations

for template in status_iterator(
files, __('reading templates... '), 'purple', len(files), self.app.verbosity
files,
__('reading templates... '),
'purple',
len(files),
self.config.verbosity,
):
try:
with codecs.open(template, encoding='utf-8') as f:
Expand Down Expand Up @@ -307,15 +311,15 @@ def finish(self) -> None:
__('writing message catalogs... '),
'darkgreen',
len(self.catalogs),
self.app.verbosity,
self.config.verbosity,
operator.itemgetter(0),
):
# noop if config.gettext_compact is set
ensuredir(self.outdir / os.path.dirname(textdomain))

context['messages'] = list(catalog)
template_path = [
self.app.srcdir / rel_path for rel_path in self.config.templates_path
self.srcdir / rel_path for rel_path in self.config.templates_path
]
renderer = GettextRenderer(template_path, outdir=self.outdir)
content = renderer.render('message.pot.jinja', context)
Expand Down
25 changes: 16 additions & 9 deletions sphinx/builders/html/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,12 @@ def get_theme_config(self) -> tuple[str, dict[str, str | int | bool]]:
return self.config.html_theme, self.config.html_theme_options

def init_templates(self) -> None:
theme_factory = HTMLThemeFactory(self.app)
theme_factory = HTMLThemeFactory(
confdir=self.confdir,
app=self._app,
config=self.config,
registry=self.env._registry,
)
theme_name, theme_options = self.get_theme_config()
self.theme = theme_factory.create(theme_name)
self.theme_options = theme_options
Expand All @@ -255,11 +260,6 @@ def init_highlighter(self) -> None:
self.dark_highlighter: PygmentsBridge | None
if dark_style is not None:
self.dark_highlighter = PygmentsBridge('html', dark_style)
self.app.add_css_file(
'pygments_dark.css',
media='(prefers-color-scheme: dark)',
id='pygments_dark_css',
)
else:
self.dark_highlighter = None

Expand All @@ -273,6 +273,13 @@ def css_files(self) -> list[_CascadingStyleSheet]:
def init_css_files(self) -> None:
self._css_files = []
self.add_css_file('pygments.css', priority=200)
if self.dark_highlighter is not None:
self.add_css_file(
'pygments_dark.css',
priority=200,
media='(prefers-color-scheme: dark)',
id='pygments_dark_css',
)

for filename in self._get_style_filenames():
self.add_css_file(filename, priority=200)
Expand Down Expand Up @@ -780,7 +787,7 @@ def copy_image_files(self) -> None:
__('copying images... '),
'brown',
len(self.images),
self.app.verbosity,
self.config.verbosity,
stringify_func=stringify_func,
):
dest = self.images[src]
Expand All @@ -807,7 +814,7 @@ def to_relpath(f: str) -> str:
__('copying downloadable files... '),
'brown',
len(self.env.dlfiles),
self.app.verbosity,
self.config.verbosity,
stringify_func=to_relpath,
):
try:
Expand Down Expand Up @@ -1128,7 +1135,7 @@ def hasdoc(name: str) -> bool:
# 'blah.html' should have content_root = './' not ''.
ctx['content_root'] = (f'..{SEP}' * default_baseuri.count(SEP)) or f'.{SEP}'

outdir = self.app.outdir
outdir = self.outdir

def css_tag(css: _CascadingStyleSheet) -> str:
attrs = [
Expand Down
4 changes: 2 additions & 2 deletions sphinx/builders/latex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def init(self) -> None:
self.context: dict[str, Any] = {}
self.docnames: Iterable[str] = {}
self.document_data: list[tuple[str, str, str, str, str, bool]] = []
self.themes = ThemeFactory(self.app)
self.themes = ThemeFactory(srcdir=self.srcdir, config=self.config)
texescape.init()

self.init_context()
Expand Down Expand Up @@ -481,7 +481,7 @@ def copy_image_files(self) -> None:
__('copying images... '),
'brown',
len(self.images),
self.app.verbosity,
self.config.verbosity,
stringify_func=stringify_func,
):
dest = self.images[src]
Expand Down
9 changes: 4 additions & 5 deletions sphinx/builders/latex/theming.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
if TYPE_CHECKING:
from pathlib import Path

from sphinx.application import Sphinx
from sphinx.config import Config

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -102,11 +101,11 @@ def __init__(self, name: str, filename: Path) -> None:
class ThemeFactory:
"""A factory class for LaTeX Themes."""

def __init__(self, app: Sphinx) -> None:
def __init__(self, *, srcdir: Path, config: Config) -> None:
self.themes: dict[str, Theme] = {}
self.theme_paths = [app.srcdir / p for p in app.config.latex_theme_path]
self.config = app.config
self.load_builtin_themes(app.config)
self.theme_paths = [srcdir / p for p in config.latex_theme_path]
self.config = config
self.load_builtin_themes(config)

def load_builtin_themes(self, config: Config) -> None:
"""Load built-in themes."""
Expand Down
6 changes: 3 additions & 3 deletions sphinx/builders/linkcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def finish(self) -> None:
self.process_result(result)

if self.broken_hyperlinks or self.timed_out_hyperlinks:
self.app.statuscode = 1
self._app.statuscode = 1

def process_result(self, result: CheckResult) -> None:
filename = self.env.doc2path(result.docname, False)
Expand Down Expand Up @@ -130,7 +130,7 @@ def process_result(self, result: CheckResult) -> None:
case _Status.WORKING:
logger.info(darkgreen('ok ') + f'{res_uri}{result.message}') # NoQA: G003
case _Status.TIMEOUT:
if self.app.quiet:
if self.config.verbosity < 0:
msg = 'timeout ' + f'{res_uri}{result.message}'
logger.warning(msg, location=(result.docname, result.lineno))
else:
Expand All @@ -145,7 +145,7 @@ def process_result(self, result: CheckResult) -> None:
)
self.timed_out_hyperlinks += 1
case _Status.BROKEN:
if self.app.quiet:
if self.config.verbosity < 0:
logger.warning(
__('broken link: %s (%s)'),
res_uri,
Expand Down
2 changes: 1 addition & 1 deletion sphinx/builders/texinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def copy_image_files(self, targetname: str) -> None:
__('copying images... '),
'brown',
len(self.images),
self.app.verbosity,
self.config.verbosity,
stringify_func=stringify_func,
):
dest = self.images[src]
Expand Down
6 changes: 6 additions & 0 deletions sphinx/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ def __init__(
raw_config['extensions'] = extensions
self.extensions: list[str] = raw_config.get('extensions', [])

self._verbosity: int = 0 # updated in Sphinx.__init__()

@property
def values(self) -> dict[str, _Opt]:
return self._options
Expand All @@ -341,6 +343,10 @@ def values(self) -> dict[str, _Opt]:
def overrides(self) -> dict[str, Any]:
return self._overrides

@property
def verbosity(self) -> int:
return self._verbosity

@classmethod
def read(
cls: type[Config],
Expand Down
8 changes: 4 additions & 4 deletions sphinx/ext/coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def write_c_coverage(self) -> None:
for typ, name in sorted(undoc):
op.write(f' * {name:<50} [{typ:>9}]\n')
if self.config.coverage_show_missing_items:
if self.app.quiet:
if self.config.verbosity < 0:
logger.warning(
__('undocumented c api: %s [%s] in file %s'),
name,
Expand Down Expand Up @@ -446,7 +446,7 @@ def write_py_coverage(self) -> None:
op.write('Functions:\n')
op.writelines(f' * {x}\n' for x in undoc['funcs'])
if self.config.coverage_show_missing_items:
if self.app.quiet:
if self.config.verbosity < 0:
for func in undoc['funcs']:
logger.warning(
__('undocumented python function: %s :: %s'),
Expand All @@ -468,7 +468,7 @@ def write_py_coverage(self) -> None:
if not methods:
op.write(f' * {class_name}\n')
if self.config.coverage_show_missing_items:
if self.app.quiet:
if self.config.verbosity < 0:
logger.warning(
__('undocumented python class: %s :: %s'),
name,
Expand All @@ -485,7 +485,7 @@ def write_py_coverage(self) -> None:
op.write(f' * {class_name} -- missing methods:\n\n')
op.writelines(f' - {x}\n' for x in methods)
if self.config.coverage_show_missing_items:
if self.app.quiet:
if self.config.verbosity < 0:
for meth in methods:
logger.warning(
__(
Expand Down
4 changes: 2 additions & 2 deletions sphinx/ext/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ def _out(self, text: str) -> None:
self.outfile.write(text)

def _warn_out(self, text: str) -> None:
if self.app.quiet:
if self.config.verbosity < 0:
logger.warning(text)
else:
logger.info(text, nonl=True)
Expand All @@ -360,7 +360,7 @@ def s(v: int) -> str:

header = 'Doctest summary'
if self.total_failures or self.setup_failures or self.cleanup_failures:
self.app.statuscode = 1
self._app.statuscode = 1
if self.config.doctest_fail_fast:
header = f'{header} (exiting after first failed test)'
underline = '=' * len(header)
Expand Down
20 changes: 15 additions & 5 deletions sphinx/theming.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
from typing import Any, Required, TypedDict

from sphinx.application import Sphinx
from sphinx.config import Config
from sphinx.registry import SphinxComponentRegistry

class _ThemeToml(TypedDict, total=False):
theme: Required[_ThemeTomlTheme]
Expand Down Expand Up @@ -148,13 +150,21 @@ def _cleanup(self) -> None:
class HTMLThemeFactory:
"""A factory class for HTML Themes."""

def __init__(self, app: Sphinx) -> None:
def __init__(
self,
*,
confdir: Path,
app: Sphinx,
config: Config,
registry: SphinxComponentRegistry,
) -> None:
self._app = app
self._themes = app.registry.html_themes
self._confdir = confdir
self._themes = registry.html_themes
self._entry_point_themes: dict[str, Callable[[], None]] = {}
self._load_builtin_themes()
if getattr(app.config, 'html_theme_path', None):
self._load_additional_themes(app.config.html_theme_path)
if html_theme_path := getattr(config, 'html_theme_path', None):
self._load_additional_themes(html_theme_path)
self._load_entry_point_themes()

def _load_builtin_themes(self) -> None:
Expand All @@ -166,7 +176,7 @@ def _load_builtin_themes(self) -> None:
def _load_additional_themes(self, theme_paths: list[str]) -> None:
"""Load additional themes placed at specified directories."""
for theme_path in theme_paths:
abs_theme_path = (self._app.confdir / theme_path).resolve()
abs_theme_path = (self._confdir / theme_path).resolve()
themes = self._find_themes(abs_theme_path)
for name, theme in themes.items():
self._themes[name] = _StrPath(theme)
Expand Down
2 changes: 1 addition & 1 deletion sphinx/transforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def app(self) -> Sphinx:
cls_module = self.__class__.__module__
cls_name = self.__class__.__qualname__
_deprecation_warning(cls_module, f'{cls_name}.app', remove=(10, 0))
return self.env.app
return self.env._app

@property
def env(self) -> BuildEnvironment:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_extensions/test_ext_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def test_show_missing_items(app: SphinxTestApp) -> None:
'coverage', testroot='root', confoverrides={'coverage_show_missing_items': True}
)
def test_show_missing_items_quiet(app: SphinxTestApp) -> None:
app.quiet = True
app.config._verbosity = -1 # mimics status=None / app.quiet = True
app.build(force_all=True)

assert (
Expand Down
8 changes: 4 additions & 4 deletions tests/test_theming/test_theming.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ def test_dark_style(app, monkeypatch):
app.build()
assert (app.outdir / '_static' / 'pygments_dark.css').exists()

css_file, properties = app.registry.css_files[0]
assert css_file == 'pygments_dark.css'
assert 'media' in properties
assert properties['media'] == '(prefers-color-scheme: dark)'
css_file = app.builder._css_files[1]
assert css_file.filename == '_static/pygments_dark.css'
assert 'media' in css_file.attributes
assert css_file.attributes['media'] == '(prefers-color-scheme: dark)'

assert sorted(f.filename for f in app.builder._css_files) == [
'_static/classic.css',
Expand Down
Loading