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): ...@@ -53,6 +53,9 @@ class Locator(object):
doctest that appears in a text file (rather than a Python file). doctest that appears in a text file (rather than a Python file).
""" """
if not hasattr(obj, '__module__'):
return None
module = sys.modules[obj.__module__] module = sys.modules[obj.__module__]
if not hasattr(module, '__file__'): if not hasattr(module, '__file__'):
...@@ -94,17 +97,30 @@ class Locator(object): ...@@ -94,17 +97,30 @@ class Locator(object):
return re.sub('[A-Z]', repl, template_name)[1:] 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) file_name = self.make_file_name(template_name)
path = self._find_path(file_name, search_dirs) path = self._find_path(file_name, search_dirs)
if path is not None: if path is None:
return path # 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. return self.find_path(search_dirs, template_name)
raise IOError('Template %s not found in directories: %s' %
(repr(template_name), repr(search_dirs)))
...@@ -190,8 +190,8 @@ class Renderer(object): ...@@ -190,8 +190,8 @@ class Renderer(object):
locator = self.make_locator() locator = self.make_locator()
def load_template(template_name): def load_template(template_name):
path = locator.locate_path(template_name=template_name, search_dirs=self.search_dirs) template_path = locator.find_path(self.search_dirs, template_name)
return reader.read(path) return reader.read(template_path)
return load_template return load_template
...@@ -263,19 +263,13 @@ class Renderer(object): ...@@ -263,19 +263,13 @@ class Renderer(object):
class definition. class definition.
""" """
search_dirs = self.search_dirs
locator = self.make_locator() locator = self.make_locator()
template_name = locator.make_template_name(obj) template_name = locator.make_template_name(obj)
directory = locator.get_object_directory(obj) template_path = locator.find_path_by_object(self.search_dirs, template_name, 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
path = locator.locate_path(template_name=template_name, search_dirs=search_dirs) return self.read(template_path)
return self.read(path)
def _render_string(self, template, *context, **kwargs): def _render_string(self, template, *context, **kwargs):
""" """
......
...@@ -8,7 +8,7 @@ This module provides a View class. ...@@ -8,7 +8,7 @@ This module provides a View class.
import os.path import os.path
from .context import Context from .context import Context
from .locator import Locator from .locator import Locator as TemplateLocator
from .renderer import Renderer from .renderer import Renderer
...@@ -22,7 +22,7 @@ class View(object): ...@@ -22,7 +22,7 @@ class View(object):
_renderer = None _renderer = None
locator = Locator() locator = TemplateLocator()
def __init__(self, template=None, context=None, partials=None, **kwargs): def __init__(self, template=None, context=None, partials=None, **kwargs):
""" """
...@@ -114,8 +114,9 @@ class Locator(object): ...@@ -114,8 +114,9 @@ class Locator(object):
""" """
def __init__(self, reader): def __init__(self, reader, template_locator):
self.reader = reader self.reader = reader
self.template_locator = template_locator
# TODO: unit test # TODO: unit test
def get_relative_template_location(self, view): def get_relative_template_location(self, view):
...@@ -135,6 +136,11 @@ class Locator(object): ...@@ -135,6 +136,11 @@ class Locator(object):
Return the path to the view's associated template. 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: if view.template_path is not None:
return os.path.split(view.template_path) return os.path.split(view.template_path)
......
...@@ -5,6 +5,7 @@ Contains locator.py unit tests. ...@@ -5,6 +5,7 @@ Contains locator.py unit tests.
""" """
from datetime import datetime
import os import os
import sys import sys
import unittest import unittest
...@@ -13,12 +14,10 @@ from pystache.locator import Locator ...@@ -13,12 +14,10 @@ from pystache.locator import Locator
from pystache.reader import Reader from pystache.reader import Reader
from .common import DATA_DIR from .common import DATA_DIR
from data.templates import SayHello
class LocatorTests(unittest.TestCase): class LocatorTests(unittest.TestCase):
search_dirs = 'examples'
def _locator(self): def _locator(self):
return Locator(search_dirs=DATA_DIR) return Locator(search_dirs=DATA_DIR)
...@@ -36,12 +35,20 @@ class LocatorTests(unittest.TestCase): ...@@ -36,12 +35,20 @@ class LocatorTests(unittest.TestCase):
def test_get_object_directory(self): def test_get_object_directory(self):
locator = Locator() locator = Locator()
reader = Reader() obj = SayHello()
actual = locator.get_object_directory(reader) 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): def test_make_file_name(self):
locator = Locator() locator = Locator()
...@@ -55,21 +62,21 @@ class LocatorTests(unittest.TestCase): ...@@ -55,21 +62,21 @@ class LocatorTests(unittest.TestCase):
locator.template_extension = '' locator.template_extension = ''
self.assertEquals(locator.make_file_name('foo'), 'foo.') self.assertEquals(locator.make_file_name('foo'), 'foo.')
def test_locate_path(self): def test_find_path(self):
locator = Locator() 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') 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() 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) 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() locator = Locator()
...@@ -77,19 +84,40 @@ class LocatorTests(unittest.TestCase): ...@@ -77,19 +84,40 @@ class LocatorTests(unittest.TestCase):
dir1 = DATA_DIR dir1 = DATA_DIR
dir2 = os.path.join(DATA_DIR, 'locator') dir2 = os.path.join(DATA_DIR, 'locator')
self.assertTrue(locator.locate_path('duplicate', search_dirs=[dir1])) self.assertTrue(locator.find_path(search_dirs=[dir1], template_name='duplicate'))
self.assertTrue(locator.locate_path('duplicate', search_dirs=[dir2])) 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) dirpath = os.path.dirname(path)
dirname = os.path.split(dirpath)[-1] dirname = os.path.split(dirpath)[-1]
self.assertEquals(dirname, 'locator') 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() 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): def test_make_template_name(self):
""" """
......
...@@ -179,12 +179,13 @@ class LocatorTests(unittest.TestCase, AssertIsMixin): ...@@ -179,12 +179,13 @@ class LocatorTests(unittest.TestCase, AssertIsMixin):
return "read: %s" % repr(path) return "read: %s" % repr(path)
reader = MockReader() reader = MockReader()
locator = Locator(reader=reader) # TODO: include a locator?
locator = Locator(reader=reader, template_locator=None)
return locator return locator
def test_init__reader(self): def test_init__reader(self):
reader = "reader" # in practice, this is a reader instance. reader = "reader" # in practice, this is a reader instance.
locator = Locator(reader) locator = Locator(reader, template_locator=None)
self.assertIs(locator.reader, reader) 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