Ejemplo n.º 1
0
def start_watch(cmd, debug):
    global p
    event_handler = when_file_chanage(kill_progress, harakiri)
    observer = Observer(timeout=1)
    observer.schedule(event_handler, path=os.getcwd(), recursive=True)
    observer.start()
    p = subprocess.Popen(cmd, stderr=subprocess.PIPE)
    return_code = p.poll()
    while return_code is None:
        sleep_time = 1
        if debug:
            sleep_time = 0.05
        time.sleep(sleep_time)
        if not observer.is_alive():
            kill_progress()
            break
        return_code = p.poll()
        if debug:
            line_byte = p.stderr.readline()
            line = line_byte.decode("UTF-8")
            line = line.strip()
            if len(line) != 0:
                print(line)
                sys.stderr.flush()
            while len(line) != 0:
                line_byte = p.stderr.readline()
                line = line_byte.decode("UTF-8")
                line = line.strip()
                print(line)
                sys.stderr.flush()
    observer.stop()
    return return_code
Ejemplo n.º 2
0
class ObserverBase:
    '''
    create doc content observer
    '''
    def __init__(self, event_handler):
        self.event_handler = event_handler
        self.path = event_handler.path

        self._init_observer()
        self._init_section()

    def _init_section(self):
        pass

    def _create_items(self, tree_elements):
        pass

    def _init_observer(self):
        self.go_recursively = True
        self.observer = Observer()
        self.observer.schedule(self.event_handler,
                               self.path,
                               recursive=self.go_recursively)

    def start_observer(self):
        self.observer.start()

    def stop_observer(self):
        if self.observer.is_alive():
            self.observer.stop()
            self.observer.join()
Ejemplo n.º 3
0
class MyEventHandler(FileSystemEventHandler):
    def __init__(self, path, alert_file):
        self.file_name = alert_file
        self.path = path
        self.observer = Observer()
        self.text_operations = text_operations.TextOperations(self.file_name)
        self.solution = solution.Solution()
        self.end_program = end_program.EndProgram()
        self.today_events = []

    def on_modified(self, event):
        if not event.is_directory and event.src_path.endswith(self.file_name):
            new_event = self.text_operations.new_alert()
            if new_event:
                self.today_events.append(new_event)

    def observe(self):
        self.observer.schedule(self, self.path, recursive=False)
        self.observer.start()
        try:
            while self.observer.is_alive():
                self.observer.join(1)
        except KeyboardInterrupt:
            self.observer.stop()
            self.end_program.check_firewall()
            self.end_program.make_email_message(self.today_events)
            print('Bye!')
Ejemplo n.º 4
0
 def wait_on_entry_calc(self, key):
     if self.separate_files:
         entry = self._get_cache_by_key(key)
         filename = f'{self._cache_fname()}_{hashlib.sha256(pickle.dumps(key)).hexdigest()}'
     else:
         with self.lock:
             self._reload_cache()
             entry = self._get_cache()[key]
         filename = self._cache_fname()
     if not entry['being_calculated']:
         return entry['value']
     event_handler = _PickleCore.CacheChangeHandler(filename=filename,
                                                    core=self,
                                                    key=key)
     observer = Observer()
     event_handler.inject_observer(observer)
     observer.schedule(event_handler,
                       path=self.expended_cache_dir,
                       recursive=True)
     observer.start()
     time_spent = 0
     while observer.is_alive():
         observer.join(timeout=1.0)
         time_spent += 1
         if 0 < self.wait_for_calc_timeout < time_spent:
             raise RecalculationNeeded()
     # print("Returned value: {}".format(event_handler.value))
     return event_handler.value
Ejemplo n.º 5
0
def watch(watch_dir='/tmp/wt_screens',
          archive_dir='/tmp/wt_archive',
          error_dir='/tmp/wt_archive/errors'):
    """Watch a directory and process files going into it"""
    observer = Observer()
    handler = EventHandler(watch_dir,
                           archive_dir=archive_dir,
                           error_dir=error_dir)

    print('Starting watch on {}, archive to {}, errors to {}'.format(
        watch_dir, archive_dir, error_dir))
    observer.schedule(handler, watch_dir, recursive=False)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print('Stopping directory watch as requested...')
        observer.stop()
        observer.join()
    finally:
        if observer.is_alive():
            print('Stopping directory watch on unexpected event...')
            observer.stop()
            observer.join()
Ejemplo n.º 6
0
class Watcher:
    def __init__(self, klasor: Klasor):
        self.watchHandler = WatchHandler()
        self.observer = None
        self.klasor = klasor
        self.thread = None
        # self.watchHandler.den.alt():
        # print("aha")
    def Start(self):
        self.observer = Observer()
        self.observer.schedule(self.watchHandler,
                               path=str(self.klasor),
                               recursive=False)
        self.observer.start()
        print("izleme başladı")
        sys.stderr.write("hede")
        # sys.stdout.write("eauiea")
        hata = sys.stderr
        print(hata)

    def Stop(self):
        self.observer.stop()
        self.observer.join()
        print("watcher is closed")
        print(self.observer.is_alive())
def main() -> None:
    """The main function."""
    args = parse_args()

    # Check the target
    target = args.target
    if not os.path.isfile(target):
        raise Exception('Target `%s` does not exist' % target)

    # Maxmimum number of tasks. Two 2 tasks are required as a minimum: one for
    # running afl-showmap, and another for updating the coverage bitmap
    max_task = args.jobs
    if max_task == 0:
        max_task = multiprocessing.cpu_count()

    # Check afl-showmap
    if not which('afl-showmap'):
        raise Exception('Could not find afl-showmap. Check PATH')

    # Wait for fuzzer_stats to exist
    out_dir = args.out_dir
    fuzzer_stats_path = out_dir / 'fuzzer_stats'
    if not fuzzer_stats_path.exists():
        raise Exception('No fuzzer_stats in `%s`' % out_dir)

    # Open CSV plot_data
    csv_path = args.csv
    if csv_path:
        csv_path = Path(csv_path)
        with open(csv_path, 'w') as outf:
            CsvDictWriter(outf, fieldnames=CSV_FIELDNAMES).writeheader()

    with Executor(max_workers=max_task) as executor, \
            open(out_dir / 'blackbox.tar.gz', 'wb') as tar_file:
        # The coverage bitmap
        cov_bitmap = [255] * MAP_SIZE
        cov_queue = Queue(max_task)

        # Thread responsible for deduplicating entries in the output directory
        # and logging coverage to a CSV
        cov_thread = Thread(target=remove_duplicate_testcases,
                            args=(cov_bitmap, cov_queue, tar_file, csv_path))
        cov_thread.daemon = True
        cov_thread.start()

        # Start the monitor
        handler = TestCaseHandler(executor, cov_queue, target, afl_stats,
                                  args.timeout)
        observer = Observer()
        observer.schedule(handler, out_dir / 'queue' / '.blackbox')
        observer.start()

        # Continue until interrupted
        try:
            while observer.is_alive():
                observer.join(1)
        except KeyboardInterrupt:
            print('\nCtrl-C detected, goodbye')
            observer.stop()
            observer.join()
class FileSystemWatchDog(WatchDog):
    def __init__(self, watchedFolder: str, watchedExtensions: List[str] = None, recursive=False) -> None:
        super().__init__(watchedFolder, watchedExtensions, recursive)

        self.observer = None

    def run(self):
        self.observer = Observer()
        self.observer.schedule(WatchDogFileSystemEventHandler(self), self.watchedFolder, recursive=self.recursive)
        self.observer.start()
        self.observer.join()

    @property
    def running(self):
        return self.observer and self.observer.is_alive()

    def stop(self):
        if self.observer:
            self.observer.stop()

    def processFiles(self, fileHandler):
        for root, _, filenames in os.walk(self.watchedFolder):
            for filename in filenames:
                if self.checkExtension(filename):
                    fileHandler(os.path.join(root, filename))

            if not self.recursive:
                return

    def copyFile(self, srcFilename, destFilename):
        shutil.copy(srcFilename, destFilename)

    def renameFile(self, srcFilename, destFilename):
        os.rename(srcFilename, destFilename)
Ejemplo n.º 9
0
    def process(self, received_file_queue, exception_handler):
        """
        The file watcher process.

        :param received_file_queue:     queue transfering the detected changed files
        :type received_file_queue:      multiprocessing.queues.Queue
        :param exception_handler:       exception handler callback method receiving all exception from the process
        :type exception_handler:        method
        """
        filesystem_observer = Observer()
        try:
            # required for correct handling of Crtl + C in a multiprocess environment
            signal.signal(signal.SIGINT, signal.SIG_IGN)
            signal.signal(signal.SIGTERM, signal.SIG_IGN)

            self._processed_files_lock = threading.Lock()

            self._received_file_queue = received_file_queue
            if not os.path.isdir(self._data_directory):
                raise IOError("Data directory \"%s\" not found." % self._data_directory)

            filesystem_observer.schedule(self, self._data_directory, recursive=True)
            filesystem_observer.start()

            # wait until stop is signalled
            self._exception_event.wait()
        except Exception as e:
            exception_handler(DelayedException(e))
        finally:
            if filesystem_observer.is_alive():
                filesystem_observer.stop()
                filesystem_observer.join()
Ejemplo n.º 10
0
def sneakernet_import_thread():
    """Add block data dir & confed paths to fs observer to watch for new bls"""
    observer = Observer()
    for path in watch_paths:
        observer.schedule(_Importer(), path, recursive=True)
    observer.start()
    while observer.is_alive():
        # call import func with timeout
        observer.join(60)
Ejemplo n.º 11
0
 def auto_refresher():
     observer = Observer()
     observer.schedule(Refresher(),
                       identify_home(),
                       recursive=False)
     observer.start()
     while observer.is_alive():
         # call import func with timeout
         observer.join(120)
Ejemplo n.º 12
0
def replicate_files_on_change(
    src_dir,
    copy_file,
    timeout=None,
    use_gitignore=True,
    debugging=False,
    observer_up_event=None,
    terminate_event=None,
):
    """Wait for changes to files in src_dir and copy with copy_file().

    If provided, the timeout indicates when to return after that many seconds of no change.
    """
    print("debug: replicate on change start")
    src_dir = os.path.abspath(src_dir)
    if use_gitignore:
        spec = get_pathspec(src_dir, use_gitignore)
        event_handler = GitIgnoreCopyFileEventHandler(copy_file,
                                                      spec,
                                                      debugging=debugging)
    else:
        event_handler = CopyFileEventHandler(copy_file, debugging=debugging)
    observer = Observer()
    observer.schedule(event_handler, src_dir, recursive=True)
    if debugging:
        print("Starting observer")
    observer.start()
    if observer_up_event is not None:
        while not observer.is_alive():
            pass
        # wait for event listeners to settle
        time.sleep(0.5)
        observer_up_event.set()
        print("notified observer up")
    try:
        while True:
            time.sleep(0.5)
            if timeout:
                raise_if_timeout(event_handler.last_event_timestamp, timeout)
            if terminate_event and terminate_event.is_set():
                raise ConditionalTermination("Termination condition was set.")
    except (KeyboardInterrupt, NoChangeTimeout, ConditionalTermination) as e:
        if debugging:
            print(f"Exitting on {type(e).__name__}: {e}")
    finally:
        now = time.time()
        # still, dispatch the existing change events before we part ways
        while time.time(
        ) - now < TAIL_TIMEOUT and not observer.event_queue.empty():
            print("flushing events")
            observer.dispatch_events(observer.event_queue, observer.timeout)
        left = now + TAIL_TIMEOUT - time.time()
        observer.stop()
        observer.join(timeout=max(0, left))
        print(f"debug: finished replicate on change with {left} left")
Ejemplo n.º 13
0
        def auto_refresher():
            class Refresher(FileSystemEventHandler):
                @staticmethod
                def on_modified(event):
                    self.amount = _read_data_file(self.data_file)

            observer = Observer()
            observer.schedule(Refresher(), usage_file)
            observer.start()
            while observer.is_alive():
                # call import func with timeout
                observer.join(120)
Ejemplo n.º 14
0
def run_watch(handler, path):
    obsrv = Observer()
    obsrv.schedule(handler, path, recursive=True)
    obsrv.start()
    print('start watching: %s' % path)
    try:
        while obsrv.is_alive():
            obsrv.join(1)
    except KeyboardInterrupt:
        obsrv.stop()
        print('pywatcher KeyboardInterrupt')
    print('pywatcher stop.')
    obsrv.join()
Ejemplo n.º 15
0
def main() -> None:
    """The main function."""
    args = parse_args()

    # Check the target
    target = args.target
    if not os.path.isfile(target):
        raise Exception('Target `%s` does not exist' % target)

    # Maxmimum number of tasks. Two 2 tasks are required as a minimum: one for
    # running afl-showmap, and another for updating the coverage bitmap
    max_task = args.j
    if max_task == 0:
        max_task = multiprocessing.cpu_count()
    elif max_task <= 2:
        max_task = 2

    # Check afl-showmap
    if not which('afl-showmap'):
        raise Exception('Could not find afl-showmap. Check PATH')

    # Wait for fuzzer_stats to exist
    out_dir = Path(args.out_dir)
    fuzzer_stats_path = out_dir / 'fuzzer_stats'
    while not fuzzer_stats_path.exists():
        sleep(1)
    with open(fuzzer_stats_path, 'r') as inf:
        afl_stats = FuzzerStats(inf)

    # Open CSV plot_data
    csv_path = args.csv
    if csv_path:
        csv_path = Path(csv_path)
        with open(csv_path, 'w') as outf:
            CsvDictWriter(outf, fieldnames=CSV_FIELDNAMES).writeheader()

    # Start the watchdog
    handler = TestCaseHandler(max_task - 1, target, afl_stats, csv_path)
    observer = Observer()
    observer.schedule(handler, out_dir / 'queue' / '.blackbox')
    observer.start()

    # Continue until interrupted
    try:
        while observer.is_alive():
            observer.join(1)
    except KeyboardInterrupt:
        print('\nCtrl-C detected, goodbye')
        observer.stop()
        observer.join()
        os.kill(0, 9)
Ejemplo n.º 16
0
async def watch(path, **kwargs):
    """Watch on files of in a directory and log new lines"""
    handler = WatcherHandler(**kwargs)
    handler.read_initial_size(path)
    observer = Observer()
    observer.schedule(handler, path=path, recursive=True)
    observer.start()

    try:
        while observer.is_alive():
            await asyncio.sleep(0.1)
    finally:
        observer.stop()
        observer.join()
Ejemplo n.º 17
0
def main():
    global args
    args = parser.parse_args()
    validate_args(args)

    if args.enable == 0 or args.disable:
        info('functionality disabled, waiting for termination signal')
        signal.signal(signal.SIGINT, handle_term)
        signal.signal(signal.SIGTERM, handle_term)
        signal.pause()

    if args.recognize_regex or args.ignore_regex:
        try:
            event_handler = RestartRegexMatchingEventHandler(
                regexes=args.recognize_regex or ['.*'],
                ignore_regexes=args.ignore_regex +
                ['.*/\..*'] if args.ignore_hidden else [],
                ignore_directories=args.ignore_directories,
                case_sensitive=args.case_sensitive)
        except re.error as exc:
            error('regex: ' + str(exc))
    else:
        event_handler = RestartPatternMatchingEventHandler(
            patterns=args.recognize,
            ignore_patterns=args.ignore +
            ['*/.*'] if args.ignore_hidden else [],
            ignore_directories=args.ignore_directories,
            case_sensitive=args.case_sensitive)

    observer = Observer()
    observer.schedule(event_handler, args.path, recursive=args.recursive)

    try:
        global rpc
        rpc = childutils.getRPCInterface(os.environ)
    except KeyError as exc:
        error('missing environment variable ' + str(exc))

    info('watching ' + args.path)

    try:
        observer.start()
    except OSError as exc:
        error(str(exc))

    signal.signal(signal.SIGINT, handle_term)
    signal.signal(signal.SIGTERM, handle_term)

    while observer.is_alive():
        observer.join(1)
Ejemplo n.º 18
0
def sharpei(
    local: str,
    remote: str,
    initial_sync: bool,
):
    """
    Sync LOCAL to REMOTE

    LOCAL is a local file or directory
    REMOTE is an s3 target of format s3://bucket/[key / key prefix]
    """
    local = path.abspath(local)
    click.echo(
        click.style("Sharpei", fg="cyan", bold=True) +
        f" {__version__} watching {local} for changes")

    # Break up s3 string
    match = re.fullmatch(_s3_path_re, remote)
    if not match:
        raise click.ClickException(
            "Invalid remote path or prefix, must be of format s3://bucket/[path]"
        )
    s3_bucket, s3_prefix = match.groups()

    event_handler = SharpeiEventHandler(
        base_path=local,
        bucket=s3_bucket,
        base_key=s3_prefix or "",
        s3_args={},  # TODO
    )

    if initial_sync:
        if path.isfile(local):
            initial_sync_event = FileCreatedEvent(local)
        else:
            initial_sync_event = DirCreatedEvent(local)
        initial_sync_event.is_synthetic = True
        event_handler.on_created(initial_sync_event)

    observer = Observer()
    observer.schedule(event_handler, local, recursive=True)
    observer.start()
    try:
        while observer.is_alive():
            observer.join(1)
    except KeyboardInterrupt:
        click.echo(f"Sharpei exiting.")
        observer.stop()
    observer.join()
Ejemplo n.º 19
0
class Monitor():
    def __init__(self, target_path: str, recursive: bool = False):
        self.path = target_path
        self.recursive = recursive
        self.observer = Observer()
        event_handler = FileEventHandler(self.path)
        self.observer.schedule(event_handler, self.path, self.recursive)
        self.observer.start()
        print("Start monitor " + self.path)
        try:
            while self.observer.is_alive():
                self.observer.join(1)
        except KeyboardInterrupt:
            self.observer.stop()
        self.observer.join()
Ejemplo n.º 20
0
def do_watch(fn, path, pattern, ignore_pattern=None, outfile=None):
    outfile = outfile and os.path.normpath(outfile)
    try:
        from watchdog.observers import Observer
        from watchdog.events import PatternMatchingEventHandler
        from watchdog.events import LoggingEventHandler
    except ImportError:
        msg = """\
watch dog is not found.
please run `pip install "swagger_bundler[watch]`
        """
        highlight.show_on_warning(msg)
        sys.exit(1)

    class _CallbackHandler(PatternMatchingEventHandler):
        def process(self, event):
            sys.stderr.write("event detect: event_type={}, src={}\n".format(event.event_type, event.src_path))
            try:
                return fn()
            except:
                logger.warn("exception", exc_info=True)

        def on_any_event(self, event):
            if outfile is None or outfile != os.path.normpath(event.src_path):
                self.process(event)

    observer = Observer()
    patterns = [pattern]
    ignore_patterns = []
    if ignore_pattern is not None:
        ignore_patterns.append(ignore_pattern)
    sys.stderr.write("watch starting patterns={}, ignore_patterns={}\n".format(patterns, ignore_patterns))
    callback_handler = _CallbackHandler(patterns=patterns, ignore_patterns=ignore_patterns)

    observer.schedule(LoggingEventHandler(), path=path, recursive=True)
    observer.schedule(callback_handler, path=path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(0.5)
    except KeyboardInterrupt:
        observer.stop()
    try:
        while observer.is_alive():
            observer.join(1)
    except Exception as e:
        sys.stderr.write(str(e))
Ejemplo n.º 21
0
class DirectoryWatcher:
    """A directory watcher class."""
    def __init__(
        self,
        directory: Path,
        on_modified: Callable[[Path], None],
    ) -> None:
        """
        Initialize a watcher which observes modifications in `directory`.

        on_modified: A callable which is invoked with the path of modified
                     files within `directory`.
        """
        self.on_modified = on_modified
        self.watched_directory = str(directory)
        self.observer = Observer()

    def start(self) -> None:
        """Start watching the specified directory for file modifications."""
        event_handler = DirectoryEventHandler(self.on_modified)
        self.observer.schedule(
            event_handler,
            self.watched_directory,
            recursive=True,
        )
        try:
            self.observer.start()
        except BaseException as e:
            logger = logging.getLogger(__name__)
            logger.exception(
                'Could not start filesystem watcher.\n'
                f'Error message: "{e}".\n'
                'Set logging level to DEBUG for full stack trace.',
                exc_info=logger.getEffectiveLevel() <= logging.DEBUG,
            )

    def stop(self) -> None:
        """Stop watching the directory."""
        if self.observer.is_alive():
            try:
                self.observer.stop()
                self.observer.join()
            except (RuntimeError, SystemError):
                # TODO: Understand exactly what join() does, and why
                # it sometimes throws a RuntimeError
                # Also find out why MacOS throws SystemError
                pass
Ejemplo n.º 22
0
class FileWatch(FileSystemEventHandler):
    def __init__(self, origin, watch_path, event_func):
        FileSystemEventHandler.__init__(self)
        self.origin = origin
        self.watch_path = watch_path
        self.event_func = event_func
        self.observer = Observer()
        self.watch = None
        self.mutex = threading.Lock()

    def get_lock(self):
        return self.mutex

    def start(self):
        dir = os.path.abspath(os.path.dirname(self.watch_path))
        self.origin.dbg('FileWatch: scheduling watch for directory %s' % dir)
        self.watch = self.observer.schedule(self, dir, recursive=False)
        self.observer.start()

    def stop(self):
        if self.watch:
            self.origin.dbg('FileWatch: unscheduling watch %r' % self.watch)
            self.observer.unschedule(self.watch)
            self.watch = None
        if self.observer.is_alive():
            self.observer.stop()
            self.observer.join()

    def __del__(self):
        self.stop()
        self.observer = None

    # Override from FileSystemEventHandler
    def on_any_event(self, event):
        if event.is_directory:
            return None
        if os.path.abspath(event.src_path) != os.path.abspath(self.watch_path):
            return None
        self.origin.dbg('FileWatch: received event %r' % event)
        try:
            self.mutex.acquire()
            self.event_func(event)
        finally:
            self.mutex.release()
Ejemplo n.º 23
0
class FileSystemObserver(object):
    def __init__(self, test_output_dir):

        self.test_output_dir = test_output_dir

        # Start observing output dir
        self.done_event = Event()
        self.event_handler = OutputEventHandler(self.done_event)
        self.observer = Observer()
        self.observer.schedule(self.event_handler,
                               self.test_output_dir,
                               recursive=True)
        self.observer.start()

    def get_output_dir(self):
        return self.test_output_dir

    def restart_observer_if_needed(self):
        if self.observer.is_alive():
            return

        self.observer = Observer()
        self.done_event.clear()
        self.observer.schedule(self.event_handler,
                               self.test_output_dir,
                               recursive=True)
        self.observer.start()

    def wait_for_output(self, timeout_seconds, output_validator, max_files):
        logging.info('Waiting up to %d seconds for %d test outputs...',
                     timeout_seconds, max_files)
        self.restart_observer_if_needed()
        wait_start_time = time.perf_counter()
        for i in range(0, max_files):
            # Note: The timing on Event.wait() is inaccurate
            self.done_event.wait(timeout_seconds)
            self.done_event.clear()
            current_time = time.perf_counter()
            if timeout_seconds < (current_time - wait_start_time
                                  ) or output_validator.validate():
                break
        self.observer.stop()
        self.observer.join()
Ejemplo n.º 24
0
def main():
    """:"""
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s - %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    )
    # TODO (jam) set this path to whatever dir the user sets in config
    path = sys.argv[1] if len(sys.argv) > 1 else "."
    event_handler = LoggingEventHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while observer.is_alive():
            observer.join(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
Ejemplo n.º 25
0
class IPCom:
    """IPC async thread"""

    INSTANCE: Optional["IPCom"] = None

    def __init__(self):
        self.observer = Observer()
        self.observer.start()
        self.pid = os.getpid()

    def fswatch(self, watcher: FileSystemEventHandler, path: Path, recursive=False):
        if not self.observer.is_alive():
            # Just in case...
            self.observer.start()
        return self.observer.schedule(
            watcher, str(path.absolute()), recursive=recursive
        )

    def fsunwatch(self, watcher):
        self.observer.unschedule(watcher)
Ejemplo n.º 26
0
 def wait_on_entry_calc(self, key):
     with self.lock:
         self._reload_cache()
         entry = self._get_cache()[key]
         if not entry['being_calculated']:
             return entry['value']
     event_handler = _PickleCore.CacheChangeHandler(
         filename=self._cache_fname(), core=self, key=key)
     observer = Observer()
     event_handler.inject_observer(observer)
     observer.schedule(event_handler,
                       path=self.expended_cache_dir,
                       recursive=True)
     observer.start()
     observer.join(timeout=1.0)
     if observer.is_alive():
         # print('Timedout waiting. Starting again...')
         return self.wait_on_entry_calc(key)
     # print("Returned value: {}".format(event_handler.value))
     return event_handler.value
Ejemplo n.º 27
0
class Target(FileSystemEventHandler):
    def __init__(self, watchDir):
        self.observer = None
        self.watchDir = watchDir

    def run(self):
        self.observer = Observer()
        self.observer.schedule(self, self.watchDir, recursive=True)
        self.observer.start()

        try:
            while True:
                time.sleep(1)

                if not self.status():
                    q.put(self.status())
                    break

        except KeyboardInterrupt:
            self.observer.stop()

        self.stop()
        self.observer.join()

    def stop(self):
        self.observer.stop()

    def status(self):
        return self.observer.is_alive()

    def on_moved(self, event):
        pass

    def on_created(self, event):
        pass

    def on_deleted(self, event):
        pass

    def on_modified(self, event):
        pass
Ejemplo n.º 28
0
def do_rsync_auto(config, servers, additional_args=None, command=None, run_once=False,
                  burst_limit=0, verbose=True, local_path=None, remote_path=None):
    """Launch rsync-auto for providers."""
    local_path = base_rsync.get_local_path(config, local_path)
    remote_path = base_rsync.get_remote_path(config, remote_path)

    logging.info(click.style('Doing an initial rsync...', bold=True))
    base_rsync.do_rsync(config, servers, additional_args=additional_args,
                        verbose=verbose, local_path=local_path, remote_path=remote_path)

    if command and run_once:
        logging.info(click.style('Launching run-once command...', bold=True))

        for server in servers:
            Thread(
                target=base_ssh.do_ssh,
                args=(config, [server]),
                kwargs={
                    'command': command,
                    'verbose': verbose,
                },
            ).start()

        command = None

    _show_monitoring_message(config)

    handler = RsyncHandler(config, servers, additional_args=additional_args, command=command,
                           burst_limit=burst_limit, run_once=run_once, verbose=verbose,
                           local_path=local_path, remote_path=remote_path)
    observer = Observer()
    observer.schedule(handler, path=local_path, recursive=True)
    observer.start()

    try:
        while observer.is_alive():
            sleep(1)
    except KeyboardInterrupt:
        observer.stop()

    observer.join()
Ejemplo n.º 29
0
class DirectoryWatcher:
    """A directory watcher class."""

    def __init__(
        self,
        directory: Path,
        on_modified: Callable[[Path], None],
    ) -> None:
        """
        Initialize a watcher which observes modifications in `directory`.

        on_modified: A callable which is invoked with the path of modified
                     files within `directory`.
        """
        self.on_modified = on_modified
        self.watched_directory = str(directory)
        self.observer = Observer()

    def start(self) -> None:
        """Start watching the specified directory for file modifications."""
        event_handler = DirectoryEventHandler(self.on_modified)
        self.observer.schedule(
            event_handler,
            self.watched_directory,
            recursive=True,
        )
        self.observer.start()

    def stop(self) -> None:
        """Stop watching the directory."""
        if self.observer.is_alive():
            try:
                self.observer.stop()
                self.observer.join()
            except (RuntimeError, SystemError):
                # TODO: Understand exactly what join() does, and why
                # it sometimes throws a RuntimeError
                # Also find out why MacOS throws SystemError
                pass
Ejemplo n.º 30
0
    async def _start_monitoring(self, category_name):
        observer = None

        try:
            category = self.bot.config.pics_categories[category_name]
            directory = category['send_directory']

            event_handler = _FileSystemEventHandler(
                directory, self.monitoring_events[category_name],
                self.bot.loop)

            observer = Observer()
            observer.schedule(event_handler, directory)
            observer.start()

            await self.to_close.wait()
            observer.stop()
            observer.join()
        except asyncio.CancelledError:
            if observer is not None and observer.is_alive():
                observer.stop()
                observer.join()
Ejemplo n.º 31
0
    def start_observer(self, app):
        restart_timeout = self._config.get('restart')

        lock = threading.Lock()

        source = app._observer_source()
        app._beforeObserve()

        producer = consumer = observer = None

        def _default_except_handler(timeout=None):
            if consumer is not None and consumer.is_alive():
                consumer.stop()
            observer = None

            if timeout:
                time.sleep(timeout)

        observer_found = None

        producer = LogProducer(app,
                               lock,
                               source=source,
                               logger=self._logger,
                               watch_everything=self.watch_everything)
        consumer = LogConsumer(args=(app, producer, lock, self._logger,
                                     self.consumer_sleep))
        consumer.start()

        try:
            observer = Observer(timeout=self.observer_timeout)
            observer.schedule(producer, source, recursive=True)
            observer.start()

            observer_found = {}

            while not self.stop_requested:
                if restart_timeout and producer.timestamp is not None:
                    timestamp = getToday() - producer.timestamp
                    if timestamp.total_seconds() > restart_timeout:
                        self._out('restart on producer.timestamp: %s' %
                                  restart_timeout,
                                  is_error=True)
                        self.restart_requested = True

                time.sleep(5)

                if app is None or app.is_dead(force=0):
                    self._out('app is dead', is_error=True)
                    self.restart_requested = True
                    app = None
                if not observer.is_alive():
                    self._out('observer is lifeless', is_error=True)
                    self.restart_requested = True
                if not consumer.is_alive():
                    self._out('cunsumer is lifeless', is_error=True)
                    self.restart_requested = True

                if self.restart_requested:
                    break

        except (OSError, FileNotFoundError) as ex:
            self.restart_requested = True
            self._out('!!! Observer Exception: %s' % ex, is_error=True)

            _default_except_handler(15)

        except Exception as ex:
            self.restart_requested = True
            self._out('!!! Unexpected Exception: %s' % ex, is_error=True)

            _default_except_handler(30)

            #raise

        else:
            self._out('==> Stop, stop_requested: %s' % self.stop_requested)

        finally:
            if producer is not None:
                producer.stop()

            if observer is not None and observer.is_alive():
                observer.stop()
                observer.join()

            if consumer is not None and consumer.is_alive():
                observer_found = consumer.stop()
                consumer.join()

            if observer_found:
                self._found.update(observer_found)

        consumer = None
        producer = None
        observer = None
Ejemplo n.º 32
0
class FileModifyWatcher(object):
    """Use inotify to watch file-system for file modifications

    Usage:
    1) subclass the method handle_event, action to be performed
    2) create an object passing a list of files to be watched
    3) call the loop method
    """
    supported_platforms = ('Darwin', 'Linux')
    
    def __init__(self, path_list):
        """@param file_list (list-str): files to be watched"""
        self.file_list = set()
        self.watch_dirs = set() # all dirs to be watched
        self.notify_dirs = set() # dirs that generate notification whatever file
        for filename in path_list:
            path = os.path.abspath(filename)
            if os.path.isfile(path):
                self.file_list.add(path)
                self.watch_dirs.add(os.path.dirname(path))
            else:
                self.notify_dirs.add(path)
                self.watch_dirs.add(path)
        self.platform = get_platform_system()
        if self.platform not in self.supported_platforms:
            msg = "Unsupported platform '%s'\n" % self.platform
            msg += ("'auto' command is supported only on %s" %
                    (self.supported_platforms,))
            raise Exception(msg)
        self.observer = Observer()
        self.observer.start()
        while not self.observer.is_alive():
            time.sleep(0.1)


    def __del__(self):
        self.observer.stop()
        self.observer.join()
        
    def _handle(self, event):
        """calls platform specific handler"""
        filename = event.src_path

        if (filename in self.file_list or
            os.path.dirname(filename) in self.notify_dirs):
            self.handle_event(event)

    def handle_event(self, event):
        """this should be sub-classed """
        raise NotImplementedError

    def _loop(self):
        handler = self._handle
        observer = self.observer
        
        class EventHandler(FileSystemEventHandler):
            def on_modified(self, event):
                try:
                    handler(event)
                except KeyboardInterrupt:
                    pass

        event_handler = EventHandler()

        for watch_this in self.watch_dirs:
            observer.schedule(event_handler, watch_this, recursive=False)
        
    def loop(self):
        """Infinite loop watching for file modifications

        """

        self._loop()
Ejemplo n.º 33
0
class Merger:
    def __init__(self, ledger_file, rules_file, yes_append, csv_files):
        self._ledger_file = ledger_file
        self._rules_file = rules_file
        self._yes_append = yes_append
        self._csv_files = csv_files
        self._observer = None

        def on_rules_modified(event):
            print()
            self.reload()
            self.print_transactions()
            self._prompt_append(wait=False)
        self._event_handler = PatternMatchingEventHandler([rules_file])
        self._event_handler.on_modified = on_rules_modified
        self._observer = Observer()
        self._observer.schedule(self._event_handler,
                                os.path.dirname(rules_file))

    def __del__(self):
        if self._observer and self._observer.is_alive():
            self._observer.stop()
            self._observer.join()

    def _prompt_append(self, wait=True):
        click.secho('\nLedger file: %s' % self._ledger_file, fg='yellow')
        click.secho('Append these transactions to Ledger file?',
                    fg='yellow', nl=False)
        if wait:
            return click.confirm('')
        else:
            click.secho(' [y/N]: ', nl=False)
            return

    def reload(self):
        print('\rReloading...\n')
        rules = Rules(self._rules_file)
        self.transactions = []
        self.unknown = []

        for csv_file in self._csv_files:
            click.secho('>>> {}'.format(csv_file), fg='blue')
            ts = []
            self.transactions.append((csv_file, ts))
            for t in get_transactions(csv_file, rules, self._ledger_file):
                print(t)
                print()
                ts.append(t)
                if t.account2 == 'expenses:unknown':
                    self.unknown.append(t)

    def print_transactions(self):
        if not any(x for (_, x) in self.transactions):
            click.secho('No new transactions found')
            return False

        if self.unknown:
            click.secho('{} transactions with unknown account:'
                        .format(len(self.unknown)), fg='yellow')
            for t in self.unknown:
                click.secho('   {}: {} (£{:0.2f})'
                            .format(t.date, t.description, t.amount))

    def main(self):
        self.reload()
        if self.print_transactions() is False:
            return

        self._observer.start()
        if self._ledger_file and (self._yes_append or self._prompt_append()):
            print('Appending...', end=' ')
            now = datetime.now().replace(microsecond=0)
            with open(self._ledger_file, 'ta') as f:
                for filename, txns in self.transactions:
                    print('; Converted from {}'.format(filename), file=f)
                    print('; [{}]\n'.format(now), file=f)
                    for t in txns:
                        print(str(t) + '\n', file=f)
            print('done')
Ejemplo n.º 34
0
class FileMonitor(FileSystemEventHandler):
	def __init__(self):
		self._observer = Observer()

		self._event_callback = {
			'modified': [],
			'moved': [],
			'created': [],
			'deleted': [],
		}

	def start(self, directory, recursive=False):
		self._observer.schedule(self, directory, recursive)
		self._observer.start()

	def reset(self, directory, recursive=False):
		if self._observer.is_alive():
			self._observer.unschedule_all()
			self._observer.stop()
			self._observer.join()
		
		self._observer.schedule(self, directory, recursive)
		self._observer.start()

	def stop(self):
		self._observer.unschedule_all()
		self._observer.stop()
		self._observer.join()

	def bind(self, event, func):
		if event in self._event_callback:
			self._event_callback[event].append(func)
			return True

		return False
			
	def on_moved(self, event):
		"""Called when a file or a directory is moved or renamed.

		:param event:
			Event representing file/directory movement.
		:type event:
			:class:`DirMovedEvent` or :class:`FileMovedEvent`
		"""
		print( 'moved', event.src_path, event.dest_path )
		for cb in self._event_callback['moved']:
			cb(event)


	def on_created(self, event):
		"""Called when a file or directory is created.

		:param event:
			Event representing file/directory creation.
		:type event:
			:class:`DirCreatedEvent` or :class:`FileCreatedEvent`
		"""
		print( 'created', event.src_path )
		for cb in self._event_callback['created']:
			cb(event)


	def on_deleted(self, event):
		"""Called when a file or directory is deleted.

		:param event:
			Event representing file/directory deletion.
		:type event:
			:class:`DirDeletedEvent` or :class:`FileDeletedEvent`
		"""
		print( 'deleted', event.src_path )
		for cb in self._event_callback['deleted']:
			cb(event)


	def on_modified(self, event):
		"""Called when a file or directory is modified.

		:param event:
			Event representing file/directory modification.
		:type event:
			:class:`DirModifiedEvent` or :class:`FileModifiedEvent`
		"""
		print( 'modified', event.src_path )
		for cb in self._event_callback['modified']:
			cb(event)
Ejemplo n.º 35
0
class APIDocumentObserver(with_metaclass(SingletonMeta, object)):
    """
    ``APIDocumentObserver`` is observer of API Documents.
    """

    def __init__(self, doc_path=None, doc_index_path=None, doc_file_path_list=None):
        """
        Construct method of ``APIDocumentObserver``.

        :param doc_path: API Document Directory path
        :param doc_index_path: API Document index path
        :param doc_file_path_list: Document file list ``ORDER`` in ``index.json``
        :return:  APIDocumentObserver Singleton instance
        """
        from watchdog.observers import Observer
        from .document_trace_handler import DocumentTraceHandler
        from .document_trace_file import DocumentTraceFile

        if doc_path:
            if doc_file_path_list and isinstance(doc_file_path_list, list):
                tracing_files = [DocumentTraceFile(tracing_file_path=f) for f in doc_file_path_list]
            else:
                tracing_files = list()

            if doc_index_path:
                tracing_files.append(DocumentTraceFile(tracing_file_path=doc_index_path, is_index_file=True))

            event_handler = DocumentTraceHandler(tracing_files=tracing_files)
            self.observer = Observer()
            self.observer.schedule(event_handler, doc_path, recursive=True)
        else:
            raise Exception("doc_path is None.")

    def start_watch(self):
        """
        Start watch docs
        """

        if self.observer:
            self.observer.start()
            logger.info("Start watchdocs..")
        else:
            pass

    @property
    def is_started(self):
        """
        After run ``start_watch()``, ``is_started`` is True, or False.

        :return: True | False
        """

        if self.observer:
            return self.observer.is_alive()
        return False

    def stop_watch(self):
        """
        Stop watch docs
        """

        if self.observer and self.observer.is_alive():
            self.observer.stop()
            self.observer.join()

            logger.info("Stop watchdocs..")
Ejemplo n.º 36
0
class Client(LoggerMixin, Process, FileSystemEventHandler):
    """
    Responsible for Listener and Processor components. Provides
    functions to start/stop both itself and its components. In addition, it is
    also capable of receiving file-system events via the 'watchdog' library.

    General procedure:

        1. Starts both the Process and Listener components.
        2. Listen and act upon exit/error notifications from components
        3. Listen for file-system events and acts accordingly.
    """

    def __init__(self, dsn, watch_path=None, failover_files=None):
        """
        To make the client listen for Postgres 'recovery.conf, recovery.done'
        events::
            from hermes.client import Client

            dsn = {'database': 'example_db',
                   'host': '127.0.0.1',
                   'port': 5432,
                   'user': '******',
                   'password': '******'}

            watch_path = '/var/lib/postgresql/9.4/main/'
            failover_files = ['recovery.done', 'recovery.conf']

            client = Client(dsn, watch_path, failover_files)

            # Add processor and listener
            ...

            # Start the client
            client.start()

        Or, if you decide you don't want to use a file watcher, then you
        can omit those parameters. However, the Client will still perform
        master/slave checks if a problem is encountered::
            from hermes.client import Client

            dsn = {'database': 'example_db',
                   'host': '127.0.0.1',
                   'port': 5432,
                   'user': '******',
                   'password': '******'}

            client = Client(dsn)

            # Add processor and listener
            ...

            # Start the client
            client.start()

        :param dsn: A Postgres-compatible DSN dictionary
        :param watch_path: The directory to monitor for filechanges. If None,
            then file monitoring is disabled.
        :param failover_files: A list of files which, when modified, will
            cause the client to call :func:`~execute_role_based_procedure`
        """
        super(Client, self).__init__()

        self.directory_observer = Observer()

        self._processor = None
        self._listener = None

        self._watch_path = watch_path
        self._failover_files = failover_files
        self.master_pg_conn = PostgresConnector(dsn)

        self._should_run = False
        self._child_interrupted = False
        self._exception_raised = False

        self._exit_queue = Queue(1)

    def add_processor(self, processor):
        """
        :param processor: A :class:`~hermes.components.Component` object which
            will receive notifications and run the
            :func:`~hermes.components.Component.execute` method.

        :raises: :class:`~hermes.exceptions.InvalidConfigurationException` if
            the provided processor is not a subclass of
            :class:`~hermes.components.Component`
        """
        if not isinstance(processor, Component):
            raise InvalidConfigurationException(
                "Processor must of type Component"
            )
        self._processor = processor

    def add_listener(self, listener):
        """
        :param listener: A :class:`~hermes.components.Component` object which
            will listen for notifications from Postgres and pass an event down
            a queue.

        :raises: :class:`~hermes.exceptions.InvalidConfigurationException` if
            the provided listener is not a subclass of
            :class:`~hermes.components.Component`
        """
        if not isinstance(listener, Component):
            raise InvalidConfigurationException(
                "Listener must of type Component"
            )
        self._listener = listener

    def _validate_components(self):
        """
        Checks through a set of validation procedures to ensure the client is
        configured properly.

        :raises: :class:`~hermes.exceptions.InvalidConfigurationException`
        """
        if not self._processor:
            raise InvalidConfigurationException("A processor must be defined")

        if not self._listener:
            raise InvalidConfigurationException("A listener must be defined")

        if self._processor.error_queue is not self._listener.error_queue:
            raise InvalidConfigurationException(
                "A processor and listener's error queue must be the same"
            )

    def start(self):
        """
        Starts the Client, its Components and the directory observer

        :raises: :class:`~hermes.exceptions.InvalidConfigurationException`
        """
        signal(SIGINT, self._handle_terminate)
        signal(SIGTERM, self._handle_terminate)
        self._validate_components()
        super(Client, self).start()

    def run(self):
        """
        Performs a :func:`~select.select` on the components' error queue.
        When a notification is detected, the client will log the message and
        then calculate if the Postgres server is still a Master -  if not, the
        components are shutdown.
        """
        super(Client, self).run()
        self._start_observer()

        signal(SIGCHLD, self._handle_sigchld)

        self._should_run = True

        self.execute_role_based_procedure()
        while self._should_run:
            self._exception_raised = self._child_interrupted = False
            try:
                exit_pipe = self._exit_queue._reader

                ready_pipes, _, _ = select.select(
                    (exit_pipe, ), (), ()
                )

                if exit_pipe in ready_pipes:
                    self.terminate()

            except select.error:
                if not self._child_interrupted and not self._exception_raised:
                    self._should_run = False

    def _start_components(self, restart=False):
        """
        Starts the Processor and Listener if the client is not running
        """
        if not self._processor.is_alive():
            if restart and self._processor.ident:
                self._processor.join()
            self._processor.start()

        if not self._listener.is_alive():
            if restart and self._listener.ident:
                self._listener.join()
            self._listener.start()

    def _stop_components(self):
        """
        Stops the Processor and Listener if the client is running
        """
        if self._listener and self._listener.ident and self._listener.is_alive():
            self._listener.terminate()
            self._listener.join()

        if self._processor and self._processor.ident and self._processor.is_alive():
            self._processor.terminate()
            self._processor.join()

    def _start_observer(self):
        """
        Schedules the observer using 'settings.WATCH_PATH'
        """
        if self._watch_path:
            self.directory_observer.schedule(
                self, self._watch_path, recursive=False
            )
            self.directory_observer.start()

    def _stop_observer(self):
        """
        Stops the observer if it is 'alive'
        """
        if self._watch_path and self.directory_observer:
            if self.directory_observer.is_alive():
                self.directory_observer.stop()

    def on_any_event(self, event):
        """
        Listens to an event passed by 'watchdog' and checks the current
        master/slave status

        :param event: A :class:`~watchdog.events.FileSystemEvent`
        object passed by 'watchdog' indicating an event change within the
        specified directory.
        """
        file_name = event.src_path.split('/')[-1]
        if file_name in self._failover_files:
            self.execute_role_based_procedure()

    def execute_role_based_procedure(self):
        """
        Starts or stops components based on the role (Master/Slave) of the
        Postgres host.

        Implements a `binary exponential backoff
        <http://en.wikipedia.org/wiki/Exponential_backoff
        #Binary_exponential_backoff_.2F_truncated_exponential_backoff>`_
        up to 32 seconds if it encounters a FATAL connection error.
        """
        backoff = 0
        while True:
            try:
                server_is_master = self.master_pg_conn.is_server_master()
                if server_is_master:
                    self.log.warning('Server is a master, starting components')
                    self._start_components(restart=True)
                else:
                    self.log.warning('Server is a slave, stopping components')
                    self._stop_components()
                break
            except OperationalError:
                self._stop_components()

                self.log.warning(
                    'Cannot connect to the DB, maybe it has been shutdown?',
                    exc_info=True
                )

                if backoff:  # pragma: no cover
                    backoff <<= 1
                    if backoff > 32:
                        backoff = 1
                else:
                    backoff = 1
                sleep(backoff)

    def _handle_sigchld(self, sig, frame):
        """
        A child process dying, and the client not shutting down, indicates
        a process has been shut down by some external caller.

        We must check both the processor and listener for 'liveness' and
        start those which have failed.
        """
        if sig == SIGCHLD and self._should_run and not self._exception_raised:
            try:
                expected, action = self._processor.error_queue.get_nowait()
                self._exception_raised = True
                if expected:
                    if action == TERMINATE:
                        self.execute_role_based_procedure()
                else:
                    self.log.critical(
                        'An unexpected error was raised - shutting down'
                    )
                    self._shutdown()
            except Empty:
                self._child_interrupted = True
                self._start_components(restart=True)

    def _handle_terminate(self, sig, frame):
        """
        Handles SIGINT and SIGTERM signals.

        If called from another process then puts to the exit queue, else
        calls _shutdown.
        """
        if self.ident != os.getpid():
            self._exit_queue.put_nowait(True)
        else:
            self._shutdown()

    def _shutdown(self):
        """
        Shuts down the Client:
            * Sets '_should_run' to False.
            * Stops the components.
            * Stops the observer.
        """
        self.log.warning('Shutting down...')
        self._should_run = False
        self._stop_components()
        self._stop_observer()
Ejemplo n.º 37
0
class LocalSyncWorker(ConsolidatedEventHandler, metaclass=Singleton):
    def __init__(self):
        super().__init__()

        self.ignore = threading.Event()

        try:
            user = get_current_user()
        except NoResultFound:
            # TODO: This only happens when a user logs out and the db has
            # been cleared. The app tries to run again without a user being
            # being set. This error doesn't disrupt user experience, but we
            # might consider tracking down the specific source and preventing
            # it from happening.
            raise
        self.folder = user.folder

        self.observer = Observer()
        self.observer.schedule(self, self.folder, recursive=True)

    def start(self):
        logger.debug('Starting watchdog observer')
        self.observer.start()

    def stop(self):
        logger.debug('Stopping LocalSyncWorker')
        # observer is actually a separate child thread and must be join()ed
        self.observer.stop()
        self.join()

    def is_alive(self):
        return self.observer.is_alive()

    def join(self):
        self.observer.join()
        logger.debug('LocalSyncWorker Stopped')

    def dispatch(self, event):
        if self.ignore.is_set():
            return logger.debug('Ignoring event {}'.format(event))
        super().dispatch(event)

    def on_moved(self, event):
        logger.info('Move event for {}: from {} to {}'.format('directory' if event.is_directory else 'file', event.src_path, event.dest_path))

        if is_ignored(event.dest_path):
            logger.info('Removing {} {} from DB, it was moved to an ignored file'.format('directory' if event.is_directory else 'file', event.src_path, event.dest_path))
            context = OperationContext(local=Path(event.src_path), check_is_folder=False)
            return self.put_event(operations.DatabaseDelete(context))

        # Note: OperationContext should extrapolate all attributes from what it is given
        if event.is_directory:
            try:
                # TODO: avoid a lazy context load in this case to catch the NodeNotFound exception?
                _ = OperationContext(local=Path(event.src_path), is_folder=True).remote
                return self.put_event(operations.RemoteMoveFolder(
                    OperationContext(local=Path(event.src_path), is_folder=True),
                    OperationContext(local=Path(event.dest_path), is_folder=True),
                ))
            except NodeNotFound:
                return self.put_event(operations.RemoteCreateFolder(
                    OperationContext(local=Path(event.dest_path), is_folder=True),
                ))

        try:
            # TODO: avoid a lazy context load in this case to catch the NodeNotFound exception?
            _ = OperationContext(local=Path(event.src_path)).remote  # noqa
            return self.put_event(operations.RemoteMoveFile(
                OperationContext(local=Path(event.src_path)),
                OperationContext(local=Path(event.dest_path)),
            ))
        except NodeNotFound:
            return self.put_event(operations.RemoteCreateFile(
                OperationContext(local=Path(event.dest_path)),
            ))

    def on_created(self, event):
        logger.info('Creation event for {}: {}'.format('directory' if event.is_directory else 'file', event.src_path))
        node = utils.extract_node(event.src_path)
        path = Path(event.src_path)

        # If the file exists in the database, this is a modification
        # This logic may not be the most correct, #TODO re-evaluate
        if utils.local_to_db(path, node):
            return self.on_modified(event)

        context = OperationContext(local=path, node=node)

        if event.is_directory:
            return self.put_event(operations.RemoteCreateFolder(context))
        return self.put_event(operations.RemoteCreateFile(context))

    def on_deleted(self, event, *args, is_folder=False, **kwargs):
        logger.info('Deletion event for {}: {}'.format('directory' if event.is_directory else 'file', event.src_path))
        # A hack: override checking if the passed path is a directory. Since Windows
        # emits folder deletion events as file deletes we need to ignore whether or not
        # a delete event is for a folder. Since the RemoteDelete operation works identically
        # for files and folders we can get away with this here.
        context = OperationContext(local=Path(event.src_path), check_is_folder=False)
        context.db  # noqa

        return self.put_event(operations.RemoteDelete(context))

    def on_modified(self, event):
        logger.info('Modification event  for {}: {}'.format('directory' if event.is_directory else 'file', event.src_path))
        node = utils.extract_node(event.src_path)
        path = Path(event.src_path)

        # If the file does not exist in the database, this may be a create
        if not utils.local_to_db(path, node):
            # for e in self._create_cache:
            #     if e.src_path == event.src_path:
            #         logging.warning('Found a duplicate create event {}. Ignoring...'.format(event))
            #         return
            return self.on_created(event)

        context = OperationContext(local=Path(event.src_path))

        if event.is_directory:
            # FIXME: This branch should never be reached, due to a check in dispatch method
            logger.error("Received unexpected modification event for folder: {}".format(event.src_path))
            return self.put_event(operations.RemoteCreateFolder(context))
        return self.put_event(operations.RemoteUpdateFile(context))

    def put_event(self, event):
        OperationWorker().put(event)