def _is_b3(self, filename): if filename in IGNORED_FILES: return False if filename.endswith(B3_BASE): return True parser = DjangoParser(charset=settings.FILE_CHARSET) template = parser.parse(filename) return self._is_b3_base_template(template)
class Command(BaseCommand): help = "Compile SASS/SCSS into CSS outside of the request/response cycle" option_list = BaseCommand.option_list + (make_option('--delete-files', action='store_true', dest='delete_files', default=False, help='Delete generated `*.css` files instead of creating them.'),) def __init__(self): self.parser = DjangoParser(charset=settings.FILE_CHARSET) super(Command, self).__init__() def handle(self, *args, **options): self.verbosity = int(options['verbosity']) self.delete_files = options['delete_files'] self.compiled_files = [] templates = self.find_templates() for template_name in templates: self.parse_template(template_name) if self.verbosity > 0: if self.delete_files: self.stdout.write('Successfully deleted {0} previously generated `*.css` files.'.format(len(self.compiled_files))) else: self.stdout.write('Successfully compiled {0} referred SASS/SCSS files.'.format(len(self.compiled_files))) def find_templates(self): paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', loader.get_template_sources) paths.update(list(get_template_sources(''))) except (ImportError, AttributeError): pass if not paths: raise CommandError("No template paths found. None of the configured template loaders provided template paths") templates = set() for path in paths: for root, _, files in os.walk(path): templates.update(os.path.join(root, name) for name in files if not name.startswith('.') and name.endswith('.html')) if not templates: raise CommandError("No templates found. Make sure your TEMPLATE_LOADERS and TEMPLATE_DIRS settings are correct.") return templates def get_loaders(self): from django.template.loader import template_source_loaders if template_source_loaders is None: try: from django.template.loader import ( find_template as finder_func) except ImportError: from django.template.loader import (find_template_source as finder_func) try: # Force Django to calculate template_source_loaders from # TEMPLATE_LOADERS settings, by asking to find a dummy template finder_func('test') except TemplateDoesNotExist: pass loaders = [] for loader in template_source_loaders: if hasattr(loader, 'loaders'): loaders.extend(loader.loaders) else: loaders.append(loader) return loaders def parse_template(self, template_name): try: template = self.parser.parse(template_name) except IOError: # unreadable file -> ignore self.stdout.write("Unreadable template at: %s\n" % template_name) return except TemplateSyntaxError as e: # broken template -> ignore self.stdout.write("Invalid template %s: %s\n" % (template_name, e)) return except TemplateDoesNotExist: # non existent template -> ignore self.stdout.write("Non-existent template at: %s\n" % template_name) return except UnicodeDecodeError: self.stdout.write("UnicodeDecodeError while trying to read template %s\n" % template_name) try: nodes = list(self.walk_nodes(template)) except Exception as e: # Could be an error in some base template self.stdout.write("Error parsing template %s: %s\n" % (template_name, e)) else: for node in nodes: if self.delete_files: self.delete_file(node) else: self.compile(node) def compile(self, node): sass_filename = find_file(node.path) if not sass_filename or sass_filename in self.compiled_files: return content = sass.compile(include_paths=node.include_paths, filename=sass_filename, output_style='compact') basename, _ = os.path.splitext(sass_filename) destpath = basename + '.css' with open(destpath, 'w') as fh: fh.write(content) self.compiled_files.append(sass_filename) if self.verbosity > 1: self.stdout.write("Compiled SASS/SCSS file: '{0}'\n".format(node.path)) def delete_file(self, node): """ Delete a *.css file, but only if it has been generated through a SASS/SCSS file. """ sass_filename = find_file(node.path) if not sass_filename: return basename, _ = os.path.splitext(sass_filename) destpath = basename + '.css' if os.path.isfile(destpath): os.remove(destpath) self.compiled_files.append(sass_filename) if self.verbosity > 1: self.stdout.write("Deleted '{0}'\n".format(destpath)) def walk_nodes(self, node): """ Iterate over the nodes recursively yielding the templatetag 'sass_src' """ for node in self.parser.get_nodelist(node): if isinstance(node, SassSrcNode): if node.is_sass: yield node else: for node in self.walk_nodes(node): yield node
class Command(BaseCommand): help = "Compile SASS/SCSS into CSS outside of the request/response cycle" option_list = BaseCommand.option_list + ( make_option( "--delete-files", action="store_true", dest="delete_files", default=False, help="Delete generated `*.css` files instead of creating them.", ), ) def __init__(self): self.parser = DjangoParser(charset=settings.FILE_CHARSET) self.template_exts = getattr(settings, "SASS_TEMPLATE_EXTS", [".html"]) self.output_style = getattr(settings, "SASS_OUTPUT_STYLE", "compact") super(Command, self).__init__() def handle(self, *args, **options): self.verbosity = int(options["verbosity"]) self.delete_files = options["delete_files"] self.compiled_files = [] templates = self.find_templates() for template_name in templates: self.parse_template(template_name) if self.verbosity > 0: if self.delete_files: self.stdout.write( "Successfully deleted {0} previously generated `*.css` files.".format(len(self.compiled_files)) ) else: self.stdout.write( "Successfully compiled {0} referred SASS/SCSS files.".format(len(self.compiled_files)) ) def find_templates(self): paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, "get_template_sources", loader.get_template_sources) paths.update(list(get_template_sources(""))) except (ImportError, AttributeError): pass if not paths: raise CommandError( "No template paths found. None of the configured template loaders provided template paths" ) templates = set() for path in paths: for root, _, files in os.walk(path): templates.update( os.path.join(root, name) for name in files if not name.startswith(".") and any(name.endswith(ext) for ext in self.template_exts) ) if not templates: raise CommandError( "No templates found. Make sure your TEMPLATE_LOADERS and TEMPLATE_DIRS settings are correct." ) return templates def get_loaders(self): try: from django.template.loader import find_template as finder_func except ImportError: from django.template.loader import find_template_source as finder_func try: # Force Django to calculate template_source_loaders from # TEMPLATE_LOADERS settings, by asking to find a dummy template finder_func("test") # Had to transform this Exception, because otherwise even if there # was a try catch it was crashing, this is a broad Exception but at # it does what the try catch does by not crashing the command line # execution. except Exception: pass loaders = [] # At the top when you first import template_source_loaders it is set # to None, because in django that is what it is set too. While it # executes the finder_func it is setting the template_source_loaders # I needed to re-import the value of it at this point because it was # still None and importing it again made it filled with the proper # django default values. from django.template.loader import template_source_loaders for loader in template_source_loaders: if hasattr(loader, "loaders"): loaders.extend(loader.loaders) else: loaders.append(loader) return loaders def parse_template(self, template_name): try: template = self.parser.parse(template_name) except IOError: # unreadable file -> ignore self.stdout.write("Unreadable template at: %s\n" % template_name) return except TemplateSyntaxError as e: # broken template -> ignore self.stdout.write("Invalid template %s: %s\n" % (template_name, e)) return except TemplateDoesNotExist: # non existent template -> ignore self.stdout.write("Non-existent template at: %s\n" % template_name) return except UnicodeDecodeError: self.stdout.write("UnicodeDecodeError while trying to read template %s\n" % template_name) try: nodes = list(self.walk_nodes(template)) except Exception as e: # Could be an error in some base template self.stdout.write("Error parsing template %s: %s\n" % (template_name, e)) else: for node in nodes: if self.delete_files: self.delete_file(node) else: self.compile(node) def compile(self, node): sass_filename = find_file(node.path) if not sass_filename or sass_filename in self.compiled_files: return content = sass.compile(include_paths=node.include_paths, filename=sass_filename, output_style=self.output_style) basename, _ = os.path.splitext(sass_filename) destpath = basename + ".css" with open(destpath, "wb") as fh: fh.write(force_bytes(content)) self.compiled_files.append(sass_filename) if self.verbosity > 1: self.stdout.write("Compiled SASS/SCSS file: '{0}'\n".format(node.path)) def delete_file(self, node): """ Delete a *.css file, but only if it has been generated through a SASS/SCSS file. """ sass_filename = find_file(node.path) if not sass_filename: return basename, _ = os.path.splitext(sass_filename) destpath = basename + ".css" if os.path.isfile(destpath): os.remove(destpath) self.compiled_files.append(sass_filename) if self.verbosity > 1: self.stdout.write("Deleted '{0}'\n".format(destpath)) def walk_nodes(self, node): """ Iterate over the nodes recursively yielding the templatetag 'sass_src' """ for node in self.parser.get_nodelist(node): if isinstance(node, SassSrcNode): if node.is_sass: yield node else: for node in self.walk_nodes(node): yield node
class Command(BaseCommand): help = "Compile SASS/SCSS into CSS outside of the request/response cycle" option_list = BaseCommand.option_list + (make_option('--delete-files', action='store_true', dest='delete_files', default=False, help='Delete generated `*.css` files instead of creating them.'), make_option('--show-errors', default=0, action='store_true', dest='show_errors', help='Display error messages.')) def __init__(self): self.parser = DjangoParser(charset=settings.FILE_CHARSET) self.template_exts = getattr(settings, 'SASS_TEMPLATE_EXTS', ['.html']) self.output_style = getattr(settings, 'SASS_OUTPUT_STYLE', 'compact') super(Command, self).__init__() def handle(self, *args, **options): self.show_errors = int(options.get('show_errors', 0)) self.delete_files = options['delete_files'] self.compiled_files = [] templates = self.find_templates() for template_name in templates: self.parse_template(template_name) if self.delete_files: self.stdout.write('Successfully deleted {0} previously generated `*.css` files.'.format(len(self.compiled_files))) else: self.stdout.write('Successfully compiled {0} referred SASS/SCSS files.'.format(len(self.compiled_files))) def get_loaders(self): from django.template import engines template_source_loaders = [] for e in engines.all(): template_source_loaders.extend(e.engine.get_template_loaders(e.engine.loaders)) loaders = [] for loader in template_source_loaders: if hasattr(loader, 'loaders'): loaders.extend(loader.loaders) else: loaders.append(loader) return loaders def find_templates(self): extensions = 'html' if not settings.TEMPLATE_LOADERS: raise ImproperlyConfigured("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, TypeError): pass if not paths: raise ImproperlyConfigured("No template paths found. None of the configured template loaders provided template paths.") templates = set() for path in paths: for root, dirs, files in os.walk(path): 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 ImproperlyConfigured("No templates found. Make sure your TEMPLATE_LOADERS and TEMPLATE_DIRS settings are correct.") return templates def parse_template(self, template_name): try: template = self.parser.parse(template_name) except IOError: # unreadable file -> ignore if self.show_errors: self.stdout.write("Unreadable template at: %s\n" % template_name) return except TemplateSyntaxError as e: # broken template -> ignore if self.show_errors: self.stdout.write("Invalid template %s: %s\n" % (template_name, e)) return except TemplateDoesNotExist: # non existent template -> ignore if self.show_errors: self.stdout.write("Non-existent template at: %s\n" % template_name) return except UnicodeDecodeError: if self.show_errors: self.stdout.write("UnicodeDecodeError while trying to read template %s\n" % template_name) try: nodes = list(self.walk_nodes(template)) except Exception as e: # Could be an error in some base template if self.show_errors: self.stdout.write("Error parsing template %s: %s\n" % (template_name, e)) else: for node in nodes: if self.delete_files: self.delete_file(node) else: self.compile(node) def compile(self, node): sass_filename = find_file(node.path) if not sass_filename or sass_filename in self.compiled_files: return content = sass.compile(include_paths=node.include_paths, filename=sass_filename, output_style=self.output_style) basename, _ = os.path.splitext(sass_filename) destpath = basename + '.css' with open(destpath, 'w') as fh: fh.write(str(content)) self.compiled_files.append(sass_filename) self.stdout.write("Compiled SASS/SCSS file: '{0}'\n".format(node.path)) def delete_file(self, node): """ Delete a *.css file, but only if it has been generated through a SASS/SCSS file. """ sass_filename = find_file(node.path) if not sass_filename: return basename, _ = os.path.splitext(sass_filename) destpath = basename + '.css' if os.path.isfile(destpath): os.remove(destpath) self.compiled_files.append(sass_filename) self.stdout.write("Deleted '{0}'\n".format(destpath)) def walk_nodes(self, node, original=None): """ Iterate over the nodes recursively yielding the templatetag 'sass_src' """ if original is None: original = node for node in self.parser.get_nodelist(node, original): if isinstance(node, SassSrcNode): if node.is_sass: yield node else: for node in self.walk_nodes(node, original): yield node