Commit 14d9932a by Chris Jerdonek

Switched the Loader class to using the new Reader class.

parent 7a4dbe22
...@@ -8,13 +8,15 @@ This module provides a Loader class. ...@@ -8,13 +8,15 @@ This module provides a Loader class.
import os import os
import sys import sys
DEFAULT_DECODE_ERRORS = 'strict' from .reader import Reader
DEFAULT_EXTENSION = 'mustache' DEFAULT_EXTENSION = 'mustache'
class Loader(object): class Loader(object):
def __init__(self, search_dirs=None, extension=None, encoding=None, decode_errors=None): def __init__(self, search_dirs=None, extension=None, reader=None):
""" """
Construct a template loader. Construct a template loader.
...@@ -28,21 +30,13 @@ class Loader(object): ...@@ -28,21 +30,13 @@ class Loader(object):
extension: the template file extension. Defaults to "mustache". extension: the template file extension. Defaults to "mustache".
Pass False for no extension (i.e. extensionless template files). Pass False for no extension (i.e. extensionless template files).
encoding: the name of the encoding to use when converting file reader: the Reader instance to use to read file contents and
contents to unicode. This name will be passed as the encoding return them as unicode strings. Defaults to constructing
argument to the built-in function unicode(). Defaults to the the default Reader with no constructor arguments.
encoding name returned by sys.getdefaultencoding().
decode_errors: the string to pass as the "errors" argument to the
built-in function unicode() when converting file contents to
unicode. Defaults to "strict".
""" """
if decode_errors is None: if reader is None:
decode_errors = DEFAULT_DECODE_ERRORS reader = Reader()
if encoding is None:
encoding = sys.getdefaultencoding()
if extension is None: if extension is None:
extension = DEFAULT_EXTENSION extension = DEFAULT_EXTENSION
...@@ -53,11 +47,17 @@ class Loader(object): ...@@ -53,11 +47,17 @@ class Loader(object):
if isinstance(search_dirs, basestring): if isinstance(search_dirs, basestring):
search_dirs = [search_dirs] search_dirs = [search_dirs]
self.decode_errors = decode_errors self.reader = reader
self.search_dirs = search_dirs self.search_dirs = search_dirs
self.template_encoding = encoding
self.template_extension = extension self.template_extension = extension
def _read(self, path):
"""
Read and return a template as a unicode string.
"""
return self.reader.read(path)
def make_file_name(self, template_name): def make_file_name(self, template_name):
file_name = template_name file_name = template_name
if self.template_extension is not False: if self.template_extension is not False:
...@@ -79,23 +79,8 @@ class Loader(object): ...@@ -79,23 +79,8 @@ class Loader(object):
for dir_path in search_dirs: for dir_path in search_dirs:
file_path = os.path.join(dir_path, file_name) file_path = os.path.join(dir_path, file_name)
if os.path.exists(file_path): if os.path.exists(file_path):
return self._load_template_file(file_path) return self._read(file_path)
# TODO: we should probably raise an exception of our own type. # TODO: we should probably raise an exception of our own type.
raise IOError('"%s" not found in "%s"' % (template_name, ':'.join(search_dirs),)) raise IOError('"%s" not found in "%s"' % (template_name, ':'.join(search_dirs),))
def _load_template_file(self, file_path):
"""
Read a template file, and return it as a string.
"""
f = open(file_path, 'r')
try:
template = f.read()
finally:
f.close()
template = unicode(template, self.template_encoding, self.decode_errors)
return template
...@@ -10,6 +10,7 @@ import sys ...@@ -10,6 +10,7 @@ import sys
from .context import Context from .context import Context
from .loader import Loader from .loader import Loader
from .reader import Reader
from .renderengine import RenderEngine from .renderengine import RenderEngine
...@@ -86,7 +87,8 @@ class Renderer(object): ...@@ -86,7 +87,8 @@ class Renderer(object):
escape = lambda s: cgi.escape(s, quote=True) escape = lambda s: cgi.escape(s, quote=True)
if loader is None: if loader is None:
loader = Loader(encoding=default_encoding, decode_errors=decode_errors) reader = Reader(encoding=default_encoding, decode_errors=decode_errors)
loader = Loader(reader=reader)
self.decode_errors = decode_errors self.decode_errors = decode_errors
self.default_encoding = default_encoding self.default_encoding = default_encoding
......
...@@ -10,6 +10,7 @@ from types import UnboundMethodType ...@@ -10,6 +10,7 @@ from types import UnboundMethodType
from .context import Context from .context import Context
from .loader import Loader from .loader import Loader
from .reader import Reader
from .renderer import Renderer from .renderer import Renderer
...@@ -57,7 +58,8 @@ class View(object): ...@@ -57,7 +58,8 @@ class View(object):
# user did not supply a load_template to the constructor) # user did not supply a load_template to the constructor)
# to let users set the template_extension attribute, etc. after # to let users set the template_extension attribute, etc. after
# View.__init__() has already been called. # View.__init__() has already been called.
loader = Loader(search_dirs=self.template_path, encoding=self.template_encoding, reader = Reader(encoding=self.template_encoding)
loader = Loader(search_dirs=self.template_path, reader=reader,
extension=self.template_extension) extension=self.template_extension)
self._loader = loader self._loader = loader
......
...@@ -5,6 +5,7 @@ import sys ...@@ -5,6 +5,7 @@ import sys
import unittest import unittest
from pystache.loader import Loader from pystache.loader import Loader
from pystache.reader import Reader
DATA_DIR = 'tests/data' DATA_DIR = 'tests/data'
...@@ -23,22 +24,6 @@ class LoaderTestCase(unittest.TestCase): ...@@ -23,22 +24,6 @@ class LoaderTestCase(unittest.TestCase):
loader = Loader(search_dirs=['foo']) loader = Loader(search_dirs=['foo'])
self.assertEquals(loader.search_dirs, ['foo']) self.assertEquals(loader.search_dirs, ['foo'])
def test_init__decode_errors(self):
# Test the default value.
loader = Loader()
self.assertEquals(loader.decode_errors, 'strict')
loader = Loader(decode_errors='replace')
self.assertEquals(loader.decode_errors, 'replace')
def test_init__encoding(self):
# Test the default value.
loader = Loader()
self.assertEquals(loader.template_encoding, sys.getdefaultencoding())
loader = Loader(encoding='foo')
self.assertEquals(loader.template_encoding, 'foo')
def test_init__extension(self): def test_init__extension(self):
# Test the default value. # Test the default value.
loader = Loader() loader = Loader()
...@@ -50,6 +35,17 @@ class LoaderTestCase(unittest.TestCase): ...@@ -50,6 +35,17 @@ class LoaderTestCase(unittest.TestCase):
loader = Loader(extension=False) loader = Loader(extension=False)
self.assertTrue(loader.template_extension is False) self.assertTrue(loader.template_extension is False)
def test_init__reader(self):
# Test the default value.
loader = Loader()
reader = loader.reader
self.assertEquals(reader.encoding, sys.getdefaultencoding())
self.assertEquals(reader.decode_errors, 'strict')
reader = Reader()
loader = Loader(reader=reader)
self.assertTrue(loader.reader is reader)
def test_make_file_name(self): def test_make_file_name(self):
loader = Loader() loader = Loader()
...@@ -103,25 +99,3 @@ class LoaderTestCase(unittest.TestCase): ...@@ -103,25 +99,3 @@ class LoaderTestCase(unittest.TestCase):
actual = loader.get('ascii') actual = loader.get('ascii')
self.assertEqual(type(actual), unicode) self.assertEqual(type(actual), unicode)
def test_get__encoding(self):
"""
Test get(): encoding attribute respected.
"""
loader = self._loader()
self.assertRaises(UnicodeDecodeError, loader.get, 'nonascii')
loader.template_encoding = 'utf-8'
self.assertEquals(loader.get('nonascii'), u'non-ascii: é')
def test_get__decode_errors(self):
"""
Test get(): decode_errors attribute.
"""
loader = self._loader()
self.assertRaises(UnicodeDecodeError, loader.get, 'nonascii')
loader.decode_errors = 'replace'
self.assertEquals(loader.get('nonascii'), u'non-ascii: \ufffd\ufffd')
...@@ -35,39 +35,35 @@ class RendererInitTestCase(unittest.TestCase): ...@@ -35,39 +35,35 @@ class RendererInitTestCase(unittest.TestCase):
Test that the default loader is constructed correctly. Test that the default loader is constructed correctly.
""" """
r = Renderer() renderer = Renderer()
actual = r.loader actual = renderer.loader
expected = Loader() expected = Loader()
self.assertEquals(type(actual), type(expected)) self.assertEquals(type(actual), type(expected))
self.assertEquals(actual.__dict__, expected.__dict__) self.assertEquals(actual.template_extension, expected.template_extension)
self.assertEquals(actual.search_dirs, expected.search_dirs)
self.assertEquals(actual.reader.__dict__, expected.reader.__dict__)
def test_loader__default__default_encoding(self): def test_loader__default__default_encoding(self):
""" """
Test that the default loader inherits the default_encoding. Test that the default loader inherits default_encoding.
""" """
r = Renderer(default_encoding='foo') renderer = Renderer(default_encoding='foo')
actual = r.loader reader = renderer.loader.reader
expected = Loader(encoding='foo') self.assertEquals(reader.encoding, 'foo')
self.assertEquals(actual.template_encoding, expected.template_encoding)
# Check all attributes for good measure.
self.assertEquals(actual.__dict__, expected.__dict__)
def test_loader__default__decode_errors(self): def test_loader__default__decode_errors(self):
""" """
Test that the default loader inherits the decode_errors. Test that the default loader inherits decode_errors.
""" """
r = Renderer(decode_errors='foo') renderer = Renderer(decode_errors='foo')
actual = r.loader reader = renderer.loader.reader
expected = Loader(decode_errors='foo') self.assertEquals(reader.decode_errors, 'foo')
self.assertEquals(actual.decode_errors, expected.decode_errors)
# Check all attributes for good measure.
self.assertEquals(actual.__dict__, expected.__dict__)
def test_escape__default(self): def test_escape__default(self):
escape = Renderer().escape escape = Renderer().escape
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment