1# coding: utf-8 2 3""" 4This module provides a Loader class for locating and reading templates. 5 6""" 7 8import os 9import sys 10 11from pystache import common 12from pystache import defaults 13from pystache.locator import Locator 14 15 16# We make a function so that the current defaults take effect. 17# TODO: revisit whether this is necessary. 18 19def _make_to_unicode(): 20 def to_unicode(s, encoding=None): 21 """ 22 Raises a TypeError exception if the given string is already unicode. 23 24 """ 25 if encoding is None: 26 encoding = defaults.STRING_ENCODING 27 return unicode(s, encoding, defaults.DECODE_ERRORS) 28 return to_unicode 29 30 31class Loader(object): 32 33 """ 34 Loads the template associated to a name or user-defined object. 35 36 All load_*() methods return the template as a unicode string. 37 38 """ 39 40 def __init__(self, file_encoding=None, extension=None, to_unicode=None, 41 search_dirs=None): 42 """ 43 Construct a template loader instance. 44 45 Arguments: 46 47 extension: the template file extension, without the leading dot. 48 Pass False for no extension (e.g. to use extensionless template 49 files). Defaults to the package default. 50 51 file_encoding: the name of the encoding to use when converting file 52 contents to unicode. Defaults to the package default. 53 54 search_dirs: the list of directories in which to search when loading 55 a template by name or file name. Defaults to the package default. 56 57 to_unicode: the function to use when converting strings of type 58 str to unicode. The function should have the signature: 59 60 to_unicode(s, encoding=None) 61 62 It should accept a string of type str and an optional encoding 63 name and return a string of type unicode. Defaults to calling 64 Python's built-in function unicode() using the package string 65 encoding and decode errors defaults. 66 67 """ 68 if extension is None: 69 extension = defaults.TEMPLATE_EXTENSION 70 71 if file_encoding is None: 72 file_encoding = defaults.FILE_ENCODING 73 74 if search_dirs is None: 75 search_dirs = defaults.SEARCH_DIRS 76 77 if to_unicode is None: 78 to_unicode = _make_to_unicode() 79 80 self.extension = extension 81 self.file_encoding = file_encoding 82 # TODO: unit test setting this attribute. 83 self.search_dirs = search_dirs 84 self.to_unicode = to_unicode 85 86 def _make_locator(self): 87 return Locator(extension=self.extension) 88 89 def unicode(self, s, encoding=None): 90 """ 91 Convert a string to unicode using the given encoding, and return it. 92 93 This function uses the underlying to_unicode attribute. 94 95 Arguments: 96 97 s: a basestring instance to convert to unicode. Unlike Python's 98 built-in unicode() function, it is okay to pass unicode strings 99 to this function. (Passing a unicode string to Python's unicode() 100 with the encoding argument throws the error, "TypeError: decoding 101 Unicode is not supported.") 102 103 encoding: the encoding to pass to the to_unicode attribute. 104 Defaults to None. 105 106 """ 107 if isinstance(s, unicode): 108 return unicode(s) 109 110 return self.to_unicode(s, encoding) 111 112 def read(self, path, encoding=None): 113 """ 114 Read the template at the given path, and return it as a unicode string. 115 116 """ 117 b = common.read(path) 118 119 if encoding is None: 120 encoding = self.file_encoding 121 122 return self.unicode(b, encoding) 123 124 def load_file(self, file_name): 125 """ 126 Find and return the template with the given file name. 127 128 Arguments: 129 130 file_name: the file name of the template. 131 132 """ 133 locator = self._make_locator() 134 135 path = locator.find_file(file_name, self.search_dirs) 136 137 return self.read(path) 138 139 def load_name(self, name): 140 """ 141 Find and return the template with the given template name. 142 143 Arguments: 144 145 name: the name of the template. 146 147 """ 148 locator = self._make_locator() 149 150 path = locator.find_name(name, self.search_dirs) 151 152 return self.read(path) 153 154 # TODO: unit-test this method. 155 def load_object(self, obj): 156 """ 157 Find and return the template associated to the given object. 158 159 Arguments: 160 161 obj: an instance of a user-defined class. 162 163 search_dirs: the list of directories in which to search. 164 165 """ 166 locator = self._make_locator() 167 168 path = locator.find_object(obj, self.search_dirs) 169 170 return self.read(path) 171