Hi Makoto,
Thank you very much for the new release. I would like to suggest one
small cleanup and one small refinement. The small cleanup is that you
no longer use the time import so I remove it to reduce startup
latency. The small refinement is that I would like to suggest using
lazy imports also to reduce startup latency.
Below please find a diff against pyTenjin 0.7.0 illustrating my
suggestion. I'm sorry it is not against 0.8.0 but I still need to
merge in your latest changes.
Thanks!
--Steve
diff -r 8e7d805dae62 GAE/tenjin.py
--- a/GAE/tenjin.py Sat Jun 06 09:35:49 2009 -0700
+++ b/GAE/tenjin.py Sat Jun 06 11:03:17 2009 -0700
@@ -34,7 +34,15 @@
__all__ = ['Template', 'Engine', 'helpers', 'html', ]
-import re, sys, os, time, marshal
+import re, sys, os
+
+# Lazy import
+random = None
+marshal = None
+pickle = None
+memcache = None
+unquote = None
+
python3 = sys.version_info[0] == 3
python2 = sys.version_info[0] == 2
@@ -46,9 +54,11 @@
##
def _write_binary_file(filename, content):
+ global random
f = None
try:
- import random
+ if random is None:
+ import random
tmpfile = filename + str(random.random())[1:]
f = open(tmpfile, 'wb')
f.write(content)
@@ -225,9 +235,11 @@
def _decode_params(s):
"""decode <`#...#`> and <`$...$`> into #{...} and ${...}"""
- import urllib
- if python2: from urllib import unquote
- elif python3: from urllib.parse import unquote
+ global unquote
+ if unquote is None:
+ import urllib
+ if python2: from urllib import unquote
+ elif python3: from urllib.parse import unquote
dct = { 'lt':'<', 'gt':'>', 'amp':'&', 'quot':'"',
'#039':"'", }
def unescape(s):
#return s.replace('<', '<').replace('>',
'>').replace('"', '"').replace(''', "'").replace('&',
'&')
@@ -845,6 +857,11 @@
class MarshalCacheStorage(FileCacheStorage):
+ def __init__(self, postfix='.cache'):
+ global marshal
+ if marshal is None:
+ import marshal
+ super(MarshalCacheStorage, self).__init__(postfix)
def _load(self, fullpath):
cachepath = self._cachename(fullpath)
@@ -860,10 +877,14 @@
class PickleCacheStorage(FileCacheStorage):
+ def __init__(self, postfix='.cache'):
+ global pickle
+ if pickle is None:
+ try: import cPickle as pickle
+ except: import pickle
+ super(PickleCacheStorage, self).__init__(postfix)
def _load(self, fullpath):
- try: import cPickle as pickle
- except: import pickle
cachepath = self._cachename(fullpath)
if not os.path.isfile(cachepath): return None
if logger:
logger.info("[tenjin.PickleCacheStorage] load
cache (file=%s)" % repr(cachepath))
@@ -871,8 +892,6 @@
return pickle.loads(dump)
def _store(self, fullpath, dict):
- try: import cPickle as pickle
- except: import pickle
if 'bytecode' in dict: dict.pop('bytecode')
cachepath = self._cachename(fullpath)
if logger:
logger.info("[tenjin.PickleCacheStorage] store
cache (file=%s)" % repr(cachepath))
@@ -937,16 +956,17 @@
def __init__(self, lifetime=None, postfix='.cache'):
CacheStorage.__init__(self, postfix)
if lifetime is not None: self.lifetime = lifetime
+ global memcache
+ if memcache is None:
+ from google.appengine.api import memcache
def _load(self, fullpath):
- from google.appengine.api import memcache
key = self._cachename(fullpath)
if logger:
logger.info("[tenjin.GaeMemcacheCacheStorage] load
cache (key=%s)" % repr(key))
return memcache.get(key)
def _store(self, fullpath, dict):
if 'bytecode' in dict: dict.pop('bytecode')
- from google.appengine.api import memcache
key = self._cachename(fullpath)
if logger:
logger.info("[tenjin.GaeMemcacheCacheStorage]
store cache (key=%s)" % repr(key))
ret = memcache.set(key, dict, self.lifetime)
@@ -954,7 +974,6 @@
if logger:
logger.info("[tenjin.GaeMemcacheCacheStorage:
failed to store cache (key=%s)" % repr(key))
def _delete(self, fullpath):
- from google.appengine.api import memcache
memcache.delete(self._cachename(fullpath))
@@ -1092,19 +1111,19 @@
assert filename and fullpath
cache = self.cache
template = cache and cache.get(fullpath, self.templateclass)
or None
+ mtime = os.path.getmtime(filename)
if template:
assert template.timestamp is not None
- if template.timestamp < os.path.getmtime(filename):
+ if template.timestamp != mtime:
#if cache: cache.delete(path)
template = None
if logger:
logger.info("[tenjin.Engine] cache is old
(filename=%s, template=%s)" % (repr(filename), repr(template)))
if not template:
- curr_time = time.time()
if self.preprocess: ## required for preprocess
if _context is None: _context = {}
if _globals is None: _globals = sys._getframe
(1).f_globals
template = self._create_template(filename, _context,
_globals)
- template.timestamp = curr_time
+ template.timestamp = mtime
if cache:
if not template.bytecode: template.compile()
cache.set(fullpath, template)