##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Filesystem Page Template module
Zope object encapsulating a Page Template from the filesystem.
$Id: pagetemplatefile.py 40504 2005-12-02 19:33:47Z ctheune $
"""
__all__ = ("PageTemplateFile",)
import os
import sys
import re
import logging
from zope.pagetemplate.pagetemplate import PageTemplate
DEFAULT_ENCODING = "utf-8"
meta_pattern = re.compile(
r'\s*\s*',
re.IGNORECASE)
def package_home(gdict):
filename = gdict["__file__"]
return os.path.dirname(filename)
class PageTemplateFile(PageTemplate):
"Zope wrapper for filesystem Page Template using TAL, TALES, and METAL"
_v_last_read = 0
def __init__(self, filename, _prefix=None):
path = self.get_path_from_prefix(_prefix)
self.filename = os.path.join(path, filename)
if not os.path.isfile(self.filename):
raise ValueError("No such file", self.filename)
def get_path_from_prefix(self, _prefix):
if isinstance(_prefix, str):
path = _prefix
else:
if _prefix is None:
_prefix = sys._getframe(2).f_globals
path = package_home(_prefix)
return path
def _prepare_html(self, text):
match = meta_pattern.search(text)
if match is not None:
type_, encoding = match.groups()
# TODO: Shouldn't / stripping
# be in PageTemplate.__call__()?
text = meta_pattern.sub("", text)
else:
type_ = None
encoding = DEFAULT_ENCODING
return unicode(text, encoding), type_
def _read_file(self):
__traceback_info__ = self.filename
f = open(self.filename, "rb")
try:
text = f.read(XML_PREFIX_MAX_LENGTH)
except:
f.close()
raise
type_ = sniff_type(text)
if type_ == "text/xml":
text += f.read()
else:
# For HTML, we really want the file read in text mode:
f.close()
f = open(self.filename)
text = f.read()
text, type_ = self._prepare_html(text)
f.close()
return text, type_
def _cook_check(self):
if self._v_last_read and not __debug__:
return
__traceback_info__ = self.filename
try:
mtime = os.path.getmtime(self.filename)
except OSError:
mtime = 0
if self._v_program is not None and mtime == self._v_last_read:
return
text, type_ = self._read_file()
self.pt_edit(text, type_)
self._cook()
if self._v_errors:
logging.error('PageTemplateFile: Error in template %s: %s',
self.filename, '\n'.join(self._v_errors))
return
self._v_last_read = mtime
def pt_source_file(self):
return self.filename
def __getstate__(self):
raise TypeError("non-picklable object")
XML_PREFIXES = [
"