Ejemplo n.º 1
0
def lock(connection,
         connection_lock,
         guard_time_seconds,
         printer,
         prompt,
         keep_going_flag=None,
         hw_reset=True):
    '''Lock the given connection'''
    timeout_seconds = guard_time_seconds
    success = False

    if connection:
        instance_text = u_utils.get_instance_text(get_instance(connection))
        if connection_lock:
            # Wait on the lock
            printer.string("{}instance {} waiting up to {} second(s)"   \
                           " to lock connection...".                    \
                           format(prompt, instance_text, guard_time_seconds))
            count = 0
            while not connection_lock.acquire(False) and                 \
                ((guard_time_seconds == 0) or (timeout_seconds > 0)) and \
                u_utils.keep_going(keep_going_flag, printer, prompt):
                sleep(1)
                timeout_seconds -= 1
                count += 1
                if count == 30:
                    printer.string("{}instance {} still waiting {} second(s)"     \
                                   " for a connection lock (locker is"            \
                                   " currently {}).".                             \
                                   format(prompt, instance_text, timeout_seconds,
                                          connection_lock))
                    count = 0
            if (guard_time_seconds == 0) or (timeout_seconds > 0):
                printer.string("{}instance {} has locked a connection ({}).". \
                               format(prompt, instance_text, connection_lock))
                if hw_reset:
                    kmtronic = get_kmtronic(connection)
                    usb_cutter_id_str = get_usb_cutter_id_str(connection)
                    if kmtronic:
                        printer.string("{}using KMTronic to reset {}...". \
                                       format(prompt, instance_text))
                        u_utils.kmtronic_reset(kmtronic["ip_address"],
                                               kmtronic["hex_bitmap"], printer,
                                               prompt)
                    if usb_cutter_id_str:
                        printer.string("{}using USB cutter to reset {}...". \
                                       format(prompt, instance_text))
                        u_utils.usb_cutter_reset([usb_cutter_id_str], printer,
                                                 prompt)
                success = True
        else:
            success = True
            printer.string("{}note: instance {} lock is empty.".           \
                           format(prompt, instance_text))

    return success
Ejemplo n.º 2
0
def watch_items(in_handle, connection_type, results, guard_time_seconds,
                inactivity_time_seconds, terminator, printer, reporter, prompt,
                keep_going_flag):
    '''Watch output'''
    return_value = -1
    start_time = time()
    last_activity_time = time()

    printer.string("{}watching output until run completes...".format(prompt))

    # Start a thread to read lines from in_handle
    # This is done in a separate thread as it can block or
    # hang; this way we get to detect that and time out.
    read_queue = queue.Queue()
    readline_thread = threading.Thread(target=readline_and_queue,
                                       args=(results, read_queue, in_handle,
                                             connection_type, terminator))
    readline_thread.start()

    try:
        while u_utils.keep_going(keep_going_flag, printer, prompt) and \
              not results["finished"] and                              \
              (not guard_time_seconds or                               \
               (time() - start_time < guard_time_seconds)) and         \
              (not inactivity_time_seconds or                          \
               (time() - last_activity_time < inactivity_time_seconds)):
            try:
                line = read_queue.get(timeout=0.5)
                last_activity_time = time()
                printer.string("{}{}".format(prompt, line), file_only=True)
                for entry in INTERESTING:
                    match = re.match(entry[0], line)
                    if match:
                        entry[1](match, results, printer, prompt, reporter)
            except queue.Empty:
                pass
            # Let others in
            sleep(0.01)
        # Set this to stop the read thread
        results["finished"] = True
        readline_thread.join()
        if guard_time_seconds and (time() - start_time >= guard_time_seconds):
            printer.string("{}guard timer ({} second(s))"        \
                           "  expired.".format(prompt, guard_time_seconds))
        elif inactivity_time_seconds and (time() - last_activity_time >=
                                          inactivity_time_seconds):
            printer.string("{}inactivity timer ({} second(s))"   \
                           " expired.".format(prompt, inactivity_time_seconds))
        else:
            return_value = results["items_failed"] + results["reboots"]
    except (serial.SerialException, EOFError) as ex:
        printer.string("{}{} while accessing port {}: {}.".format(
            prompt,
            type(ex).__name__, in_handle.name, str(ex)))

    return return_value
Ejemplo n.º 3
0
def run(instance,
        mcu,
        board,
        toolchain,
        connection,
        connection_lock,
        platform_lock,
        misc_locks,
        clean,
        defines,
        ubxlib_dir,
        working_dir,
        printer,
        reporter,
        test_report_handle,
        keep_going_flag=None,
        unity_dir=None):
    '''Build/run on Arduino'''
    return_value = -1
    monitor_dtr_rts_on = None
    installed = False
    sketch_paths = []
    build_paths = []
    return_values = []
    instance_text = u_utils.get_instance_text(instance)

    # None of the misc locks are required
    del misc_locks

    # Since we only currently support ESP-IDF we don't need
    # unity as ESP-IDF already has a copy built in
    del unity_dir

    prompt = PROMPT + instance_text + ": "

    toolchain = toolchain.lower()

    # Print out what we've been told to do and at the
    # same time check for the DTR/RTS off marker
    text = "running Arduino for " + mcu + " with SDK " + toolchain + \
           " on board with FQBN \"" + board + "\""
    if connection and connection["serial_port"]:
        text += ", serial port " + connection["serial_port"]
    if clean:
        text += ", clean build"
    if defines:
        text += ", with #define(s)"
        for idx, define in enumerate(defines):
            if define == MONITOR_DTR_RTS_OFF_MARKER:
                monitor_dtr_rts_on = False
            if idx == 0:
                text += " \"" + define + "\""
            else:
                text += ", \"" + define + "\""
    if ubxlib_dir:
        text += ", ubxlib directory \"" + ubxlib_dir + "\""
    if working_dir:
        text += ", working directory \"" + working_dir + "\""
    printer.string("{}{}.".format(prompt, text))

    reporter.event(u_report.EVENT_TYPE_BUILD, u_report.EVENT_START, "Arduino")
    printer.string("{}CD to {}...".format(prompt, working_dir))

    with u_utils.ChangeDir(working_dir):
        # Lock the Arduino platform while we install the tools
        with u_utils.Lock(platform_lock, PLATFORM_LOCK_GUARD_TIME_SECONDS,
                          "platform", printer, prompt,
                          keep_going_flag) as locked_platform:
            if locked_platform:
                installed = install(board, ARDUINO_BOARDS_URLS, printer,
                                    prompt, keep_going_flag)

        if installed:
            arduino_dir = os.path.join(ubxlib_dir, ARDUINO_SUB_DIR)
            library_path = os.path.join(working_dir, LIBRARIES_SUB_DIR)
            # Clear out any pre-built ubxlib library or rebuilds
            # won't pick up changes
            clear_prebuilt_library(os.path.join(library_path, LIBRARY_NAME),
                                   mcu, printer, prompt)
            # Create the ubxlib Arduino library
            if create_library(ubxlib_dir, arduino_dir, toolchain,
                              os.path.join(library_path, LIBRARY_NAME),
                              LIBRARY_NAME_LIB_POSTFIX, clean, printer, prompt,
                              keep_going_flag):
                # Create the ubxlib Arduino test library
                if create_library(ubxlib_dir, arduino_dir, toolchain,
                                  os.path.join(library_path, LIBRARY_NAME),
                                  LIBRARY_NAME_TEST_POSTFIX, clean, printer,
                                  prompt, keep_going_flag):
                    # We now build both libraries with the test sketch and we also
                    # build the examples with the just the ubxlib Arduino library.
                    # Make a list of the sketches to build
                    sketch_paths.append(
                        os.path.join(arduino_dir, TEST_SKETCH_SUB_PATH))
                    for root, _directories, files in os.walk(library_path):
                        for file in files:
                            if os.sep + "examples" + os.sep in root and file.endswith(
                                    ".ino"):
                                sketch_paths.append(os.path.join(root, file))
                    printer.string("{}{} thing(s) to build.".format(
                        prompt, len(sketch_paths)))
                    # Build the sketches: note that the first build of the ubxlib
                    # Arduino library to a .a file will be copied back into the library
                    # directory for use in the following builds
                    build_dir = os.path.join(working_dir, BUILD_SUBDIR)
                    for sketch_path in sketch_paths:
                        build_start_time = time()
                        build_path = build(build_dir, sketch_path,
                                           library_path, mcu, board, defines,
                                           clean, printer, prompt, reporter,
                                           keep_going_flag)
                        if not u_utils.keep_going(keep_going_flag, printer,
                                                  prompt) or not build_path:
                            break
                        build_paths.append(build_path)
                        reporter.event(u_report.EVENT_TYPE_BUILD,
                                       u_report.EVENT_PASSED,
                                       "build {} of {} took {:.0f} second(s)". \
                                       format(len(build_paths), len(sketch_paths),
                                              time() - build_start_time))
                    if len(build_paths) == len(sketch_paths):
                        # Download and run the builds
                        with u_connection.Lock(
                                connection, connection_lock,
                                CONNECTION_LOCK_GUARD_TIME_SECONDS, printer,
                                prompt, keep_going_flag) as locked:
                            if locked:
                                for build_path in build_paths:
                                    # I have seen download failures occur if two
                                    # are initiated at the same time so lock the
                                    # platform for this
                                    downloaded = False
                                    with u_utils.Lock(
                                            platform_lock,
                                            PLATFORM_LOCK_GUARD_TIME_SECONDS,
                                            "platform", printer, prompt,
                                            keep_going_flag
                                    ) as locked_platform:
                                        if locked_platform:
                                            # Have seen this fail, so give it a few goes
                                            reporter.event(
                                                u_report.EVENT_TYPE_DOWNLOAD,
                                                u_report.EVENT_START)
                                            retries = 0
                                            while u_utils.keep_going(keep_going_flag, printer,
                                                                     prompt) and               \
                                                  not downloaded and (retries < 3):
                                                downloaded = download(
                                                    build_path, board,
                                                    connection["serial_port"],
                                                    printer, prompt,
                                                    keep_going_flag)
                                                if not downloaded:
                                                    reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                                                   u_report.EVENT_WARNING,
                                                                   "unable to download, will" \
                                                                   " retry...")
                                                    retries += 1
                                                    sleep(5)
                                    if downloaded:
                                        reporter.event(
                                            u_report.EVENT_TYPE_DOWNLOAD,
                                            u_report.EVENT_COMPLETE)
                                        reporter.event(
                                            u_report.EVENT_TYPE_TEST,
                                            u_report.EVENT_START)
                                        # Open the COM port to get debug output
                                        serial_handle = u_utils.open_serial(
                                            connection["serial_port"],
                                            115200,
                                            printer,
                                            prompt,
                                            dtr_set_on=monitor_dtr_rts_on,
                                            rts_set_on=monitor_dtr_rts_on)
                                        if serial_handle is not None:
                                            # Monitor progress
                                            return_values.append(
                                                u_monitor.main(
                                                    serial_handle,
                                                    u_monitor.
                                                    CONNECTION_SERIAL,
                                                    RUN_GUARD_TIME_SECONDS,
                                                    RUN_INACTIVITY_TIME_SECONDS,
                                                    "\r",
                                                    instance,
                                                    printer,
                                                    reporter,
                                                    test_report_handle,
                                                    keep_going_flag=
                                                    keep_going_flag))
                                            # Delays and flushes here to make sure
                                            # that the serial port actually closes
                                            # since we might need to re-open it for
                                            # another download going around the loop
                                            serial_handle.cancel_read()
                                            sleep(1)
                                            serial_handle.reset_input_buffer()
                                            serial_handle.reset_output_buffer()
                                            sleep(1)
                                            serial_handle.close()
                                            reporter.event(
                                                u_report.
                                                EVENT_TYPE_INFRASTRUCTURE,
                                                u_report.EVENT_COMPLETE,
                                                "serial port closed")
                                            sleep(5)
                                        else:
                                            reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                                           u_report.EVENT_FAILED,
                                                           "unable to open serial port " +      \
                                                           connection["serial_port"])
                                        if return_values and return_values[
                                                -1] == 0:
                                            reporter.event(
                                                u_report.EVENT_TYPE_TEST,
                                                u_report.EVENT_COMPLETE)
                                        else:
                                            reporter.event(
                                                u_report.EVENT_TYPE_TEST,
                                                u_report.EVENT_FAILED)
                                    else:
                                        reporter.event(
                                            u_report.EVENT_TYPE_DOWNLOAD,
                                            u_report.EVENT_FAILED,
                                            "unable to download to the target")
                                if return_values:
                                    return_value = 0
                                    for item in return_values:
                                        # If a return value goes negative then
                                        # only count the negative values, i.e. the
                                        # number of infrastructure failures
                                        if (item < 0) and (return_value >= 0):
                                            return_value = item
                                        else:
                                            if (((item > 0) and (return_value >= 0)) or  \
                                                ((item < 0) and (return_value < 0))):
                                                return_value += item
                            else:
                                reporter.event(
                                    u_report.EVENT_TYPE_INFRASTRUCTURE,
                                    u_report.EVENT_FAILED,
                                    "unable to lock a connection")
                    else:
                        reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                       u_report.EVENT_FAILED, "failed a build")
                else:
                    reporter.event(
                        u_report.EVENT_TYPE_BUILD, u_report.EVENT_FAILED,
                        "unable to build library, check debug log for details")
            else:
                reporter.event(
                    u_report.EVENT_TYPE_INFRASTRUCTURE, u_report.EVENT_FAILED,
                    "unable to create library, check debug log for details")
        else:
            reporter.event(
                u_report.EVENT_TYPE_INFRASTRUCTURE, u_report.EVENT_FAILED,
                "unable to install tools, check debug log for details")

    return return_value
Ejemplo n.º 4
0
def install(esp_idf_url, esp_idf_dir, esp_idf_branch, system_lock,
            keep_going_flag, printer, prompt, reporter):
    '''Install the Espressif tools and ESP-IDF'''
    returned_env = {}
    count = 0

    # Acquire the install lock as this is a global operation
    if system_lock is None or u_utils.install_lock_acquire(
            system_lock, printer, prompt, keep_going_flag):
        # Fetch the repo
        if u_utils.keep_going(keep_going_flag, printer, prompt) and \
           u_utils.fetch_repo(esp_idf_url, esp_idf_dir,
                              esp_idf_branch, printer, prompt):

            # Set up the environment variable IDF_TOOLS_PATH
            my_env = os.environ
            my_env["IDF_TOOLS_PATH"] = IDF_TOOLS_PATH
            if u_utils.is_linux():
                install_cmd = ["./install.sh"]
                export_cmd = [".", "./export.sh"]
                bash_cmd = True
            else:
                install_cmd = ["install.bat"]
                export_cmd = ["export.bat"]
                bash_cmd = None

            printer.string("{}installing the Espressif tools to \"{}\" and"  \
                           " ESP-IDF to \"{}\".".                            \
                           format(prompt, IDF_TOOLS_PATH, esp_idf_dir))
            # Switch to where the stuff should have already
            # been fetched to
            with u_utils.ChangeDir(esp_idf_dir):
                if not u_utils.has_admin():
                    printer.string("{}NOTE: if {} fails (the return"   \
                                   " code may still be 0), then try re-running" \
                                   " as administrator.".format(prompt, " ".join(install_cmd)))
                # First call install.bat
                # set shell to True to keep Jenkins happy
                if u_utils.keep_going(keep_going_flag, printer, prompt) and \
                   u_utils.exe_run(install_cmd, INSTALL_GUARD_TIME_SECONDS,
                                   printer, prompt, shell_cmd=True,
                                   keep_going_flag=keep_going_flag):
                    # ...then export.bat to set up paths etc.
                    # which we return attached to returned_env.
                    # It is possible for the process of extracting
                    # the environment variables to fail due to machine
                    # loading (see comments against EXE_RUN_QUEUE_WAIT_SECONDS
                    # in exe_run) so give this up to three chances to succeed
                    while u_utils.keep_going(keep_going_flag, printer, prompt) and \
                          not returned_env and (count < 3):
                        # set shell to True to keep Jenkins happy
                        u_utils.exe_run(export_cmd,
                                        INSTALL_GUARD_TIME_SECONDS,
                                        printer,
                                        prompt,
                                        shell_cmd=True,
                                        returned_env=returned_env,
                                        bash_cmd=bash_cmd,
                                        keep_going_flag=keep_going_flag)
                        if not returned_env:
                            printer.string("{}warning: retrying {} to"     \
                                           " capture the environment variables...".
                                           format(prompt, " ".join(export_cmd)))
                        count += 1
                    if not returned_env:
                        reporter.event(
                            u_report.EVENT_TYPE_INFRASTRUCTURE,
                            u_report.EVENT_FAILED,
                            "{} failed".format(" ".join(export_cmd)))
                else:
                    reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                   u_report.EVENT_FAILED,
                                   "{} failed".format(" ".join(install_cmd)))
        else:
            reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                           u_report.EVENT_FAILED,
                           "unable to fetch " + esp_idf_url)
        if system_lock is not None:
            u_utils.install_lock_release(system_lock, printer, prompt)
    else:
        reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                       u_report.EVENT_FAILED, "could not acquire install lock")

    return returned_env
Ejemplo n.º 5
0
def run(instance,
        mcu,
        toolchain,
        connection,
        connection_lock,
        platform_lock,
        misc_locks,
        clean,
        defines,
        ubxlib_dir,
        working_dir,
        printer,
        reporter,
        test_report_handle,
        keep_going_flag=None):
    '''Build/run on ESP-IDF'''
    return_value = -1
    monitor_dtr_rts_on = None
    instance_text = u_utils.get_instance_text(instance)

    # No issues with running in parallel on ESP-IDF
    del platform_lock

    # Only one toolchain for ESP-IDF
    del toolchain

    prompt = PROMPT + instance_text + ": "

    # Print out what we've been told to do and at the
    # same time check for the DTR/RTS off marker
    text = "running ESP-IDF for " + mcu
    if connection and connection["serial_port"]:
        text += ", on serial port " + connection["serial_port"]
    if clean:
        text += ", clean build"
    if defines:
        text += ", with #define(s)"
        for idx, define in enumerate(defines):
            if define == MONITOR_DTR_RTS_OFF_MARKER:
                monitor_dtr_rts_on = False
            if idx == 0:
                text += " \"" + define + "\""
            else:
                text += ", \"" + define + "\""
    if ubxlib_dir:
        text += ", ubxlib directory \"" + ubxlib_dir + "\""
    if working_dir:
        text += ", working directory \"" + working_dir + "\""
    printer.string("{}{}.".format(prompt, text))

    reporter.event(u_report.EVENT_TYPE_BUILD, u_report.EVENT_START, "ESP-IDF")
    printer.string("{}CD to {}...".format(prompt, working_dir))
    with u_utils.ChangeDir(working_dir):
        # Fetch ESP-IDF into the right sub directory
        # and install the tools
        esp_idf_dir = ESP_IDF_ROOT + os.sep + ESP_IDF_LOCATION["subdir"]
        system_lock = None
        if u_utils.keep_going(keep_going_flag, printer, prompt) and \
           misc_locks and ("system_lock" in misc_locks):
            system_lock = misc_locks["system_lock"]
        returned_env = install(ESP_IDF_LOCATION["url"], esp_idf_dir,
                               ESP_IDF_LOCATION["branch"], system_lock,
                               keep_going_flag, printer, prompt, reporter)
        if u_utils.keep_going(keep_going_flag, printer, prompt) and \
           returned_env:
            # From here on the ESP-IDF tools need to set up
            # and use the set of environment variables
            # returned above.
            print_env(returned_env, printer, prompt)
            # Now do the build
            build_dir = working_dir + os.sep + BUILD_SUBDIR
            build_start_time = time()
            if u_utils.keep_going(keep_going_flag, printer, prompt) and \
               build(esp_idf_dir, ubxlib_dir, build_dir,
                     defines, returned_env, clean,
                     printer, prompt, reporter, keep_going_flag):
                reporter.event(u_report.EVENT_TYPE_BUILD,
                               u_report.EVENT_PASSED,
                               "build took {:.0f} second(s)". \
                               format(time() - build_start_time))
                with u_connection.Lock(connection, connection_lock,
                                       CONNECTION_LOCK_GUARD_TIME_SECONDS,
                                       printer, prompt,
                                       keep_going_flag) as locked:
                    if locked:
                        # Have seen this fail, only with Python 3 for
                        # some reason, so give it a few goes
                        reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                       u_report.EVENT_START)
                        retries = 0
                        downloaded = False
                        while u_utils.keep_going(keep_going_flag, printer, prompt) and \
                              not downloaded and (retries < 3):
                            downloaded = download(esp_idf_dir, ubxlib_dir,
                                                  build_dir,
                                                  connection["serial_port"],
                                                  returned_env, printer,
                                                  prompt)
                            if not downloaded:
                                reporter.event(
                                    u_report.EVENT_TYPE_DOWNLOAD,
                                    u_report.EVENT_WARNING,
                                    "unable to download, will retry...")
                                retries += 1
                                sleep(5)
                        if downloaded:
                            reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                           u_report.EVENT_COMPLETE)
                            reporter.event(u_report.EVENT_TYPE_TEST,
                                           u_report.EVENT_START)
                            # Open the COM port to get debug output
                            serial_handle = u_utils.open_serial(
                                connection["serial_port"],
                                115200,
                                printer,
                                prompt,
                                dtr_set_on=monitor_dtr_rts_on,
                                rts_set_on=monitor_dtr_rts_on)
                            if serial_handle is not None:
                                # Monitor progress
                                return_value = u_monitor.main(
                                    serial_handle,
                                    u_monitor.CONNECTION_SERIAL,
                                    RUN_GUARD_TIME_SECONDS,
                                    RUN_INACTIVITY_TIME_SECONDS,
                                    "\r",
                                    instance,
                                    printer,
                                    reporter,
                                    test_report_handle,
                                    keep_going_flag=keep_going_flag)
                                serial_handle.close()
                            else:
                                reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                               u_report.EVENT_FAILED,
                                               "unable to open serial port " +      \
                                               connection["serial_port"])
                            if return_value == 0:
                                reporter.event(u_report.EVENT_TYPE_TEST,
                                               u_report.EVENT_COMPLETE)
                            else:
                                reporter.event(u_report.EVENT_TYPE_TEST,
                                               u_report.EVENT_FAILED)
                        else:
                            reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                           u_report.EVENT_FAILED,
                                           "unable to download to the target")
                    else:
                        reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                       u_report.EVENT_FAILED,
                                       "unable to lock a connection")
            else:
                reporter.event(u_report.EVENT_TYPE_BUILD,
                               u_report.EVENT_FAILED,
                               "unable to build, check debug log for details")
        else:
            reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                           u_report.EVENT_FAILED, "tools installation failed")

    return return_value
Ejemplo n.º 6
0
def run(instance,
        mcu,
        board,
        toolchain,
        connection,
        connection_lock,
        platform_lock,
        misc_locks,
        clean,
        defines,
        ubxlib_dir,
        working_dir,
        printer,
        reporter,
        test_report_handle,
        keep_going_flag=None):
    '''Build/run on Zephyr'''
    return_value = -1
    build_dir = None
    instance_text = u_utils.get_instance_text(instance)

    # Don't need the platform or misc locks
    del platform_lock
    del misc_locks

    # Only one toolchain for Zephyr
    del toolchain

    prompt = PROMPT + instance_text + ": "

    # Print out what we've been told to do
    text = "running Zephyr for " + mcu + " (on a \"" + board + "\" board)"
    if connection and "debugger" in connection and connection["debugger"]:
        text += ", on JLink debugger serial number " + connection["debugger"]
    if clean:
        text += ", clean build"
    if defines:
        text += ", with #define(s)"
        for idx, define in enumerate(defines):
            if idx == 0:
                text += " \"" + define + "\""
            else:
                text += ", \"" + define + "\""
    if ubxlib_dir:
        text += ", ubxlib directory \"" + ubxlib_dir + "\""
    if working_dir:
        text += ", working directory \"" + working_dir + "\""
    printer.string("{}{}.".format(prompt, text))

    reporter.event(u_report.EVENT_TYPE_BUILD, u_report.EVENT_START, "Zephyr")
    # Switch to the working directory
    with u_utils.ChangeDir(working_dir):
        # Check that everything we need is installed
        # and configured
        if u_utils.keep_going(keep_going_flag, printer, prompt) and \
           check_installation(TOOLS_LIST, printer, prompt):
            # Set up the environment variables for Zephyr
            returned_env = set_env(printer, prompt)
            if u_utils.keep_going(keep_going_flag, printer, prompt) and \
               returned_env:
                # The west tools need to use the environment
                # configured above.
                print_env(returned_env, printer, prompt)
                # Note that Zephyr brings in its own
                # copy of Unity so there is no need to
                # fetch it here.
                if board:
                    # Do the build
                    build_start_time = time()
                    build_dir = build(board, clean, ubxlib_dir, defines,
                                      returned_env, printer, prompt, reporter,
                                      keep_going_flag)
                    if u_utils.keep_going(keep_going_flag, printer, prompt) and \
                       build_dir:
                        # Build succeeded, need to lock some things to do the download
                        reporter.event(
                            u_report.EVENT_TYPE_BUILD, u_report.EVENT_PASSED,
                            "build took {:.0f} second(s)".format(
                                time() - build_start_time))
                        # Do the download
                        with u_connection.Lock(
                                connection, connection_lock,
                                CONNECTION_LOCK_GUARD_TIME_SECONDS, printer,
                                prompt, keep_going_flag) as locked_connection:
                            if locked_connection:
                                # Get the device name for JLink
                                jlink_device_name = jlink_device(mcu)
                                if not jlink_device_name:
                                    reporter.event(
                                        u_report.EVENT_TYPE_INFRASTRUCTURE,
                                        u_report.EVENT_WARNING,
                                        "MCU not found in JLink devices")
                                # Do the download
                                reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                               u_report.EVENT_START)
                                retries = 0
                                downloaded = False
                                while u_utils.keep_going(keep_going_flag, printer, prompt) and \
                                      not downloaded and (retries < 3):
                                    downloaded = download(
                                        connection, jlink_device_name,
                                        DOWNLOAD_GUARD_TIME_SECONDS, build_dir,
                                        returned_env, printer, prompt)
                                    if not downloaded:
                                        reporter.event(
                                            u_report.EVENT_TYPE_DOWNLOAD,
                                            u_report.EVENT_WARNING,
                                            "unable to download, will retry..."
                                        )
                                        retries += 1
                                        sleep(5)
                                if downloaded:
                                    reporter.event(
                                        u_report.EVENT_TYPE_DOWNLOAD,
                                        u_report.EVENT_COMPLETE)
                                    # Now the target can be reset
                                    u_utils.reset_nrf_target(
                                        connection, printer, prompt)
                                    reporter.event(u_report.EVENT_TYPE_TEST,
                                                   u_report.EVENT_START)

                                    with URttReader(
                                            jlink_device(mcu),
                                            jlink_serial=connection[
                                                "debugger"],
                                            printer=printer,
                                            prompt=prompt) as rtt_reader:
                                        return_value = u_monitor.main(
                                            rtt_reader,
                                            u_monitor.CONNECTION_RTT,
                                            RUN_GUARD_TIME_SECONDS,
                                            RUN_INACTIVITY_TIME_SECONDS,
                                            "\n",
                                            instance,
                                            printer,
                                            reporter,
                                            test_report_handle,
                                            keep_going_flag=keep_going_flag)
                                    if return_value == 0:
                                        reporter.event(
                                            u_report.EVENT_TYPE_TEST,
                                            u_report.EVENT_COMPLETE)
                                    else:
                                        reporter.event(
                                            u_report.EVENT_TYPE_TEST,
                                            u_report.EVENT_FAILED)
                                else:
                                    reporter.event(
                                        u_report.EVENT_TYPE_DOWNLOAD,
                                        u_report.EVENT_FAILED,
                                        "check debug log for details")
                            else:
                                reporter.event(
                                    u_report.EVENT_TYPE_INFRASTRUCTURE,
                                    u_report.EVENT_FAILED,
                                    "unable to lock a connection")
                    else:
                        return_value = 1
                        reporter.event(u_report.EVENT_TYPE_BUILD,
                                       u_report.EVENT_FAILED,
                                       "check debug log for details")
                else:
                    return_value = 1
                    reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                   u_report.EVENT_FAILED,
                                   "unable to find overlay file")
            else:
                reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                               u_report.EVENT_FAILED,
                               "environment setup failed")
        else:
            reporter.event(
                u_report.EVENT_TYPE_INFRASTRUCTURE, u_report.EVENT_FAILED,
                "there is a problem with the tools installation for Zephyr")

    return return_value
Ejemplo n.º 7
0
def run(instance,
        mcu,
        toolchain,
        connection,
        connection_lock,
        platform_lock,
        misc_locks,
        clean,
        defines,
        ubxlib_dir,
        working_dir,
        printer,
        reporter,
        test_report_handle,
        keep_going_flag=None,
        unity_dir=None):
    '''Build/run on STM32Cube'''
    return_value = -1
    mcu_dir = ubxlib_dir + os.sep + SDK_DIR + os.sep + "mcu" + os.sep + mcu.lower(
    )
    instance_text = u_utils.get_instance_text(instance)
    workspace_dir = working_dir + os.sep + STM32CUBE_IDE_WORKSPACE_SUBDIR
    output_project_dir = working_dir + os.sep + "project"
    elf_path = None
    downloaded = False
    download_list = None

    # Only one toolchain for STM32Cube
    del toolchain

    prompt = PROMPT + instance_text + ": "

    # Print out what we've been told to do
    text = "running STM32Cube for " + mcu
    if connection and "debugger" in connection and connection["debugger"]:
        text += ", on STLink debugger serial number " + connection["debugger"]
    if clean:
        text += ", clean build"
    if defines:
        text += ", with #define(s)"
        for idx, define in enumerate(defines):
            if idx == 0:
                text += " \"" + define + "\""
            else:
                text += ", \"" + define + "\""
    if ubxlib_dir:
        text += ", ubxlib directory \"" + ubxlib_dir + "\""
    if working_dir:
        text += ", working directory \"" + working_dir + "\""
    if unity_dir:
        text += ", using Unity from \"" + unity_dir + "\""
    printer.string("{}{}.".format(prompt, text))

    # On STM32F4 we can get USB errors if we try to do a download
    # on one platform while another is performing SWO logging.
    # Since each board only runs a single instance of stuff we
    # can work around this be ensuring that all downloads are
    # completed before SWO logging begins.
    # Add us to the list of pending downloads
    if misc_locks and ("stm32f4_downloads_list" in misc_locks):
        download_list = misc_locks["stm32f4_downloads_list"]
        download_list.append(instance_text)

    reporter.event(u_report.EVENT_TYPE_BUILD, u_report.EVENT_START,
                   "STM32Cube")
    # Switch to the working directory
    with u_utils.ChangeDir(working_dir):
        # Check that everything we need is installed
        if u_utils.keep_going(keep_going_flag, printer, prompt) and \
           check_installation(PATHS_LIST, printer, prompt):
            # Fetch Unity, if necessary
            if u_utils.keep_going(keep_going_flag, printer, prompt) and \
                not unity_dir:
                if u_utils.fetch_repo(u_utils.UNITY_URL,
                                      u_utils.UNITY_SUBDIR,
                                      None,
                                      printer,
                                      prompt,
                                      submodule_init=False):
                    unity_dir = os.getcwd() + os.sep + u_utils.UNITY_SUBDIR
            if unity_dir:
                # I've no idea why but on every other
                # build STM32Cube loses track of where
                # most of the files are: you'll see it
                # say that it can't find u_cfg_sw.h and
                # fail.  Until we find out why just
                # give it two goes, deleting the project
                # we created before trying again.
                retries = 2
                while u_utils.keep_going(keep_going_flag, printer, prompt) and \
                      (elf_path is None) and (retries > 0):
                    # The STM32Cube IDE, based on Eclipse
                    # has no mechanism for overriding the locations
                    # of things so here we read the .project
                    # file and replace the locations of the
                    # STM32Cube SDK and Unity files as
                    # appropriate
                    if u_utils.keep_going(keep_going_flag, printer, prompt) and \
                       create_project(PROJECT_NAME,
                                      mcu_dir,
                                      output_project_dir,
                                      STM32CUBE_FW_PATH, unity_dir,
                                      printer, prompt):
                        # Do the build
                        build_start_time = time()
                        elf_path = build_binary(output_project_dir,
                                                workspace_dir, PROJECT_NAME,
                                                clean, defines, printer,
                                                prompt, keep_going_flag)
                        if elf_path is None:
                            reporter.event(u_report.EVENT_TYPE_BUILD,
                                           u_report.EVENT_INFORMATION,
                                           "unable to build, will retry")
                            printer.string("{}if the compilation."       \
                                           " failure was because"        \
                                           " the build couldn't"         \
                                           " even find u_cfg_sw.h"       \
                                           " then ignore it, Eclipse"    \
                                           " lost its head, happens"     \
                                           " a lot, we will try again.". \
                                           format(prompt))
                    else:
                        reporter.event(
                            u_report.EVENT_TYPE_BUILD, u_report.EVENT_WARNING,
                            "unable to create STM32Cube project, will retry")
                    retries -= 1
                if u_utils.keep_going(keep_going_flag, printer, prompt) and \
                   elf_path:
                    reporter.event(
                        u_report.EVENT_TYPE_BUILD, u_report.EVENT_PASSED,
                        "build took {:.0f} second(s)".format(time() -
                                                             build_start_time))
                    # Lock the connection.
                    with u_connection.Lock(
                            connection, connection_lock,
                            CONNECTION_LOCK_GUARD_TIME_SECONDS, printer,
                            prompt, keep_going_flag) as locked_connection:
                        if locked_connection:
                            # I have seen download failures occur if two
                            # ST-Link connections are initiated at the same time.
                            with u_utils.Lock(
                                    platform_lock,
                                    PLATFORM_LOCK_GUARD_TIME_SECONDS,
                                    "platform", printer, prompt,
                                    keep_going_flag) as locked_platform:
                                if locked_platform:
                                    reporter.event(
                                        u_report.EVENT_TYPE_DOWNLOAD,
                                        u_report.EVENT_START)
                                    # Do the download.  I have seen the STM32F4 debugger
                                    # barf on occasions so give this two bites of
                                    # the cherry
                                    retries = 2
                                    while u_utils.keep_going(keep_going_flag,
                                                             printer, prompt) and \
                                          not downloaded and (retries > 0):
                                        downloaded = download(
                                            connection,
                                            DOWNLOAD_GUARD_TIME_SECONDS,
                                            elf_path, printer, prompt)
                                        retries -= 1
                                        if not downloaded:
                                            if connection and "serial_port" in connection \
                                               and connection["serial_port"]:
                                                # Before retrying, reset the USB port
                                                u_utils.usb_reset("STMicroelectronics STLink" \
                                                                  "Virtual COM Port (" +
                                                                  connection["serial_port"] +
                                                                  ")", printer, prompt)
                                            sleep(5)
                                    if platform_lock:
                                        # Once the download has been done (or not) the platform lock
                                        # can be released, after a little safety sleep
                                        sleep(1)
                                        platform_lock.release()
                                    if downloaded:
                                        reporter.event(
                                            u_report.EVENT_TYPE_DOWNLOAD,
                                            u_report.EVENT_COMPLETE)
                                        # Remove us from the list of pending downloads
                                        if download_list:
                                            download_list.remove(instance_text)
                                            # Wait for all the other downloads to complete before
                                            # starting SWO logging
                                            u_utils.wait_for_completion(
                                                download_list,
                                                "STM32F4 downloads",
                                                DOWNLOADS_COMPLETE_GUARD_TIME_SECONDS,
                                                printer, prompt,
                                                keep_going_flag)
                                        # So that all STM32Cube instances don't start up at
                                        # once, which can also cause problems, wait the
                                        # instance-number number of seconds.
                                        hold_off = instance[0]
                                        if hold_off > 30:
                                            hold_off = 30
                                        sleep(hold_off)
                                        # Create and empty the SWO data file and decoded text file
                                        file_handle = open(SWO_DATA_FILE,
                                                           "w").close()
                                        file_handle = open(
                                            SWO_DECODED_TEXT_FILE,
                                            "w").close()
                                        reporter.event(
                                            u_report.EVENT_TYPE_TEST,
                                            u_report.EVENT_START)
                                        try:
                                            # Start a process which reads the
                                            # SWO output from a file, decodes it and
                                            # writes it back to a file
                                            process = Process(
                                                target=swo_decode_process,
                                                args=(SWO_DATA_FILE,
                                                      SWO_DECODED_TEXT_FILE))
                                            process.start()
                                            # Now start Open OCD to reset the target
                                            # and capture SWO output
                                            sleep(1)
                                            with u_utils.ExeRun(
                                                    open_ocd(
                                                        OPENOCD_COMMANDS,
                                                        connection), printer,
                                                    prompt):
                                                # Open the SWO decoded text file for
                                                # reading, binary to prevent the line
                                                # endings being munged.
                                                file_handle = open(
                                                    SWO_DECODED_TEXT_FILE,
                                                    "rb")
                                                # Monitor progress based on the decoded
                                                # SWO text
                                                return_value = u_monitor.          \
                                                               main(file_handle,
                                                                    u_monitor.CONNECTION_PIPE,
                                                                    RUN_GUARD_TIME_SECONDS,
                                                                    RUN_INACTIVITY_TIME_SECONDS,
                                                                    "\r", instance, printer,
                                                                    reporter,
                                                                    test_report_handle,
                                                                    keep_going_flag=keep_going_flag)
                                                file_handle.close()
                                            process.terminate()
                                        except KeyboardInterrupt:
                                            # Tidy up process on SIGINT
                                            printer.string(
                                                "{}caught CTRL-C, terminating..."
                                                .format(prompt))
                                            process.terminate()
                                            return_value = -1
                                        if return_value == 0:
                                            reporter.event(
                                                u_report.EVENT_TYPE_TEST,
                                                u_report.EVENT_COMPLETE)
                                        else:
                                            reporter.event(
                                                u_report.EVENT_TYPE_TEST,
                                                u_report.EVENT_FAILED)
                                    else:
                                        reporter.event(
                                            u_report.EVENT_TYPE_DOWNLOAD,
                                            u_report.EVENT_FAILED)
                        else:
                            reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                           u_report.EVENT_FAILED,
                                           "unable to lock a connection")
                else:
                    reporter.event(u_report.EVENT_TYPE_BUILD,
                                   u_report.EVENT_FAILED,
                                   "check debug log for details")

                # To avoid a build up of stuff, delete the temporary build and
                # workspace on exit
                if os.path.exists(output_project_dir):
                    printer.string("{}deleting temporary build directory {}...".   \
                                   format(prompt, output_project_dir))
                    u_utils.deltree(output_project_dir, printer, prompt)
                if os.path.exists(workspace_dir):
                    printer.string("{}deleting temporary workspace directory {}...". \
                                   format(prompt, workspace_dir))
                    u_utils.deltree(workspace_dir, printer, prompt)

            else:
                reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                               u_report.EVENT_FAILED, "unable to fetch Unity")
        else:
            reporter.event(
                u_report.EVENT_TYPE_INFRASTRUCTURE, u_report.EVENT_FAILED,
                "there is a problem with the tools installation for STM32F4")

    # Remove us from the list of pending downloads for safety
    try:
        misc_locks["stm32f4_downloads_list"].remove(instance_text)
    except (AttributeError, ValueError, TypeError):
        pass

    return return_value
Ejemplo n.º 8
0
def run(instance,
        mcu,
        toolchain,
        connection,
        connection_lock,
        platform_lock,
        misc_locks,
        clean,
        defines,
        ubxlib_dir,
        working_dir,
        printer,
        reporter,
        test_report_handle,
        keep_going_flag=None,
        unity_dir=None):
    '''Build/run on nRF5'''
    return_value = -1
    hex_file_path = None
    instance_text = u_utils.get_instance_text(instance)
    downloaded = False
    _ = (misc_locks)  # Suppress unused variable

    # Don't need the platform lock
    del platform_lock

    prompt = PROMPT + instance_text + ": "

    # Print out what we've been told to do
    text = "running nRF5 for " + mcu + " under " + toolchain
    if connection and "debugger" in connection and connection["debugger"]:
        text += ", on JLink debugger serial number " + connection["debugger"]
    if clean:
        text += ", clean build"
    if defines:
        text += ", with #define(s)"
        for idx, define in enumerate(defines):
            if idx == 0:
                text += " \"" + define + "\""
            else:
                text += ", \"" + define + "\""
    if ubxlib_dir:
        text += ", ubxlib directory \"" + ubxlib_dir + "\""
    if working_dir:
        text += ", working directory \"" + working_dir + "\""
    if unity_dir:
        text += ", using Unity from \"" + unity_dir + "\""
    printer.string("{}{}.".format(prompt, text))

    reporter.event(u_report.EVENT_TYPE_BUILD, u_report.EVENT_START,
                   "nRF5SDK/" + toolchain)
    # Switch to the working directory
    with u_utils.ChangeDir(working_dir):
        # Check that everything we need is installed
        if u_utils.keep_going(keep_going_flag, printer, prompt) and \
           check_installation(toolchain, TOOLS_LIST, printer, prompt):
            # Fetch Unity, if necessary
            if u_utils.keep_going(keep_going_flag, printer, prompt) and \
                not unity_dir:
                if u_utils.fetch_repo(u_utils.UNITY_URL,
                                      u_utils.UNITY_SUBDIR,
                                      None,
                                      printer,
                                      prompt,
                                      submodule_init=False):
                    unity_dir = os.getcwd() + os.sep + u_utils.UNITY_SUBDIR
            if unity_dir:
                # Do the build
                build_start_time = time()
                if u_utils.keep_going(keep_going_flag, printer, prompt):
                    if toolchain.lower() == "gcc":
                        build_subdir_gcc = BUILD_SUBDIR_PREFIX_GCC + instance_text.replace(
                            ".", "_")
                        hex_file_path = build_gcc(clean, build_subdir_gcc,
                                                  ubxlib_dir, unity_dir,
                                                  defines, printer, prompt,
                                                  reporter, keep_going_flag)
                    elif toolchain.lower() == "ses":
                        hex_file_path = build_ses(clean, ubxlib_dir, unity_dir,
                                                  defines, printer, prompt,
                                                  reporter, keep_going_flag)
                if hex_file_path:
                    # Build succeeded, need to lock a connection to do the download
                    reporter.event(
                        u_report.EVENT_TYPE_BUILD, u_report.EVENT_PASSED,
                        "build took {:.0f} second(s)".format(time() -
                                                             build_start_time))
                    # Do the download
                    with u_connection.Lock(
                            connection, connection_lock,
                            CONNECTION_LOCK_GUARD_TIME_SECONDS, printer,
                            prompt, keep_going_flag) as locked_connection:
                        if locked_connection:
                            reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                           u_report.EVENT_START)
                            # I have seen the download fail on occasion
                            # so give this two bites of the cherry
                            retries = 2
                            while not downloaded and (retries > 0):
                                downloaded = download(
                                    connection, DOWNLOAD_GUARD_TIME_SECONDS,
                                    hex_file_path, printer, prompt)
                                retries -= 1
                                if not downloaded and (retries > 0):
                                    reporter.event(
                                        u_report.EVENT_TYPE_DOWNLOAD,
                                        u_report.EVENT_WARNING,
                                        "unable to download, will retry...")
                                    sleep(5)
                            if downloaded:
                                reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                               u_report.EVENT_COMPLETE)

                                # Now the target can be reset
                                u_utils.reset_nrf_target(
                                    connection, printer, prompt)
                                reporter.event(u_report.EVENT_TYPE_TEST,
                                               u_report.EVENT_START)

                                with URttReader(
                                        "NRF52840_XXAA",
                                        jlink_serial=connection["debugger"],
                                        printer=printer,
                                        prompt=prompt) as rtt_reader:
                                    return_value = u_monitor.main(
                                        rtt_reader, u_monitor.CONNECTION_RTT,
                                        RUN_GUARD_TIME_SECONDS,
                                        RUN_INACTIVITY_TIME_SECONDS, "\n",
                                        instance, printer, reporter,
                                        test_report_handle)

                                if return_value == 0:
                                    reporter.event(u_report.EVENT_TYPE_TEST,
                                                   u_report.EVENT_COMPLETE)
                                else:
                                    reporter.event(u_report.EVENT_TYPE_TEST,
                                                   u_report.EVENT_FAILED)
                            else:
                                reporter.event(u_report.EVENT_TYPE_DOWNLOAD,
                                               u_report.EVENT_FAILED,
                                               "check debug log for details")
                            # Wait for a short while before giving
                            # the connection lock away to make sure
                            # that everything really has shut down
                            # in the debugger
                            sleep(5)
                        else:
                            reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                           u_report.EVENT_FAILED,
                                           "unable to lock a connection")
                else:
                    return_value = 1
                    reporter.event(u_report.EVENT_TYPE_BUILD,
                                   u_report.EVENT_FAILED,
                                   "check debug log for details")
            else:
                reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                               u_report.EVENT_FAILED, "unable to fetch Unity")
        else:
            reporter.event(
                u_report.EVENT_TYPE_INFRASTRUCTURE, u_report.EVENT_FAILED,
                "there is a problem with the tools installation for nRF5 SDK")

    return return_value
Ejemplo n.º 9
0
def run(instance,
        ubxlib_dir,
        working_dir,
        printer,
        reporter,
        keep_going_flag=None):
    '''Run Pylint'''
    return_value = 1
    got_pylint = False
    min_rating = 10
    instance_text = u_utils.get_instance_text(instance)

    prompt = PROMPT + instance_text + ": "

    # Print out what we've been told to do
    text = "running Pylint from ubxlib directory \"" + ubxlib_dir + "\""
    if working_dir:
        text += ", working directory \"" + working_dir + "\""
    text += ", checking for minimum rating " + str(MIN_RATING)
    printer.string("{}{}.".format(prompt, text))

    reporter.event(u_report.EVENT_TYPE_CHECK, u_report.EVENT_START, "Pylint")
    got_pylint = u_utils.exe_where("pylint", \
                        "ERROR: can't find pylint, please make"     \
                        " sure that it is installed and on the path.", \
                        printer, prompt)

    if got_pylint:
        # Run Pylint on all the .py files in PYTHON_PATHS
        return_value = 0
        for py_path in PYTHON_PATHS:
            abs_py_path = ubxlib_dir + os.sep + py_path
            if os.path.exists(abs_py_path):
                printer.string("{}CD to {}...".format(prompt, abs_py_path))
                with u_utils.ChangeDir(abs_py_path):
                    popen_keywords = {
                        'stderr': subprocess.STDOUT,
                        'shell': True  # Stop Jenkins hanging
                    }
                    for py_file in os.listdir(abs_py_path):
                        if py_file.endswith(".py"):
                            if not u_utils.keep_going(keep_going_flag, printer,
                                                      prompt):
                                return_value = -1
                                break
                            printer.string("{}running Pylint on {}...".format(
                                prompt, py_file))
                            got_rating = False
                            try:
                                # ignore u_settings module as it sets members programatically and
                                # will thus generate a bunch of lint warnings
                                text = subprocess.check_output(
                                    u_utils.subprocess_osify([
                                        "pylint", "--exit-zero",
                                        "--ignored-modules=u_settings", py_file
                                    ]), **popen_keywords)

                                rating = 0
                                for line in text.splitlines():
                                    line = line.decode()
                                    printer.string("{}{}".format(prompt, line))
                                    # See if there is a rating in this line
                                    outcome = line.rpartition(
                                        "Your code has been rated at ")
                                    if len(outcome) == 3:
                                        outcome = outcome[2].split("/")
                                        # Get the bit before the "/" in the "x/y" rating
                                        try:
                                            rating = float(outcome[0])
                                            got_rating = True
                                            if rating < min_rating:
                                                min_rating = rating
                                            if rating < MIN_RATING:
                                                return_value += 1
                                        except ValueError:
                                            # Can't have been a rating line
                                            pass
                                # Let other things in
                                sleep(0.01)
                                if got_rating:
                                    if rating < MIN_RATING:
                                        reporter.event(u_report.EVENT_TYPE_CHECK,
                                                       u_report.EVENT_ERROR,
                                                       "rating {} < minimum ({})".  \
                                                       format(rating, MIN_RATING))
                                        for line in text.splitlines():
                                            line = line.strip().decode()
                                            if line:
                                                reporter.event_extra_information(
                                                    line)
                                else:
                                    reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                                                   u_report.EVENT_FAILED,
                                                   "Pylint returned no rating for file \"{}\"". \
                                                   format(py_file))
                                    printer.string("{}Pylint returned no rating.". \
                                                   format(prompt))
                                    # No rating returned, flag an error
                                    return_value += 1
                            except subprocess.CalledProcessError as error:
                                reporter.event(u_report.EVENT_TYPE_CHECK,
                                               u_report.EVENT_FAILED)
                                printer.string(
                                    "{}Pylint returned error {}:".format(
                                        prompt, error.returncode))
                                for line in error.output.splitlines():
                                    line = line.strip().decode()
                                    if line:
                                        reporter.event_extra_information(line)
                                        printer.string("{}{}".format(
                                            prompt, line))
            else:
                # Flag an error if a path doesn't exist
                reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                               u_report.EVENT_FAILED,
                               "path {} does not exit".format(abs_py_path))
                printer.string("{}path \"{}\" does not exist.".   \
                               format(prompt, abs_py_path))
                return_value += 1

        printer.string("{}Pylint check complete, minimum rating {}.".format(
            prompt, min_rating))
        if min_rating < MIN_RATING:
            reporter.event(u_report.EVENT_TYPE_CHECK, u_report.EVENT_FAILED)
        else:
            reporter.event(u_report.EVENT_TYPE_CHECK, u_report.EVENT_PASSED)

    else:
        reporter.event(u_report.EVENT_TYPE_INFRASTRUCTURE,
                       u_report.EVENT_FAILED,
                       "there is a problem with the Pylint installation")

    return return_value