forked from github/pelican
Add unit test utilities temporary_locale and TestCaseWithCLocale (#3224)
This commit is contained in:
parent
fec78ebf33
commit
fad2ff7ae3
5 changed files with 111 additions and 119 deletions
|
|
@ -254,3 +254,16 @@ class LoggedTestCase(unittest.TestCase):
|
|||
actual, count,
|
||||
msg='expected {} occurrences of {!r}, but found {}'.format(
|
||||
count, msg, actual))
|
||||
|
||||
|
||||
class TestCaseWithCLocale(unittest.TestCase):
|
||||
"""Set locale to C for each test case, then restore afterward.
|
||||
|
||||
Use utils.temporary_locale if you want a context manager ("with" statement).
|
||||
"""
|
||||
def setUp(self):
|
||||
self.old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
|
||||
def tearDown(self):
|
||||
locale.setlocale(locale.LC_ALL, self.old_locale)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import locale
|
||||
import os
|
||||
import sys
|
||||
from shutil import copy, rmtree
|
||||
|
|
@ -9,26 +8,21 @@ from pelican.generators import (ArticlesGenerator, Generator, PagesGenerator,
|
|||
PelicanTemplateNotFound, StaticGenerator,
|
||||
TemplatePagesGenerator)
|
||||
from pelican.tests.support import (can_symlink, get_context, get_settings,
|
||||
unittest)
|
||||
unittest, TestCaseWithCLocale)
|
||||
from pelican.writers import Writer
|
||||
|
||||
|
||||
CUR_DIR = os.path.dirname(__file__)
|
||||
CONTENT_DIR = os.path.join(CUR_DIR, 'content')
|
||||
|
||||
|
||||
class TestGenerator(unittest.TestCase):
|
||||
class TestGenerator(TestCaseWithCLocale):
|
||||
def setUp(self):
|
||||
self.old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
super().setUp()
|
||||
self.settings = get_settings()
|
||||
self.settings['READERS'] = {'asc': None}
|
||||
self.generator = Generator(self.settings.copy(), self.settings,
|
||||
CUR_DIR, self.settings['THEME'], None)
|
||||
|
||||
def tearDown(self):
|
||||
locale.setlocale(locale.LC_ALL, self.old_locale)
|
||||
|
||||
def test_include_path(self):
|
||||
self.settings['IGNORE_FILES'] = {'ignored1.rst', 'ignored2.rst'}
|
||||
|
||||
|
|
@ -408,8 +402,6 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
def test_period_archives_context(self):
|
||||
"""Test correctness of the period_archives context values."""
|
||||
|
||||
old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
settings = get_settings()
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
|
||||
|
|
@ -532,15 +524,11 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
self.assertEqual(sample_archive['dates'][0].title, dates[0].title)
|
||||
self.assertEqual(sample_archive['dates'][0].date, dates[0].date)
|
||||
|
||||
locale.setlocale(locale.LC_ALL, old_locale)
|
||||
|
||||
def test_period_in_timeperiod_archive(self):
|
||||
"""
|
||||
Test that the context of a generated period_archive is passed
|
||||
'period' : a tuple of year, month, day according to the time period
|
||||
"""
|
||||
old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
settings = get_settings()
|
||||
|
||||
settings['YEAR_ARCHIVE_SAVE_AS'] = 'posts/{date:%Y}/index.html'
|
||||
|
|
@ -625,7 +613,6 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
dates=dates, template_name='period_archives',
|
||||
url="posts/1970/Jan/01/",
|
||||
all_articles=generator.articles)
|
||||
locale.setlocale(locale.LC_ALL, old_locale)
|
||||
|
||||
def test_nonexistent_template(self):
|
||||
"""Attempt to load a non-existent template"""
|
||||
|
|
@ -926,20 +913,18 @@ class TestPageGenerator(unittest.TestCase):
|
|||
context['static_links'])
|
||||
|
||||
|
||||
class TestTemplatePagesGenerator(unittest.TestCase):
|
||||
class TestTemplatePagesGenerator(TestCaseWithCLocale):
|
||||
|
||||
TEMPLATE_CONTENT = "foo: {{ foo }}"
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.temp_content = mkdtemp(prefix='pelicantests.')
|
||||
self.temp_output = mkdtemp(prefix='pelicantests.')
|
||||
self.old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
|
||||
def tearDown(self):
|
||||
rmtree(self.temp_content)
|
||||
rmtree(self.temp_output)
|
||||
locale.setlocale(locale.LC_ALL, self.old_locale)
|
||||
|
||||
def test_generate_output(self):
|
||||
|
||||
|
|
@ -1299,18 +1284,15 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
self.assertTrue(os.path.isfile(self.endfile))
|
||||
|
||||
|
||||
class TestJinja2Environment(unittest.TestCase):
|
||||
class TestJinja2Environment(TestCaseWithCLocale):
|
||||
|
||||
def setUp(self):
|
||||
self.temp_content = mkdtemp(prefix='pelicantests.')
|
||||
self.temp_output = mkdtemp(prefix='pelicantests.')
|
||||
self.old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
|
||||
def tearDown(self):
|
||||
rmtree(self.temp_content)
|
||||
rmtree(self.temp_output)
|
||||
locale.setlocale(locale.LC_ALL, self.old_locale)
|
||||
|
||||
def _test_jinja2_helper(self, additional_settings, content, expected):
|
||||
settings = get_settings()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import locale
|
||||
import os
|
||||
import re
|
||||
from posixpath import join as posix_join
|
||||
|
|
@ -6,7 +5,7 @@ from unittest.mock import patch
|
|||
|
||||
from pelican.settings import DEFAULT_CONFIG
|
||||
from pelican.tests.support import (mute, skipIfNoExecutable, temporary_folder,
|
||||
unittest)
|
||||
unittest, TestCaseWithCLocale)
|
||||
from pelican.tools.pelican_import import (blogger2fields, build_header,
|
||||
build_markdown_header,
|
||||
decode_wp_content,
|
||||
|
|
@ -16,7 +15,6 @@ from pelican.tools.pelican_import import (blogger2fields, build_header,
|
|||
)
|
||||
from pelican.utils import path_to_file_url, slugify
|
||||
|
||||
|
||||
CUR_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
BLOGGER_XML_SAMPLE = os.path.join(CUR_DIR, 'content', 'bloggerexport.xml')
|
||||
WORDPRESS_XML_SAMPLE = os.path.join(CUR_DIR, 'content', 'wordpressexport.xml')
|
||||
|
|
@ -38,19 +36,9 @@ except ImportError:
|
|||
LXML = False
|
||||
|
||||
|
||||
class TestWithOsDefaults(unittest.TestCase):
|
||||
"""Set locale to C and timezone to UTC for tests, then restore."""
|
||||
def setUp(self):
|
||||
self.old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
|
||||
def tearDown(self):
|
||||
locale.setlocale(locale.LC_ALL, self.old_locale)
|
||||
|
||||
|
||||
@skipIfNoExecutable(['pandoc', '--version'])
|
||||
@unittest.skipUnless(BeautifulSoup, 'Needs BeautifulSoup module')
|
||||
class TestBloggerXmlImporter(TestWithOsDefaults):
|
||||
class TestBloggerXmlImporter(TestCaseWithCLocale):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
|
@ -95,7 +83,7 @@ class TestBloggerXmlImporter(TestWithOsDefaults):
|
|||
|
||||
@skipIfNoExecutable(['pandoc', '--version'])
|
||||
@unittest.skipUnless(BeautifulSoup, 'Needs BeautifulSoup module')
|
||||
class TestWordpressXmlImporter(TestWithOsDefaults):
|
||||
class TestWordpressXmlImporter(TestCaseWithCLocale):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
|
@ -433,15 +421,11 @@ class TestBuildHeader(unittest.TestCase):
|
|||
|
||||
@unittest.skipUnless(BeautifulSoup, 'Needs BeautifulSoup module')
|
||||
@unittest.skipUnless(LXML, 'Needs lxml module')
|
||||
class TestWordpressXMLAttachements(unittest.TestCase):
|
||||
class TestWordpressXMLAttachements(TestCaseWithCLocale):
|
||||
def setUp(self):
|
||||
self.old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
super().setUp()
|
||||
self.attachments = get_attachments(WORDPRESS_XML_SAMPLE)
|
||||
|
||||
def tearDown(self):
|
||||
locale.setlocale(locale.LC_ALL, self.old_locale)
|
||||
|
||||
def test_recognise_attachments(self):
|
||||
self.assertTrue(self.attachments)
|
||||
self.assertTrue(len(self.attachments.keys()) == 3)
|
||||
|
|
@ -485,7 +469,7 @@ class TestWordpressXMLAttachements(unittest.TestCase):
|
|||
directory)
|
||||
|
||||
|
||||
class TestTumblrImporter(TestWithOsDefaults):
|
||||
class TestTumblrImporter(TestCaseWithCLocale):
|
||||
@patch("pelican.tools.pelican_import._get_tumblr_posts")
|
||||
def test_posts(self, get):
|
||||
def get_posts(api_key, blogname, offset=0):
|
||||
|
|
|
|||
|
|
@ -484,33 +484,25 @@ class TestUtils(LoggedTestCase):
|
|||
locale_available('Turkish'),
|
||||
'Turkish locale needed')
|
||||
def test_strftime_locale_dependent_turkish(self):
|
||||
# store current locale
|
||||
old_locale = locale.setlocale(locale.LC_ALL)
|
||||
temp_locale = 'Turkish' if platform == 'win32' else 'tr_TR.UTF-8'
|
||||
|
||||
if platform == 'win32':
|
||||
locale.setlocale(locale.LC_ALL, 'Turkish')
|
||||
else:
|
||||
locale.setlocale(locale.LC_ALL, 'tr_TR.UTF-8')
|
||||
with utils.temporary_locale(temp_locale):
|
||||
d = utils.SafeDatetime(2012, 8, 29)
|
||||
|
||||
d = utils.SafeDatetime(2012, 8, 29)
|
||||
# simple
|
||||
self.assertEqual(utils.strftime(d, '%d %B %Y'), '29 Ağustos 2012')
|
||||
self.assertEqual(utils.strftime(d, '%A, %d %B %Y'),
|
||||
'Çarşamba, 29 Ağustos 2012')
|
||||
|
||||
# simple
|
||||
self.assertEqual(utils.strftime(d, '%d %B %Y'), '29 Ağustos 2012')
|
||||
self.assertEqual(utils.strftime(d, '%A, %d %B %Y'),
|
||||
'Çarşamba, 29 Ağustos 2012')
|
||||
# with text
|
||||
self.assertEqual(
|
||||
utils.strftime(d, 'Yayınlanma tarihi: %A, %d %B %Y'),
|
||||
'Yayınlanma tarihi: Çarşamba, 29 Ağustos 2012')
|
||||
|
||||
# with text
|
||||
self.assertEqual(
|
||||
utils.strftime(d, 'Yayınlanma tarihi: %A, %d %B %Y'),
|
||||
'Yayınlanma tarihi: Çarşamba, 29 Ağustos 2012')
|
||||
|
||||
# non-ascii format candidate (someone might pass it… for some reason)
|
||||
self.assertEqual(
|
||||
utils.strftime(d, '%Y yılında %üretim artışı'),
|
||||
'2012 yılında %üretim artışı')
|
||||
|
||||
# restore locale back
|
||||
locale.setlocale(locale.LC_ALL, old_locale)
|
||||
# non-ascii format candidate (someone might pass it… for some reason)
|
||||
self.assertEqual(
|
||||
utils.strftime(d, '%Y yılında %üretim artışı'),
|
||||
'2012 yılında %üretim artışı')
|
||||
|
||||
# test the output of utils.strftime in a different locale
|
||||
# French locale
|
||||
|
|
@ -518,34 +510,26 @@ class TestUtils(LoggedTestCase):
|
|||
locale_available('French'),
|
||||
'French locale needed')
|
||||
def test_strftime_locale_dependent_french(self):
|
||||
# store current locale
|
||||
old_locale = locale.setlocale(locale.LC_ALL)
|
||||
temp_locale = 'French' if platform == 'win32' else 'fr_FR.UTF-8'
|
||||
|
||||
if platform == 'win32':
|
||||
locale.setlocale(locale.LC_ALL, 'French')
|
||||
else:
|
||||
locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8')
|
||||
with utils.temporary_locale(temp_locale):
|
||||
d = utils.SafeDatetime(2012, 8, 29)
|
||||
|
||||
d = utils.SafeDatetime(2012, 8, 29)
|
||||
# simple
|
||||
self.assertEqual(utils.strftime(d, '%d %B %Y'), '29 août 2012')
|
||||
|
||||
# simple
|
||||
self.assertEqual(utils.strftime(d, '%d %B %Y'), '29 août 2012')
|
||||
# depending on OS, the first letter is m or M
|
||||
self.assertTrue(utils.strftime(d, '%A') in ('mercredi', 'Mercredi'))
|
||||
|
||||
# depending on OS, the first letter is m or M
|
||||
self.assertTrue(utils.strftime(d, '%A') in ('mercredi', 'Mercredi'))
|
||||
# with text
|
||||
self.assertEqual(
|
||||
utils.strftime(d, 'Écrit le %d %B %Y'),
|
||||
'Écrit le 29 août 2012')
|
||||
|
||||
# with text
|
||||
self.assertEqual(
|
||||
utils.strftime(d, 'Écrit le %d %B %Y'),
|
||||
'Écrit le 29 août 2012')
|
||||
|
||||
# non-ascii format candidate (someone might pass it… for some reason)
|
||||
self.assertEqual(
|
||||
utils.strftime(d, '%écrits en %Y'),
|
||||
'%écrits en 2012')
|
||||
|
||||
# restore locale back
|
||||
locale.setlocale(locale.LC_ALL, old_locale)
|
||||
# non-ascii format candidate (someone might pass it… for some reason)
|
||||
self.assertEqual(
|
||||
utils.strftime(d, '%écrits en %Y'),
|
||||
'%écrits en 2012')
|
||||
|
||||
def test_maybe_pluralize(self):
|
||||
self.assertEqual(
|
||||
|
|
@ -558,6 +542,23 @@ class TestUtils(LoggedTestCase):
|
|||
utils.maybe_pluralize(2, 'Article', 'Articles'),
|
||||
'2 Articles')
|
||||
|
||||
def test_temporary_locale(self):
|
||||
# test with default LC category
|
||||
orig_locale = locale.setlocale(locale.LC_ALL)
|
||||
|
||||
with utils.temporary_locale('C'):
|
||||
self.assertEqual(locale.setlocale(locale.LC_ALL), 'C')
|
||||
|
||||
self.assertEqual(locale.setlocale(locale.LC_ALL), orig_locale)
|
||||
|
||||
# test with custom LC category
|
||||
orig_locale = locale.setlocale(locale.LC_TIME)
|
||||
|
||||
with utils.temporary_locale('C', locale.LC_TIME):
|
||||
self.assertEqual(locale.setlocale(locale.LC_TIME), 'C')
|
||||
|
||||
self.assertEqual(locale.setlocale(locale.LC_TIME), orig_locale)
|
||||
|
||||
|
||||
class TestCopy(unittest.TestCase):
|
||||
'''Tests the copy utility'''
|
||||
|
|
@ -673,27 +674,27 @@ class TestDateFormatter(unittest.TestCase):
|
|||
def test_french_strftime(self):
|
||||
# This test tries to reproduce an issue that
|
||||
# occurred with python3.3 under macos10 only
|
||||
if platform == 'win32':
|
||||
locale.setlocale(locale.LC_ALL, 'French')
|
||||
else:
|
||||
locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8')
|
||||
date = utils.SafeDatetime(2014, 8, 14)
|
||||
# we compare the lower() dates since macos10 returns
|
||||
# "Jeudi" for %A whereas linux reports "jeudi"
|
||||
self.assertEqual(
|
||||
'jeudi, 14 août 2014',
|
||||
utils.strftime(date, date_format="%A, %d %B %Y").lower())
|
||||
df = utils.DateFormatter()
|
||||
self.assertEqual(
|
||||
'jeudi, 14 août 2014',
|
||||
df(date, date_format="%A, %d %B %Y").lower())
|
||||
temp_locale = 'French' if platform == 'win32' else 'fr_FR.UTF-8'
|
||||
|
||||
with utils.temporary_locale(temp_locale):
|
||||
date = utils.SafeDatetime(2014, 8, 14)
|
||||
# we compare the lower() dates since macos10 returns
|
||||
# "Jeudi" for %A whereas linux reports "jeudi"
|
||||
self.assertEqual(
|
||||
'jeudi, 14 août 2014',
|
||||
utils.strftime(date, date_format="%A, %d %B %Y").lower())
|
||||
df = utils.DateFormatter()
|
||||
self.assertEqual(
|
||||
'jeudi, 14 août 2014',
|
||||
df(date, date_format="%A, %d %B %Y").lower())
|
||||
|
||||
# Let us now set the global locale to C:
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
# DateFormatter should still work as expected
|
||||
# since it is the whole point of DateFormatter
|
||||
# (This is where pre-2014/4/15 code fails on macos10)
|
||||
df_date = df(date, date_format="%A, %d %B %Y").lower()
|
||||
self.assertEqual('jeudi, 14 août 2014', df_date)
|
||||
with utils.temporary_locale('C'):
|
||||
# DateFormatter should still work as expected
|
||||
# since it is the whole point of DateFormatter
|
||||
# (This is where pre-2014/4/15 code fails on macos10)
|
||||
df_date = df(date, date_format="%A, %d %B %Y").lower()
|
||||
self.assertEqual('jeudi, 14 août 2014', df_date)
|
||||
|
||||
@unittest.skipUnless(locale_available('fr_FR.UTF-8') or
|
||||
locale_available('French'),
|
||||
|
|
|
|||
|
|
@ -116,18 +116,14 @@ class DateFormatter:
|
|||
self.locale = locale.setlocale(locale.LC_TIME)
|
||||
|
||||
def __call__(self, date, date_format):
|
||||
old_lc_time = locale.setlocale(locale.LC_TIME)
|
||||
old_lc_ctype = locale.setlocale(locale.LC_CTYPE)
|
||||
|
||||
locale.setlocale(locale.LC_TIME, self.locale)
|
||||
# on OSX, encoding from LC_CTYPE determines the unicode output in PY3
|
||||
# make sure it's same as LC_TIME
|
||||
locale.setlocale(locale.LC_CTYPE, self.locale)
|
||||
with temporary_locale(self.locale, locale.LC_TIME), \
|
||||
temporary_locale(self.locale, locale.LC_CTYPE):
|
||||
|
||||
formatted = strftime(date, date_format)
|
||||
formatted = strftime(date, date_format)
|
||||
|
||||
locale.setlocale(locale.LC_TIME, old_lc_time)
|
||||
locale.setlocale(locale.LC_CTYPE, old_lc_ctype)
|
||||
return formatted
|
||||
|
||||
|
||||
|
|
@ -872,3 +868,19 @@ def maybe_pluralize(count, singular, plural):
|
|||
if count == 1:
|
||||
selection = singular
|
||||
return '{} {}'.format(count, selection)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def temporary_locale(temp_locale=None, lc_category=locale.LC_ALL):
|
||||
'''
|
||||
Enable code to run in a context with a temporary locale
|
||||
Resets the locale back when exiting context.
|
||||
|
||||
Use tests.support.TestCaseWithCLocale if you want every unit test in a
|
||||
class to use the C locale.
|
||||
'''
|
||||
orig_locale = locale.setlocale(lc_category)
|
||||
if temp_locale:
|
||||
locale.setlocale(lc_category, temp_locale)
|
||||
yield
|
||||
locale.setlocale(lc_category, orig_locale)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue