Commit a8464737 by Chris Jerdonek

Moved some locator logic from Renderer to locator.Locator.find_path_by_object().

parent 10bba6f1
......@@ -53,6 +53,9 @@ class Locator(object):
doctest that appears in a text file (rather than a Python file).
"""
if not hasattr(obj, '__module__'):
return None
module = sys.modules[obj.__module__]
if not hasattr(module, '__file__'):
......@@ -94,17 +97,30 @@ class Locator(object):
return re.sub('[A-Z]', repl, template_name)[1:]
def locate_path(self, template_name, search_dirs):
def find_path(self, search_dirs, template_name):
"""
Find and return the path to the template with the given name.
Return the path to a template with the given name.
"""
file_name = self.make_file_name(template_name)
path = self._find_path(file_name, search_dirs)
if path is not None:
return path
if path is None:
# TODO: we should probably raise an exception of our own type.
raise IOError('Template %s not found in directories: %s' %
(repr(template_name), repr(search_dirs)))
return path
def find_path_by_object(self, search_dirs, template_name, obj):
"""
Return the path to a template associated with the given object.
"""
dir_path = self.get_object_directory(obj)
if dir_path is not None:
search_dirs = [dir_path] + search_dirs
# TODO: we should probably raise an exception of our own type.
raise IOError('Template %s not found in directories: %s' %
(repr(template_name), repr(search_dirs)))
return self.find_path(search_dirs, template_name)
......@@ -190,8 +190,8 @@ class Renderer(object):
locator = self.make_locator()
def load_template(template_name):
path = locator.locate_path(template_name=template_name, search_dirs=self.search_dirs)
return reader.read(path)
template_path = locator.find_path(self.search_dirs, template_name)
return reader.read(template_path)
return load_template
......@@ -263,19 +263,13 @@ class Renderer(object):
class definition.
"""
search_dirs = self.search_dirs
locator = self.make_locator()
template_name = locator.make_template_name(obj)
directory = locator.get_object_directory(obj)
# TODO: add a unit test for the case of a None return value.
if directory is not None:
search_dirs = [directory] + self.search_dirs
template_path = locator.find_path_by_object(self.search_dirs, template_name, obj)
path = locator.locate_path(template_name=template_name, search_dirs=search_dirs)
return self.read(path)
return self.read(template_path)
def _render_string(self, template, *context, **kwargs):
"""
......
......@@ -8,7 +8,7 @@ This module provides a View class.
import os.path
from .context import Context
from .locator import Locator
from .locator import Locator as TemplateLocator
from .renderer import Renderer
......@@ -22,7 +22,7 @@ class View(object):
_renderer = None
locator = Locator()
locator = TemplateLocator()
def __init__(self, template=None, context=None, partials=None, **kwargs):
"""
......@@ -114,8 +114,9 @@ class Locator(object):
"""
def __init__(self, reader):
def __init__(self, reader, template_locator):
self.reader = reader
self.template_locator = template_locator
# TODO: unit test
def get_relative_template_location(self, view):
......@@ -135,6 +136,11 @@ class Locator(object):
Return the path to the view's associated template.
"""
dir_path, file_name = self.get_relative_template_location(view)
if dir_path is None:
path = self.template_locator.find_path(search_dirs, file_name, obj=view)
if view.template_path is not None:
return os.path.split(view.template_path)
......
......@@ -5,6 +5,7 @@ Contains locator.py unit tests.
"""
from datetime import datetime
import os
import sys
import unittest
......@@ -13,12 +14,10 @@ from pystache.locator import Locator
from pystache.reader import Reader
from .common import DATA_DIR
from data.templates import SayHello
class LocatorTests(unittest.TestCase):
search_dirs = 'examples'
def _locator(self):
return Locator(search_dirs=DATA_DIR)
......@@ -36,12 +35,20 @@ class LocatorTests(unittest.TestCase):
def test_get_object_directory(self):
locator = Locator()
reader = Reader()
actual = locator.get_object_directory(reader)
obj = SayHello()
actual = locator.get_object_directory(obj)
self.assertEquals(actual, os.path.abspath(DATA_DIR))
def test_get_object_directory__not_hasattr_module(self):
locator = Locator()
expected = os.path.join(os.path.dirname(__file__), os.pardir, 'pystache')
obj = datetime(2000, 1, 1)
self.assertFalse(hasattr(obj, '__module__'))
self.assertEquals(locator.get_object_directory(obj), None)
self.assertEquals(os.path.normpath(actual), os.path.normpath(expected))
self.assertFalse(hasattr(None, '__module__'))
self.assertEquals(locator.get_object_directory(None), None)
def test_make_file_name(self):
locator = Locator()
......@@ -55,21 +62,21 @@ class LocatorTests(unittest.TestCase):
locator.template_extension = ''
self.assertEquals(locator.make_file_name('foo'), 'foo.')
def test_locate_path(self):
def test_find_path(self):
locator = Locator()
path = locator.locate_path('simple', search_dirs=['examples'])
path = locator.find_path(search_dirs=['examples'], template_name='simple')
self.assertEquals(os.path.basename(path), 'simple.mustache')
def test_locate_path__using_list_of_paths(self):
def test_find_path__using_list_of_paths(self):
locator = Locator()
path = locator.locate_path('simple', search_dirs=['doesnt_exist', 'examples'])
path = locator.find_path(search_dirs=['doesnt_exist', 'examples'], template_name='simple')
self.assertTrue(path)
def test_locate_path__precedence(self):
def test_find_path__precedence(self):
"""
Test the order in which locate_path() searches directories.
Test the order in which find_path() searches directories.
"""
locator = Locator()
......@@ -77,19 +84,40 @@ class LocatorTests(unittest.TestCase):
dir1 = DATA_DIR
dir2 = os.path.join(DATA_DIR, 'locator')
self.assertTrue(locator.locate_path('duplicate', search_dirs=[dir1]))
self.assertTrue(locator.locate_path('duplicate', search_dirs=[dir2]))
self.assertTrue(locator.find_path(search_dirs=[dir1], template_name='duplicate'))
self.assertTrue(locator.find_path(search_dirs=[dir2], template_name='duplicate'))
path = locator.locate_path('duplicate', search_dirs=[dir2, dir1])
path = locator.find_path(search_dirs=[dir2, dir1], template_name='duplicate')
dirpath = os.path.dirname(path)
dirname = os.path.split(dirpath)[-1]
self.assertEquals(dirname, 'locator')
def test_locate_path__non_existent_template_fails(self):
def test_find_path__non_existent_template_fails(self):
locator = Locator()
self.assertRaises(IOError, locator.find_path, search_dirs=[], template_name='doesnt_exist')
def test_find_path_by_object(self):
locator = Locator()
self.assertRaises(IOError, locator.locate_path, 'doesnt_exist', search_dirs=[])
obj = SayHello()
actual = locator.find_path_by_object(search_dirs=[], template_name='say_hello', obj=obj)
expected = os.path.abspath(os.path.join(DATA_DIR, 'say_hello.mustache'))
self.assertEquals(actual, expected)
def test_find_path_by_object__none_object_directory(self):
locator = Locator()
obj = None
self.assertEquals(None, locator.get_object_directory(obj))
actual = locator.find_path_by_object(search_dirs=[DATA_DIR], template_name='say_hello', obj=obj)
expected = os.path.join(DATA_DIR, 'say_hello.mustache')
self.assertEquals(actual, expected)
def test_make_template_name(self):
"""
......
......@@ -179,12 +179,13 @@ class LocatorTests(unittest.TestCase, AssertIsMixin):
return "read: %s" % repr(path)
reader = MockReader()
locator = Locator(reader=reader)
# TODO: include a locator?
locator = Locator(reader=reader, template_locator=None)
return locator
def test_init__reader(self):
reader = "reader" # in practice, this is a reader instance.
locator = Locator(reader)
locator = Locator(reader, template_locator=None)
self.assertIs(locator.reader, reader)
......
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