From 89eae3cc302909811cd269bde7a9a80ac17ab747 Mon Sep 17 00:00:00 2001 From: Mike Bayer <mike_mp@zzzcomputing.com> Date: Fri, 5 Mar 2010 18:47:56 +0000 Subject: [PATCH] - Windows paths are handled correctly if a Template is passed only an absolute filename (i.e. with c: drive etc.) and no URI - the URI is converted to a forward-slash path and module_directory is treated as a windows path. [ticket:128] --- CHANGES | 6 ++++ mako/template.py | 76 +++++++++++++++++++++++-------------------- test/test_template.py | 63 +++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 35 deletions(-) diff --git a/CHANGES b/CHANGES index 06d7643..eb38534 100644 --- a/CHANGES +++ b/CHANGES @@ -44,6 +44,12 @@ no longer get doubly-rendered in the body() scope, and now allow local variable assignment without breakage. [ticket:109] + +- Windows paths are handled correctly if a Template + is passed only an absolute filename (i.e. with c: + drive etc.) and no URI - the URI is converted + to a forward-slash path and module_directory + is treated as a windows path. [ticket:128] 0.2.6 diff --git a/mako/template.py b/mako/template.py index 9104683..b7c5419 100644 --- a/mako/template.py +++ b/mako/template.py @@ -57,7 +57,9 @@ class Template(object): self.uri = uri elif filename: self.module_id = re.sub(r'\W', "_", filename) - self.uri = filename + drive, path = os.path.splitdrive(filename) + path = os.path.normpath(path).replace(os.path.sep, "/") + self.uri = path else: self.module_id = "memory:" + hex(id(self)) self.uri = self.module_id @@ -101,43 +103,14 @@ class Template(object): u = u[1:] path = os.path.abspath( os.path.join( - module_directory.replace('/', os.path.sep), - u + ".py" + os.path.normpath(module_directory), + os.path.normpath(u) + ".py" ) ) else: - path = None - if path is not None: - util.verify_directory(os.path.dirname(path)) - filemtime = os.stat(filename)[stat.ST_MTIME] - if not os.path.exists(path) or \ - os.stat(path)[stat.ST_MTIME] < filemtime: - _compile_module_file( - self, - open(filename, 'rb').read(), - filename, - path) - module = imp.load_source(self.module_id, path, open(path, 'rb')) - del sys.modules[self.module_id] - if module._magic_number != codegen.MAGIC_NUMBER: - _compile_module_file( - self, - open(filename, 'rb').read(), - filename, - path) - module = imp.load_source(self.module_id, path, open(path, 'rb')) - del sys.modules[self.module_id] - ModuleInfo(module, path, self, filename, None, None) - else: - # template filename and no module directory, compile code - # in memory - (code, module) = _compile_text( - self, - open(filename, 'rb').read(), - filename) - self._source = None - self._code = code - ModuleInfo(module, None, self, filename, code, None) + path = None + + module = self._compile_from_file(path, filename) else: raise exceptions.RuntimeException( "Template requires text or filename") @@ -153,6 +126,39 @@ class Template(object): self.cache_url = cache_url self.cache_enabled = cache_enabled + def _compile_from_file(self, path, filename): + if path is not None: + util.verify_directory(os.path.dirname(path)) + filemtime = os.stat(filename)[stat.ST_MTIME] + if not os.path.exists(path) or \ + os.stat(path)[stat.ST_MTIME] < filemtime: + _compile_module_file( + self, + open(filename, 'rb').read(), + filename, + path) + module = imp.load_source(self.module_id, path, open(path, 'rb')) + del sys.modules[self.module_id] + if module._magic_number != codegen.MAGIC_NUMBER: + _compile_module_file( + self, + open(filename, 'rb').read(), + filename, + path) + module = imp.load_source(self.module_id, path, open(path, 'rb')) + del sys.modules[self.module_id] + ModuleInfo(module, path, self, filename, None, None) + else: + # template filename and no module directory, compile code + # in memory + code, module = _compile_text( + self, + open(filename, 'rb').read(), + filename) + self._source = None + self._code = code + ModuleInfo(module, None, self, filename, code, None) + return module @property def source(self): """return the template source code for this Template.""" diff --git a/test/test_template.py b/test/test_template.py index c738012..4b5b94a 100644 --- a/test/test_template.py +++ b/test/test_template.py @@ -678,6 +678,69 @@ class ModuleDirTest(TemplateTest): os.path.join(module_base, 'subdir', 'foo', 'modtest.html.py') ) +class FilenameToURITest(TemplateTest): + def test_windows_paths(self): + """test that windows filenames are handled appropriately by Template.""" + + current_path = os.path + import ntpath + os.path = ntpath + try: + class NoCompileTemplate(Template): + def _compile_from_file(self, path, filename): + self.path = path + return Template("foo bar").module + + t1 = NoCompileTemplate( + filename="c:\\foo\\template.html", + module_directory="c:\\modules\\") + + eq_(t1.uri, "/foo/template.html") + eq_(t1.path, "c:\\modules\\foo\\template.html.py") + + t1 = NoCompileTemplate( + filename="c:\\path\\to\\templates\\template.html", + uri = "/bar/template.html", + module_directory="c:\\modules\\") + + eq_(t1.uri, "/bar/template.html") + eq_(t1.path, "c:\\modules\\bar\\template.html.py") + + finally: + os.path = current_path + + def test_posix_paths(self): + """test that posixs filenames are handled appropriately by Template.""" + + current_path = os.path + import posixpath + os.path = posixpath + try: + class NoCompileTemplate(Template): + def _compile_from_file(self, path, filename): + self.path = path + return Template("foo bar").module + + t1 = NoCompileTemplate( + filename="/var/www/htdocs/includes/template.html", + module_directory="/var/lib/modules") + + eq_(t1.uri, "/var/www/htdocs/includes/template.html") + eq_(t1.path, "/var/lib/modules/var/www/htdocs/includes/template.html.py") + + t1 = NoCompileTemplate( + filename="/var/www/htdocs/includes/template.html", + uri = "/bar/template.html", + module_directory="/var/lib/modules") + + eq_(t1.uri, "/bar/template.html") + eq_(t1.path, "/var/lib/modules/bar/template.html.py") + + finally: + os.path = current_path + + + class ModuleTemplateTest(TemplateTest): def test_module_roundtrip(self): lookup = TemplateLookup() -- GitLab