Beispiel #1
0
    def test_build(self):
        """
        Initialize a new project and try to build it
        """
        project = stm32pio.core.project.Stm32pio(
            STAGE_PATH, parameters={'project': {
                'board': PROJECT_BOARD
            }})
        project.generate_code()
        project.pio_init()
        project.patch()

        self.assertEqual(project.build(), 0, msg="Build failed")
Beispiel #2
0
    def test_build_should_handle_error(self):
        """
        Build an empty project so PlatformIO should return an error
        """
        project = stm32pio.core.project.Stm32pio(
            STAGE_PATH, parameters={'project': {
                'board': PROJECT_BOARD
            }})
        project.pio_init()

        with self.assertLogs(level='ERROR') as logs:
            self.assertNotEqual(project.build(),
                                0,
                                msg="Build error was not indicated")
            # next() - Technique to find something in array, string, etc. (or to indicate that there is no of such)
            self.assertTrue(next(
                (True
                 for item in logs.output if "PlatformIO build error" in item),
                False),
                            msg="Error message does not match")
Beispiel #3
0
def main(sys_argv: List[str] = None, should_setup_logging: bool = True) -> int:
    """
    Can be used as a high-level wrapper to perform independent tasks.

    Example:
        ret_code = stm32pio.app.main(sys_argv=['new', '-d', '~/path/to/project', '-b', 'nucleo_f031k6', '--with-build'])

    Args:
        sys_argv: list of strings CLI arguments
        should_setup_logging: if this is true, the preferable default logging schema would be applied, otherwise it is a
            caller responsibility to provide (or do not) some logging configuration. The latter can be useful when the
            outer code makes sequential calls to this API so it is unwanted to append the logging handlers every time
            (e.g. when unit-testing)

    Returns:
        0 on success, -1 otherwise
    """

    if sys_argv is None:
        sys_argv = sys.argv[1:]

    args = parse_args(sys_argv)

    if args is not None and args.subcommand == 'gui':
        gui_args = [arg for arg in sys_argv if arg != 'gui']
        import stm32pio.gui.app as gui_app
        return gui_app.main(sys_argv=gui_args).exec_()
    elif args is not None and args.subcommand is not None:
        logger = setup_logging(verbose=args.verbose,
                               dummy=not should_setup_logging)
    else:
        print("\nNo arguments were given, exiting...")
        return 0

    project = None

    # Main routine
    try:
        if args.subcommand == 'init':
            project = stm32pio.core.project.Stm32pio(
                args.path,
                parameters={'project': {
                    'board': args.board
                }},
                instance_options={'save_on_destruction': True})
            if args.store_content:
                project.config.save_content_as_ignore_list()
            if project.config.get('project', 'board') == '':
                logger.warning(
                    "PlatformIO board identifier is not specified, it will be needed on PlatformIO project "
                    "creation. Type 'pio boards' or go to https://platformio.org to find an appropriate "
                    "identifier")
            logger.info(
                f"project has been initialized. You can now edit {stm32pio.core.settings.config_file_name} "
                "config file")
            if args.editor:
                project.start_editor(args.editor)

        elif args.subcommand == 'generate':
            project = stm32pio.core.project.Stm32pio(args.path)
            project.generate_code()
            if args.with_build:
                project.build()
            if args.editor:
                project.start_editor(args.editor)

        elif args.subcommand == 'pio_init':
            project = stm32pio.core.project.Stm32pio(
                args.path,
                parameters={'project': {
                    'board': args.board
                }},
                instance_options={'save_on_destruction': True})
            project.pio_init()

        elif args.subcommand == 'patch':
            project = stm32pio.core.project.Stm32pio(args.path)
            project.patch()

        elif args.subcommand == 'new':
            project = stm32pio.core.project.Stm32pio(
                args.path,
                parameters={'project': {
                    'board': args.board
                }},
                instance_options={'save_on_destruction': True})
            if args.store_content:
                project.config.save_content_as_ignore_list()
            if project.config.get('project', 'board') == '':
                logger.info(
                    f"project has been initialized. You can now edit {stm32pio.core.settings.config_file_name} "
                    "config file")
                raise Exception(
                    "PlatformIO board identifier is not specified, it is needed for PlatformIO project "
                    "creation. Type 'pio boards' or go to https://platformio.org to find an appropriate "
                    "identifier")
            project.generate_code()
            project.pio_init()
            project.patch()
            if args.with_build:
                project.build()
            if args.editor:
                project.start_editor(args.editor)

        elif args.subcommand == 'status':
            project = stm32pio.core.project.Stm32pio(args.path)
            print(project.state)

        elif args.subcommand == 'validate':
            project = stm32pio.core.project.Stm32pio(args.path)
            print(project.validate_environment())

        elif args.subcommand == 'clean':
            project = stm32pio.core.project.Stm32pio(args.path)
            if args.store_content:
                project.config.save_content_as_ignore_list()
            else:
                project.clean(quiet_on_cli=args.quiet)

    # Global errors catching. Core library is designed to throw the exception in cases when there is no sense to
    # proceed. Of course this also suppose to handle any unexpected behavior, too
    except Exception:
        stm32pio.core.logging.log_current_exception(
            logger,
            config=project.config if
            (project is not None and hasattr(project, 'config')) else None)
        return -1

    return 0
Beispiel #4
0
def main(sys_argv: List[str] = None, should_setup_logging: bool = True) -> int:
    """
    Entry point to the CLI edition of application. Since this is a highest-order wrapper, it can be used to
    programmatically the application (for testing, embedding, etc.). Example:

        ret_code = stm32pio.app.main(sys_argv=['new', '-d', '~/path/to/project', '-b', 'nucleo_f031k6', '--with-build'])

    :param sys_argv: list of CLI arguments
    :param should_setup_logging: if True, a reasonable default logging schema would be applied, otherwise it is on
    caller to resolve (or not) some logging configuration. The latter can be useful when an outer code makes sequential
    calls to this API so it is unwanted to append logging handlers every time (e.g. when unit-testing)
    :return: 0 on success, -1 otherwise
    """

    if sys_argv is None:
        sys_argv = sys.argv[1:]

    args = parse_args(sys_argv)

    if args is not None and args.command == 'gui':
        gui_args = [arg for arg in sys_argv if arg != 'gui']
        import stm32pio.gui.app as gui
        app = gui.create_app(sys_argv=gui_args)
        return app.exec_()
    elif args is not None and args.command is not None:
        logger = setup_logging(verbose=args.verbose,
                               dummy=not should_setup_logging)
    else:
        print("\nNo arguments were given, exiting...")
        return 0

    project = None

    # Wrap the main routine into try...except to gently handle possible error (API is designed to throw in certain
    # situations when it doesn't make much sense to continue with the met conditions)
    try:
        if args.command == 'init':
            project = stm32pio.core.project.Stm32pio(
                args.path,
                parameters={'project': {
                    'board': args.board
                }},
                save_on_destruction=True)
            if args.store_content:
                project.config.set_content_as_ignore_list()
            if project.config.get('project', 'board') == '':
                logger.warning(no_board_message)
            project.inspect_ioc_config()
            logger.info(init_message)
            if args.editor:
                project.start_editor(args.editor)

        elif args.command == 'generate':
            project = stm32pio.core.project.Stm32pio(args.path)
            if project.config.get('project', 'inspect_ioc',
                                  fallback='0').lower(
                                  ) in stm32pio.core.settings.yes_options:
                project.inspect_ioc_config()
            project.generate_code()
            if args.with_build:
                project.build()
            if args.editor:
                project.start_editor(args.editor)

        elif args.command == 'pio_init':
            project = stm32pio.core.project.Stm32pio(
                args.path,
                parameters={'project': {
                    'board': args.board
                }},
                save_on_destruction=True)
            if project.config.get('project', 'inspect_ioc',
                                  fallback='0').lower(
                                  ) in stm32pio.core.settings.yes_options:
                project.inspect_ioc_config()
            project.pio_init()

        elif args.command == 'patch':
            project = stm32pio.core.project.Stm32pio(args.path)
            if project.config.get('project', 'inspect_ioc',
                                  fallback='0').lower(
                                  ) in stm32pio.core.settings.yes_options:
                project.inspect_ioc_config()
            project.patch()

        elif args.command == 'new':
            project = stm32pio.core.project.Stm32pio(
                args.path,
                parameters={'project': {
                    'board': args.board
                }},
                save_on_destruction=True)
            if args.store_content:
                project.config.set_content_as_ignore_list()
            if project.config.get('project', 'board') == '':
                logger.info(init_message)
                raise Exception(no_board_message)
            if project.config.get('project', 'inspect_ioc',
                                  fallback='0').lower(
                                  ) in stm32pio.core.settings.yes_options:
                project.inspect_ioc_config()
            project.generate_code()
            project.pio_init()
            project.patch()
            if args.with_build:
                project.build()
            if args.editor:
                project.start_editor(args.editor)

        elif args.command == 'status':
            project = stm32pio.core.project.Stm32pio(args.path)
            print(project.state)

        elif args.command == 'validate':
            project = stm32pio.core.project.Stm32pio(args.path)
            print(project.validate_environment())

        elif args.command == 'clean':
            project = stm32pio.core.project.Stm32pio(args.path)
            if args.store_content:
                project.config.set_content_as_ignore_list()
                project.config.save()
            else:
                project.clean(quiet=args.quiet)

    except (Exception, ):
        stm32pio.core.log.log_current_exception(
            logger, config=project.config if project is not None else None)
        return -1

    return 0