Use loggers

This commit is contained in:
Takeshi KOMIYA 2016-12-25 01:03:06 +09:00
parent 6bf201533a
commit e755a8c004
43 changed files with 368 additions and 364 deletions

View File

@ -233,9 +233,9 @@ class Sphinx(object):
if self.config.needs_extensions:
for extname, needs_ver in self.config.needs_extensions.items():
if extname not in self._extensions:
self.warn('needs_extensions config value specifies a '
logger.warning('needs_extensions config value specifies a '
'version requirement for extension %s, but it is '
'not loaded' % extname)
'not loaded', extname)
continue
has_ver = self._extension_metadata[extname]['version']
if has_ver == 'unknown version' or needs_ver > has_ver:
@ -246,7 +246,7 @@ class Sphinx(object):
# check primary_domain if requested
if self.config.primary_domain and self.config.primary_domain not in self.domains:
self.warn('primary_domain %r not found, ignored.' % self.config.primary_domain)
logger.warning('primary_domain %r not found, ignored.', self.config.primary_domain)
# set up translation infrastructure
self._init_i18n()

View File

@ -161,9 +161,8 @@ class Builder(object):
if candidate:
break
else:
self.warn(
'no matching candidate for image URI %r' % node['uri'],
'%s:%s' % (node.source, getattr(node, 'line', '')))
logger.warn_node('no matching candidate for image URI %r' % node['uri'],
node)
continue
node['uri'] = candidate
else:
@ -246,13 +245,13 @@ class Builder(object):
for filename in filenames:
filename = path.normpath(path.abspath(filename))
if not filename.startswith(self.srcdir):
self.warn('file %r given on command line is not under the '
'source directory, ignoring' % filename)
logger.warning('file %r given on command line is not under the '
'source directory, ignoring', filename)
continue
if not (path.isfile(filename) or
any(path.isfile(filename + suffix) for suffix in suffixes)):
self.warn('file %r given on command line does not exist, '
'ignoring' % filename)
logger.warning('file %r given on command line does not exist, '
'ignoring', filename)
continue
filename = filename[dirlen:]
for suffix in suffixes:
@ -297,7 +296,7 @@ class Builder(object):
updated_docnames.add(docname)
outdated = len(updated_docnames) - doccount
if outdated:
logger.info('%d found' % outdated)
logger.info('%d found', outdated)
else:
logger.info('none found')
@ -330,8 +329,8 @@ class Builder(object):
for extname, md in self.app._extension_metadata.items():
par_ok = md.get('parallel_write_safe', True)
if not par_ok:
self.app.warn('the %s extension is not safe for parallel '
'writing, doing serial write' % extname)
logger.warning('the %s extension is not safe for parallel '
'writing, doing serial write', extname)
self.parallel_ok = False
break
@ -374,12 +373,10 @@ class Builder(object):
self.prepare_writing(docnames)
logger.info('done')
warnings = [] # type: List[Tuple[Tuple, Dict]]
if self.parallel_ok:
# number of subprocesses is parallel-1 because the main process
# is busy loading doctrees and doing write_doc_serialized()
warnings = []
self._write_parallel(sorted(docnames), warnings,
self._write_parallel(sorted(docnames),
nproc=self.app.parallel - 1)
else:
self._write_serial(sorted(docnames))
@ -393,21 +390,12 @@ class Builder(object):
self.write_doc_serialized(docname, doctree)
self.write_doc(docname, doctree)
def _write_parallel(self, docnames, warnings, nproc):
# type: (Iterable[unicode], List[Tuple[Tuple, Dict]], int) -> None
def _write_parallel(self, docnames, nproc):
# type: (Iterable[unicode], int) -> None
def write_process(docs):
# type: (List[Tuple[unicode, nodes.Node]]) -> List[Tuple[Tuple, Dict]]
local_warnings = []
def warnfunc(*args, **kwargs):
local_warnings.append((args, kwargs))
self.env.set_warnfunc(warnfunc)
# type: (List[Tuple[unicode, nodes.Node]]) -> None
for docname, doctree in docs:
self.write_doc(docname, doctree)
return local_warnings
def add_warnings(docs, wlist):
warnings.extend(wlist)
# warm up caches/compile templates using the first document
firstname, docnames = docnames[0], docnames[1:] # type: ignore
@ -425,15 +413,12 @@ class Builder(object):
doctree = self.env.get_and_resolve_doctree(docname, self)
self.write_doc_serialized(docname, doctree)
arg.append((docname, doctree))
tasks.add_task(write_process, arg, add_warnings)
tasks.add_task(write_process, arg)
# make sure all threads have finished
logger.info(bold('waiting for workers...'))
tasks.join()
for warning, kwargs in warnings:
self.warn(*warning, **kwargs)
def prepare_writing(self, docnames):
# type: (Set[unicode]) -> None
"""A place where you can add logic before :meth:`write_doc` is run"""

View File

@ -184,9 +184,8 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
logger.info('done')
except Exception as err:
self.warn('cannot copy icon file %r: %s' %
(path.join(self.srcdir, self.config.applehelp_icon),
err))
logger.warning('cannot copy icon file %r: %s',
path.join(self.srcdir, self.config.applehelp_icon), err)
del info_plist['HPDBookIconPath']
# Build the access page
@ -223,8 +222,8 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
if self.config.applehelp_disable_external_tools:
logger.info('skipping')
self.warn('you will need to index this help book with:\n %s'
% (' '.join([pipes.quote(arg) for arg in args])))
logger.warning('you will need to index this help book with:\n %s',
' '.join([pipes.quote(arg) for arg in args]))
else:
try:
p = subprocess.Popen(args,
@ -256,9 +255,8 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
if self.config.applehelp_disable_external_tools:
logger.info('skipping')
self.warn('you will need to sign this help book with:\n %s'
% (' '.join([pipes.quote(arg) for arg in args])))
logger.warning('you will need to sign this help book with:\n %s',
' '.join([pipes.quote(arg) for arg in args]))
else:
try:
p = subprocess.Popen(args,

View File

@ -136,7 +136,7 @@ class ChangesBuilder(Builder):
try:
lines = f.readlines()
except UnicodeDecodeError:
self.warn('could not read %r for changelog creation' % docname)
logger.warning('could not read %r for changelog creation', docname)
continue
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
ensuredir(path.dirname(targetfn))

View File

@ -477,14 +477,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
img = Image.open(path.join(self.srcdir, src))
except IOError:
if not self.is_vector_graphics(src):
self.warn('cannot read image file %r: copying it instead' %
(path.join(self.srcdir, src), ))
logger.warning('cannot read image file %r: copying it instead',
path.join(self.srcdir, src))
try:
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, self.imagedir, dest))
except (IOError, OSError) as err:
self.warn('cannot copy image file %r: %s' %
(path.join(self.srcdir, src), err))
logger.warning('cannot copy image file %r: %s',
path.join(self.srcdir, src), err)
continue
if self.config.epub_fix_images:
if img.mode in ('P',):
@ -499,8 +499,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
try:
img.save(path.join(self.outdir, self.imagedir, dest))
except (IOError, OSError) as err:
self.warn('cannot write image file %r: %s' %
(path.join(self.srcdir, src), err))
logger.warning('cannot write image file %r: %s',
path.join(self.srcdir, src), err)
def copy_image_files(self):
# type: () -> None
@ -510,7 +510,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
if self.images:
if self.config.epub_fix_images or self.config.epub_max_image_width:
if not Image:
self.warn('PIL not found - copying image files')
logger.warning('PIL not found - copying image files')
super(EpubBuilder, self).copy_image_files()
else:
self.copy_image_files_pil()
@ -551,14 +551,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
def build_mimetype(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file mimetype."""
logger.info('writing %s file...' % outname)
logger.info('writing %s file...', outname)
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore
f.write(self.mimetype_template)
def build_container(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file META-INF/cointainer.xml."""
logger.info('writing %s file...' % outname)
logger.info('writing %s file...', outname)
fn = path.join(outdir, outname)
try:
os.mkdir(path.dirname(fn))
@ -593,7 +593,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""Write the metainfo file content.opf It contains bibliographic data,
a file list and the spine (the reading order).
"""
logger.info('writing %s file...' % outname)
logger.info('writing %s file...', outname)
# files
if not outdir.endswith(os.sep):
@ -618,7 +618,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
# we always have JS and potentially OpenSearch files, don't
# always warn about them
if ext not in ('.js', '.xml'):
self.warn('unknown mimetype for %s, ignoring' % filename,
logger.warning('unknown mimetype for %s, ignoring', filename,
type='epub', subtype='unknown_project_files')
continue
filename = filename.replace(os.sep, '/')
@ -804,7 +804,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
def build_toc(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file toc.ncx."""
logger.info('writing %s file...' % outname)
logger.info('writing %s file...', outname)
if self.config.epub_tocscope == 'default':
doctree = self.env.get_and_resolve_doctree(self.config.master_doc,
@ -828,7 +828,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
It is a zip file with the mimetype file stored uncompressed as the first
entry.
"""
logger.info('writing %s file...' % outname)
logger.info('writing %s file...', outname)
projectfiles = ['META-INF/container.xml', 'content.opf', 'toc.ncx'] # type: List[unicode] # NOQA
projectfiles.extend(self.files)
epub = zipfile.ZipFile(path.join(outdir, outname), 'w', # type: ignore

View File

@ -239,7 +239,7 @@ class Epub3Builder(EpubBuilder):
def build_navigation_doc(self, outdir, outname):
"""Write the metainfo file nav.xhtml."""
logger.info('writing %s file...' % outname)
logger.info('writing %s file...', outname)
if self.config.epub_tocscope == 'default':
doctree = self.env.get_and_resolve_doctree(
@ -262,15 +262,15 @@ class Epub3Builder(EpubBuilder):
def validate_config_values(app):
if app.config.epub3_description is not None:
app.warn('epub3_description is deprecated. Use epub_description instead.')
logger.warning('epub3_description is deprecated. Use epub_description instead.')
app.config.epub_description = app.config.epub3_description
if app.config.epub3_contributor is not None:
app.warn('epub3_contributor is deprecated. Use epub_contributor instead.')
logger.warning('epub3_contributor is deprecated. Use epub_contributor instead.')
app.config.epub_contributor = app.config.epub3_contributor
if app.config.epub3_page_progression_direction is not None:
app.warn('epub3_page_progression_direction option is deprecated'
logger.warning('epub3_page_progression_direction option is deprecated'
' from 1.5. Use epub_writing_mode instead.')

View File

@ -220,7 +220,7 @@ class MessageCatalogBuilder(I18nBuilder):
# type: () -> None
files = self._collect_templates()
logger.info(bold('building [%s]: ' % self.name), nonl=1)
logger.info('targets for %d template files' % len(files))
logger.info('targets for %d template files', len(files))
extract_translations = self.templates.environment.extract_translations

View File

@ -209,7 +209,7 @@ class StandaloneHTMLBuilder(Builder):
if tag != 'tags':
raise ValueError
except ValueError:
self.warn('unsupported build info format in %r, building all' %
logger.warning('unsupported build info format in %r, building all',
path.join(self.outdir, '.buildinfo'))
except Exception:
pass
@ -325,10 +325,10 @@ class StandaloneHTMLBuilder(Builder):
favicon = self.config.html_favicon and \
path.basename(self.config.html_favicon) or ''
if favicon and os.path.splitext(favicon)[1] != '.ico':
self.warn('html_favicon is not an .ico file')
logger.warning('html_favicon is not an .ico file')
if not isinstance(self.config.html_use_opensearch, string_types):
self.warn('html_use_opensearch config value must now be a string')
logger.warning('html_use_opensearch config value must now be a string')
self.relations = self.env.collect_relations()
@ -595,8 +595,8 @@ class StandaloneHTMLBuilder(Builder):
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, self.imagedir, dest))
except Exception as err:
self.warn('cannot copy image file %r: %s' %
(path.join(self.srcdir, src), err))
logger.warning('cannot copy image file %r: %s',
path.join(self.srcdir, src), err)
def copy_download_files(self):
# type: () -> None
@ -614,8 +614,8 @@ class StandaloneHTMLBuilder(Builder):
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, '_downloads', dest))
except Exception as err:
self.warn('cannot copy downloadable file %r: %s' %
(path.join(self.srcdir, src), err))
logger.warning('cannot copy downloadable file %r: %s',
path.join(self.srcdir, src), err)
def copy_static_files(self):
# type: () -> None
@ -655,7 +655,7 @@ class StandaloneHTMLBuilder(Builder):
for static_path in self.config.html_static_path:
entry = path.join(self.confdir, static_path)
if not path.exists(entry):
self.warn('html_static_path entry %r does not exist' % entry)
logger.warning('html_static_path entry %r does not exist', entry)
continue
copy_asset(entry, path.join(self.outdir, '_static'), excluded,
context=ctx, renderer=self.templates)
@ -664,7 +664,7 @@ class StandaloneHTMLBuilder(Builder):
logobase = path.basename(self.config.html_logo)
logotarget = path.join(self.outdir, '_static', logobase)
if not path.isfile(path.join(self.confdir, self.config.html_logo)):
self.warn('logo file %r does not exist' % self.config.html_logo)
logger.warning('logo file %r does not exist', self.config.html_logo)
elif not path.isfile(logotarget):
copyfile(path.join(self.confdir, self.config.html_logo),
logotarget)
@ -672,7 +672,7 @@ class StandaloneHTMLBuilder(Builder):
iconbase = path.basename(self.config.html_favicon)
icontarget = path.join(self.outdir, '_static', iconbase)
if not path.isfile(path.join(self.confdir, self.config.html_favicon)):
self.warn('favicon file %r does not exist' % self.config.html_favicon)
logger.warning('favicon file %r does not exist', self.config.html_favicon)
elif not path.isfile(icontarget):
copyfile(path.join(self.confdir, self.config.html_favicon),
icontarget)
@ -687,7 +687,7 @@ class StandaloneHTMLBuilder(Builder):
for extra_path in self.config.html_extra_path:
entry = path.join(self.confdir, extra_path)
if not path.exists(entry):
self.warn('html_extra_path entry %r does not exist' % entry)
logger.warning('html_extra_path entry %r does not exist', entry)
continue
copy_asset(entry, self.outdir, excluded)
@ -748,7 +748,7 @@ class StandaloneHTMLBuilder(Builder):
self.indexer.load(f, self.indexer_format) # type: ignore
except (IOError, OSError, ValueError):
if keep:
self.warn('search index couldn\'t be loaded, but not all '
logger.warning('search index couldn\'t be loaded, but not all '
'documents will be built: the index will be '
'incomplete.')
# delete all entries for files that will be rebuilt
@ -789,9 +789,9 @@ class StandaloneHTMLBuilder(Builder):
if has_wildcard(pattern):
# warn if both patterns contain wildcards
if has_wildcard(matched):
self.warn('page %s matches two patterns in '
'html_sidebars: %r and %r' %
(pagename, matched, pattern))
logger.warning('page %s matches two patterns in '
'html_sidebars: %r and %r',
pagename, matched, pattern)
# else the already matched pattern is more specific
# than the present one, because it contains no wildcard
continue
@ -863,9 +863,9 @@ class StandaloneHTMLBuilder(Builder):
try:
output = self.templates.render(templatename, ctx)
except UnicodeError:
self.warn("a Unicode error occurred when rendering the page %s. "
logger.warning("a Unicode error occurred when rendering the page %s. "
"Please make sure all config values that contain "
"non-ASCII content are Unicode strings." % pagename)
"non-ASCII content are Unicode strings.", pagename)
return
if not outfilename:
@ -876,7 +876,7 @@ class StandaloneHTMLBuilder(Builder):
with codecs.open(outfilename, 'w', encoding, 'xmlcharrefreplace') as f: # type: ignore # NOQA
f.write(output)
except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (outfilename, err))
logger.warning("error writing file %s: %s", outfilename, err)
if self.copysource and ctx.get('sourcename'):
# copy the source file for the "show source" link
source_name = path.join(self.outdir, '_sources',
@ -1270,7 +1270,7 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
def validate_config_values(app):
# type: (Sphinx) -> None
if app.config.html_translator_class:
app.warn('html_translator_class is deprecated. '
logger.warning('html_translator_class is deprecated. '
'Use Sphinx.set_translator() API instead.')

View File

@ -76,7 +76,7 @@ class LaTeXBuilder(Builder):
# type: () -> None
preliminary_document_data = [list(x) for x in self.config.latex_documents]
if not preliminary_document_data:
self.warn('no "latex_documents" config value found; no documents '
logger.warning('no "latex_documents" config value found; no documents '
'will be written')
return
# assign subdirs to titles
@ -84,8 +84,8 @@ class LaTeXBuilder(Builder):
for entry in preliminary_document_data:
docname = entry[0]
if docname not in self.env.all_docs:
self.warn('"latex_documents" config value references unknown '
'document %s' % docname)
logger.warning('"latex_documents" config value references unknown '
'document %s', docname)
continue
self.document_data.append(entry) # type: ignore
if docname.endswith(SEP+'index'):
@ -241,49 +241,57 @@ class LaTeXBuilder(Builder):
def validate_config_values(app):
# type: (Sphinx) -> None
if app.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'):
app.warn('invalid latex_toplevel_sectioning, ignored: %s' %
logger.warning('invalid latex_toplevel_sectioning, ignored: %s' %
app.config.latex_toplevel_sectioning)
app.config.latex_toplevel_sectioning = None # type: ignore
if app.config.latex_use_parts:
if app.config.latex_toplevel_sectioning:
app.warn('latex_use_parts conflicts with latex_toplevel_sectioning, ignored.')
logger.warning('latex_use_parts conflicts with '
'latex_toplevel_sectioning, ignored.')
else:
app.warn('latex_use_parts is deprecated. Use latex_toplevel_sectioning instead.')
logger.warning('latex_use_parts is deprecated. '
'Use latex_toplevel_sectioning instead.')
app.config.latex_toplevel_sectioning = 'part' # type: ignore
if app.config.latex_use_modindex is not True: # changed by user
app.warn('latex_use_modindex is deprecated. Use latex_domain_indices instead.')
logger.warning('latex_use_modindex is deprecated. '
'Use latex_domain_indices instead.')
if app.config.latex_preamble:
if app.config.latex_elements.get('preamble'):
app.warn("latex_preamble conflicts with latex_elements['preamble'], ignored.")
logger.warning("latex_preamble conflicts with "
"latex_elements['preamble'], ignored.")
else:
app.warn("latex_preamble is deprecated. Use latex_elements['preamble'] instead.")
logger.warning("latex_preamble is deprecated. "
"Use latex_elements['preamble'] instead.")
app.config.latex_elements['preamble'] = app.config.latex_preamble
if app.config.latex_paper_size != 'letter':
if app.config.latex_elements.get('papersize'):
app.warn("latex_paper_size conflicts with latex_elements['papersize'], ignored.")
logger.warning("latex_paper_size conflicts with "
"latex_elements['papersize'], ignored.")
else:
app.warn("latex_paper_size is deprecated. "
logger.warning("latex_paper_size is deprecated. "
"Use latex_elements['papersize'] instead.")
if app.config.latex_paper_size:
app.config.latex_elements['papersize'] = app.config.latex_paper_size + 'paper'
if app.config.latex_font_size != '10pt':
if app.config.latex_elements.get('pointsize'):
app.warn("latex_font_size conflicts with latex_elements['pointsize'], ignored.")
logger.warning("latex_font_size conflicts with "
"latex_elements['pointsize'], ignored.")
else:
app.warn("latex_font_size is deprecated. Use latex_elements['pointsize'] instead.")
logger.warning("latex_font_size is deprecated. "
"Use latex_elements['pointsize'] instead.")
app.config.latex_elements['pointsize'] = app.config.latex_font_size
if 'footer' in app.config.latex_elements:
if 'postamble' in app.config.latex_elements:
app.warn("latex_elements['footer'] conflicts with "
logger.warning("latex_elements['footer'] conflicts with "
"latex_elements['postamble'], ignored.")
else:
app.warn("latex_elements['footer'] is deprecated. "
logger.warning("latex_elements['footer'] is deprecated. "
"Use latex_elements['preamble'] instead.")
app.config.latex_elements['postamble'] = app.config.latex_elements['footer']

View File

@ -233,7 +233,7 @@ class CheckExternalLinksBuilder(Builder):
if status == 'working' and info == 'old':
return
if lineno:
logger.info('(line %4d) ' % lineno, nonl=1)
logger.info('(line %4d) ', lineno, nonl=1)
if status == 'ignored':
if info:
logger.info(darkgray('-ignored- ') + uri + ': ' + info)
@ -247,8 +247,8 @@ class CheckExternalLinksBuilder(Builder):
elif status == 'broken':
self.write_entry('broken', docname, lineno, uri + ': ' + info)
if self.app.quiet or self.app.warningiserror:
self.warn('broken link: %s (%s)' % (uri, info),
'%s:%s' % (self.env.doc2path(docname), lineno))
logger.warning('broken link: %s (%s)', uri, info,
location=(self.env.doc2path(docname), lineno))
else:
logger.info(red('broken ') + uri + red(' - ' + info))
elif status == 'redirected':

View File

@ -45,7 +45,7 @@ class ManualPageBuilder(Builder):
def init(self):
# type: () -> None
if not self.config.man_pages:
self.warn('no "man_pages" config value found; no manual pages '
logger.warning('no "man_pages" config value found; no manual pages '
'will be written')
def get_outdated_docs(self):

View File

@ -124,7 +124,7 @@ class TexinfoBuilder(Builder):
# type: () -> None
preliminary_document_data = [list(x) for x in self.config.texinfo_documents]
if not preliminary_document_data:
self.warn('no "texinfo_documents" config value found; no documents '
logger.warning('no "texinfo_documents" config value found; no documents '
'will be written')
return
# assign subdirs to titles
@ -132,8 +132,8 @@ class TexinfoBuilder(Builder):
for entry in preliminary_document_data:
docname = entry[0]
if docname not in self.env.all_docs:
self.warn('"texinfo_documents" config value references unknown '
'document %s' % docname)
logger.warning('"texinfo_documents" config value references unknown '
'document %s', docname)
continue
self.document_data.append(entry) # type: ignore
if docname.endswith(SEP+'index'):
@ -240,7 +240,7 @@ class TexinfoBuilder(Builder):
with open(fn, 'w') as mkfile:
mkfile.write(TEXINFO_MAKEFILE)
except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (fn, err))
logger.warning("error writing file %s: %s", fn, err)
logger.info(' done')

View File

@ -15,9 +15,12 @@ from os import path
from docutils.io import StringOutput
from sphinx.builders import Builder
from sphinx.util import logging
from sphinx.util.osutil import ensuredir, os_path
from sphinx.writers.text import TextWriter
logger = logging.getLogger(__name__)
class TextBuilder(Builder):
name = 'text'
@ -65,7 +68,7 @@ class TextBuilder(Builder):
with codecs.open(outfilename, 'w', 'utf-8') as f:
f.write(self.writer.output)
except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (outfilename, err))
logger.warning("error writing file %s: %s", outfilename, err)
def finish(self):
pass

View File

@ -16,9 +16,12 @@ from docutils import nodes
from docutils.io import StringOutput
from sphinx.builders import Builder
from sphinx.util import logging
from sphinx.util.osutil import ensuredir, os_path
from sphinx.writers.xml import XMLWriter, PseudoXMLWriter
logger = logging.getLogger(__name__)
class XMLBuilder(Builder):
"""
@ -80,7 +83,7 @@ class XMLBuilder(Builder):
with codecs.open(outfilename, 'w', 'utf-8') as f:
f.write(self.writer.output)
except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (outfilename, err))
logger.warning("error writing file %s: %s", outfilename, err)
def finish(self):
pass

View File

@ -219,7 +219,7 @@ class Config(object):
if isinstance(value, binary_type) and nonascii_re.search(value): # type: ignore
logger.warning('the config value %r is set to a string with non-ASCII '
'characters; this can lead to Unicode errors occurring. '
'Please use Unicode strings, e.g. %r.' % (name, u'Content'))
'Please use Unicode strings, e.g. %r.', name, u'Content')
def convert_overrides(self, name, value):
# type: (unicode, Any) -> Any
@ -258,7 +258,7 @@ class Config(object):
elif name in self._raw_config:
self.__dict__[name] = self._raw_config[name]
except ValueError as exc:
logger.warning("%s" % exc)
logger.warning("%s", exc)
def init_values(self):
# type: () -> None
@ -270,14 +270,14 @@ class Config(object):
config.setdefault(realvalname, {})[key] = value # type: ignore
continue
elif valname not in self.values:
logger.warning('unknown config value %r in override, ignoring' % valname)
logger.warning('unknown config value %r in override, ignoring', valname)
continue
if isinstance(value, string_types):
config[valname] = self.convert_overrides(valname, value)
else:
config[valname] = value
except ValueError as exc:
logger.warning("%s" % exc)
logger.warning("%s", exc)
for name in config:
if name in self.values:
self.__dict__[name] = config[name]

View File

@ -22,6 +22,7 @@ from sphinx.roles import XRefRole
from sphinx.locale import l_, _
from sphinx.domains import Domain, ObjType
from sphinx.directives import ObjectDescription
from sphinx.util import logging
from sphinx.util.nodes import make_refnode
from sphinx.util.pycompat import UnicodeMixin
from sphinx.util.docfields import Field, GroupedField
@ -34,6 +35,8 @@ if False:
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
logger = logging.getLogger(__name__)
"""
Important note on ids
----------------------------------------------------------------------------
@ -3060,7 +3063,7 @@ class Symbol(object):
msg = "Duplicate declaration, also defined in '%s'.\n"
msg += "Declaration is '%s'."
msg = msg % (ourChild.docname, name)
env.warn(otherChild.docname, msg)
logger.warning(msg, location=otherChild.docname)
else:
# Both have declarations, and in the same docname.
# This can apparently happen, it should be safe to
@ -4872,7 +4875,7 @@ class CPPDomain(Domain):
msg = "Duplicate declaration, also defined in '%s'.\n"
msg += "Name of declaration is '%s'."
msg = msg % (ourNames[name], name)
self.env.warn(docname, msg)
logger.warning(msg, docname)
else:
ourNames[name] = docname
@ -4882,7 +4885,7 @@ class CPPDomain(Domain):
class Warner(object):
def warn(self, msg):
if emitWarnings:
env.warn_node(msg, node)
logger.warn_node(msg, node)
warner = Warner()
parser = DefinitionParser(target, warner, env.config)
try:

View File

@ -21,6 +21,7 @@ from sphinx.roles import XRefRole
from sphinx.locale import l_, _
from sphinx.domains import Domain, ObjType, Index
from sphinx.directives import ObjectDescription
from sphinx.util import logging
from sphinx.util.nodes import make_refnode
from sphinx.util.docfields import Field, GroupedField, TypedField
@ -31,6 +32,8 @@ if False:
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
logger = logging.getLogger(__name__)
# REs for Python signatures
py_sig_re = re.compile(
@ -784,7 +787,7 @@ class PythonDomain(Domain):
if not matches:
return None
elif len(matches) > 1:
env.warn_node(
logger.warn_node(
'more than one target found for cross-reference '
'%r: %s' % (target, ', '.join(match[0] for match in matches)),
node)

View File

@ -23,7 +23,7 @@ from sphinx.roles import XRefRole
from sphinx.locale import l_, _
from sphinx.domains import Domain, ObjType
from sphinx.directives import ObjectDescription
from sphinx.util import ws_re
from sphinx.util import ws_re, logging
from sphinx.util.nodes import clean_astext, make_refnode
if False:
@ -41,6 +41,8 @@ if False:
RoleFunction = Callable[[unicode, unicode, unicode, int, Inliner, Dict, List[unicode]],
Tuple[List[nodes.Node], List[nodes.Node]]]
logger = logging.getLogger(__name__)
# RE for option descriptions
option_desc_re = re.compile(r'((?:/|--|-|\+)?[-\.?@#_a-zA-Z0-9]+)(=?\s*.*)')
@ -163,12 +165,10 @@ class Cmdoption(ObjectDescription):
potential_option = potential_option.strip()
m = option_desc_re.match(potential_option) # type: ignore
if not m:
self.env.warn(
self.env.docname,
'Malformed option description %r, should '
logger.warning('Malformed option description %r, should '
'look like "opt", "-opt args", "--opt args", '
'"/opt args" or "+opt args"' % potential_option,
self.lineno)
'"/opt args" or "+opt args"', potential_option,
location=(self.env.docname, self.lineno))
continue
optname, args = m.groups()
if count:
@ -573,7 +573,7 @@ class StandardDomain(Domain):
label = node[0].astext()
if label in self.data['citations']:
path = env.doc2path(self.data['citations'][label][0])
env.warn_node('duplicate citation %s, other instance in %s' %
logger.warn_node('duplicate citation %s, other instance in %s' %
(label, path), node)
self.data['citations'][label] = (docname, node['ids'][0])
@ -596,7 +596,7 @@ class StandardDomain(Domain):
# link and object descriptions
continue
if name in labels:
env.warn_node('duplicate label %s, ' % name + 'other instance '
logger.warn_node('duplicate label %s, ' % name + 'other instance '
'in ' + env.doc2path(labels[name][0]), node)
anonlabels[name] = docname, labelid
if node.tagname == 'section':
@ -688,7 +688,7 @@ class StandardDomain(Domain):
return None
if env.config.numfig is False:
env.warn_node('numfig is disabled. :numref: is ignored.', node)
logger.warn_node('numfig is disabled. :numref: is ignored.', node)
return contnode
target_node = env.get_doctree(docname).ids.get(labelid)
@ -701,7 +701,7 @@ class StandardDomain(Domain):
if fignumber is None:
return contnode
except ValueError:
env.warn_node("no number is assigned for %s: %s" % (figtype, labelid), node)
logger.warn_node("no number is assigned for %s: %s" % (figtype, labelid), node)
return contnode
try:
@ -711,7 +711,7 @@ class StandardDomain(Domain):
title = env.config.numfig_format.get(figtype, '')
if figname is None and '%{name}' in title:
env.warn_node('the link has no caption: %s' % title, node)
logger.warn_node('the link has no caption: %s' % title, node)
return contnode
else:
fignum = '.'.join(map(str, fignumber))
@ -725,10 +725,10 @@ class StandardDomain(Domain):
# old style format (cf. "Fig.%s")
newtitle = title % fignum
except KeyError as exc:
env.warn_node('invalid numfig_format: %s (%r)' % (title, exc), node)
logger.warn_node('invalid numfig_format: %s (%r)' % (title, exc), node)
return contnode
except TypeError:
env.warn_node('invalid numfig_format: %s' % title, node)
logger.warn_node('invalid numfig_format: %s' % title, node)
return contnode
return self.build_reference_node(fromdocname, builder,

View File

@ -447,7 +447,7 @@ class BuildEnvironment(object):
if os.access(self.doc2path(docname), os.R_OK):
self.found_docs.add(docname)
else:
self.warn(docname, "document not readable. Ignored.")
logger.warning("document not readable. Ignored.", location=docname)
# Current implementation is applying translated messages in the reading
# phase.Therefore, in order to apply the updated message catalog, it is
@ -594,14 +594,14 @@ class BuildEnvironment(object):
if ext_ok:
continue
if ext_ok is None:
app.warn('the %s extension does not declare if it '
logger.warning('the %s extension does not declare if it '
'is safe for parallel reading, assuming it '
'isn\'t - please ask the extension author to '
'check and make it explicit' % extname)
app.warn('doing serial read')
'check and make it explicit', extname)
logger.warning('doing serial read')
else:
app.warn('the %s extension is not safe for parallel '
'reading, doing serial read' % extname)
logger.warning('the %s extension is not safe for parallel '
'reading, doing serial read', extname)
par_ok = False
break
if par_ok:
@ -690,11 +690,11 @@ class BuildEnvironment(object):
if lineend == -1:
lineend = len(error.object)
lineno = error.object.count(b'\n', 0, error.start) + 1
self.warn(self.docname, 'undecodable source characters, '
'replacing with "?": %r' %
logger.warning('undecodable source characters, replacing with "?": %r',
(error.object[linestart+1:error.start] + b'>>>' +
error.object[error.start:error.end] + b'<<<' +
error.object[error.end:lineend]), lineno)
error.object[error.end:lineend]),
location=(self.docname, lineno))
return (u'?', error.end)
def read_doc(self, docname, app=None):
@ -724,8 +724,8 @@ class BuildEnvironment(object):
if role_fn:
roles._roles[''] = role_fn
else:
self.warn(docname, 'default role %s not found' %
self.config.default_role)
logger.warning('default role %s not found', self.config.default_role,
location=docname)
codecs.register_error('sphinx', self.warn_and_replace) # type: ignore
@ -816,16 +816,18 @@ class BuildEnvironment(object):
def currmodule(self):
# type () -> None
"""Backwards compatible alias. Will be removed."""
self.warn(self.docname, 'env.currmodule is being referenced by an '
'extension; this API will be removed in the future')
logger.warning('env.currmodule is being referenced by an '
'extension; this API will be removed in the future',
location=self.docname)
return self.ref_context.get('py:module')
@property
def currclass(self):
# type: () -> None
"""Backwards compatible alias. Will be removed."""
self.warn(self.docname, 'env.currclass is being referenced by an '
'extension; this API will be removed in the future')
logger.warning('env.currclass is being referenced by an '
'extension; this API will be removed in the future',
location=self.docname)
return self.ref_context.get('py:class')
def new_serialno(self, category=''):
@ -900,7 +902,7 @@ class BuildEnvironment(object):
rel_filename, filename = self.relfn2path(targetname, docname)
self.dependencies[docname].add(rel_filename)
if not os.access(filename, os.R_OK):
self.warn_node('download file not readable: %s' % filename,
logger.warn_node('download file not readable: %s' % filename,
node)
continue
uniquename = self.dlfiles.add_file(docname, filename)
@ -919,7 +921,7 @@ class BuildEnvironment(object):
if mimetype not in candidates:
globbed.setdefault(mimetype, []).append(new_imgpath)
except (OSError, IOError) as err:
self.warn_node('image file %s not readable: %s' %
logger.warn_node('image file %s not readable: %s' %
(filename, err), node)
for key, files in iteritems(globbed):
candidates[key] = sorted(files, key=len)[0] # select by similarity
@ -932,12 +934,12 @@ class BuildEnvironment(object):
node['candidates'] = candidates = {}
imguri = node['uri']
if imguri.startswith('data:'):
self.warn_node('image data URI found. some builders might not support', node,
logger.warn_node('image data URI found. some builders might not support', node,
type='image', subtype='data_uri')
candidates['?'] = imguri
continue
elif imguri.find('://') != -1:
self.warn_node('nonlocal image URI found: %s' % imguri, node,
logger.warn_node('nonlocal image URI found: %s' % imguri, node,
type='image', subtype='nonlocal_uri')
candidates['?'] = imguri
continue
@ -967,7 +969,7 @@ class BuildEnvironment(object):
for imgpath in itervalues(candidates):
self.dependencies[docname].add(imgpath)
if not os.access(path.join(self.srcdir, imgpath), os.R_OK):
self.warn_node('image file not readable: %s' % imgpath,
logger.warn_node('image file not readable: %s' % imgpath,
node)
continue
self.images.add_file(docname, imgpath)
@ -1152,7 +1154,7 @@ class BuildEnvironment(object):
node.replace_self(newnode or contnode)
# remove only-nodes that do not belong to our builder
process_only_nodes(doctree, builder.tags, warn_node=self.warn_node)
process_only_nodes(doctree, builder.tags)
# allow custom references to be resolved
builder.app.emit('doctree-resolved', doctree, fromdocname)
@ -1181,7 +1183,7 @@ class BuildEnvironment(object):
(node['refdomain'], typ)
else:
msg = '%r reference target not found: %%(target)s' % typ
self.warn_node(msg % {'target': target}, node, type='ref', subtype=typ)
logger.warn_node(msg % {'target': target}, node, type='ref', subtype=typ)
def _resolve_doc_reference(self, builder, refdoc, node, contnode):
# type: (Builder, unicode, nodes.Node, nodes.Node) -> nodes.Node
@ -1232,7 +1234,7 @@ class BuildEnvironment(object):
return None
if len(results) > 1:
nice_results = ' or '.join(':%s:' % r[0] for r in results)
self.warn_node('more than one target found for \'any\' cross-'
logger.warn_node('more than one target found for \'any\' cross-'
'reference %r: could be %s' % (target, nice_results),
node)
res_role, newnode = results[0]
@ -1255,7 +1257,7 @@ class BuildEnvironment(object):
def traverse_toctree(parent, docname):
if parent == docname:
self.warn(docname, 'self referenced toctree found. Ignored.')
logger.warning('self referenced toctree found. Ignored.', location=docname)
return
# traverse toctree by pre-order
@ -1295,4 +1297,5 @@ class BuildEnvironment(object):
continue
if 'orphan' in self.metadata[docname]:
continue
self.warn(docname, 'document isn\'t included in any toctree')
logger.warning('document isn\'t included in any toctree',
location=docname)

View File

@ -16,7 +16,7 @@ from itertools import groupby
from six import text_type
from sphinx import addnodes
from sphinx.util import iteritems, split_index_msg, split_into
from sphinx.util import iteritems, split_index_msg, split_into, logging
from sphinx.locale import _
from sphinx.environment.managers import EnvironmentManager
@ -27,6 +27,8 @@ if False:
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
logger = logging.getLogger(__name__)
class IndexEntries(EnvironmentManager):
name = 'indices'
@ -53,7 +55,7 @@ class IndexEntries(EnvironmentManager):
for entry in node['entries']:
split_index_msg(entry[0], entry[1])
except ValueError as exc:
self.env.warn_node(exc, node)
logger.warn_node(str(exc), node)
node.parent.remove(node)
else:
for entry in node['entries']:
@ -119,9 +121,9 @@ class IndexEntries(EnvironmentManager):
add_entry(first, _('see also %s') % second, None,
link=False, key=index_key)
else:
self.env.warn(fn, 'unknown index entry type %r' % type)
logger.warning('unknown index entry type %r', type, location=fn)
except ValueError as err:
self.env.warn(fn, str(err))
logger.warning(str(err), location=fn)
# sort the index entries; put all symbols at the front, even those
# following the letters in ASCII, this is where the chr(127) comes from

View File

@ -14,7 +14,7 @@ from six import iteritems
from docutils import nodes
from sphinx import addnodes
from sphinx.util import url_re
from sphinx.util import url_re, logging
from sphinx.util.nodes import clean_astext, process_only_nodes
from sphinx.transforms import SphinxContentsFilter
from sphinx.environment.managers import EnvironmentManager
@ -25,6 +25,8 @@ if False:
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
logger = logging.getLogger(__name__)
class Toctree(EnvironmentManager):
name = 'toctree'
@ -169,7 +171,7 @@ class Toctree(EnvironmentManager):
# the document does not exist anymore: return a dummy node that
# renders to nothing
return nodes.paragraph()
process_only_nodes(toc, builder.tags, warn_node=self.env.warn_node)
process_only_nodes(toc, builder.tags)
for node in toc.traverse(nodes.reference):
node['refuri'] = node['anchorname'] or '#'
return toc
@ -296,16 +298,17 @@ class Toctree(EnvironmentManager):
toc = nodes.bullet_list('', item)
else:
if ref in parents:
self.env.warn(ref, 'circular toctree references '
'detected, ignoring: %s <- %s' %
(ref, ' <- '.join(parents)))
logger.warning('circular toctree references '
'detected, ignoring: %s <- %s',
ref, ' <- '.join(parents),
location=ref)
continue
refdoc = ref
toc = self.tocs[ref].deepcopy()
maxdepth = self.env.metadata[ref].get('tocdepth', 0)
if ref not in toctree_ancestors or (prune and maxdepth > 0):
self._toctree_prune(toc, 2, maxdepth, collapse)
process_only_nodes(toc, builder.tags, warn_node=self.env.warn_node)
process_only_nodes(toc, builder.tags)
if title and toc.children and len(toc.children) == 1:
child = toc.children[0]
for refnode in child.traverse(nodes.reference):
@ -314,13 +317,13 @@ class Toctree(EnvironmentManager):
refnode.children = [nodes.Text(title)]
if not toc.children:
# empty toc means: no titles will show up in the toctree
self.env.warn_node(
logger.warn_node(
'toctree contains reference to document %r that '
'doesn\'t have a title: no link will be generated'
% ref, toctreenode)
except KeyError:
# this is raised if the included file does not exist
self.env.warn_node(
logger.warn_node(
'toctree contains reference to nonexisting document %r'
% ref, toctreenode)
else:

View File

@ -10,8 +10,11 @@
"""
from docutils import nodes
from sphinx.util import logging
from sphinx.util.nodes import clean_astext
logger = logging.getLogger(__name__)
def register_sections_as_label(app, document):
labels = app.env.domaindata['std']['labels']
@ -23,7 +26,7 @@ def register_sections_as_label(app, document):
sectname = clean_astext(node[0])
if name in labels:
app.env.warn_node('duplicate label %s, ' % name + 'other instance '
logger.warn_node('duplicate label %s, ' % name + 'other instance '
'in ' + app.env.doc2path(labels[name][0]), node)
anonlabels[name] = docname, labelid

View File

@ -608,13 +608,13 @@ def process_generate_options(app):
suffix = get_rst_suffix(app)
if suffix is None:
app.warn('autosummary generats .rst files internally. '
logging.warning('autosummary generats .rst files internally. '
'But your source_suffix does not contain .rst. Skipped.')
return
generate_autosummary_docs(genfiles, builder=app.builder,
warn=app.warn, info=app.info, suffix=suffix,
base_path=app.srcdir)
warn=logger.warning, info=logger.info,
suffix=suffix, base_path=app.srcdir)
def setup(app):

View File

@ -20,6 +20,7 @@ from six.moves import cPickle as pickle
import sphinx
from sphinx.builders import Builder
from sphinx.util import logging
from sphinx.util.inspect import safe_getattr
if False:
@ -27,6 +28,8 @@ if False:
from typing import Any, Callable, IO, Pattern, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
# utility
def write_header(f, text, char='-'):
@ -35,14 +38,14 @@ def write_header(f, text, char='-'):
f.write(char * len(text) + '\n')
def compile_regex_list(name, exps, warnfunc):
# type: (unicode, unicode, Callable) -> List[Pattern]
def compile_regex_list(name, exps):
# type: (unicode, unicode) -> List[Pattern]
lst = []
for exp in exps:
try:
lst.append(re.compile(exp))
except Exception:
warnfunc('invalid regex %r in %s' % (exp, name))
logger.warning('invalid regex %r in %s', exp, name)
return lst
@ -62,21 +65,18 @@ class CoverageBuilder(Builder):
try:
self.c_regexes.append((name, re.compile(exp)))
except Exception:
self.warn('invalid regex %r in coverage_c_regexes' % exp)
logger.warning('invalid regex %r in coverage_c_regexes', exp)
self.c_ignorexps = {} # type: Dict[unicode, List[Pattern]]
for (name, exps) in iteritems(self.config.coverage_ignore_c_items):
self.c_ignorexps[name] = compile_regex_list(
'coverage_ignore_c_items', exps, self.warn)
self.mod_ignorexps = compile_regex_list(
'coverage_ignore_modules', self.config.coverage_ignore_modules,
self.warn)
self.cls_ignorexps = compile_regex_list(
'coverage_ignore_classes', self.config.coverage_ignore_classes,
self.warn)
self.fun_ignorexps = compile_regex_list(
'coverage_ignore_functions', self.config.coverage_ignore_functions,
self.warn)
self.c_ignorexps[name] = compile_regex_list('coverage_ignore_c_items',
exps)
self.mod_ignorexps = compile_regex_list('coverage_ignore_modules',
self.config.coverage_ignore_modules)
self.cls_ignorexps = compile_regex_list('coverage_ignore_classes',
self.config.coverage_ignore_classes)
self.fun_ignorexps = compile_regex_list('coverage_ignore_functions',
self.config.coverage_ignore_functions)
def get_outdated_docs(self):
# type: () -> unicode
@ -147,8 +147,7 @@ class CoverageBuilder(Builder):
try:
mod = __import__(mod_name, fromlist=['foo'])
except ImportError as err:
self.warn('module %s could not be imported: %s' %
(mod_name, err))
logger.warning('module %s could not be imported: %s', mod_name, err)
self.py_undoc[mod_name] = {'error': err}
continue

View File

@ -270,7 +270,7 @@ Results of doctest builder run on %s
def _warn_out(self, text):
# type: (unicode) -> None
if self.app.quiet or self.app.warningiserror:
self.warn(text)
logger.warning(text)
else:
logger.info(text, nonl=True)
if isinstance(text, binary_type):
@ -347,9 +347,9 @@ Doctest summary
for node in doctree.traverse(condition):
source = 'test' in node and node['test'] or node.astext()
if not source:
self.warn('no code/output in %s block at %s:%s' %
(node.get('testnodetype', 'doctest'),
self.env.doc2path(docname), node.line))
logger.warning('no code/output in %s block at %s:%s',
node.get('testnodetype', 'doctest'),
self.env.doc2path(docname), node.line)
code = TestCode(source, type=node.get('testnodetype', 'doctest'),
lineno=node.line, options=node.get('options'))
node_groups = node.get('groups', ['default'])
@ -442,9 +442,8 @@ Doctest summary
doctest_encode(code[0].code, self.env.config.source_encoding), {}, # type: ignore # NOQA
group.name, filename_str, code[0].lineno)
except Exception:
self.warn('ignoring invalid doctest code: %r' %
code[0].code,
'%s:%s' % (filename, code[0].lineno))
logger.warning('ignoring invalid doctest code: %r', code[0].code,
location=(filename, code[0].lineno))
continue
if not test.examples:
continue

View File

@ -26,6 +26,7 @@ from docutils.statemachine import ViewList
import sphinx
from sphinx.errors import SphinxError
from sphinx.locale import _
from sphinx.util import logging
from sphinx.util.i18n import search_image_for_language
from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL
@ -34,6 +35,8 @@ if False:
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
mapname_re = re.compile(r'<map id="(.*?)"')
@ -204,8 +207,8 @@ def render_dot(self, code, options, format, prefix='graphviz'):
except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('dot command %r cannot be run (needed for graphviz '
'output), check the graphviz_dot setting' % graphviz_dot)
logger.warning('dot command %r cannot be run (needed for graphviz '
'output), check the graphviz_dot setting', graphviz_dot)
if not hasattr(self.builder, '_graphviz_warned_dot'):
self.builder._graphviz_warned_dot = {}
self.builder._graphviz_warned_dot[graphviz_dot] = True
@ -236,7 +239,7 @@ def warn_for_deprecated_option(self, node):
return
if 'inline' in node:
self.builder.warn(':inline: option for graphviz is deprecated since version 1.4.0.')
logger.warning(':inline: option for graphviz is deprecated since version 1.4.0.')
self.builder._graphviz_warned_inline = True
@ -250,7 +253,7 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
"'svg', but is %r" % format)
fname, outfn = render_dot(self, code, options, format, prefix)
except GraphvizError as exc:
self.builder.warn('dot code %r: ' % code + str(exc))
logger.warning('dot code %r: ' % code + str(exc))
raise nodes.SkipNode
if fname is None:
@ -296,7 +299,7 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'):
try:
fname, outfn = render_dot(self, code, options, 'pdf', prefix)
except GraphvizError as exc:
self.builder.warn('dot code %r: ' % code + str(exc))
logger.warning('dot code %r: ' % code + str(exc))
raise nodes.SkipNode
is_inline = self.is_inline(node)
@ -333,7 +336,7 @@ def render_dot_texinfo(self, node, code, options, prefix='graphviz'):
try:
fname, outfn = render_dot(self, code, options, 'png', prefix)
except GraphvizError as exc:
self.builder.warn('dot code %r: ' % code + str(exc))
logger.warning('dot code %r: ' % code + str(exc))
raise nodes.SkipNode
if fname is not None:
self.body.append('@image{%s,,,[graphviz],png}\n' % fname[:-4])

View File

@ -25,6 +25,7 @@ from docutils import nodes
import sphinx
from sphinx.locale import _
from sphinx.errors import SphinxError, ExtensionError
from sphinx.util import logging
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.osutil import ensuredir, ENOENT, cd
from sphinx.util.pycompat import sys_encoding
@ -36,6 +37,8 @@ if False:
from sphinx.application import Sphinx # NOQA
from sphinx.ext.mathbase import math as math_node, displaymath # NOQA
logger = logging.getLogger(__name__)
class MathExtError(SphinxError):
category = 'Math extension error'
@ -142,8 +145,8 @@ def render_math(self, math):
except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('LaTeX command %r cannot be run (needed for math '
'display), check the imgmath_latex setting' %
logger.warning('LaTeX command %r cannot be run (needed for math '
'display), check the imgmath_latex setting',
self.builder.config.imgmath_latex)
self.builder._imgmath_warned_latex = True
return None, None
@ -183,10 +186,10 @@ def render_math(self, math):
except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('%s command %r cannot be run (needed for math '
'display), check the imgmath_%s setting' %
(image_translator, image_translator_executable,
image_translator))
logger.warning('%s command %r cannot be run (needed for math '
'display), check the imgmath_%s setting',
image_translator, image_translator_executable,
image_translator)
self.builder._imgmath_warned_image_translator = True
return None, None
@ -234,7 +237,7 @@ def html_visit_math(self, node):
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
self.builder.warn('display latex %r: ' % node['latex'] + msg)
logger.warning('display latex %r: ' % node['latex'] + msg)
raise nodes.SkipNode
if fname is None:
# something failed -- use text-only as a bad substitute
@ -262,7 +265,7 @@ def html_visit_displaymath(self, node):
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
self.builder.warn('inline latex %r: ' % node['latex'] + msg)
logger.warning('inline latex %r: ' % node['latex'] + msg)
raise nodes.SkipNode
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('<p>')

View File

@ -229,14 +229,14 @@ def fetch_inventory(app, uri, inv):
else:
f = open(path.join(app.srcdir, inv), 'rb')
except Exception as err:
app.warn('intersphinx inventory %r not fetchable due to '
'%s: %s' % (inv, err.__class__, err))
logger.warning('intersphinx inventory %r not fetchable due to %s: %s',
inv, err.__class__, err)
return
try:
if hasattr(f, 'url'):
newinv = f.url # type: ignore
if inv != newinv:
logger.info('intersphinx inventory has moved: %s -> %s' % (inv, newinv))
logger.info('intersphinx inventory has moved: %s -> %s', inv, newinv)
if uri in (inv, path.dirname(inv), path.dirname(inv) + '/'):
uri = path.dirname(newinv)
@ -247,8 +247,8 @@ def fetch_inventory(app, uri, inv):
except ValueError:
raise ValueError('unknown or unsupported inventory version')
except Exception as err:
app.warn('intersphinx inventory %r not readable due to '
'%s: %s' % (inv, err.__class__.__name__, err))
logger.warning('intersphinx inventory %r not readable due to %s: %s',
inv, err.__class__.__name__, err)
else:
return invdata
@ -274,7 +274,7 @@ def load_mappings(app):
# new format
name, (uri, inv) = key, value
if not isinstance(name, string_types):
app.warn('intersphinx identifier %r is not string. Ignored' % name)
logger.warning('intersphinx identifier %r is not string. Ignored', name)
continue
else:
# old format, no name
@ -295,8 +295,7 @@ def load_mappings(app):
if '://' not in inv or uri not in cache \
or cache[uri][1] < cache_time:
safe_inv_url = _get_safe_url(inv) # type: ignore
logger.info(
'loading intersphinx inventory from %s...' % safe_inv_url)
logger.info('loading intersphinx inventory from %s...', safe_inv_url)
invdata = fetch_inventory(app, uri, inv)
if invdata:
cache[uri] = (name, now, invdata)

View File

@ -25,6 +25,7 @@ from docutils import nodes
import sphinx
from sphinx.errors import SphinxError, ExtensionError
from sphinx.util import logging
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.osutil import ensuredir, ENOENT, cd
from sphinx.util.pycompat import sys_encoding
@ -36,6 +37,8 @@ if False:
from sphinx.application import Sphinx # NOQA
from sphinx.ext.mathbase import math as math_node, displaymath # NOQA
logger = logging.getLogger(__name__)
class MathExtError(SphinxError):
category = 'Math extension error'
@ -133,8 +136,8 @@ def render_math(self, math):
except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('LaTeX command %r cannot be run (needed for math '
'display), check the pngmath_latex setting' %
logger.warning('LaTeX command %r cannot be run (needed for math '
'display), check the pngmath_latex setting',
self.builder.config.pngmath_latex)
self.builder._mathpng_warned_latex = True
return None, None
@ -158,8 +161,8 @@ def render_math(self, math):
except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('dvipng command %r cannot be run (needed for math '
'display), check the pngmath_dvipng setting' %
logger.warning('dvipng command %r cannot be run (needed for math '
'display), check the pngmath_dvipng setting',
self.builder.config.pngmath_dvipng)
self.builder._mathpng_warned_dvipng = True
return None, None
@ -206,7 +209,7 @@ def html_visit_math(self, node):
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
self.builder.warn('display latex %r: ' % node['latex'] + msg)
logger.warning('display latex %r: ' % node['latex'] + msg)
raise nodes.SkipNode
if fname is None:
# something failed -- use text-only as a bad substitute
@ -234,7 +237,7 @@ def html_visit_displaymath(self, node):
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
self.builder.warn('inline latex %r: ' % node['latex'] + msg)
logger.warning('inline latex %r: ' % node['latex'] + msg)
raise nodes.SkipNode
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('<p>')
@ -252,7 +255,8 @@ def html_visit_displaymath(self, node):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.warn('sphinx.ext.pngmath has been deprecated. Please use sphinx.ext.imgmath instead.')
logger.warning('sphinx.ext.pngmath has been deprecated. '
'Please use sphinx.ext.imgmath instead.')
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:

View File

@ -18,6 +18,7 @@ from docutils.parsers.rst import directives
import sphinx
from sphinx.locale import _
from sphinx.environment import NoUri
from sphinx.util import logging
from sphinx.util.nodes import set_source_info
from docutils.parsers.rst import Directive
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
@ -28,6 +29,8 @@ if False:
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
logger = logging.getLogger(__name__)
class todo_node(nodes.Admonition, nodes.Element):
pass
@ -97,7 +100,7 @@ def process_todos(app, doctree):
})
if env.config.todo_emit_warnings:
env.warn_node("TODO entry found: %s" % node[1].astext(), node)
logger.warn_node("TODO entry found: %s" % node[1].astext(), node)
class TodoList(Directive):

View File

@ -39,7 +39,7 @@ def _get_full_modname(app, modname, attribute):
except AttributeError:
# sphinx.ext.viewcode can't follow class instance attribute
# then AttributeError logging output only verbose mode.
logger.verbose('Didn\'t find %s in %s' % (attribute, modname))
logger.verbose('Didn\'t find %s in %s', attribute, modname)
return None
except Exception as e:
# sphinx.ext.viewcode follow python domain directives.

View File

@ -177,12 +177,11 @@ class AutoIndexUpgrader(Transform):
def apply(self):
# type: () -> None
env = self.document.settings.env
for node in self.document.traverse(addnodes.index):
if 'entries' in node and any(len(entry) == 4 for entry in node['entries']):
msg = ('4 column based index found. '
'It might be a bug of extensions you use: %r' % node['entries'])
env.warn_node(msg, node)
logger.warn_node(msg, node)
for i, entry in enumerate(node['entries']):
if len(entry) == 4:
node['entries'][i] = entry + (None,)

View File

@ -17,7 +17,7 @@ from docutils.utils import relative_path
from docutils.transforms import Transform
from sphinx import addnodes
from sphinx.util import split_index_msg
from sphinx.util import split_index_msg, logging
from sphinx.util.i18n import find_catalog
from sphinx.util.nodes import (
LITERAL_TYPE_NODES, IMAGE_TYPE_NODES,
@ -33,6 +33,8 @@ if False:
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
logger = logging.getLogger(__name__)
def publish_msgstr(app, source, source_path, source_line, config, settings):
# type: (Sphinx, unicode, unicode, int, Config, Dict) -> nodes.document
@ -272,7 +274,7 @@ class Locale(Transform):
old_foot_refs = node.traverse(is_autonumber_footnote_ref)
new_foot_refs = patch.traverse(is_autonumber_footnote_ref)
if len(old_foot_refs) != len(new_foot_refs):
env.warn_node('inconsistent footnote references in '
logger.warn_node('inconsistent footnote references in '
'translated message', node)
old_foot_namerefs = {} # type: Dict[unicode, List[nodes.footnote_reference]]
for r in old_foot_refs:
@ -307,8 +309,7 @@ class Locale(Transform):
old_refs = node.traverse(is_refnamed_ref)
new_refs = patch.traverse(is_refnamed_ref)
if len(old_refs) != len(new_refs):
env.warn_node('inconsistent references in '
'translated message', node)
logger.warn_node('inconsistent references in translated message', node)
old_ref_names = [r['refname'] for r in old_refs]
new_ref_names = [r['refname'] for r in new_refs]
orphans = list(set(old_ref_names) - set(new_ref_names))
@ -336,8 +337,7 @@ class Locale(Transform):
new_refs = patch.traverse(is_refnamed_footnote_ref)
refname_ids_map = {}
if len(old_refs) != len(new_refs):
env.warn_node('inconsistent references in '
'translated message', node)
logger.warn_node('inconsistent references in translated message', node)
for old in old_refs:
refname_ids_map[old["refname"]] = old["ids"]
for new in new_refs:
@ -352,8 +352,7 @@ class Locale(Transform):
new_refs = patch.traverse(addnodes.pending_xref)
xref_reftarget_map = {}
if len(old_refs) != len(new_refs):
env.warn_node('inconsistent term references in '
'translated message', node)
logger.warn_node('inconsistent term references in translated message', node)
def get_ref_key(node):
# type: (nodes.Node) -> Tuple[unicode, unicode, unicode]

View File

@ -23,7 +23,7 @@ from sphinx.util.console import colorize
if False:
# For type annotation
from typing import Any, Generator, IO, Tuple # NOQA
from typing import Any, Generator, IO, Tuple, Union # NOQA
from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA
@ -422,12 +422,12 @@ def setup(app, status, warning):
for handler in logger.handlers[:]:
logger.removeHandler(handler)
info_handler = NewLineStreamHandler(SafeEncodingWriter(status))
info_handler = NewLineStreamHandler(SafeEncodingWriter(status)) # type: ignore
info_handler.addFilter(InfoFilter())
info_handler.setLevel(VERBOSITY_MAP.get(app.verbosity))
info_handler.setFormatter(ColorizeFormatter())
warning_handler = WarningStreamHandler(SafeEncodingWriter(warning))
warning_handler = WarningStreamHandler(SafeEncodingWriter(warning)) # type: ignore
warning_handler.addFilter(WarningSuppressor(app))
warning_handler.addFilter(WarningIsErrorFilter(app))
warning_handler.addFilter(WarningLogRecordTranslator(app))

View File

@ -18,6 +18,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.locale import pairindextypes
from sphinx.util import logging
if False:
# For type annotation
@ -25,6 +26,8 @@ if False:
from sphinx.builders import Builder # NOQA
from sphinx.utils.tags import Tags # NOQA
logger = logging.getLogger(__name__)
class WarningStream(object):
@ -304,15 +307,14 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc, traversed
if includefile not in traversed:
try:
traversed.append(includefile)
builder.info(colorfunc(includefile) + " ", nonl=1)
logger.info(colorfunc(includefile) + " ", nonl=1)
subtree = inline_all_toctrees(builder, docnameset, includefile,
builder.env.get_doctree(includefile),
colorfunc, traversed)
docnameset.add(includefile)
except Exception:
builder.warn('toctree contains ref to nonexisting '
'file %r' % includefile,
builder.env.doc2path(docname))
logger.warning('toctree contains ref to nonexisting file %r',
includefile, location=docname)
else:
sof = addnodes.start_of_file(docname=includefile)
sof.children = subtree.children
@ -350,8 +352,8 @@ def set_role_source_info(inliner, lineno, node):
node.source, node.line = inliner.reporter.get_source_and_line(lineno)
def process_only_nodes(doctree, tags, warn_node=None):
# type: (nodes.Node, Tags, Callable) -> None
def process_only_nodes(doctree, tags):
# type: (nodes.Node, Tags) -> None
# A comment on the comment() nodes being inserted: replacing by [] would
# result in a "Losing ids" exception if there is a target node before
# the only node, so we make sure docutils can transfer the id to
@ -360,9 +362,7 @@ def process_only_nodes(doctree, tags, warn_node=None):
try:
ret = tags.eval_condition(node['expr'])
except Exception as err:
if warn_node is None:
raise err
warn_node('exception while evaluating only '
logger.warn_node('exception while evaluating only '
'directive expression: %s' % err, node)
node.replace_self(node.children or nodes.comment())
else:

View File

@ -22,9 +22,12 @@ from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx16Warning
from sphinx.locale import admonitionlabels, _
from sphinx.util import logging
from sphinx.util.images import get_image_size
from sphinx.util.smartypants import sphinx_smarty_pants
logger = logging.getLogger(__name__)
# A good overview of the purpose behind these classes can be found here:
# http://www.arnebrodowski.de/blog/write-your-own-restructuredtext-writer.html
@ -289,7 +292,7 @@ class HTMLTranslator(BaseTranslator):
prefix = self.builder.config.numfig_format.get(figtype)
if prefix is None:
msg = 'numfig_format is not defined for %s' % figtype
self.builder.warn(msg)
logger.warning(msg)
else:
numbers = self.builder.fignumbers[key][figure_id]
self.body.append(prefix % '.'.join(map(str, numbers)) + ' ')
@ -299,7 +302,7 @@ class HTMLTranslator(BaseTranslator):
if figtype:
if len(node['ids']) == 0:
msg = 'Any IDs not assigned for %s node' % node.tagname
self.builder.env.warn_node(msg, node)
logger.warn_node(msg, node)
else:
append_fignumber(figtype, node['ids'][0])
@ -522,7 +525,7 @@ class HTMLTranslator(BaseTranslator):
if not ('width' in node and 'height' in node):
size = get_image_size(os.path.join(self.builder.srcdir, olduri))
if size is None:
self.builder.env.warn_node('Could not obtain image size. '
logger.warn_node('Could not obtain image size. '
':scale: option is ignored.', node)
else:
if 'width' not in node:
@ -755,10 +758,10 @@ class HTMLTranslator(BaseTranslator):
self.body.append(self.starttag(node, 'tr', '', CLASS='field'))
def visit_math(self, node, math_env=''):
self.builder.warn('using "math" markup without a Sphinx math extension '
logger.warning('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/ext/math.html',
(self.builder.current_docname, node.line))
location=(self.builder.current_docname, node.line))
raise nodes.SkipNode
def unknown_visit(self, node):

View File

@ -26,7 +26,7 @@ from sphinx import highlighting
from sphinx.errors import SphinxError
from sphinx.deprecation import RemovedInSphinx16Warning
from sphinx.locale import admonitionlabels, _
from sphinx.util import split_into
from sphinx.util import split_into, logging
from sphinx.util.i18n import format_date
from sphinx.util.nodes import clean_astext, traverse_parent
from sphinx.util.template import LaTeXRenderer
@ -38,6 +38,7 @@ if False:
from typing import Any, Callable, Iterator, Pattern, Tuple, Union # NOQA
from sphinx.builder import Builder # NOQA
logger = logging.getLogger(__name__)
BEGIN_DOC = r'''
\begin{document}
@ -438,7 +439,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
if builder.config.language and not self.babel.is_supported_language():
# emit warning if specified language is invalid
# (only emitting, nothing changed to processing)
self.builder.warn('no Babel option known for language %r' %
logger.warning('no Babel option known for language %r',
builder.config.language)
# simply use babel.get_language() always, as get_language() returns
@ -490,7 +491,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
tocdepth = document['tocdepth'] + self.top_sectionlevel - 2
maxdepth = len(self.sectionnames) - self.top_sectionlevel
if tocdepth > maxdepth:
self.builder.warn('too large :maxdepth:, ignored.')
logger.warning('too large :maxdepth:, ignored.')
tocdepth = maxdepth
self.elements['tocdepth'] = '\\setcounter{tocdepth}{%d}' % tocdepth
@ -566,7 +567,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
for key in self.builder.config.latex_elements:
if key not in self.elements:
msg = _("Unknown configure key: latex_elements[%r] is ignored.")
self.builder.warn(msg % key)
logger.warning(msg % key)
def restrict_footnote(self, node):
# type: (nodes.Node) -> None
@ -891,8 +892,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
if self.this_is_the_title:
if len(node.children) != 1 and not isinstance(node.children[0],
nodes.Text):
self.builder.warn('document title is not a single Text node',
(self.curfilestack[-1], node.line))
logger.warning('document title is not a single Text node',
location=(self.curfilestack[-1], node.line))
if not self.elements['title']:
# text needs to be escaped since it is inserted into
# the output literally
@ -930,10 +931,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
# Redirect body output until title is finished.
self.pushbody([])
else:
self.builder.warn(
'encountered title node not in section, topic, table, '
logger.warning('encountered title node not in section, topic, table, '
'admonition or sidebar',
(self.curfilestack[-1], node.line or ''))
location=(self.curfilestack[-1], node.line or ''))
self.body.append('\\sphinxstyleothertitle{')
self.context.append('}\n')
self.in_title = 1
@ -1573,7 +1573,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
try:
return rstdim_to_latexdim(width_str)
except ValueError:
self.builder.warn('dimension unit %s is invalid. Ignored.' % width_str)
logger.warning('dimension unit %s is invalid. Ignored.', width_str)
def is_inline(self, node):
# type: (nodes.Node) -> bool
@ -1886,10 +1886,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
p1, p2 = [self.encode(x) for x in split_into(2, 'seealso', string)]
self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
else:
self.builder.warn(
'unknown index entry type %s found' % type)
logger.warning('unknown index entry type %s found', type)
except ValueError as err:
self.builder.warn(str(err))
logger.warning(str(err))
raise nodes.SkipNode
def visit_raw(self, node):
@ -1953,8 +1952,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
else:
self.context.append('}}}')
else:
self.builder.warn('unusable reference target found: %s' % uri,
(self.curfilestack[-1], node.line))
logger.warning('unusable reference target found: %s', uri,
location=(self.curfilestack[-1], node.line))
self.context.append('')
def depart_reference(self, node):
@ -2459,10 +2458,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_math(self, node):
# type: (nodes.Node) -> None
self.builder.warn('using "math" markup without a Sphinx math extension '
logger.warning('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/ext/math.html',
(self.curfilestack[-1], node.line))
location=(self.curfilestack[-1], node.line))
raise nodes.SkipNode
visit_math_block = visit_math

View File

@ -21,9 +21,12 @@ from docutils.writers.manpage import (
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx16Warning
from sphinx.locale import admonitionlabels, _
from sphinx.util import logging
import sphinx.util.docutils
from sphinx.util.i18n import format_date
logger = logging.getLogger(__name__)
class ManualPageWriter(Writer):
def __init__(self, builder):
@ -437,7 +440,7 @@ class ManualPageTranslator(BaseTranslator):
pass
def visit_math(self, node):
self.builder.warn('using "math" markup without a Sphinx math extension '
logger.warning('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/ext/math.html')
raise nodes.SkipNode

View File

@ -23,6 +23,7 @@ from sphinx import addnodes, __display_version__
from sphinx.errors import ExtensionError
from sphinx.deprecation import RemovedInSphinx16Warning
from sphinx.locale import admonitionlabels, _
from sphinx.util import logging
from sphinx.util.i18n import format_date
from sphinx.writers.latex import collected_footnote
@ -31,6 +32,8 @@ if False:
from typing import Any, Callable, Iterator, Pattern, Tuple, Union # NOQA
from sphinx.builders.texinfo import TexinfoBuilder # NOQA
logger = logging.getLogger(__name__)
COPYING = """\
@quotation
@ -651,9 +654,9 @@ class TexinfoTranslator(nodes.NodeVisitor):
if isinstance(parent, (nodes.Admonition, nodes.sidebar, nodes.topic)):
raise nodes.SkipNode
elif not isinstance(parent, nodes.section):
self.builder.warn(
'encountered title node not in section, topic, table, '
'admonition or sidebar', (self.curfilestack[-1], node.line))
logger.warning('encountered title node not in section, topic, table, '
'admonition or sidebar',
location=(self.curfilestack[-1], node.line))
self.visit_rubric(node)
else:
try:
@ -1331,8 +1334,8 @@ class TexinfoTranslator(nodes.NodeVisitor):
node.parent.get('literal_block'))):
self.body.append('\n@caption{')
else:
self.builder.warn('caption not inside a figure.',
(self.curfilestack[-1], node.line))
logger.warning('caption not inside a figure.',
location=(self.curfilestack[-1], node.line))
def depart_caption(self, node):
# type: (nodes.Node) -> None
@ -1434,13 +1437,13 @@ class TexinfoTranslator(nodes.NodeVisitor):
def unimplemented_visit(self, node):
# type: (nodes.Node) -> None
self.builder.warn("unimplemented node type: %r" % node,
(self.curfilestack[-1], node.line))
logger.warning("unimplemented node type: %r", node,
location=(self.curfilestack[-1], node.line))
def unknown_visit(self, node):
# type: (nodes.Node) -> None
self.builder.warn("unknown node type: %r" % node,
(self.curfilestack[-1], node.line))
logger.warning("unknown node type: %r", node,
location=(self.curfilestack[-1], node.line))
def unknown_departure(self, node):
# type: (nodes.Node) -> None
@ -1756,7 +1759,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
def visit_math(self, node):
# type: (nodes.Node) -> None
self.builder.warn('using "math" markup without a Sphinx math extension '
logger.warning('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/ext/math.html')
raise nodes.SkipNode

View File

@ -22,12 +22,15 @@ from docutils.utils import column_width
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx16Warning
from sphinx.locale import admonitionlabels, _
from sphinx.util import logging
if False:
# For type annotation
from typing import Any, Callable, Tuple, Union # NOQA
from sphinx.builders.text import TextBuilder # NOQA
logger = logging.getLogger(__name__)
class TextWrapper(textwrap.TextWrapper):
"""Custom subclass that uses a different word separator regex."""
@ -1174,10 +1177,10 @@ class TextTranslator(nodes.NodeVisitor):
def visit_math(self, node):
# type: (nodes.Node) -> None
self.builder.warn('using "math" markup without a Sphinx math extension '
logger.warning('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/ext/math.html',
(self.builder.current_docname, node.line))
location=(self.builder.current_docname, node.line))
raise nodes.SkipNode
visit_math_block = visit_math

View File

@ -47,26 +47,6 @@ def test_emit_with_nonascii_name_node(app, status, warning):
app.emit('my_event', node)
@with_app()
def test_output(app, status, warning):
# info with newline
status.truncate(0) # __init__ writes to status
status.seek(0)
app.info("Nothing here...")
assert status.getvalue() == "Nothing here...\n"
# info without newline
status.truncate(0)
status.seek(0)
app.info("Nothing here...", True)
assert status.getvalue() == "Nothing here..."
# warning
old_count = app._warncount
app.warn("Bad news!")
assert strip_escseq(warning.getvalue()) == "WARNING: Bad news!\n"
assert app._warncount == old_count + 1
@with_app()
def test_extensions(app, status, warning):
app.setup_extension('shutil')

View File

@ -9,35 +9,26 @@
:license: BSD, see LICENSE for details.
"""
from six import PY3
from six import StringIO
from util import TestApp, remove_unicode_literals, path
from util import TestApp, path
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.builders.latex import LaTeXBuilder
app = env = None
warnings = []
def setup_module():
global app, env
app = TestApp(srcdir='root-envtest')
app = TestApp(srcdir='root-envtest', warning=StringIO())
env = app.env
env.set_warnfunc(lambda *args, **kwargs: warnings.append(args))
def teardown_module():
app.cleanup()
def warning_emitted(file, text):
for warning in warnings:
if len(warning) == 2 and file in warning[1] and text in warning[0]:
return True
return False
# Tests are run in the order they appear in the file, therefore we can
# afford to not run update() in the setup but in its own test
@ -49,12 +40,12 @@ def test_first_update():
def test_images():
assert warning_emitted('images', 'image file not readable: foo.png')
assert warning_emitted('images', 'nonlocal image URI found: '
'http://www.python.org/logo.png')
assert ('image file not readable: foo.png'
in app._warning.getvalue())
assert ('nonlocal image URI found: http://www.python.org/logo.png'
in app._warning.getvalue())
tree = env.get_doctree('images')
app._warning.reset()
htmlbuilder = StandaloneHTMLBuilder(app)
htmlbuilder.imgpath = 'dummy'
htmlbuilder.post_process_images(tree)
@ -64,7 +55,6 @@ def test_images():
assert set(htmlbuilder.images.values()) == \
set(['img.png', 'img1.png', 'simg.png', 'svgimg.svg', 'img.foo.png'])
app._warning.reset()
latexbuilder = LaTeXBuilder(app)
latexbuilder.post_process_images(tree)
assert set(latexbuilder.images.keys()) == \

View File

@ -296,9 +296,10 @@ def test_output_with_unencodable_char(app, status, warning):
self.stream.write(object.encode('cp1252').decode('cp1252'))
logging.setup(app, StreamWriter(status), warning)
logger = logging.getLogger(__name__)
# info with UnicodeEncodeError
status.truncate(0)
status.seek(0)
app.info(u"unicode \u206d...")
logger.info(u"unicode \u206d...")
assert status.getvalue() == "unicode ?...\n"