From e50abb20b3c6debd9fc35da83b637422437c7e7c Mon Sep 17 00:00:00 2001 From: derwinlu Date: Mon, 19 Oct 2015 22:38:23 +0200 Subject: [PATCH 1/7] Add logging for warnings during test suite run The default configuration for the warnings module changed some time ago so we lost the ability to detect deprecation warnings and such early. This commit sets up the test suite to redirect all warnings through our logging system. Additionally we enable DeprecationWarnings as a default and throw exceptions on all warnings related to pelican modules. This enables output of warnings related to dependencies, while letting tests only fail if the warnings are originating from pelican's source. Also adding a test to detect if warnings cause an Exception as expected. --- pelican/log.py | 24 +++++++++++++++++------- pelican/tests/__init__.py | 13 +++++++++++++ pelican/tests/test_testsuite.py | 16 ++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 pelican/tests/test_testsuite.py diff --git a/pelican/log.py b/pelican/log.py index 0f4b795b..ddeeb6d0 100644 --- a/pelican/log.py +++ b/pelican/log.py @@ -172,21 +172,31 @@ class LimitLogger(SafeLogger): logging.setLoggerClass(LimitLogger) -def init(level=None, handler=logging.StreamHandler()): - - logger = logging.getLogger() - +def get_formatter(): if os.isatty(sys.stdout.fileno()) and not sys.platform.startswith('win'): - fmt = ANSIFormatter() + return ANSIFormatter() else: - fmt = TextFormatter() - handler.setFormatter(fmt) + return TextFormatter() + + +def init(level=None, handler=logging.StreamHandler(), name=None): + + logger = logging.getLogger(name) + + handler.setFormatter(get_formatter()) logger.addHandler(handler) if level: logger.setLevel(level) +def log_warnings(): + import warnings + logging.captureWarnings(True) + warnings.simplefilter("default", DeprecationWarning) + init(logging.DEBUG, name='py.warnings') + + if __name__ == '__main__': init(level=logging.DEBUG) diff --git a/pelican/tests/__init__.py b/pelican/tests/__init__.py index 32353ea2..4605a02b 100644 --- a/pelican/tests/__init__.py +++ b/pelican/tests/__init__.py @@ -1,2 +1,15 @@ import logging +import warnings + +from pelican.log import log_warnings + +# redirect warnings modulole to use logging instead +log_warnings() + +# setup warnings to log DeprecationWarning's and error on +# warnings in pelican's codebase +warnings.simplefilter("default", DeprecationWarning) +warnings.filterwarnings("error", ".*", Warning, "pelican") + +# Add a NullHandler to silence warning about no available handlers logging.getLogger().addHandler(logging.NullHandler()) diff --git a/pelican/tests/test_testsuite.py b/pelican/tests/test_testsuite.py new file mode 100644 index 00000000..5dc92bb1 --- /dev/null +++ b/pelican/tests/test_testsuite.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function, unicode_literals + +import sys +import warnings + +from pelican.tests.support import unittest + + +class TestSuiteTest(unittest.TestCase): + + @unittest.skipIf(sys.version_info[:2] == (3, 3), + "does not throw an exception on python 3.3") + def test_error_on_warning(self): + with self.assertRaises(UserWarning): + warnings.warn('test warning') From 8b299098c95004bbe8079bea95ab4bb05cf53e2b Mon Sep 17 00:00:00 2001 From: derwinlu Date: Mon, 19 Oct 2015 18:33:14 +0200 Subject: [PATCH 2/7] Make HTMLParser Python 3.5 ready --- pelican/utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pelican/utils.py b/pelican/utils.py index cc9eb405..92e819f9 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -424,7 +424,11 @@ class _HTMLWordTruncator(HTMLParser): def __init__(self, max_words): # In Python 2, HTMLParser is not a new-style class, # hence super() cannot be used. - HTMLParser.__init__(self) + try: + HTMLParser.__init__(self, convert_charrefs=False) + except TypeError: + # pre Python 3.3 + HTMLParser.__init__(self) self.max_words = max_words self.words_found = 0 From 2d84c04add032b96092c3e578584a7ab9e503580 Mon Sep 17 00:00:00 2001 From: derwinlu Date: Tue, 20 Oct 2015 10:26:32 +0200 Subject: [PATCH 3/7] Make ReaderTest py2 and py3 compatible --- pelican/tests/test_readers.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pelican/tests/test_readers.py b/pelican/tests/test_readers.py index 5fabc470..6aa777c0 100644 --- a/pelican/tests/test_readers.py +++ b/pelican/tests/test_readers.py @@ -3,6 +3,8 @@ from __future__ import print_function, unicode_literals import os +import six + from pelican import readers from pelican.tests.support import get_settings, unittest from pelican.utils import SafeDatetime @@ -55,7 +57,8 @@ class TestAssertDictHasSubset(ReaderTest): self.assertDictHasSubset(self.dictionary, self.dictionary) def test_fail_not_set(self): - self.assertRaisesRegexp( + six.assertRaisesRegex( + self, AssertionError, 'Expected.*key-c.*to have value.*val-c.*but was not in Dict', self.assertDictHasSubset, @@ -63,7 +66,8 @@ class TestAssertDictHasSubset(ReaderTest): {'key-c': 'val-c'}) def test_fail_wrong_val(self): - self.assertRaisesRegexp( + six.assertRaisesRegex( + self, AssertionError, 'Expected .*key-a.* to have value .*val-b.* but was .*val-a.*', self.assertDictHasSubset, From bfafb3a492a16d3e5f3b4fc15a8c79021b889b08 Mon Sep 17 00:00:00 2001 From: derwinlu Date: Mon, 19 Oct 2015 16:30:52 +0200 Subject: [PATCH 4/7] Add python 3.5 testing environment Python 3.5 is not yet fully integrated in travis. Include workaround to enable it for now. --- .travis.yml | 5 +++++ tox.ini | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1be196f2..7bb5a89f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,11 @@ env: - TOX_ENV=py27 - TOX_ENV=py33 - TOX_ENV=py34 +matrix: + include: + - python: 3.5 + env: + - TOX_ENV=py35 addons: apt_packages: - pandoc diff --git a/tox.ini b/tox.ini index 56ad0c14..151fad85 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,12 @@ [tox] -envlist = py{27,33,34},docs,flake8 +envlist = py{27,33,34,35},docs,flake8 [testenv] basepython = py27: python2.7 py33: python3.3 py34: python3.4 + py35: python3.5 passenv = * usedevelop=True deps = From c3f2e888a573b9c8d0887c74ca0b06f6680c9591 Mon Sep 17 00:00:00 2001 From: derwinlu Date: Mon, 19 Oct 2015 19:26:31 +0200 Subject: [PATCH 5/7] Add 3.5 to setup.py tags --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 86028424..99cf7cb0 100755 --- a/setup.py +++ b/setup.py @@ -55,6 +55,7 @@ setup( 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Software Development :: Libraries :: Python Modules', ], From 22ec94ee560ad07fa0cafea9aca9a3c4d13189dc Mon Sep 17 00:00:00 2001 From: derwinlu Date: Tue, 13 Oct 2015 10:31:59 +0200 Subject: [PATCH 6/7] Do not fail tox run if coveralls push fails When tox environments are run locally, coveralls exits with an error code as it is not authenticated to push to coveralls. Adding the - in front allows tox to ignore a fail on this command and not mark the test case as failed. --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 151fad85..609be886 100644 --- a/tox.ini +++ b/tox.ini @@ -18,7 +18,7 @@ deps = commands = {envpython} --version nosetests -sv --with-coverage --cover-package=pelican pelican - coveralls + - coveralls [testenv:docs] basepython = python2.7 From ab2eec854d59a46f1a291bf318e996959fb57172 Mon Sep 17 00:00:00 2001 From: derwinlu Date: Tue, 20 Oct 2015 11:13:02 +0200 Subject: [PATCH 7/7] Redo ANSI support detection When using nose to directly run the test suite it 'steals' stdout per default. This causes the old implementation of ANSI detection to error as stdout does not have a fileno function anymore. --- pelican/log.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pelican/log.py b/pelican/log.py index ddeeb6d0..d99cad88 100644 --- a/pelican/log.py +++ b/pelican/log.py @@ -172,8 +172,26 @@ class LimitLogger(SafeLogger): logging.setLoggerClass(LimitLogger) +def supports_color(): + """ + Returns True if the running system's terminal supports color, + and False otherwise. + + from django.core.management.color + """ + plat = sys.platform + supported_platform = plat != 'Pocket PC' and \ + (plat != 'win32' or 'ANSICON' in os.environ) + + # isatty is not always implemented, #6223. + is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() + if not supported_platform or not is_a_tty: + return False + return True + + def get_formatter(): - if os.isatty(sys.stdout.fileno()) and not sys.platform.startswith('win'): + if supports_color(): return ANSIFormatter() else: return TextFormatter()