diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/Archiver/HyperArch.py | 2 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_bounces.py | 24 | ||||
| -rw-r--r-- | src/mailman/config/config.py | 6 | ||||
| -rw-r--r-- | src/mailman/config/schema.cfg | 9 | ||||
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 4 | ||||
| -rw-r--r-- | src/mailman/rest/root.py | 24 | ||||
| -rw-r--r-- | src/mailman/utilities/i18n.py | 138 | ||||
| -rw-r--r-- | src/mailman/utilities/tests/test_templates.py | 245 |
8 files changed, 248 insertions, 204 deletions
diff --git a/src/mailman/Archiver/HyperArch.py b/src/mailman/Archiver/HyperArch.py index cfb7813bf..017c14342 100644 --- a/src/mailman/Archiver/HyperArch.py +++ b/src/mailman/Archiver/HyperArch.py @@ -183,7 +183,7 @@ def quick_maketext(templatefile, dict=None, lang=None, mlist=None): template = _templatecache.get(filepath) if filepath is None or template is None: # Use the basic maketext, with defaults to get the raw template - template, filepath = find(templatefile, mailing_list=mlist, + template, filepath = find(templatefile, mlist=mlist, language=lang.code) _templatefilepathcache[cachekey] = filepath _templatecache[filepath] = template diff --git a/src/mailman/app/tests/test_bounces.py b/src/mailman/app/tests/test_bounces.py index 3e2571e55..3c4c80faf 100644 --- a/src/mailman/app/tests/test_bounces.py +++ b/src/mailman/app/tests/test_bounces.py @@ -17,7 +17,7 @@ """Testing app.bounces functions.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -289,30 +289,29 @@ Message-ID: <first> """) # Set up the translation context. - self._template_dir = tempfile.mkdtemp() + self._var_dir = tempfile.mkdtemp() xx_template_path = os.path.join( - self._template_dir, 't', 'xx', 'probe.txt') + self._var_dir, 'templates', 'site', 'xx', 'probe.txt') os.makedirs(os.path.dirname(xx_template_path)) config.push('xx template dir', """\ [paths.testing] - template_dir: {0}/t - var_dir: {0}/v - """.format(self._template_dir)) + var_dir: {0} + """.format(self._var_dir)) language_manager = getUtility(ILanguageManager) language_manager.add('xx', 'utf-8', 'Freedonia') self._member.preferences.preferred_language = 'xx' with open(xx_template_path, 'w') as fp: - print >> fp, """\ + print("""\ blah blah blah $listname $address $optionsurl $owneraddr -""" +""", file=fp) def tearDown(self): config.pop('xx template dir') - shutil.rmtree(self._template_dir) + shutil.rmtree(self._var_dir) def test_subject_with_member_nonenglish(self): # Test that members with non-English preferred language get a Subject @@ -329,7 +328,12 @@ $owneraddr send_probe(self._member, self._msg) message = get_queue_messages('virgin')[0].msg notice = message.get_payload(0).get_payload() - self.assertEqual(notice, """\ + try: + # Python 2.7 + eq = self.assertMultiLineEqual + except AttributeError: + eq = self.assertEqual + eq(notice, """\ blah blah blah test@example.com anne@example.com http://example.com/anne@example.com test-owner@example.com""") diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py index 89d9e39ad..034b76b4f 100644 --- a/src/mailman/config/config.py +++ b/src/mailman/config/config.py @@ -17,7 +17,7 @@ """Configuration file loading and management.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -152,7 +152,7 @@ class Configuration: if category.name == layout: break else: - print >> sys.stderr, 'No path configuration found:', layout + print('No path configuration found:', layout, file=sys.stderr) sys.exit(1) # First, collect all variables in a substitution dictionary. $VAR_DIR # is taken from the environment or from the configuration file if the @@ -202,7 +202,7 @@ class Configuration: if dollar_count == 0: break if dollar_count == last_dollar_count: - print >> sys.stderr, 'Path expansion infloop detected' + print('Path expansion infloop detected', file=sys.stderr) sys.exit(1) last_dollar_count = dollar_count # Ensure that all paths are normalized and made absolute. Handle the diff --git a/src/mailman/config/schema.cfg b/src/mailman/config/schema.cfg index 5a64db268..cde01cbd7 100644 --- a/src/mailman/config/schema.cfg +++ b/src/mailman/config/schema.cfg @@ -102,13 +102,8 @@ messages_dir: $var_dir/messages pipermail_public_dir: $var_dir/archives/public # Directory for private Pipermail archiver artifacts. pipermail_private_dir: $var_dir/archives/private -# -# Where Mailman looks for its templates. This can either be a file system -# path or the special symbol ':source:' to locate them within the source tree -# (specifically, inside the mailman.templates package directory). -# -template_dir: :source: -# +# Root directory for site-specific template override files. +template_dir: $var_dir/templates # There are also a number of paths to specific file locations that can be # defined. For these, the directory containing the file must already exist, # or be one of the directories created by Mailman as per above. diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 368483c05..2b4deb9c2 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -21,6 +21,10 @@ Architecture * Separate out the RFC 2369 header adding handler. * Dynamically calculate the `List-Id` header instead of storing it in the database. This means it cannot be changed. + * Major redesign of the template search system, fixing LP: #788309. $var_dir + is now used when search for all template overrides, site, domain, or + mailing list. The in-tree English templates are used only as a last + fallback. REST ---- diff --git a/src/mailman/rest/root.py b/src/mailman/rest/root.py index 794d7510f..8c1a31cf2 100644 --- a/src/mailman/rest/root.py +++ b/src/mailman/rest/root.py @@ -27,16 +27,19 @@ __all__ = [ from base64 import b64decode from restish import guard, http, resource +from zope.component import getUtility from mailman.config import config from mailman.core.constants import system_preferences from mailman.core.system import system +from mailman.interfaces.listmanager import IListManager from mailman.rest.addresses import AllAddresses, AnAddress from mailman.rest.domains import ADomain, AllDomains from mailman.rest.helpers import etag, path_to from mailman.rest.lists import AList, AllLists from mailman.rest.members import AMember, AllMembers, FindMembers from mailman.rest.preferences import ReadOnlyPreferences +from mailman.rest.templates import TemplateFinder from mailman.rest.users import AUser, AllUsers @@ -144,3 +147,24 @@ class TopLevel(resource.Resource): else: user_id = segments.pop(0) return AUser(user_id), segments + + @resource.child() + def templates(self, request, segments): + """/<api>/templates/<fqdn_listname>/<template>/[<language>] + + Use content negotiation to request language and suffix (content-type). + """ + if len(segments) == 3: + fqdn_listname, template, language = segments + elif len(segments) == 2: + fqdn_listname, template = segments + language = 'en' + else: + return http.bad_request() + mlist = getUtility(IListManager).get(fqdn_listname) + if mlist is None: + return http.not_found() + # XXX dig out content-type from request + content_type = None + return TemplateFinder( + fqdn_listname, template, language, content_type) diff --git a/src/mailman/utilities/i18n.py b/src/mailman/utilities/i18n.py index e2d14390a..c02c6d5ba 100644 --- a/src/mailman/utilities/i18n.py +++ b/src/mailman/utilities/i18n.py @@ -17,13 +17,14 @@ """i18n template search and interpolation.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'TemplateNotFoundError', 'find', 'make', + 'search', ] @@ -32,6 +33,7 @@ import sys import errno from itertools import product +from pkg_resources import resource_filename from mailman.config import config from mailman.core.constants import system_preferences @@ -52,62 +54,29 @@ class TemplateNotFoundError(MailmanException): -def _search(template_file, mailing_list=None, language=None): - """Generator that provides file system search order.""" +def search(template_file, mlist=None, language=None): + """Generator that provides file system search order. - languages = ['en', system_preferences.preferred_language.code] - if mailing_list is not None: - languages.append(mailing_list.preferred_language.code) - if language is not None: - languages.append(language) - languages.reverse() - # File system locations to search. - paths = [config.TEMPLATE_DIR, - os.path.join(config.TEMPLATE_DIR, 'site')] - if mailing_list is not None: - paths.append(os.path.join(config.TEMPLATE_DIR, - mailing_list.mail_host)) - paths.append(os.path.join(config.LIST_DATA_DIR, - mailing_list.fqdn_listname)) - paths.reverse() - for language, path in product(languages, paths): - yield os.path.join(path, language, template_file) + This is Mailman's internal template search algorithm. The first locations + searched are within the $var_dir/templates directory, allowing a site to + override a template for a specific mailing list, all the mailing lists in + a domain, or site-wide. - - -def find(template_file, mailing_list=None, language=None, _trace=False): - """Locate an i18n template file. - - When something in Mailman needs a template file, it always asks for the - file through this interface. The results of the search is path to the - 'matching' template, with the search order depending on whether - `mailing_list` and `language` are provided. - - When looking for a template in a specific language, there are 4 locations - that are searched, in this order: + The <language> path component is variable, and described below. * The list-specific language directory - <var_dir>/lists/<fqdn_listname>/<language> + <var_dir>/templates/lists/<mlist.fqdn_listname>/<language> * The domain-specific language directory - <template_dir>/<list-host-name>/<language> + <var_dir>/templates/domains/<mlist.mail_host>/<language> * The site-wide language directory - <template_dir>/site/<language> - - * The global default language directory - <template_dir>/<language> - - The first match stops the search. In this way, you can specialize - templates at the desired level, or if you only use the default templates, - you don't need to change anything. NEVER modify files in - <template_dir>/<language> since Mailman will overwrite these when you - upgrade. Instead you can use <template_dir>/site. + <var_dir>/templates/site/<language> The <language> path component is calculated as follows, in this order: * The `language` parameter if given - * `mailing_list.preferred_language` if given + * `mlist.preferred_language` if given * The server's default language * English ('en') @@ -117,32 +86,59 @@ def find(template_file, mailing_list=None, language=None, _trace=False): is 'de' and the `language` parameter is 'it', these locations are searched in order: - * <var_dir>/lists/test@example.com/it/foo.txt - * <template_dir>/example.com/it/foo.txt - * <template_dir>/site/it/foo.txt - * <template_dir>/it/foo.txt + * <var_dir>/templates/lists/test@example.com/it/foo.txt + * <var_dir>/templates/domains/example.com/it/foo.txt + * <var_dir>/templates/site/it/foo.txt - * <var_dir>/lists/test@example.com/de/foo.txt - * <template_dir>/example.com/de/foo.txt - * <template_dir>/site/de/foo.txt - * <template_dir>/de/foo.txt + * <var_dir>/templates/lists/test@example.com/de/foo.txt + * <var_dir>/templates/domains/example.com/de/foo.txt + * <var_dir>/templates/site/de/foo.txt - * <var_dir>/lists/test@example.com/fr/foo.txt - * <template_dir>/example.com/fr/foo.txt - * <template_dir>/site/fr/foo.txt - * <template_dir>/fr/foo.txt + * <var_dir>/templates/lists/test@example.com/fr/foo.txt + * <var_dir>/templates/domains/example.com/fr/foo.txt + * <var_dir>/templates/site/fr/foo.txt - * <var_dir>/lists/test@example.com/en/foo.txt - * <template_dir>/example.com/en/foo.txt - * <template_dir>/site/en/foo.txt - * <template_dir>/en/foo.txt + * <var_dir>/templates/lists/test@example.com/en/foo.txt + * <var_dir>/templates/domains/example.com/en/foo.txt + * <var_dir>/templates/site/en/foo.txt + + After all those paths are searched, the final fallback is the English + template within the Mailman source tree. + + * <source_dir>/templates/en/foo.txt + """ + # The languages in search order. + languages = ['en', system_preferences.preferred_language.code] + if mlist is not None: + languages.append(mlist.preferred_language.code) + if language is not None: + languages.append(language) + languages.reverse() + # The non-language qualified $var_dir paths in search order. + paths = [os.path.join(config.VAR_DIR, 'templates', 'site')] + if mlist is not None: + paths.append(os.path.join( + config.VAR_DIR, 'templates', 'domains', mlist.mail_host)) + paths.append(os.path.join( + config.VAR_DIR, 'templates', 'lists', mlist.fqdn_listname)) + paths.reverse() + for language, path in product(languages, paths): + yield os.path.join(path, language, template_file) + # Finally, fallback to the in-tree English template. + templates_dir = resource_filename('mailman', 'templates') + yield os.path.join(templates_dir, 'en', template_file) + + + +def find(template_file, mlist=None, language=None, _trace=False): + """Use Mailman's internal template search order to find a template. :param template_file: The name of the template file to search for. :type template_file: string - :param mailing_list: Optional mailing list used as the context for + :param mlist: Optional mailing list used as the context for searching for the template file. The list's preferred language will influence the search, as will the list's data directory. - :type mailing_list: `IMailingList` + :type mlist: `IMailingList` :param language: Optional language code, which influences the search. :type language: string :param _trace: Enable printing of debugging information during @@ -153,26 +149,26 @@ def find(template_file, mailing_list=None, language=None, _trace=False): :rtype: (string, file) :raises TemplateNotFoundError: when the template could not be found. """ - raw_search_order = _search(template_file, mailing_list, language) + raw_search_order = search(template_file, mlist, language) for path in raw_search_order: try: if _trace: - print >> sys.stderr, '@@@', path, + print('@@@', path, end='', file=sys.stderr) fp = open(path) except IOError as error: if error.errno == errno.ENOENT: if _trace: - print >> sys.stderr, 'MISSING' + print('MISSING', file=sys.stderr) else: raise else: if _trace: - print >> sys.stderr, 'FOUND:', path + print('FOUND:', path, file=sys.stderr) return path, fp raise TemplateNotFoundError(template_file) -def make(template_file, mailing_list=None, language=None, wrap=True, +def make(template_file, mlist=None, language=None, wrap=True, _trace=False, **kw): """Locate and 'make' a template file. @@ -181,10 +177,10 @@ def make(template_file, mailing_list=None, language=None, wrap=True, :param template_file: The name of the template file to search for. :type template_file: string - :param mailing_list: Optional mailing list used as the context for + :param mlist: Optional mailing list used as the context for searching for the template file. The list's preferred language will influence the search, as will the list's data directory. - :type mailing_list: `IMailingList` + :type mlist: `IMailingList` :param language: Optional language code, which influences the search. :type language: string :param wrap: When True, wrap the text. @@ -197,7 +193,7 @@ def make(template_file, mailing_list=None, language=None, wrap=True, :rtype: string :raises TemplateNotFoundError: when the template could not be found. """ - path, fp = find(template_file, mailing_list, language, _trace) + path, fp = find(template_file, mlist, language, _trace) try: # XXX Removing the trailing newline is a hack carried over from # Mailman 2. The (stripped) template text is then passed through the diff --git a/src/mailman/utilities/tests/test_templates.py b/src/mailman/utilities/tests/test_templates.py index 1b2f1db07..d205eef34 100644 --- a/src/mailman/utilities/tests/test_templates.py +++ b/src/mailman/utilities/tests/test_templates.py @@ -17,7 +17,7 @@ """Testing i18n template search and interpolation.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -29,13 +29,14 @@ import shutil import tempfile import unittest +from pkg_resources import resource_filename from zope.component import getUtility from mailman.app.lifecycle import create_list from mailman.config import config from mailman.interfaces.languages import ILanguageManager from mailman.testing.layers import ConfigLayer -from mailman.utilities.i18n import TemplateNotFoundError, _search, find, make +from mailman.utilities.i18n import TemplateNotFoundError, find, make, search @@ -45,14 +46,13 @@ class TestSearchOrder(unittest.TestCase): layer = ConfigLayer def setUp(self): - self.template_dir = tempfile.mkdtemp() + self.var_dir = tempfile.mkdtemp() config.push('no template dir', """\ [mailman] default_language: fr [paths.testing] - template_dir: {0}/t - var_dir: {0}/v - """.format(self.template_dir)) + var_dir: {0} + """.format(self.var_dir)) language_manager = getUtility(ILanguageManager) language_manager.add('de', 'utf-8', 'German') language_manager.add('it', 'utf-8', 'Italian') @@ -61,82 +61,110 @@ class TestSearchOrder(unittest.TestCase): def tearDown(self): config.pop('no template dir') - shutil.rmtree(self.template_dir) + shutil.rmtree(self.var_dir) def _stripped_search_order(self, template_file, mailing_list=None, language=None): - raw_search_order = _search(template_file, mailing_list, language) + # Return the search path order for a given template, possibly using + # the mailing list and the language as context. Note that this only + # returns the search path, and does not check for whether the paths + # exist or not. + # + # Replace the tempdir prefix with a placeholder for more readable and + # reproducible tests. Essentially the paths below are rooted at + # $var_dir, except those files that live within Mailman's source + # tree. The former will use /v/ as the root and the latter will use + # /m/ as the root. + in_tree = os.path.dirname(resource_filename('mailman', 'templates')) + raw_search_order = search(template_file, mailing_list, language) for path in raw_search_order: - yield path[len(self.template_dir):] + if path.startswith(self.var_dir): + path = '/v' + path[len(self.var_dir):] + elif path.startswith(in_tree): + path = '/m' + path[len(in_tree):] + else: + # This will cause tests to fail, so keep the full bogus + # pathname for better debugging. + pass + yield path def test_fully_specified_search_order(self): search_order = self._stripped_search_order('foo.txt', self.mlist, 'it') - # language argument - self.assertEqual(next(search_order), - '/v/lists/l@example.com/it/foo.txt') - self.assertEqual(next(search_order), '/t/example.com/it/foo.txt') - self.assertEqual(next(search_order), '/t/site/it/foo.txt') - self.assertEqual(next(search_order), '/t/it/foo.txt') - # mlist.preferred_language - self.assertEqual(next(search_order), - '/v/lists/l@example.com/de/foo.txt') - self.assertEqual(next(search_order), '/t/example.com/de/foo.txt') - self.assertEqual(next(search_order), '/t/site/de/foo.txt') - self.assertEqual(next(search_order), '/t/de/foo.txt') - # site's default language - self.assertEqual(next(search_order), - '/v/lists/l@example.com/fr/foo.txt') - self.assertEqual(next(search_order), '/t/example.com/fr/foo.txt') - self.assertEqual(next(search_order), '/t/site/fr/foo.txt') - self.assertEqual(next(search_order), '/t/fr/foo.txt') - # English - self.assertEqual(next(search_order), - '/v/lists/l@example.com/en/foo.txt') - self.assertEqual(next(search_order), '/t/example.com/en/foo.txt') - self.assertEqual(next(search_order), '/t/site/en/foo.txt') - self.assertEqual(next(search_order), '/t/en/foo.txt') + # For convenience. + def nexteq(path): + self.assertEqual(next(search_order), path) + # 1: Use the given language argument + nexteq('/v/templates/lists/l@example.com/it/foo.txt') + nexteq('/v/templates/domains/example.com/it/foo.txt') + nexteq('/v/templates/site/it/foo.txt') + # 2: Use mlist.preferred_language + nexteq('/v/templates/lists/l@example.com/de/foo.txt') + nexteq('/v/templates/domains/example.com/de/foo.txt') + nexteq('/v/templates/site/de/foo.txt') + # 3: Use the site's default language + nexteq('/v/templates/lists/l@example.com/fr/foo.txt') + nexteq('/v/templates/domains/example.com/fr/foo.txt') + nexteq('/v/templates/site/fr/foo.txt') + # 4: English + nexteq('/v/templates/lists/l@example.com/en/foo.txt') + nexteq('/v/templates/domains/example.com/en/foo.txt') + nexteq('/v/templates/site/en/foo.txt') + # 5: After all the site-admin override paths have been searched, the + # Mailman in-tree paths are searched. Note that Mailman only ships + # one set of English templates. + nexteq('/m/templates/en/foo.txt') def test_no_language_argument_search_order(self): search_order = self._stripped_search_order('foo.txt', self.mlist) - # mlist.preferred_language - self.assertEqual(next(search_order), - '/v/lists/l@example.com/de/foo.txt') - self.assertEqual(next(search_order), '/t/example.com/de/foo.txt') - self.assertEqual(next(search_order), '/t/site/de/foo.txt') - self.assertEqual(next(search_order), '/t/de/foo.txt') - # site's default language - self.assertEqual(next(search_order), - '/v/lists/l@example.com/fr/foo.txt') - self.assertEqual(next(search_order), '/t/example.com/fr/foo.txt') - self.assertEqual(next(search_order), '/t/site/fr/foo.txt') - self.assertEqual(next(search_order), '/t/fr/foo.txt') - # English - self.assertEqual(next(search_order), - '/v/lists/l@example.com/en/foo.txt') - self.assertEqual(next(search_order), '/t/example.com/en/foo.txt') - self.assertEqual(next(search_order), '/t/site/en/foo.txt') - self.assertEqual(next(search_order), '/t/en/foo.txt') + # For convenience. + def nexteq(path): + self.assertEqual(next(search_order), path) + # 1: Use mlist.preferred_language + nexteq('/v/templates/lists/l@example.com/de/foo.txt') + nexteq('/v/templates/domains/example.com/de/foo.txt') + nexteq('/v/templates/site/de/foo.txt') + # 2: Use the site's default language + nexteq('/v/templates/lists/l@example.com/fr/foo.txt') + nexteq('/v/templates/domains/example.com/fr/foo.txt') + nexteq('/v/templates/site/fr/foo.txt') + # 3: English + nexteq('/v/templates/lists/l@example.com/en/foo.txt') + nexteq('/v/templates/domains/example.com/en/foo.txt') + nexteq('/v/templates/site/en/foo.txt') + # 4: After all the site-admin override paths have been searched, the + # Mailman in-tree paths are searched. Note that Mailman only ships + # one set of English templates. + nexteq('/m/templates/en/foo.txt') def test_no_mailing_list_argument_search_order(self): search_order = self._stripped_search_order('foo.txt', language='it') - # language argument - self.assertEqual(next(search_order), '/t/site/it/foo.txt') - self.assertEqual(next(search_order), '/t/it/foo.txt') - # site's default language - self.assertEqual(next(search_order), '/t/site/fr/foo.txt') - self.assertEqual(next(search_order), '/t/fr/foo.txt') - # English - self.assertEqual(next(search_order), '/t/site/en/foo.txt') - self.assertEqual(next(search_order), '/t/en/foo.txt') + # For convenience. + def nexteq(path): + self.assertEqual(next(search_order), path) + # 1: Use the given language argument + nexteq('/v/templates/site/it/foo.txt') + # 2: Use the site's default language + nexteq('/v/templates/site/fr/foo.txt') + # 3: English + nexteq('/v/templates/site/en/foo.txt') + # 4: After all the site-admin override paths have been searched, the + # Mailman in-tree paths are searched. Note that Mailman only ships + # one set of English templates. + nexteq('/m/templates/en/foo.txt') def test_no_optional_arguments_search_order(self): search_order = self._stripped_search_order('foo.txt') - # site's default language - self.assertEqual(next(search_order), '/t/site/fr/foo.txt') - self.assertEqual(next(search_order), '/t/fr/foo.txt') - # English - self.assertEqual(next(search_order), '/t/site/en/foo.txt') - self.assertEqual(next(search_order), '/t/en/foo.txt') + # For convenience. + def nexteq(path): + self.assertEqual(next(search_order), path) + # 1: Use the site's default language + nexteq('/v/templates/site/fr/foo.txt') + # 2: English + nexteq('/v/templates/site/en/foo.txt') + # 3: After all the site-admin override paths have been searched, the + # Mailman in-tree paths are searched. Note that Mailman only ships + # one set of English templates. + nexteq('/m/templates/en/foo.txt') @@ -146,60 +174,53 @@ class TestFind(unittest.TestCase): layer = ConfigLayer def setUp(self): - self.template_dir = tempfile.mkdtemp() + self.var_dir = tempfile.mkdtemp() config.push('template config', """\ [paths.testing] - template_dir: {0} - """.format(self.template_dir)) + var_dir: {0} + """.format(self.var_dir)) # The following MUST happen AFTER the push() above since pushing a new # config also clears out the language manager. getUtility(ILanguageManager).add('xx', 'utf-8', 'Xlandia') self.mlist = create_list('test@example.com') self.mlist.preferred_language = 'xx' self.fp = None - # Populate global tempdir with a few fake templates. - self.xxdir = os.path.join(self.template_dir, 'xx') - os.mkdir(self.xxdir) - with open(os.path.join(self.xxdir, 'global.txt'), 'w') as fp: - fp.write('Global template') - self.sitedir = os.path.join(self.template_dir, 'site', 'xx') - os.makedirs(self.sitedir) - with open(os.path.join(self.sitedir, 'site.txt'), 'w') as fp: - fp.write('Site template') - self.domaindir = os.path.join(self.template_dir, 'example.com', 'xx') - os.makedirs(self.domaindir) - with open(os.path.join(self.domaindir, 'domain.txt'), 'w') as fp: - fp.write('Domain template') - self.listdir = os.path.join(self.mlist.data_path, 'xx') - os.makedirs(self.listdir) - with open(os.path.join(self.listdir, 'list.txt'), 'w') as fp: - fp.write('List template') + # Populate the template directories with a few fake templates. + def write(text, path): + os.makedirs(os.path.dirname(path)) + with open(path, 'w') as fp: + fp.write(text) + self.xxsite = os.path.join( + self.var_dir, 'templates', 'site', 'xx', 'site.txt') + write('Site template', self.xxsite) + self.xxdomain = os.path.join( + self.var_dir, 'templates', + 'domains', 'example.com', 'xx', 'domain.txt') + write('Domain template', self.xxdomain) + self.xxlist = os.path.join( + self.var_dir, 'templates', + 'lists', 'test@example.com', 'xx', 'list.txt') + write('List template', self.xxlist) def tearDown(self): if self.fp is not None: self.fp.close() config.pop('template config') - shutil.rmtree(self.template_dir) - shutil.rmtree(self.listdir) - - def test_find_global_template(self): - filename, self.fp = find('global.txt', language='xx') - self.assertEqual(filename, os.path.join(self.xxdir, 'global.txt')) - self.assertEqual(self.fp.read(), 'Global template') + shutil.rmtree(self.var_dir) def test_find_site_template(self): filename, self.fp = find('site.txt', language='xx') - self.assertEqual(filename, os.path.join(self.sitedir, 'site.txt')) + self.assertEqual(filename, self.xxsite) self.assertEqual(self.fp.read(), 'Site template') def test_find_domain_template(self): filename, self.fp = find('domain.txt', self.mlist) - self.assertEqual(filename, os.path.join(self.domaindir, 'domain.txt')) + self.assertEqual(filename, self.xxdomain) self.assertEqual(self.fp.read(), 'Domain template') def test_find_list_template(self): filename, self.fp = find('list.txt', self.mlist) - self.assertEqual(filename, os.path.join(self.listdir, 'list.txt')) + self.assertEqual(filename, self.xxlist) self.assertEqual(self.fp.read(), 'List template') def test_template_not_found(self): @@ -219,41 +240,41 @@ class TestMake(unittest.TestCase): layer = ConfigLayer def setUp(self): - self.template_dir = tempfile.mkdtemp() + self.var_dir = tempfile.mkdtemp() config.push('template config', """\ [paths.testing] - template_dir: {0} - """.format(self.template_dir)) + var_dir: {0} + """.format(self.var_dir)) # The following MUST happen AFTER the push() above since pushing a new # config also clears out the language manager. getUtility(ILanguageManager).add('xx', 'utf-8', 'Xlandia') self.mlist = create_list('test@example.com') self.mlist.preferred_language = 'xx' - # Populate the template directory with some samples. - self.xxdir = os.path.join(self.template_dir, 'xx') - os.mkdir(self.xxdir) - with open(os.path.join(self.xxdir, 'nosub.txt'), 'w') as fp: - print >> fp, """\ + # Populate the template directories with a few fake templates. + path = os.path.join(self.var_dir, 'templates', 'site', 'xx') + os.makedirs(path) + with open(os.path.join(path, 'nosub.txt'), 'w') as fp: + print("""\ This is a global template. It has no substitutions. It will be wrapped. -""" - with open(os.path.join(self.xxdir, 'subs.txt'), 'w') as fp: - print >> fp, """\ +""", file=fp) + with open(os.path.join(path, 'subs.txt'), 'w') as fp: + print("""\ This is a $kind template. It has $howmany substitutions. It will be wrapped. -""" - with open(os.path.join(self.xxdir, 'nowrap.txt'), 'w') as fp: - print >> fp, """\ +""", file=fp) + with open(os.path.join(path, 'nowrap.txt'), 'w') as fp: + print("""\ This is a $kind template. It has $howmany substitutions. It will not be wrapped. -""" +""", file=fp) def tearDown(self): config.pop('template config') - shutil.rmtree(self.template_dir) + shutil.rmtree(self.var_dir) def test_no_substitutions(self): self.assertEqual(make('nosub.txt', self.mlist), """\ |
