Example #1
0
    def __init__(self, *tasks, **kw):
        """
        ``tasks`` - A list of Compiler instances to run
        ``directory`` - Must be the top level of the project. All files will be relative to this path.
            Defaults to the current directory.
        """
        self.tasks = tasks
        self.directory = kw.pop('directory', None) or os.path.abspath(os.path.curdir)
        self.jobs = int(kw.pop('jobs', multiprocessing.cpu_count() * 1.5))
        # observed changes
        self.changes = []

        if kw:
            raise TypeError('Unknown keyword arguments: {0}'.format(', '.join(kw.keys())))

        for task in self.tasks:
            task.maker = self

        self.executor = DelayedThreadPoolExecutor(self.jobs)
        super(Maker, self).__init__()
Example #2
0
class Maker(object):
    """
    Main class of chimney. Executes compilers and stuff.
    """
    STOP_WATCHING = 0
    RELOAD = 1

    def __init__(self, *tasks, **kw):
        """
        ``tasks`` - A list of Compiler instances to run
        ``directory`` - Must be the top level of the project. All files will be relative to this path.
            Defaults to the current directory.
        """
        self.tasks = tasks
        self.directory = kw.pop('directory', None) or os.path.abspath(os.path.curdir)
        self.jobs = int(kw.pop('jobs', multiprocessing.cpu_count() * 1.5))
        # observed changes
        self.changes = []

        if kw:
            raise TypeError('Unknown keyword arguments: {0}'.format(', '.join(kw.keys())))

        for task in self.tasks:
            task.maker = self

        self.executor = DelayedThreadPoolExecutor(self.jobs)
        super(Maker, self).__init__()

    def execute(self):
        runners = Scheduler().load(self.tasks).run()
        # schedule all of the runners
        for runner in six.itervalues(runners):
            runner.schedule(self.executor)

        self.executor.wait()

    def watch(self, reload_patterns=None):
        scheduler = Scheduler().load(self.tasks)
        runners = scheduler.run()

        # schedule all of the runners
        self.by_source = {}
        for runner in six.itervalues(runners):
            runner.schedule(self.executor)
            for dep in runner.task.dependent:
                self.by_source[os.path.abspath(dep)] = runner.task

        self.executor.wait()

        def change_handler(obs):
            self.changes.append(obs)
        self.watcher = Watcher(change_handler)
        log.info('Watching for changes. Control-C to cancel')

        try:
            while self.sleep():
                ret = self.process_changes(reload_patterns)
                if ret == Maker.RELOAD:
                    return Maker.RELOAD
        except KeyboardInterrupt:
            self.close()

        return Maker.STOP_WATCHING

    def process_changes(self, reload_patterns=None):
        batch = self.changes
        self.changes = []
        for obs in set(batch):
            if obs.type in ('created', 'deleted',):
                if reload_patterns is None:
                    log.info(u'File %s: %s, reloading', obs.type, obs.path)
                    return Maker.RELOAD

                for p in reload_patterns:
                    if fnmatch.fnmatch(obs.path, p):
                        log.info(u'File created: %s, reloading', obs.path)
                        return Maker.RELOAD

            if obs.type != 'modified':
                continue

            task = self.by_source.get(os.path.abspath(obs.path))
            if task:
                log.info('Detected %s: %s', obs.type, obs.path)
                runner = Runner(task)
                runner.schedule(self.executor)

        return None

    def sleep(self):
        time.sleep(.1)
        return True

    def close(self):
        self.executor.shutdown()