mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Fix --fatal to honor LOG_FILTER
This commit is contained in:
parent
ed4dd50864
commit
f5cec6f13e
9 changed files with 63 additions and 51 deletions
|
|
@ -1,3 +1,3 @@
|
|||
Release type: minor
|
||||
Release type: patch
|
||||
|
||||
Add setting to allow for empty `alt` attributes in images; it defaults to `False`, which is the current behavior. Empty `alt` text can be indicative of an accessibility oversight, but can be intentional and desired, e.g. https://webaim.org/techniques/alttext/, https://www.w3.org/WAI/tutorials/images/decorative/.
|
||||
Address an issue where `--fatal=warnings|errors` would not honor entries in the `LOG_FILTER` setting.
|
||||
|
|
@ -364,10 +364,6 @@ Basic settings
|
|||
A list of metadata fields containing reST/Markdown content to be parsed and
|
||||
translated to HTML.
|
||||
|
||||
.. data:: IMAGES_ALLOW_EMPTY_ALT_TEXT = False
|
||||
|
||||
If ``True``, warnings will not be emitted when empty ``alt`` attributes for images are found.
|
||||
|
||||
.. data:: PORT = 8000
|
||||
|
||||
The TCP port to serve content from the output folder via HTTP when pelican
|
||||
|
|
|
|||
|
|
@ -149,24 +149,9 @@ class LimitLogger(logging.Logger):
|
|||
self.addFilter(LimitLogger.limit_filter)
|
||||
|
||||
|
||||
class FatalLogger(LimitLogger):
|
||||
warnings_fatal = False
|
||||
errors_fatal = False
|
||||
|
||||
def warning(self, *args, **kwargs):
|
||||
super().warning(*args, **kwargs)
|
||||
if FatalLogger.warnings_fatal:
|
||||
raise RuntimeError('Warning encountered')
|
||||
|
||||
def error(self, *args, **kwargs):
|
||||
super().error(*args, **kwargs)
|
||||
if FatalLogger.errors_fatal:
|
||||
raise RuntimeError('Error encountered')
|
||||
|
||||
|
||||
logging.setLoggerClass(FatalLogger)
|
||||
logging.setLoggerClass(LimitLogger)
|
||||
# force root logger to be of our preferred class
|
||||
logging.getLogger().__class__ = FatalLogger
|
||||
logging.getLogger().__class__ = LimitLogger
|
||||
|
||||
|
||||
def supports_color():
|
||||
|
|
@ -194,11 +179,13 @@ def get_formatter():
|
|||
return TextFormatter()
|
||||
|
||||
|
||||
class FatalHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def init(level=None, fatal='', handler=logging.StreamHandler(), name=None,
|
||||
logs_dedup_min_level=None):
|
||||
FatalLogger.warnings_fatal = fatal.startswith('warning')
|
||||
FatalLogger.errors_fatal = bool(fatal)
|
||||
|
||||
logger = logging.getLogger(name)
|
||||
|
||||
handler.setFormatter(get_formatter())
|
||||
|
|
@ -209,6 +196,11 @@ def init(level=None, fatal='', handler=logging.StreamHandler(), name=None,
|
|||
if logs_dedup_min_level:
|
||||
LimitFilter.LOGS_DEDUP_MIN_LEVEL = logs_dedup_min_level
|
||||
|
||||
if fatal.startswith('warning'):
|
||||
logger.addHandler(FatalHandler(level=logging.WARNING))
|
||||
if fatal:
|
||||
logger.addHandler(FatalHandler(level=logging.ERROR))
|
||||
|
||||
|
||||
def log_warnings():
|
||||
import warnings
|
||||
|
|
|
|||
|
|
@ -574,7 +574,7 @@ class Readers(FileStampDataCacher):
|
|||
self.cache_data(path, (content, reader_metadata))
|
||||
metadata.update(_filter_discardable_metadata(reader_metadata))
|
||||
|
||||
if not self.settings['IMAGES_ALLOW_EMPTY_ALT_TEXT'] and content:
|
||||
if content:
|
||||
# find images with empty alt
|
||||
find_empty_alt(content, path)
|
||||
|
||||
|
|
|
|||
|
|
@ -163,8 +163,7 @@ DEFAULT_CONFIG = {
|
|||
'WRITE_SELECTED': [],
|
||||
'FORMATTED_FIELDS': ['summary'],
|
||||
'PORT': 8000,
|
||||
'BIND': '127.0.0.1',
|
||||
'IMAGES_ALLOW_EMPTY_ALT_TEXT': False
|
||||
'BIND': '127.0.0.1'
|
||||
}
|
||||
|
||||
PYGMENTS_RST_OPTIONS = None
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
Images
|
||||
<img alt="" src="test-image.png" width="300px" />
|
||||
<img src="test-image.png" width="300px" alt="" />
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -153,7 +153,7 @@ class TestCache(unittest.TestCase):
|
|||
- empty.md
|
||||
- empty_with_bom.md
|
||||
"""
|
||||
self.assertEqual(generator.readers.read_file.call_count, 7)
|
||||
self.assertEqual(generator.readers.read_file.call_count, 6)
|
||||
|
||||
def test_article_reader_content_caching(self):
|
||||
"""Test raw article content caching at the reader level"""
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import logging
|
|||
import unittest
|
||||
from collections import defaultdict
|
||||
from contextlib import contextmanager
|
||||
from unittest import mock
|
||||
|
||||
from pelican import log
|
||||
from pelican.tests.support import LogCountHandler
|
||||
|
|
@ -130,3 +131,48 @@ class TestLog(unittest.TestCase):
|
|||
self.assertEqual(
|
||||
self.handler.count_logs('Another log \\d', logging.WARNING),
|
||||
0)
|
||||
|
||||
|
||||
@mock.patch.object(log, 'sys')
|
||||
class TestLogInit(unittest.TestCase):
|
||||
def init(self, fatal, name):
|
||||
logger = logging.getLogger(name)
|
||||
log.init(fatal=fatal, name=name)
|
||||
return logger
|
||||
|
||||
def test_fatal_warnings(self, sys):
|
||||
logger = self.init('warnings', 'test_fatal_warnings')
|
||||
logger.warning('foo')
|
||||
logger.error('bar')
|
||||
sys.exit.assert_called_with(1)
|
||||
|
||||
def test_fatal_errors(self, sys):
|
||||
logger = self.init('errors', 'test_fatal_errors')
|
||||
logger.warning('foo')
|
||||
logger.error('bar')
|
||||
sys.exit.assert_called_with(1)
|
||||
|
||||
def test_no_fatal(self, sys):
|
||||
logger = self.init('', 'test_no_fatal')
|
||||
logger.warning('foo')
|
||||
logger.error('bar')
|
||||
sys.exit.assert_not_called()
|
||||
|
||||
def test_fatal_warnings_log_filter(self, sys):
|
||||
limit_filter = log.LimitFilter()
|
||||
limit_filter._ignore = {(logging.WARNING, 'foo')}
|
||||
lf = mock.PropertyMock(return_value=limit_filter)
|
||||
with mock.patch('pelican.log.LimitLogger.limit_filter', new=lf):
|
||||
logger = self.init('warnings', 'test_fatal_warnings_log_filter')
|
||||
logger.warning('foo')
|
||||
sys.exit.assert_not_called()
|
||||
|
||||
def test_fatal_errors_log_filter(self, sys):
|
||||
limit_filter = log.LimitFilter()
|
||||
limit_filter.LOGS_DEDUP_MIN_LEVEL = logging.CRITICAL
|
||||
limit_filter._ignore = {(logging.ERROR, 'bar')}
|
||||
lf = mock.PropertyMock(return_value=limit_filter)
|
||||
with mock.patch('pelican.log.LimitLogger.limit_filter', new=lf):
|
||||
logger = self.init('errors', 'test_fatal_errors_log_filter')
|
||||
logger.error('bar')
|
||||
sys.exit.assert_not_called()
|
||||
|
|
|
|||
|
|
@ -134,18 +134,6 @@ class DefaultReaderTest(ReaderTest):
|
|||
'Other images have empty alt attributes'}
|
||||
)
|
||||
|
||||
@patch('pelican.readers.logger')
|
||||
def test_read_file_with_images_allow_empty_alt_text_false(self, log_mock):
|
||||
test_file = 'article_with_images.html'
|
||||
self.read_file(path=test_file, IMAGES_ALLOW_EMPTY_ALT_TEXT=False)
|
||||
assert 2 == log_mock.warning.call_count
|
||||
|
||||
@patch('pelican.readers.logger')
|
||||
def test_read_file_with_images_allow_empty_alt_text_true(self, log_mock):
|
||||
test_file = 'article_with_images.html'
|
||||
self.read_file(path=test_file, IMAGES_ALLOW_EMPTY_ALT_TEXT=True)
|
||||
log_mock.warning.assert_not_called()
|
||||
|
||||
|
||||
class RstReaderTest(ReaderTest):
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue