From bc4bd773a0374fd0d169d41666b6c16b67219474 Mon Sep 17 00:00:00 2001 From: Deniz Turgut Date: Sat, 13 Apr 2013 16:36:05 -0400 Subject: [PATCH 1/2] remove unittest2 and fix various warnings in py3 --- .travis.yml | 5 ++--- pelican/readers.py | 17 +++++++++------- pelican/settings.py | 28 ++++++++++++++++---------- pelican/tests/support.py | 6 +----- pelican/tests/test_generators.py | 14 ++++++------- pelican/tests/test_importer.py | 12 ++++++++--- pelican/tests/test_readers.py | 34 ++++++++++++++++---------------- pelican/tests/test_utils.py | 14 ++++++------- pelican/tools/pelican_import.py | 4 +++- pelican/utils.py | 3 ++- 10 files changed, 76 insertions(+), 61 deletions(-) diff --git a/.travis.yml b/.travis.yml index 19cb7e89..608979c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,7 @@ before_install: - sudo apt-get install -qq --no-install-recommends asciidoc install: - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then ln -s /usr/share/asciidoc/asciidocapi.py ~/virtualenv/python2.7/lib/python2.7/site-packages/; fi - - pip install nose mock --use-mirrors - - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors unittest2; else pip install --use-mirrors unittest2py3k; fi + - pip install mock --use-mirrors - pip install . --use-mirrors - pip install --use-mirrors Markdown -script: nosetests -s pelican +script: python -m unittest discover diff --git a/pelican/readers.py b/pelican/readers.py index 6c23ce19..d075a039 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -22,8 +22,10 @@ try: asciidoc = True except ImportError: asciidoc = False - -import cgi +try: + from html import escape +except ImportError: + from cgi import escape try: from html.parser import HTMLParser except ImportError: @@ -122,7 +124,8 @@ class RstReader(Reader): def _get_publisher(self, source_path): extra_params = {'initial_header_level': '2', - 'syntax_highlight': 'short'} + 'syntax_highlight': 'short', + 'input_encoding': 'utf-8'} pub = docutils.core.Publisher( destination_class=docutils.io.StringOutput) pub.set_components('standalone', 'restructuredtext', 'html') @@ -229,7 +232,7 @@ class HTMLReader(Reader): self._in_body = False self._in_top_level = True elif self._in_body: - self._data_buffer += ''.format(cgi.escape(tag)) + self._data_buffer += ''.format(escape(tag)) def handle_startendtag(self, tag, attrs): if tag == 'meta' and self._in_head: @@ -250,11 +253,11 @@ class HTMLReader(Reader): self._data_buffer += '&#{};'.format(data) def build_tag(self, tag, attrs, close_tag): - result = '<{}'.format(cgi.escape(tag)) + result = '<{}'.format(escape(tag)) for k, v in attrs: - result += ' ' + cgi.escape(k) + result += ' ' + escape(k) if v is not None: - result += '="{}"'.format(cgi.escape(v)) + result += '="{}"'.format(escape(v)) if close_tag: return result + ' />' return result + '>' diff --git a/pelican/settings.py b/pelican/settings.py index 319df7f8..9f853393 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -3,12 +3,20 @@ from __future__ import unicode_literals, print_function import six import copy -import imp import inspect import os import locale import logging +try: + # SourceFileLoader is the recommended way in 3.3+ + from importlib.machinery import SourceFileLoader + load_source = lambda name, path: SourceFileLoader(name, path).load_module() +except ImportError: + # but it does not exist in 3.2-, so fall back to imp + import imp + load_source = imp.load_source + from os.path import isabs @@ -130,7 +138,7 @@ def get_settings_from_file(path, default_settings=_DEFAULT_CONFIG): """Loads settings from a file path, returning a dict.""" name, ext = os.path.splitext(os.path.basename(path)) - module = imp.load_source(name, path) + module = load_source(name, path) return get_settings_from_module(module, default_settings=default_settings) @@ -172,14 +180,14 @@ def configure_settings(settings): except locale.Error: pass else: - logger.warn("LOCALE option doesn't contain a correct value") + logger.warning("LOCALE option doesn't contain a correct value") if ('SITEURL' in settings): # If SITEURL has a trailing slash, remove it and provide a warning siteurl = settings['SITEURL'] if (siteurl.endswith('/')): settings['SITEURL'] = siteurl[:-1] - logger.warn("Removed extraneous trailing slash from SITEURL.") + logger.warning("Removed extraneous trailing slash from SITEURL.") # If SITEURL is defined but FEED_DOMAIN isn't, # set FEED_DOMAIN to SITEURL if not 'FEED_DOMAIN' in settings: @@ -195,24 +203,24 @@ def configure_settings(settings): if any(settings.get(k) for k in feed_keys): if not settings.get('FEED_DOMAIN'): - logger.warn( + logger.warning( "Since feed URLs should always be absolute, you should specify" " FEED_DOMAIN in your settings. (e.g., 'FEED_DOMAIN = " "http://www.example.com')") if not settings.get('SITEURL'): - logger.warn('Feeds generated without SITEURL set properly may not' + logger.warning('Feeds generated without SITEURL set properly may not' ' be valid') if not 'TIMEZONE' in settings: - logger.warn( + logger.warning( 'No timezone information specified in the settings. Assuming' ' your timezone is UTC for feed generation. Check ' 'http://docs.notmyidea.org/alexis/pelican/settings.html#timezone ' 'for more information') if 'LESS_GENERATOR' in settings: - logger.warn( + logger.warning( 'The LESS_GENERATOR setting has been removed in favor ' 'of the Webassets plugin') @@ -221,7 +229,7 @@ def configure_settings(settings): six.string_types): settings['OUTPUT_SOURCES_EXTENSION'] = ( _DEFAULT_CONFIG['OUTPUT_SOURCES_EXTENSION']) - logger.warn( + logger.warning( 'Detected misconfiguration with OUTPUT_SOURCES_EXTENSION, ' 'falling back to the default extension ' + _DEFAULT_CONFIG['OUTPUT_SOURCES_EXTENSION']) @@ -252,7 +260,7 @@ def configure_settings(settings): 'THEME_STATIC_PATHS',) for PATH_KEY in filter(lambda k: k in settings, path_keys): if isinstance(settings[PATH_KEY], six.string_types): - logger.warn("Detected misconfiguration with %s setting (must " + logger.warning("Detected misconfiguration with %s setting (must " "be a list), falling back to the default" % PATH_KEY) settings[PATH_KEY] = _DEFAULT_CONFIG[PATH_KEY] diff --git a/pelican/tests/support.py b/pelican/tests/support.py index b81e6eff..d7466c63 100644 --- a/pelican/tests/support.py +++ b/pelican/tests/support.py @@ -9,6 +9,7 @@ import sys from six import StringIO import logging from logging.handlers import BufferingHandler +import unittest from functools import wraps from contextlib import contextmanager @@ -18,11 +19,6 @@ from shutil import rmtree from pelican.contents import Article from pelican.settings import _DEFAULT_CONFIG -try: - import unittest2 as unittest -except ImportError: - import unittest - @contextmanager def temporary_folder(): diff --git a/pelican/tests/test_generators.py b/pelican/tests/test_generators.py index 43c9058d..c2a5cc67 100644 --- a/pelican/tests/test_generators.py +++ b/pelican/tests/test_generators.py @@ -91,7 +91,7 @@ class TestArticlesGenerator(unittest.TestCase): ['This is a super article !', 'published', 'yeah', 'article'], ['マックOS X 10.8でパイソンとVirtualenvをインストールと設定', 'published', '指導書', 'article'] ] - self.assertItemsEqual(articles_expected, articles) + self.assertEqual(sorted(articles_expected), sorted(articles)) def test_generate_categories(self): @@ -99,7 +99,7 @@ class TestArticlesGenerator(unittest.TestCase): categories = [cat.name for cat, _ in generator.categories] categories_expected = ['Default', 'TestCategory', 'Yeah', 'test', 'yeah', '指導書'] - self.assertEquals(categories, categories_expected) + self.assertEqual(categories, categories_expected) def test_do_not_use_folder_as_category(self): @@ -115,7 +115,7 @@ class TestArticlesGenerator(unittest.TestCase): generator.generate_context() categories = [cat.name for cat, _ in generator.categories] - self.assertEquals(categories, ['Default', 'Yeah', 'test', 'yeah', '指導書']) + self.assertEqual(categories, ['Default', 'Yeah', 'test', 'yeah', '指導書']) def test_direct_templates_save_as_default(self): @@ -172,7 +172,7 @@ class TestArticlesGenerator(unittest.TestCase): class TestPageGenerator(unittest.TestCase): # Note: Every time you want to test for a new field; Make sure the test # pages in "TestPages" have all the fields Add it to distilled in - # distill_pages Then update the assertItemsEqual in test_generate_context + # distill_pages Then update the assertEqual in test_generate_context # to match expected def distill_pages(self, pages): @@ -211,8 +211,8 @@ class TestPageGenerator(unittest.TestCase): 'custom'] ] - self.assertItemsEqual(pages_expected, pages) - self.assertItemsEqual(hidden_pages_expected, hidden_pages) + self.assertEqual(sorted(pages_expected), sorted(pages)) + self.assertEqual(sorted(hidden_pages_expected), sorted(hidden_pages)) class TestTemplatePagesGenerator(unittest.TestCase): @@ -256,4 +256,4 @@ class TestTemplatePagesGenerator(unittest.TestCase): # output content is correct with open(output_path, 'r') as output_file: - self.assertEquals(output_file.read(), 'foo: bar') + self.assertEqual(output_file.read(), 'foo: bar') diff --git a/pelican/tests/test_importer.py b/pelican/tests/test_importer.py index 61424774..c18f447f 100644 --- a/pelican/tests/test_importer.py +++ b/pelican/tests/test_importer.py @@ -36,7 +36,9 @@ class TestWordpressXmlImporter(unittest.TestCase): self.assertTrue(title.strip()) def test_can_toggle_raw_html_code_parsing(self): - r = lambda f: open(f).read() + def r(f): + with open(f) as infile: + return infile.read() silent_f2p = mute(True)(fields2pelican) with temporary_folder() as temp: @@ -76,7 +78,9 @@ class TestWordpressXmlImporter(unittest.TestCase): self.assertEqual(decode_wp_content(encoded_content, br=False), decoded_content) def test_preserve_verbatim_formatting(self): - r = lambda f: open(f).read() + def r(f): + with open(f) as infile: + return infile.read() silent_f2p = mute(True)(fields2pelican) test_post = filter(lambda p: p[0].startswith("Code in List"), self.posts) with temporary_folder() as temp: @@ -89,7 +93,9 @@ class TestWordpressXmlImporter(unittest.TestCase): self.assertTrue(for_line.rindex('for') < print_line.rindex('print')) def test_code_in_list(self): - r = lambda f: open(f).read() + def r(f): + with open(f) as infile: + return infile.read() silent_f2p = mute(True)(fields2pelican) test_post = filter(lambda p: p[0].startswith("Code in List"), self.posts) with temporary_folder() as temp: diff --git a/pelican/tests/test_readers.py b/pelican/tests/test_readers.py index 9c644541..49fe0c81 100644 --- a/pelican/tests/test_readers.py +++ b/pelican/tests/test_readers.py @@ -33,7 +33,7 @@ class RstReaderTest(unittest.TestCase): } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) def test_article_with_filename_metadata(self): content, metadata = readers.read_file( @@ -45,7 +45,7 @@ class RstReaderTest(unittest.TestCase): 'title': 'Rst with filename metadata', } for key, value in metadata.items(): - self.assertEquals(value, expected[key], key) + self.assertEqual(value, expected[key], key) content, metadata = readers.read_file( _path('2012-11-29_rst_w_filename_meta#foo-bar.rst'), @@ -59,7 +59,7 @@ class RstReaderTest(unittest.TestCase): 'date': datetime.datetime(2012, 11, 29), } for key, value in metadata.items(): - self.assertEquals(value, expected[key], key) + self.assertEqual(value, expected[key], key) content, metadata = readers.read_file( _path('2012-11-29_rst_w_filename_meta#foo-bar.rst'), @@ -77,7 +77,7 @@ class RstReaderTest(unittest.TestCase): 'mymeta': 'foo', } for key, value in metadata.items(): - self.assertEquals(value, expected[key], key) + self.assertEqual(value, expected[key], key) def test_article_metadata_key_lowercase(self): # Keys of metadata should be lowercase. @@ -86,7 +86,7 @@ class RstReaderTest(unittest.TestCase): _path('article_with_uppercase_metadata.rst')) self.assertIn('category', metadata, 'Key should be lowercase.') - self.assertEquals('Yeah', metadata.get('category'), + self.assertEqual('Yeah', metadata.get('category'), 'Value keeps case.') def test_typogrify(self): @@ -129,7 +129,7 @@ class MdReaderTest(unittest.TestCase): 'tags': ['foo', 'bar', 'foobar'], } for key, value in metadata.items(): - self.assertEquals(value, expected[key], key) + self.assertEqual(value, expected[key], key) content, metadata = reader.read( _path('article_with_markdown_and_nonascii_summary.md')) @@ -142,7 +142,7 @@ class MdReaderTest(unittest.TestCase): 'slug': 'python-virtualenv-on-mac-osx-mountain-lion-10.8', } for key, value in metadata.items(): - self.assertEquals(value, expected[key], key) + self.assertEqual(value, expected[key], key) @unittest.skipUnless(readers.Markdown, "markdown isn't installed") def test_article_with_file_extensions(self): @@ -203,7 +203,7 @@ class MdReaderTest(unittest.TestCase): 'author': 'Alexis Métaireau', } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) content, metadata = readers.read_file( _path('2012-11-30_md_w_filename_meta#foo-bar.md'), @@ -216,7 +216,7 @@ class MdReaderTest(unittest.TestCase): 'date': datetime.datetime(2012, 11, 30), } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) content, metadata = readers.read_file( _path('2012-11-30_md_w_filename_meta#foo-bar.md'), @@ -233,7 +233,7 @@ class MdReaderTest(unittest.TestCase): 'mymeta': 'foo', } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) class AdReaderTest(unittest.TestCase): @@ -258,7 +258,7 @@ class AdReaderTest(unittest.TestCase): } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) expected = { 'category': 'Blog', @@ -269,7 +269,7 @@ class AdReaderTest(unittest.TestCase): } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) @unittest.skipUnless(readers.asciidoc, "asciidoc isn't installed") def test_article_with_asc_options(self): @@ -289,7 +289,7 @@ class HTMLReaderTest(unittest.TestCase): reader = readers.HTMLReader({}) content, metadata = reader.read(_path('article_with_comments.html')) - self.assertEquals(''' + self.assertEqual(''' Body content ''', content) @@ -302,7 +302,7 @@ class HTMLReaderTest(unittest.TestCase): } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) def test_article_with_metadata(self): reader = readers.HTMLReader({}) @@ -318,14 +318,14 @@ class HTMLReaderTest(unittest.TestCase): } for key, value in expected.items(): - self.assertEquals(value, metadata[key], key) + self.assertEqual(value, metadata[key], key) def test_article_with_null_attributes(self): reader = readers.HTMLReader({}) content, metadata = reader.read( _path('article_with_null_attributes.html')) - self.assertEquals(''' + self.assertEqual(''' Ensure that empty attributes are copied properly. ''', content) @@ -336,5 +336,5 @@ class HTMLReaderTest(unittest.TestCase): content, metadata = reader.read( _path('article_with_uppercase_metadata.html')) self.assertIn('category', metadata, 'Key should be lowercase.') - self.assertEquals('Yeah', metadata.get('category'), + self.assertEqual('Yeah', metadata.get('category'), 'Value keeps cases.') diff --git a/pelican/tests/test_utils.py b/pelican/tests/test_utils.py index 9865b10b..f5e530f3 100644 --- a/pelican/tests/test_utils.py +++ b/pelican/tests/test_utils.py @@ -22,7 +22,7 @@ class TestUtils(LoggedTestCase): def test_deprecated_attribute(self): value = self._old_attribute - self.assertEquals(value, self._new_attribute) + self.assertEqual(value, self._new_attribute) self.assertLogCountEqual( count=1, msg=('_old_attribute has been deprecated since 3.1.0 and will be ' @@ -48,7 +48,7 @@ class TestUtils(LoggedTestCase): '2012-11-22 22:11:10': date_hour_sec} for value, expected in dates.items(): - self.assertEquals(utils.get_date(value), expected, value) + self.assertEqual(utils.get_date(value), expected, value) # invalid ones invalid_dates = ('2010-110-12', 'yay') @@ -67,7 +67,7 @@ class TestUtils(LoggedTestCase): 'da-fan-yuan-fa-4hao-ji-18ri-ye-qi-dong-he'),) for value, expected in samples: - self.assertEquals(utils.slugify(value), expected) + self.assertEqual(utils.slugify(value), expected) def test_get_relative_path(self): @@ -81,7 +81,7 @@ class TestUtils(LoggedTestCase): ('/test.html', os.curdir),) for value, expected in samples: - self.assertEquals(utils.get_relative_path(value), expected) + self.assertEqual(utils.get_relative_path(value), expected) def test_process_translations(self): # create a bunch of articles @@ -132,15 +132,15 @@ class TestUtils(LoggedTestCase): dirname = os.path.join(os.path.dirname(__file__), 'content') path = os.path.join(dirname, 'article_with_metadata.rst') changed = utils.files_changed(dirname, 'rst') - self.assertEquals(changed, True) + self.assertEqual(changed, True) changed = utils.files_changed(dirname, 'rst') - self.assertEquals(changed, False) + self.assertEqual(changed, False) t = time.time() os.utime(path, (t, t)) changed = utils.files_changed(dirname, 'rst') - self.assertEquals(changed, True) + self.assertEqual(changed, True) self.assertAlmostEqual(utils.LAST_MTIME, t, delta=1) empty_path = os.path.join(os.path.dirname(__file__), 'empty') diff --git a/pelican/tools/pelican_import.py b/pelican/tools/pelican_import.py index a3bac84c..31db20be 100755 --- a/pelican/tools/pelican_import.py +++ b/pelican/tools/pelican_import.py @@ -102,7 +102,9 @@ def wp2fields(xml): '"BeautifulSoup4" and "lxml" required to import Wordpress XML files.') sys.exit(error) - xmlfile = open(xml, encoding='utf-8').read() + + with open(xml, encoding='utf-8') as infile: + xmlfile = infile.read() soup = BeautifulSoup(xmlfile, "xml") items = soup.rss.channel.findAll('item') diff --git a/pelican/utils.py b/pelican/utils.py index 73abd358..7e7b9ccb 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -192,7 +192,8 @@ class pelican_open(object): self.filename = filename def __enter__(self): - content = open(self.filename, encoding='utf-8').read() + with open(self.filename, encoding='utf-8') as infile: + content = infile.read() if content[0] == BOM_UTF8.decode('utf8'): content = content[1:] return content From 68921fe94d307cfb8c80d8f3292d9f8464260794 Mon Sep 17 00:00:00 2001 From: Deniz Turgut Date: Sat, 13 Apr 2013 17:07:48 -0400 Subject: [PATCH 2/2] remove warning for FEED_DOMAIN when SITEURL undefined --- pelican/settings.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pelican/settings.py b/pelican/settings.py index 9f853393..989644fc 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -202,12 +202,6 @@ def configure_settings(settings): ] if any(settings.get(k) for k in feed_keys): - if not settings.get('FEED_DOMAIN'): - logger.warning( - "Since feed URLs should always be absolute, you should specify" - " FEED_DOMAIN in your settings. (e.g., 'FEED_DOMAIN = " - "http://www.example.com')") - if not settings.get('SITEURL'): logger.warning('Feeds generated without SITEURL set properly may not' ' be valid')