def handle_noargs(self, **options): ignore_patterns = options['ignore_patterns'] if options['use_default_ignore_patterns']: ignore_patterns += ['CVS', '.*', '*~'] options['ignore_patterns'] = ignore_patterns self.ignore_patterns = ignore_patterns if (options['add'] and options['clean']) or (not options['add'] and not options['clean']): raise CommandError('Please specify either "--add" or "--clean"') if not settings.COMPRESS_MTIME_DELAY: raise CommandError( 'mtime caching is currently disabled. Please ' 'set the COMPRESS_MTIME_DELAY setting to a number of seconds.') files_to_add = set() keys_to_delete = set() for root, dirs, files in walk(settings.COMPRESS_ROOT, followlinks=options['follow_links']): for dir_ in dirs: if self.is_ignored(dir_): dirs.remove(dir_) for filename in files: common = "".join(root.split(settings.COMPRESS_ROOT)) if common.startswith(os.sep): common = common[len(os.sep):] if self.is_ignored(os.path.join(common, filename)): continue filename = os.path.join(root, filename) keys_to_delete.add(get_mtime_cachekey(filename)) if options['add']: files_to_add.add(filename) if keys_to_delete: cache.delete_many(list(keys_to_delete)) print "Deleted mtimes of %d files from the cache." % len( keys_to_delete) if files_to_add: for filename in files_to_add: get_mtime(filename) print "Added mtimes of %d files to cache." % len(files_to_add)
def handle_noargs(self, **options): ignore_patterns = options['ignore_patterns'] if options['use_default_ignore_patterns']: ignore_patterns += ['CVS', '.*', '*~'] options['ignore_patterns'] = ignore_patterns self.ignore_patterns = ignore_patterns if (options['add'] and options['clean']) or (not options['add'] and not options['clean']): raise CommandError('Please specify either "--add" or "--clean"') if not settings.COMPRESS_MTIME_DELAY: raise CommandError('mtime caching is currently disabled. Please ' 'set the COMPRESS_MTIME_DELAY setting to a number of seconds.') files_to_add = set() keys_to_delete = set() for root, dirs, files in walk(settings.COMPRESS_ROOT, followlinks=options['follow_links']): for dir_ in dirs: if self.is_ignored(dir_): dirs.remove(dir_) for filename in files: common = "".join(root.split(settings.COMPRESS_ROOT)) if common.startswith(os.sep): common = common[len(os.sep):] if self.is_ignored(os.path.join(common, filename)): continue filename = os.path.join(root, filename) keys_to_delete.add(get_mtime_cachekey(filename)) if options['add']: files_to_add.add(filename) if keys_to_delete: cache.delete_many(list(keys_to_delete)) log.debug("Deleted mtimes of %d files from the cache." % len(keys_to_delete)) if files_to_add: for filename in files_to_add: get_mtime(filename) log.debug("Added mtimes of %d files to cache." % len(files_to_add))
def compress(self, log=None, **options): """ Searches templates containing 'compress' nodes and compresses them "offline" -- outside of the request/response cycle. The result is cached with a cache-key derived from the content of the compress nodes (not the content of the possibly linked files!). """ extensions = options.get('extensions') extensions = self.handle_extensions(extensions or ['html']) verbosity = int(options.get("verbosity", 0)) if not log: log = StringIO() if not settings.TEMPLATE_LOADERS: raise OfflineGenerationError("No template loaders defined. You " "must set TEMPLATE_LOADERS in your " "settings.") paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', None) if get_template_sources is None: get_template_sources = loader.get_template_sources paths.update(list(get_template_sources(''))) except (ImportError, AttributeError): # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError("No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders.") if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get('followlinks', False)): templates.update(os.path.join(root, name) for name in files if not name.startswith('.') and any(fnmatch(name, "*%s" % glob) for glob in extensions)) if not templates: raise OfflineGenerationError("No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct.") if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") #from compressor.contrib.jinja2ext import CompressorExtension from jingo_offline_compressor.jinja2ext import CompressorExtension env.add_extension(CompressorExtension) template_encoding = options.get('encoding') compressor_nodes = SortedDict() for template_name in templates: try: #template_content = env.loader.get_source(env, template_name)[0] #template_content = open(template_name).read() template_content = codecs.open( template_name, 'r', template_encoding ).read() template = env.parse(template_content) except IOError: # unreadable file -> ignore if verbosity > 0: log.write("Unreadable template at: %s\n" % template_name) continue except TemplateSyntaxError, e: # broken template -> ignore if verbosity > 0: log.write("Invalid template %s: %s\n" % (template_name, e)) continue except TemplateDoesNotExist: # non existent template -> ignore if verbosity > 0: log.write("Non-existent template at: %s\n" % template_name) continue
def compress(self, log=None, **options): """ Searches templates containing 'compress' nodes and compresses them "offline" -- outside of the request/response cycle. The result is cached with a cache-key derived from the content of the compress nodes (not the content of the possibly linked files!). """ extensions = options.get('extensions') extensions = self.handle_extensions(extensions or ['html']) verbosity = int(options.get("verbosity", 0)) if not log: log = StringIO() if not settings.TEMPLATE_LOADERS: raise OfflineGenerationError("No template loaders defined. You " "must set TEMPLATE_LOADERS in your " "settings.") paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', None) if get_template_sources is None: get_template_sources = loader.get_template_sources paths.update(list(get_template_sources(''))) except (ImportError, AttributeError): # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError("No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders.") if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get('followlinks', False)): templates.update(os.path.join(root, name) for name in files if not name.startswith('.') and any(fnmatch(name, "*%s" % glob) for glob in extensions)) if not templates: raise OfflineGenerationError("No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct.") if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") compressor_nodes = SortedDict() for template_name in templates: try: template_file = open(template_name) try: template = Template(template_file.read().decode( settings.FILE_CHARSET)) finally: template_file.close() except IOError: # unreadable file -> ignore if verbosity > 0: log.write("Unreadable template at: %s\n" % template_name) continue except TemplateSyntaxError: # broken template -> ignore if verbosity > 0: log.write("Invalid template at: %s\n" % template_name) continue except TemplateDoesNotExist: # non existent template -> ignore if verbosity > 0: log.write("Non-existent template at: %s\n" % template_name) continue except UnicodeDecodeError: if verbosity > 0: log.write("UnicodeDecodeError while trying to read " "template %s\n" % template_name) nodes = list(self.walk_nodes(template)) if nodes: template.template_name = template_name compressor_nodes.setdefault(template, []).extend(nodes) if not compressor_nodes: raise OfflineGenerationError( "No 'compress' template tags found in templates.") if verbosity > 0: log.write("Found 'compress' tags in:\n\t" + "\n\t".join((t.template_name for t in compressor_nodes.keys())) + "\n") log.write("Compressing... ") count = 0 results = [] offline_manifest = {} for template, nodes in compressor_nodes.iteritems(): context = Context(settings.COMPRESS_OFFLINE_CONTEXT) extra_context = {} firstnode = template.nodelist[0] if isinstance(firstnode, ExtendsNode): # If this template has a ExtendsNode, we apply our patch to # generate the necessary context, and then use it for all the # nodes in it, just in case (we don't know which nodes were # in a block) firstnode._old_get_parent = firstnode.get_parent firstnode.get_parent = MethodType(patched_get_parent, firstnode) try: extra_context = firstnode.render(context) context.render_context = extra_context.render_context except (IOError, TemplateSyntaxError, TemplateDoesNotExist): # That first node we are trying to render might cause more errors # that we didn't catch when simply creating a Template instance # above, so we need to catch that (and ignore it, just like above) # as well. if verbosity > 0: log.write("Caught error when rendering extend node from template %s\n" % template.template_name) continue for node in nodes: context.push() if extra_context and node._block_name: context['block'] = context.render_context[BLOCK_CONTEXT_KEY].pop(node._block_name) if context['block']: context['block'].context = context key = get_offline_hexdigest(node.nodelist.render(context)) try: result = node.render(context, forced=True) except Exception, e: raise CommandError("An error occured during rendering %s: " "%s" % (template.template_name, e)) offline_manifest[key] = result context.pop() results.append(result) count += 1
def compress(self, log=None, **options): """ Searches templates containing 'compress' nodes and compresses them "offline" -- outside of the request/response cycle. The result is cached with a cache-key derived from the content of the compress nodes (not the content of the possibly linked files!). """ extensions = options.get('extensions') extensions = self.handle_extensions(extensions or ['html']) verbosity = int(options.get("verbosity", 0)) if not log: log = StringIO() if not settings.TEMPLATE_LOADERS: raise OfflineGenerationError("No template loaders defined. You " "must set TEMPLATE_LOADERS in your " "settings.") paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', None) if get_template_sources is None: get_template_sources = loader.get_template_sources paths.update(list(get_template_sources(''))) except (ImportError, AttributeError): # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError("No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders.") if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get( 'followlinks', False)): templates.update( os.path.join(root, name) for name in files if not name.startswith('.') and any( fnmatch(name, "*%s" % glob) for glob in extensions)) if not templates: raise OfflineGenerationError("No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct.") if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") compressor_nodes = SortedDict() for template_name in templates: try: template_file = open(template_name) try: template = Template(template_file.read().decode( settings.FILE_CHARSET)) finally: template_file.close() except IOError: # unreadable file -> ignore if verbosity > 0: log.write("Unreadable template at: %s\n" % template_name) continue except TemplateSyntaxError: # broken template -> try jinja -> ignore if still broken try: template_file = open(template_name) template = jinja_env.parse(template_file.read().decode( settings.FILE_CHARSET)) template.is_jinja = True template.name = template_name except jinja2.exceptions.TemplateSyntaxError: if verbosity > 0: log.write("Invalid template at: %s\n" % template_name) continue finally: template_file.close() except UnicodeDecodeError: if verbosity > 0: log.write("UnicodeDecodeError while trying to read " "template %s\n" % template_name) if getattr(template, 'is_jinja', False): nodes = template.find_all(jinja2.nodes.CallBlock) for node in nodes: try: compress_node = node.call.node if (compress_node.identifier == 'compressor.contrib.jinja2ext.CompressorExtension' and compress_node.name == '_compress'): template.template_name = template_name compressor_nodes.setdefault(template, []).append(node) except AttributeError, IndexError: pass else: nodes = list(self.walk_nodes(template)) if nodes: template.template_name = template_name compressor_nodes.setdefault(template, []).extend(nodes)
def compress(self, log=None, **options): """ Searches templates containing 'compress' nodes and compresses them "offline" -- outside of the request/response cycle. The result is cached with a cache-key derived from the content of the compress nodes (not the content of the possibly linked files!). """ extensions = options.get('extensions') extensions = self.handle_extensions(extensions or ['html']) verbosity = int(options.get("verbosity", 0)) if not log: log = StringIO() if not settings.TEMPLATE_LOADERS: raise OfflineGenerationError("No template loaders defined. You " "must set TEMPLATE_LOADERS in your " "settings.") paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', None) if get_template_sources is None: get_template_sources = loader.get_template_sources paths.update(list(get_template_sources(''))) except (ImportError, AttributeError): # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError("No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders.") if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get('followlinks', False)): templates.update(os.path.join(root, name) for name in files if not name.startswith('.') and any(fnmatch(name, "*%s" % glob) for glob in extensions)) if not templates: raise OfflineGenerationError("No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct.") if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") compressor_nodes = SortedDict() for template_name in templates: try: template_file = open(template_name) try: template = Template(template_file.read().decode( settings.FILE_CHARSET)) finally: template_file.close() except IOError: # unreadable file -> ignore if verbosity > 0: log.write("Unreadable template at: %s\n" % template_name) continue except TemplateSyntaxError: # broken template -> ignore if verbosity > 0: log.write("Invalid template at: %s\n" % template_name) continue except UnicodeDecodeError: if verbosity > 0: log.write("UnicodeDecodeError while trying to read " "template %s\n" % template_name) nodes = list(self.walk_nodes(template)) if nodes: compressor_nodes.setdefault(template_name, []).extend(nodes) if not compressor_nodes: raise OfflineGenerationError( "No 'compress' template tags found in templates.") if verbosity > 0: log.write("Found 'compress' tags in:\n\t" + "\n\t".join(compressor_nodes.keys()) + "\n") log.write("Compressing... ") count = 0 results = [] context = Context(settings.COMPRESS_OFFLINE_CONTEXT) for nodes in compressor_nodes.values(): for node in nodes: key = get_offline_cachekey(node.nodelist) try: result = node.render(context, forced=True) except Exception, e: raise CommandError("An error occured during rending: " "%s" % e) cache.set(key, result, settings.COMPRESS_OFFLINE_TIMEOUT) results.append(result) count += 1
def compress(self, log=None, **options): """ Searches templates containing 'compress' nodes and compresses them "offline" -- outside of the request/response cycle. The result is cached with a cache-key derived from the content of the compress nodes (not the content of the possibly linked files!). """ extensions = options.get('extensions') extensions = self.handle_extensions(extensions or ['html']) verbosity = int(options.get("verbosity", 0)) if not log: log = StringIO() if not settings.TEMPLATE_LOADERS: raise OfflineGenerationError("No template loaders defined. You " "must set TEMPLATE_LOADERS in your " "settings.") #from jingo import env paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', None) if get_template_sources is None: get_template_sources = loader.get_template_sources paths.update(list(get_template_sources(''))) except (ImportError, AttributeError): # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError("No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders.") if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get( 'followlinks', False)): templates.update( os.path.join(root, name) for name in files if not name.startswith('.') and any( fnmatch(name, "*%s" % glob) for glob in extensions)) if not templates: raise OfflineGenerationError("No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct.") if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") #from compressor.contrib.jinja2ext import CompressorExtension from jingo_offline_compressor.jinja2ext import CompressorExtension env.add_extension(CompressorExtension) compressor_nodes = SortedDict() for template_name in templates: try: #template_content = env.loader.get_source(env, template_name)[0] template_content = open(template_name).read() template = env.parse(template_content) except IOError: # unreadable file -> ignore if verbosity > 0: log.write("Unreadable template at: %s\n" % template_name) continue except TemplateSyntaxError, e: # broken template -> ignore if verbosity > 0: log.write("Invalid template %s: %s\n" % (template_name, e)) continue except TemplateDoesNotExist: # non existent template -> ignore if verbosity > 0: log.write("Non-existent template at: %s\n" % template_name) continue
def compress(self, log=None, **options): """ Searches templates containing 'compress' nodes and compresses them "offline" -- outside of the request/response cycle. The result is cached with a cache-key derived from the content of the compress nodes (not the content of the possibly linked files!). """ extensions = options.get("extensions") extensions = self.handle_extensions(extensions or ["html"]) verbosity = int(options.get("verbosity", 0)) if not log: log = StringIO() if not settings.TEMPLATE_LOADERS: raise OfflineGenerationError( "No template loaders defined. You " "must set TEMPLATE_LOADERS in your " "settings." ) paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, "get_template_sources", None) if get_template_sources is None: get_template_sources = loader.get_template_sources paths.update(list(get_template_sources(""))) except (ImportError, AttributeError): # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError( "No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders." ) if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get("followlinks", False)): templates.update( os.path.join(root, name) for name in files if not name.startswith(".") and any(fnmatch(name, "*%s" % glob) for glob in extensions) ) if not templates: raise OfflineGenerationError( "No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct." ) if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") compressor_nodes = SortedDict() for template_name in templates: try: template_file = open(template_name) try: template = Template(template_file.read().decode(settings.FILE_CHARSET)) finally: template_file.close() except IOError: # unreadable file -> ignore if verbosity > 0: log.write("Unreadable template at: %s\n" % template_name) continue except TemplateSyntaxError: # broken template -> try jinja -> ignore if still broken try: template_file = open(template_name) template = jinja_env.parse(template_file.read().decode(settings.FILE_CHARSET)) template.is_jinja = True template.name = template_name except jinja2.exceptions.TemplateSyntaxError: if verbosity > 0: log.write("Invalid template at: %s\n" % template_name) continue finally: template_file.close() except UnicodeDecodeError: if verbosity > 0: log.write("UnicodeDecodeError while trying to read " "template %s\n" % template_name) if getattr(template, "is_jinja", False): nodes = template.find_all(jinja2.nodes.CallBlock) for node in nodes: try: compress_node = node.call.node if ( compress_node.identifier == "compressor.contrib.jinja2ext.CompressorExtension" and compress_node.name == "_compress" ): template.template_name = template_name compressor_nodes.setdefault(template, []).append(node) except AttributeError, IndexError: pass else: nodes = list(self.walk_nodes(template)) if nodes: template.template_name = template_name compressor_nodes.setdefault(template, []).extend(nodes)
def compress(self, log=None, **options): """ Searches templates containing 'compress' nodes and compresses them "offline" -- outside of the request/response cycle. The result is cached with a cache-key derived from the content of the compress nodes (not the content of the possibly linked files!). """ extensions = options.get('extensions') extensions = self.handle_extensions(extensions or ['html']) verbosity = int(options.get("verbosity", 0)) if not log: log = StringIO() if not settings.TEMPLATE_LOADERS: raise OfflineGenerationError("No template loaders defined. You " "must set TEMPLATE_LOADERS in your " "settings.") paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', None) if get_template_sources is None: get_template_sources = loader.get_template_sources paths.update(list(get_template_sources(''))) except (ImportError, AttributeError): # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError("No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders.") if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get( 'followlinks', False)): templates.update( os.path.join(root, name) for name in files if not name.startswith('.') and any( fnmatch(name, "*%s" % glob) for glob in extensions)) if not templates: raise OfflineGenerationError("No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct.") if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") compressor_nodes = SortedDict() for template_name in templates: try: template_file = open(template_name) try: template = Template(template_file.read().decode( settings.FILE_CHARSET)) finally: template_file.close() except IOError: # unreadable file -> ignore if verbosity > 0: log.write("Unreadable template at: %s\n" % template_name) continue except TemplateSyntaxError: # broken template -> ignore if verbosity > 0: log.write("Invalid template at: %s\n" % template_name) continue except UnicodeDecodeError: if verbosity > 0: log.write("UnicodeDecodeError while trying to read " "template %s\n" % template_name) nodes = list(self.walk_nodes(template)) if nodes: template.template_name = template_name compressor_nodes.setdefault(template, []).extend(nodes) if not compressor_nodes: raise OfflineGenerationError( "No 'compress' template tags found in templates.") if verbosity > 0: log.write("Found 'compress' tags in:\n\t" + "\n\t".join((t.template_name for t in compressor_nodes.keys())) + "\n") log.write("Compressing... ") count = 0 results = [] offline_manifest = {} for template, nodes in compressor_nodes.iteritems(): context = Context(settings.COMPRESS_OFFLINE_CONTEXT) extra_context = {} firstnode = template.nodelist[0] if isinstance(firstnode, ExtendsNode): # If this template has a ExtendsNode, we apply our patch to # generate the necessary context, and then use it for all the # nodes in it, just in case (we don't know which nodes were # in a block) firstnode._old_get_parent = firstnode.get_parent firstnode.get_parent = MethodType(patched_get_parent, firstnode) extra_context = firstnode.render(context) context.render_context = extra_context.render_context for node in nodes: context.push() if extra_context and node._block_name: context['block'] = context.render_context[ BLOCK_CONTEXT_KEY].pop(node._block_name) if context['block']: context['block'].context = context key = get_offline_hexdigest(node.nodelist) try: result = node.render(context, forced=True) except Exception, e: raise CommandError("An error occured during rendering: " "%s" % e) offline_manifest[key] = result context.pop() results.append(result) count += 1
paths.update(list(get_template_sources(''))) except (ImportError, AttributeError), e: # Yeah, this didn't work out so well, let's move on pass if not paths: raise OfflineGenerationError("No template paths found. None of " "the configured template loaders " "provided template paths. See " "http://django.me/template-loaders " "for more information on template " "loaders.") if verbosity > 1: log.write("Considering paths:\n\t" + "\n\t".join(paths) + "\n") templates = set() for path in paths: for root, dirs, files in walk(path, followlinks=options.get('followlinks', False)): templates.update(os.path.join(root, name) for name in files if any(fnmatch(name, "*%s" % glob) for glob in extensions)) if not templates: raise OfflineGenerationError("No templates found. Make sure your " "TEMPLATE_LOADERS and TEMPLATE_DIRS " "settings are correct.") if verbosity > 1: log.write("Found templates:\n\t" + "\n\t".join(templates) + "\n") compressor_nodes = SortedDict() for template_name in templates: try: template_file = open(template_name) try: