Exemple #1
0
    def test_traceback(self, _get_cleaned_args):
        """
        Make sure the --trace option works.
        """

        def test_command():
            print("Command called")

        def test_exception():
            raise Exception("Bad things")

        cli = CLI()
        cli.register(test_command)
        cli.register(test_exception)

        with patch("builtins.print", side_effect=print_) as print_mock:

            # Make sure commands work as usual if no exceptions are raised.
            config = Config(
                params=["test_command", "--trace"], output="Command called"
            )
            _get_cleaned_args.return_value = config.params
            cli.run()
            print_mock.assert_called_with(config.output)
            print_mock.reset_mock()

            # Make sure a traceback is shown if an exception is raised.
            with patch("targ.traceback.format_exc") as traceback_mock:
                with self.assertRaises(SystemExit):
                    _get_cleaned_args.return_value = [
                        "test_exception",
                        "--trace",
                    ]
                    cli.run()
                    traceback_mock.assert_called_once()
Exemple #2
0
    def test_invalid_command_name(self):
        """
        Make sure invalid app names are rejected.
        """
        with self.assertRaises(ValueError):
            CLI().register(add, command_name="contains spaces")

        # Shouldn't raise an exception
        CLI().register(add, command_name="my_command")
Exemple #3
0
    def test_register(self):
        """
        Make sure a command can be registered.
        """
        cli = CLI()

        cli.register(add)

        self.assertTrue(len(cli.commands) == 1)
        self.assertTrue(cli.commands[0].command is add)
Exemple #4
0
def main():
    """
    The entrypoint to the Piccolo CLI.
    """
    # In case it's run from an entrypoint:
    sys.path.insert(0, os.getcwd())

    ###########################################################################
    # Run in diagnose mode if requested.

    diagnose = get_diagnose_flag()
    if diagnose:
        print("Diagnosis...")
        if Finder(diagnose=True).get_app_registry():
            print("Everything OK")
        return

    ###########################################################################

    cli = CLI(description="Piccolo CLI")

    ###########################################################################
    # Register the base apps.

    for _app_config in [
            app_config,
            asgi_config,
            meta_config,
            migrations_config,
            playground_config,
            project_config,
            shell_config,
            sql_shell_config,
            user_config,
    ]:
        for command in _app_config.commands:
            cli.register(command, group_name=_app_config.app_name)

    ###########################################################################
    # Get user defined apps.

    try:
        APP_REGISTRY: AppRegistry = Finder().get_app_registry()
    except (ImportError, AttributeError):
        print("Can't import the APP_REGISTRY from piccolo_conf - some "
              "commands may be missing. If this is a new project don't worry. "
              f"To see a full traceback use `piccolo {DIAGNOSE_FLAG}`")
    else:
        for app_name, _app_config in APP_REGISTRY.app_configs.items():
            for command in _app_config.commands:
                if cli.command_exists(group_name=app_name,
                                      command_name=command.__name__):
                    # Skipping - already registered.
                    continue
                cli.register(command, group_name=app_name)

    ###########################################################################

    cli.run()
Exemple #5
0
    def test_float_arg(self, _get_cleaned_args):
        """
        Test command arguments which are of type float.
        """

        def test_command(arg1: float):
            """
            A command for testing float arguments.
            """
            if type(arg1) is float:
                print("arg1 is float")
            else:
                raise ValueError("arg1 is the wrong type")

        cli = CLI()
        cli.register(test_command)

        with patch("builtins.print", side_effect=print_) as print_mock:

            configs: t.List[Config] = [
                Config(
                    params=["test_command", "1.11"],
                    output="arg1 is float",
                ),
                Config(
                    params=["test_command", "--arg1=1.11"],
                    output="arg1 is float",
                ),
            ]

            for config in configs:
                _get_cleaned_args.return_value = config.params
                cli.run()
                print_mock.assert_called_with(config.output)
                print_mock.reset_mock()
Exemple #6
0
    def test_optional_bool_arg(self, _get_cleaned_args):
        """
        Test command arguments which are of type Optional[bool].
        """

        def test_command(arg1: t.Optional[bool] = None):
            """
            A command for testing optional boolean arguments.
            """
            if arg1 is None:
                print("arg1 is None")
            elif arg1 is True:
                print("arg1 is True")
            elif arg1 is False:
                print("arg1 is False")
            else:
                raise ValueError("arg1 is the wrong type")

        cli = CLI()
        cli.register(test_command)

        with patch("builtins.print", side_effect=print_) as print_mock:

            configs: t.List[Config] = [
                Config(
                    params=["test_command", "--arg1"],
                    output="arg1 is True",
                ),
                Config(
                    params=["test_command", "--arg1=True"],
                    output="arg1 is True",
                ),
                Config(
                    params=["test_command", "--arg1=true"],
                    output="arg1 is True",
                ),
                Config(
                    params=["test_command", "--arg1=t"],
                    output="arg1 is True",
                ),
                Config(
                    params=["test_command", "--arg1=False"],
                    output="arg1 is False",
                ),
                Config(
                    params=["test_command", "--arg1=false"],
                    output="arg1 is False",
                ),
                Config(
                    params=["test_command", "--arg1=f"],
                    output="arg1 is False",
                ),
                Config(params=["test_command"], output="arg1 is None"),
            ]

            for config in configs:
                _get_cleaned_args.return_value = config.params
                cli.run()
                print_mock.assert_called_with(config.output)
                print_mock.reset_mock()
Exemple #7
0
    def test_help_flag(self, _get_cleaned_args):
        """
        If the --help flag is passed in, then help text should be shown.
        """
        _get_cleaned_args.return_value = ["add", "--help"]
        cli = CLI()
        cli.register(add)

        with patch("targ.Command.print_help") as print_help:
            cli.run()
            print_help.assert_called_once()

        # And just run it once without patching, to make sure no errors
        # are raised
        cli.run()
Exemple #8
0
    def test_no_command(self, _get_cleaned_args):
        """
        If no command name is given, then help text should be shown.
        """
        _get_cleaned_args.return_value = []
        cli = CLI()
        cli.register(add)

        with patch("targ.CLI.get_help_text") as get_help_text:
            cli.run()
            get_help_text.assert_called_once()

        # And just run it once without patching, to make sure no errors
        # are raised
        cli.run()
Exemple #9
0
    def test_run_solo(self, _get_cleaned_args: MagicMock):
        """
        Make sure a command is run correctly, when the CLI is in solo mode.
        """
        _get_cleaned_args.return_value = ["1", "2"]
        cli = CLI()
        cli.register(add)

        with patch("builtins.print", side_effect=print_) as print_mock:
            cli.run(solo=True)
            print_mock.assert_called_with(3)
Exemple #10
0
    def test_run_group(self, _get_cleaned_args: MagicMock):
        """
        Make sure a command is run correctly, when the command has been
        registered in a group.
        """
        _get_cleaned_args.return_value = ["math", "add", "1", "2"]
        cli = CLI()
        cli.register(add, group_name="math")

        with patch("builtins.print", side_effect=print_) as print_mock:
            cli.run()
            print_mock.assert_called_with(3)
Exemple #11
0
    def test_no_type_annotations(self, _get_cleaned_args):
        """
        Make sure a command with no type annotations still works - the
        arguments passed to the function will just be strings.
        """

        def test_command(name):
            print(name)

        cli = CLI()
        cli.register(test_command)

        with patch("builtins.print", side_effect=print_) as print_mock:

            configs: t.List[Config] = [
                Config(params=["test_command", "hello"], output="hello"),
            ]

            for config in configs:
                _get_cleaned_args.return_value = config.params
                cli.run()
                print_mock.assert_called_with(config.output)
                print_mock.reset_mock()
Exemple #12
0
    def test_aliases(self, _get_cleaned_args):
        """
        Make sure commands with aliases can be called correctly.
        """

        def test_command():
            print("Command called")

        cli = CLI()
        cli.register(test_command, aliases=["tc"])

        with patch("builtins.print", side_effect=print_) as print_mock:

            configs: t.List[Config] = [
                Config(params=["test_command"], output="Command called"),
                Config(params=["tc"], output="Command called"),
            ]

            for config in configs:
                _get_cleaned_args.return_value = config.params
                cli.run()
                print_mock.assert_called_with(config.output)
                print_mock.reset_mock()
Exemple #13
0
def main():
    """
    The entrypoint to the Piccolo CLI.
    """
    # In case it's run from an entrypoint:
    sys.path.insert(0, os.getcwd())

    ###########################################################################
    # Run in diagnose mode if requested.

    diagnose = get_diagnose_flag()
    if diagnose:
        print("Diagnosis...")
        if Finder(diagnose=True).get_app_registry():
            print("Everything OK")
        return

    ###########################################################################

    cli = CLI(description="Piccolo CLI")

    ###########################################################################
    # Register the base apps.

    for _app_config in [
            app_config,
            asgi_config,
            fixtures_config,
            meta_config,
            migrations_config,
            playground_config,
            project_config,
            schema_config,
            shell_config,
            sql_shell_config,
            tester_config,
            user_config,
    ]:
        for command in _app_config.commands:
            cli.register(
                command.callable,
                group_name=_app_config.app_name,
                aliases=command.aliases,
            )

    ###########################################################################
    # Get user defined apps.

    try:
        APP_REGISTRY: AppRegistry = Finder().get_app_registry()
    except (ImportError, AttributeError):
        print("Can't import the APP_REGISTRY from piccolo_conf - some "
              "commands may be missing. If this is a new project don't worry. "
              f"To see a full traceback use `piccolo {DIAGNOSE_FLAG}`")
    else:
        for app_name, _app_config in APP_REGISTRY.app_configs.items():
            for command in _app_config.commands:
                if cli.command_exists(group_name=app_name,
                                      command_name=command.callable.__name__):
                    # Skipping - already registered.
                    continue
                cli.register(
                    command.callable,
                    group_name=app_name,
                    aliases=command.aliases,
                )

        if "migrations" not in sys.argv:
            # Show a warning if any migrations haven't been run.
            # Don't run it if it looks like the user is running a migration
            # command, as this information is redundant.

            try:
                havent_ran_count = run_sync(
                    CheckMigrationManager(app_name="all").havent_ran_count())
                if havent_ran_count:
                    message = (f"{havent_ran_count} migration hasn't"
                               if havent_ran_count == 1 else
                               f"{havent_ran_count} migrations haven't")

                    colored_warning(
                        message=("=> {} been run - the app "
                                 "might not behave as expected.\n"
                                 "To check which use:\n"
                                 "    piccolo migrations check\n"
                                 "To run all migrations:\n"
                                 "    piccolo migrations forwards all\n"
                                 ).format(message),
                        level=Level.high,
                    )
            except Exception:
                pass

    ###########################################################################

    cli.run()
Exemple #14
0
    def test_bool_arg(self, _get_cleaned_args):
        """
        Test the different formats for boolean flags.
        """

        def test_command(arg1: bool = False):
            """
            A command for testing boolean arguments.
            """
            if arg1 is True:
                print("arg1 is True")
            elif arg1 is False:
                print("arg1 is False")
            else:
                raise ValueError("arg1 is the wrong type")

        cli = CLI()
        cli.register(test_command)

        with patch("builtins.print", side_effect=print_) as print_mock:

            configs: t.List[Config] = [
                Config(params=["test_command"], output="arg1 is False"),
                Config(params=["test_command", "f"], output="arg1 is False"),
                Config(
                    params=["test_command", "false"], output="arg1 is False"
                ),
                Config(
                    params=["test_command", "False"], output="arg1 is False"
                ),
                Config(
                    params=["test_command", "--arg1=f"], output="arg1 is False"
                ),
                Config(
                    params=["test_command", "--arg1=false"],
                    output="arg1 is False",
                ),
                Config(
                    params=["test_command", "--arg1=False"],
                    output="arg1 is False",
                ),
                Config(params=["test_command", "t"], output="arg1 is True"),
                Config(params=["test_command", "true"], output="arg1 is True"),
                Config(params=["test_command", "True"], output="arg1 is True"),
                Config(
                    params=["test_command", "--arg1"], output="arg1 is True"
                ),
                Config(
                    params=["test_command", "--arg1=t"], output="arg1 is True"
                ),
                Config(
                    params=["test_command", "--arg1=true"],
                    output="arg1 is True",
                ),
                Config(
                    params=["test_command", "--arg1=True"],
                    output="arg1 is True",
                ),
            ]

            for config in configs:
                _get_cleaned_args.return_value = config.params
                cli.run()
                print_mock.assert_called_with(config.output)
                print_mock.reset_mock()
from targ import CLI


def add(a: int, b: int):
    """
    Add the two numbers.

    :param a:
        The first number.
    :param b:
        The second number.
    """
    print(a + b)


if __name__ == "__main__":
    cli = CLI()
    cli.register(add)
    cli.run(solo=True)
Exemple #16
0
    :param seconds:
        The number of seconds to countdown.
    """
    print(f"Sleeping for {seconds}")
    await asyncio.sleep(seconds)
    print("Finished")


def raise_error():
    """
    A command which raises an Exception.
    """
    print("Raising an exception")
    raise ValueError("Something went wrong!")


if __name__ == "__main__":
    cli = CLI()
    cli.register(say_hello)
    cli.register(echo)
    cli.register(add, aliases=["+"])
    cli.register(print_pi)
    cli.register(compound_interest)
    cli.register(compound_interest_decimal)
    cli.register(create, group_name="user")
    cli.register(timer)
    cli.register(add, command_name="sum")
    cli.register(print_address)
    cli.register(raise_error)
    cli.run()