watch.py 2.8 KB
Newer Older
1 2 3 4 5 6 7 8
import subprocess
import os
import pyinotify

from django.core.management.base import BaseCommand
from django.conf import settings

STATIC_FILES = u'--include-path={}'.format(':'.join(settings.STATICFILES_DIRS))
9
IGNORED_FOLDERS = ("static_collected", "bower_components", )
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42


class LessUtils(object):
    @staticmethod
    def less_path_to_css_path(pathname):
        return "%s.css" % pathname[:-1 * len(".less")]

    @staticmethod
    def compile_less(less_pathname, css_pathname):
        cmd = ["lessc", STATIC_FILES, less_pathname, css_pathname]

        print("\n%s" % ("=" * 30))
        print("Compiling: %s" % os.path.basename(less_pathname))

        try:
            subprocess.check_output(cmd)
        except subprocess.CalledProcessError as e:
            print(e.output)
        else:
            print("Successfully compiled:\n%s\n->\n%s" % (
                less_pathname, css_pathname))

    @staticmethod
    def initial_compile():
        """ Walks through the project looking for LESS files
        and compiles them into CSS.
        """
        for root, dirs, files in os.walk(settings.SITE_ROOT):
            for f in files:
                if not f.endswith(".less"):
                    continue

                relpath = os.path.relpath(root, settings.SITE_ROOT)
43
                if relpath.startswith(IGNORED_FOLDERS):
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
                    continue

                less_pathname = "%s/%s" % (root, f)
                css_pathname = LessUtils.less_path_to_css_path(less_pathname)
                LessUtils.compile_less(less_pathname, css_pathname)

    @staticmethod
    def start_watch():
        """ Watches for changes in LESS files recursively from the
        project's root and compiles the files
        """
        wm = pyinotify.WatchManager()

        class EventHandler(pyinotify.ProcessEvent):
            def process_IN_MODIFY(self, event):
                if not event.name.endswith(".less"):
                    return

62 63 64 65
                relpath = os.path.relpath(event.pathname, settings.SITE_ROOT)
                if relpath.startswith(IGNORED_FOLDERS):
                    return

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
                css_pathname = LessUtils.less_path_to_css_path(event.pathname)
                LessUtils.compile_less(event.pathname, css_pathname)

        handler = EventHandler()
        notifier = pyinotify.Notifier(wm, handler)
        wm.add_watch(settings.SITE_ROOT, pyinotify.IN_MODIFY, rec=True)
        notifier.loop()


class Command(BaseCommand):
    help = "Compiles all LESS files then watches for changes."

    def handle(self, *args, **kwargs):
        # for first run compile everything
        print("Initial LESS compiles")
        LessUtils.initial_compile()
        print("\n%s\n" % ("=" * 30))
        print("End of initial LESS compiles\n")

        # after first run watch less files
        LessUtils.start_watch()