def test_watcher_default_ignored_directory() -> None:
    root_path = "{}/tests/watcher_root/__tmp__".format(
        os.path.realpath(os.getcwd()))
    watcher = Watcher(root=[root_path])
    assert len(watcher.root) == 1
    assert isinstance(watcher.watched_files, dict)
    assert len(watcher.watched_files) == 0
Example #2
0
def test_watcher_empty_directory() -> None:
    root_path = '{}/tests/watcher_root/empty'.format(
        os.path.realpath(os.getcwd()))
    watcher = Watcher(root=[root_path])
    assert len(watcher.root) == 1
    assert isinstance(watcher.watched_files, dict)
    assert len(watcher.watched_files) == 0
def test_watcher_configurable_ignored_directory() -> None:
    root_path = "{}/tests/watcher_root/configurable_ignored".format(
        os.path.realpath(os.getcwd()))
    watcher = Watcher(root=[root_path])
    assert len(watcher.root) == 1
    assert isinstance(watcher.watched_files, dict)
    assert len(watcher.watched_files) == 1

    watcher = Watcher(root=[root_path],
                      configuration={
                          "options": {
                              "watcher": {
                                  "ignored_dirs": ["configurable_ignored"]
                              }
                          }
                      })
    assert len(watcher.root) == 1
    assert isinstance(watcher.watched_files, dict)
    assert len(watcher.watched_files) == 0
Example #4
0
def test_watcher_configurable_ignored_directory() -> None:
    root_path = '{}/tests/watcher_root/configurable_ignored'.format(
        os.path.realpath(os.getcwd()))
    watcher = Watcher(root=[root_path])
    assert len(watcher.root) == 1
    assert isinstance(watcher.watched_files, dict)
    assert len(watcher.watched_files) == 1

    watcher = Watcher(root=[root_path],
                      configuration={
                          'options': {
                              'watcher': {
                                  'ignored_dirs': ['configurable_ignored']
                              }
                          }
                      })
    assert len(watcher.root) == 1
    assert isinstance(watcher.watched_files, dict)
    assert len(watcher.watched_files) == 0
Example #5
0
    def run_command(self, args: List[str]) -> None:
        if len(args) == 0:
            print(self.run_command_usage())
        else:
            configuration = None
            log_level = logging.INFO

            if '-c' in args or '--config' in args:
                index = args.index('-c') if '-c' in args else args.index('--config')
                args.pop(index)

                config_files = []  # type: List[str]
                while len(args) > index and args[index][0] != '-':
                    value = args.pop(index)
                    if value not in config_files:
                        config_files.append(value)

                if not len(config_files):
                    print('Missing config file on command line')
                    sys.exit(2)

                try:
                    configuration = parse_config_files(config_files)
                except FileNotFoundError as e:
                    print('Invalid config file: {}'.format(str(e)))
                    sys.exit(2)
                except ValueError as e:
                    print('Invalid config file, invalid JSON format: {}'.format(str(e)))
                    sys.exit(2)

            if '--production' in args:
                index = args.index('--production')
                args.pop(index)
                watcher = None
            else:
                cwd = os.getcwd()
                root_directories = [os.getcwd()]
                for arg in set(args):
                    root_directories.append(os.path.dirname('{}/{}'.format(os.path.realpath(cwd), arg)))
                watcher = Watcher(root=root_directories, configuration=configuration)

            if '-l' in args or '--log' in args:
                index = args.index('-l') if '-l' in args else args.index('--log')
                args.pop(index)
                if len(args) > index:
                    try:
                        log_level = getattr(logging, args.pop(index).upper())
                    except AttributeError:
                        pass

            logging.basicConfig(format='%(asctime)s (%(name)s): %(message)s', level=log_level)
            logging.Formatter(fmt='%(asctime)s.%(msecs).03d', datefmt='%Y-%m-%d %H:%M:%S')
            ServiceLauncher.run_until_complete(set(args), configuration, watcher)
        sys.exit(0)
Example #6
0
def test_watcher_callback(loop: Any) -> None:
    root_path = '{}/tests/watcher_root'.format(os.path.realpath(os.getcwd()))
    watcher = Watcher(root=[root_path])
    assert len(watcher.root) == 1
    assert isinstance(watcher.watched_files, dict)
    assert len(watcher.watched_files) == 2

    result = watcher.update_watched_files()
    assert result == {}

    watcher.watched_files = {'_test': 0}
    result = watcher.update_watched_files(reindex=True)
    assert len(result.get('added')) == 2
    assert len(result.get('removed')) == 1
    assert len(result.get('updated')) == 0

    class Test():
        callbacks_run = {}  # type: Dict[int, bool]

        @classmethod
        async def _async(cls) -> None:
            async def cb1(updated_files: Union[List, set]) -> None:
                cls.callbacks_run[1] = True

            async def cb2(updated_files: Union[List, set]) -> None:
                cls.callbacks_run[2] = True

            task = await watcher.watch(callback_func=cb1)
            await asyncio.sleep(1.0)
            task.cancel()

            watcher.watched_files = {'_test': 0}
            task = await watcher.watch(callback_func=cb2)
            await asyncio.sleep(1.0)
            task.cancel()

            assert cls.callbacks_run.get(1) is None
            assert cls.callbacks_run.get(2) is True

    loop.run_until_complete(Test._async())
def test_watcher_auto_root() -> None:
    watcher = Watcher()
    assert watcher.root == [os.path.realpath(sys.argv[0].rsplit("/", 1)[0])]
Example #8
0
    def run_command(self, args: List[str]) -> None:
        if len(args) == 0:
            print(self.run_command_usage())
        else:
            configuration = None
            log_level = logging.INFO

            env_loop = str(os.getenv("TOMODACHI_LOOP", "")).lower() or None

            if env_loop or "--loop" in args:
                if "--loop" in args:
                    index = args.index("--loop")
                    args.pop(index)
                    value = args.pop(index).lower()

                    if env_loop and env_loop != value:
                        print(
                            "Invalid argument to --loop, '{}' differs from env TOMODACHI_LOOP"
                            .format(value))
                        sys.exit(2)
                elif env_loop:
                    value = env_loop
                else:
                    value = "auto"

                if value in ("auto", "default"):
                    pass
                elif value in ("asyncio", "aio", "async"):
                    asyncio.set_event_loop_policy(
                        asyncio.DefaultEventLoopPolicy())
                    pass
                elif value in ("uvloop", "libuv", "uv"):
                    try:
                        import uvloop  # noqa  # isort:skip
                    except Exception:  # pragma: no cover
                        print(
                            "The 'uvloop' package needs to be installed to use uvloop event loop"
                        )
                        sys.exit(2)
                    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
                else:
                    print(
                        "Invalid argument to --loop, event loop '{}' not recognized"
                        .format(value))
                    sys.exit(2)

            if "-c" in args or "--config" in args:
                index = args.index("-c") if "-c" in args else args.index(
                    "--config")
                args.pop(index)

                config_files: List[str] = []
                while len(args) > index and args[index][0] != "-":
                    value = args.pop(index)
                    if value not in config_files:
                        config_files.append(value)

                if not len(config_files):
                    print("Missing config file on command line")
                    sys.exit(2)

                try:
                    configuration = parse_config_files(config_files)
                except FileNotFoundError as e:
                    print("Invalid config file: {}".format(str(e)))
                    sys.exit(2)
                except ValueError as e:
                    print(
                        "Invalid config file, invalid JSON format: {}".format(
                            str(e)))
                    sys.exit(2)

            env_production = str(os.getenv("TOMODACHI_PRODUCTION",
                                           "")).lower() or None
            if env_production and env_production in ("0", "no", "none",
                                                     "false"):
                env_production = None

            if env_production or "--production" in args:
                if "--production" in args:
                    index = args.index("--production")
                    args.pop(index)
                watcher = None
            else:
                cwd = os.path.realpath(os.getcwd())
                root_directories = [cwd]
                for arg in set(args):
                    if not arg.startswith("/") and not arg.startswith("~"):
                        root_directories.append(
                            os.path.realpath(
                                os.path.dirname(os.path.join(cwd, arg))))
                    else:
                        root_directories.append(
                            os.path.realpath(os.path.dirname(arg)))
                for p in str(os.getenv("PYTHONPATH", "")).split(os.pathsep):
                    if not p:
                        continue
                    if not p.startswith("/") and not p.startswith("~"):
                        root_directories.append(
                            os.path.realpath(os.path.join(cwd, p)))
                    else:
                        root_directories.append(os.path.realpath(p))

                from tomodachi.watcher import Watcher  # noqa  #  isort:skip

                watcher = Watcher(root=root_directories,
                                  configuration=configuration)

            if "-l" in args or "--log" in args or "--log-level" in args:
                index = (args.index("-l")
                         if "-l" in args else args.index("--log")
                         if "--log" in args else args.index("--log-level"))
                args.pop(index)
                if len(args) > index:
                    log_level = getattr(logging,
                                        args.pop(index).upper(),
                                        None) or log_level

            logging.basicConfig(format="%(asctime)s (%(name)s): %(message)s",
                                level=log_level)
            logging.Formatter(fmt="%(asctime)s.%(msecs).03d",
                              datefmt="%Y-%m-%d %H:%M:%S")

            ServiceLauncher.run_until_complete(set(args), configuration,
                                               watcher)
        sys.exit(tomodachi.SERVICE_EXIT_CODE)