<commit_before># Copyright (c) 2016, Nordic Semiconductor
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of Nordic Semiconductor ASA nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import argparse
import sys

from device import nrf5x

class Nrfjprog():
    """
    Initializes and runs our command-line application.

    """
    NRFJPROG_DESCRIPTION = "nrfjprog is a command line tool used for programming nRF5x devices. It is implemented in Python and utilizes pynrfjprog, a Python wrapper for the nrfjprog DLL. Both nrfjprog and pynrfjprog are open source and can be found on Nordic's GitHub. To report an issue, request a feature, or contribute please see: https://github.com/mjdietzx/nrfjprog."
    NRFJPROG_EPILOG = "Just like any standard command line tool, one positional command can be specified, followed by it's specific arguments. To see arguments for a specific command type: python nrfjprog COMMAND -h (i.e. python nrfjprog erase -h)."

    def __init__(self):
        """
        Initialize our command-line interface.

        """
        self.parser = argparse.ArgumentParser(description = self.NRFJPROG_DESCRIPTION, epilog = self.NRFJPROG_EPILOG)
        self.subparsers = self.parser.add_subparsers()
        self._add_commands(self.subparsers)

    def _add_commands(self, subparsers):
        """
        Split up the functionality of nrfjprog into multiple sub-commands because nrfjprog performs several different functions which require different command-line arguments.
        
        :param Special Action Object subparsers: https://docs.python.org/3/library/argparse.html#sub-commands
        """
        _add_erase_command(subparsers)
        _add_halt_command(subparsers)
        _add_ids_command(subparsers)
        _add_memrd_command(subparsers)
        _add_memwr_command(subparsers)
        _add_pinresetenable_command(subparsers)
        _add_program_command(subparsers)
        _add_readback_command(subparsers)
        _add_readregs_command(subparsers)
        _add_readtofile_command(subparsers)
        _add_recover_command(subparsers)
        _add_reset_command(subparsers)
        _add_run_command(subparsers)
        _add_verify_command(subparsers)
        _add_version_command(subparsers)

    def start(self):
        """
        Parse user input and execute the requested functionality.

        """
        self.args = self.parser.parse_args()
        self.args.func(self.args)  # Call the default function. (i.e. nRF5x.erase() in the erase command).

"""
The top-level positional commands of our command-line interface. These contain their own unique and shared arguments.

"""

def _add_erase_command(subparsers):
    erase_parser = subparsers.add_parser('erase', help = "Erases the device's FLASH.")
    _add_clockspeed_argument(erase_parser)
    _add_erase_group(erase_parser)
    _add_quiet_argument(erase_parser)
    _add_snr_argument(erase_parser)
    erase_parser.set_defaults(func = nrf5x.erase)

def _add_halt_command(subparsers):
    halt_parser = subparsers.add_parser('halt', help = "Halts the device's CPU.")
    _add_quiet_argument(halt_parser)
    _add_snr_argument(halt_parser)
    halt_parser.set_defaults(func = nrf5x.halt)

def _add_ids_command(subparsers): # This is the only command that doesn't have the snr and quiet option.
    ids_parser = subparsers.add_parser('ids', help = 'Displays the serial numbers of all debuggers connected to the PC.')
    ids_parser.set_defaults(func = nrf5x.ids)

def _add_memrd_command(subparsers):
    memrd_parser = subparsers.add_parser('memrd', help = "Reads the device's memory.")
    _add_addr_argument(memrd_parser)
    _add_length_argument(memrd_parser)
    _add_quiet_argument(memrd_parser)
    _add_snr_argument(memrd_parser)
    memrd_parser.set_defaults(func = nrf5x.memrd)

def _add_memwr_command(subparsers):
    memwr_parser = subparsers.add_parser('memwr', help = "Writes one word in the device's memory.")
    _add_addr_argument(memwr_parser)
    _add_flash_argument(memwr_parser)
    _add_quiet_argument(memwr_parser)
    _add_snr_argument(memwr_parser)
    _add_val_argument(memwr_parser)
    memwr_parser.set_defaults(func = nrf5x.memwr)

def _add_pinresetenable_command(subparsers):
    pinresetenable_parser = subparsers.add_parser('pinresetenable', help = "Enable the pin reset on nRF52 devices. Invalid command on nRF51 devices.")
    _add_quiet_argument(pinresetenable_parser)
    _add_snr_argument(pinresetenable_parser)
    pinresetenable_parser.set_defaults(func = nrf5x.pinresetenable)

def _add_program_command(subparsers):
    program_parser = subparsers.add_parser('program', help = 'Programs the device.')
    _add_clockspeed_argument(program_parser)
    _add_file_argument(program_parser)
    _add_erase_before_flash_group(program_parser)
    _add_quiet_argument(program_parser)
    _add_verify_argument(program_parser)
    _add_reset_group(program_parser)
    _add_snr_argument(program_parser)
    program_parser.set_defaults(func = nrf5x.program)

def _add_readback_command(subparsers):
    readback_parser = subparsers.add_parser('rbp', help = 'Enables the readback protection mechanism.')
    _add_quiet_argument(readback_parser)
    _add_snr_argument(readback_parser)
    readback_parser.set_defaults(func = nrf5x.readback)

def _add_readregs_command(subparsers):
    readregs_parser = subparsers.add_parser('readregs', help = 'Reads the CPU registers.')
    _add_quiet_argument(readregs_parser)
    _add_snr_argument(readregs_parser)
    readregs_parser.set_defaults(func = nrf5x.readregs)

def _add_readtofile_command(subparsers):
    readtofile_parser = subparsers.add_parser('readtofile', help = "Reads and stores the device's memory.")
    _add_file_argument(readtofile_parser)
    _add_quiet_argument(readtofile_parser)
    _add_readcode_argument(readtofile_parser)
    _add_readram_argument(readtofile_parser)
    _add_readuicr_argument(readtofile_parser)
    _add_snr_argument(readtofile_parser)
    readtofile_parser.set_defaults(func = nrf5x.readtofile)

def _add_recover_command(subparsers):
    recover_parser = subparsers.add_parser('recover', help = 'Erases all user FLASH and RAM and disables any readback protection mechanisms that are enabled.')
    _add_clockspeed_argument(recover_parser)
    _add_quiet_argument(recover_parser)
    _add_snr_argument(recover_parser)
    recover_parser.set_defaults(func = nrf5x.recover)

def _add_reset_command(subparsers):
    reset_parser = subparsers.add_parser('reset', help = 'Resets the device.')
    _add_quiet_argument(reset_parser)
    _add_reset_group(reset_parser)
    _add_snr_argument(reset_parser)
    reset_parser.set_defaults(func = nrf5x.reset)

def _add_run_command(subparsers):
    run_parser = subparsers.add_parser('run', help = "Runs the device's CPU.")
    _add_quiet_argument(run_parser)
    _add_snr_argument(run_parser)
    run_parser.set_defaults(func = nrf5x.run)

def _add_verify_command(subparsers):
    verify_parser = subparsers.add_parser('verify', help = "Verifies that the device's memory contains the correct data.")
    _add_clockspeed_argument(verify_parser)
    _add_quiet_argument(verify_parser)
    _add_snr_argument(verify_parser)
    _add_file_argument(verify_parser)
    verify_parser.set_defaults(func = nrf5x.verify)

def _add_version_command(subparsers):
    version_parser = subparsers.add_parser('version', help = 'Display the nrfjprog and JLinkARM DLL versions.')
    version_parser.set_defaults(func = nrf5x.version)

"""
Mutually exclusive groups. argparse will make sure one of the arguments in a mutually exclusive group was present on the command-line.

"""

def _add_erase_group(subparsers):
    erase_group = subparsers.add_mutually_exclusive_group()<commit_msg>Added a command class because almost all commands share arugments.<commit_after># Copyright (c) 2016, Nordic Semiconductor
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of Nordic Semiconductor ASA nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import argparse
import sys

from device import nrf5x

class Nrfjprog():
    """
    Initializes and runs our command-line application.

    """
    NRFJPROG_DESCRIPTION = "nrfjprog is a command line tool used for programming nRF5x devices. It is implemented in Python and utilizes pynrfjprog, a Python wrapper for the nrfjprog DLL. Both nrfjprog and pynrfjprog are open source and can be found on Nordic's GitHub. To report an issue, request a feature, or contribute please see: https://github.com/mjdietzx/nrfjprog."
    NRFJPROG_EPILOG = "Just like any standard command line tool, one positional command can be specified, followed by it's specific arguments. To see arguments for a specific command type: python nrfjprog COMMAND -h (i.e. python nrfjprog erase -h)."

    def __init__(self):
        """
        Initialize our command-line interface.

        """
        self.parser = argparse.ArgumentParser(description = self.NRFJPROG_DESCRIPTION, epilog = self.NRFJPROG_EPILOG)
        self.subparsers = self.parser.add_subparsers()
        self._add_commands(self.subparsers)

    def _add_commands(self, subparsers):
        """
        Split up the functionality of nrfjprog into multiple sub-commands because nrfjprog performs several different functions which require different command-line arguments.
        
        :param Special Action Object subparsers: https://docs.python.org/3/library/argparse.html#sub-commands
        """
        _add_erase_command(subparsers)
        _add_halt_command(subparsers)
        _add_ids_command(subparsers)
        _add_memrd_command(subparsers)
        _add_memwr_command(subparsers)
        _add_pinresetenable_command(subparsers)
        _add_program_command(subparsers)
        _add_readback_command(subparsers)
        _add_readregs_command(subparsers)
        _add_readtofile_command(subparsers)
        _add_recover_command(subparsers)
        _add_reset_command(subparsers)
        _add_run_command(subparsers)
        _add_verify_command(subparsers)
        _add_version_command(subparsers)

    def start(self):
        """
        Parse user input and execute the requested functionality.

        """
        self.args = self.parser.parse_args()
        self.args.func(self.args)  # Call the default function. (i.e. nRF5x.erase() in the erase command).

class Command():
    """
    Class representing a top-level positional command.

    """
    def __init__(self, parser, callback):
        """
        All commands except the 'ids' and 'version' command share these arguments.

        """
        _add_clockspeed_argument(parser)
        _add_quiet_argument(parser)
        _add_snr_argument(parser)
        parser.set_defaults(func = callback)

"""
The top-level positional commands of our command-line interface. These contain their own unique and shared arguments.

"""

def _add_erase_command(subparsers):
    erase_parser = subparsers.add_parser('erase', help = "Erases the device's FLASH.")
    Command(erase_parser, nrf5x.erase)

    _add_erase_group(erase_parser)

def _add_halt_command(subparsers):
    halt_parser = subparsers.add_parser('halt', help = "Halts the device's CPU.")
    Command(halt_parser, nrf5x.halt)

def _add_ids_command(subparsers): # This is the only command that doesn't have the snr and quiet option.
    ids_parser = subparsers.add_parser('ids', help = 'Displays the serial numbers of all debuggers connected to the PC.')
    ids_parser.set_defaults(func = nrf5x.ids)

def _add_memrd_command(subparsers):
    memrd_parser = subparsers.add_parser('memrd', help = "Reads the device's memory.")
    Command(memrd_parser, nrf5x.memrd)

    _add_addr_argument(memrd_parser)
    _add_length_argument(memrd_parser)

def _add_memwr_command(subparsers):
    memwr_parser = subparsers.add_parser('memwr', help = "Writes one word in the device's memory.")
    Command(memwr_parser, nrf5x.memwr)

    _add_addr_argument(memwr_parser)
    _add_flash_argument(memwr_parser)
    _add_val_argument(memwr_parser)

def _add_pinresetenable_command(subparsers):
    pinresetenable_parser = subparsers.add_parser('pinresetenable', help = "Enable the pin reset on nRF52 devices. Invalid command on nRF51 devices.")
    Command(pinresetenable_parser, nrf5x.pinresetenable)

def _add_program_command(subparsers):
    program_parser = subparsers.add_parser('program', help = 'Programs the device.')
    Command(program_parser, nrf5x.program)

    _add_file_argument(program_parser)
    _add_erase_before_flash_group(program_parser)
    _add_verify_argument(program_parser)
    _add_reset_group(program_parser)

def _add_readback_command(subparsers):
    readback_parser = subparsers.add_parser('rbp', help = 'Enables the readback protection mechanism.')
    Command(readback_parser, nrf5x.readback)

def _add_readregs_command(subparsers):
    readregs_parser = subparsers.add_parser('readregs', help = 'Reads the CPU registers.')
    Command(readregs_parser, nrf5x.readregs)

def _add_readtofile_command(subparsers):
    readtofile_parser = subparsers.add_parser('readtofile', help = "Reads and stores the device's memory.")
    Command(readtofile_parser, nrf5x.readtofile)

    _add_file_argument(readtofile_parser)
    _add_readcode_argument(readtofile_parser)
    _add_readram_argument(readtofile_parser)
    _add_readuicr_argument(readtofile_parser)

def _add_recover_command(subparsers):
    recover_parser = subparsers.add_parser('recover', help = 'Erases all user FLASH and RAM and disables any readback protection mechanisms that are enabled.')
    Command(recover_parser, nrf5x.recover)

def _add_reset_command(subparsers):
    reset_parser = subparsers.add_parser('reset', help = 'Resets the device.')
    Command(reset_parser, nrf5x.reset)

    _add_reset_group(reset_parser)

def _add_run_command(subparsers):
    run_parser = subparsers.add_parser('run', help = "Runs the device's CPU.")
    Command(run_parser, nrf5x.run)

def _add_verify_command(subparsers):
    verify_parser = subparsers.add_parser('verify', help = "Verifies that the device's memory contains the correct data.")
    Command(verify_parser, nrf5x.verify)
    
    _add_file_argument(verify_parser)

def _add_version_command(subparsers):
    version_parser = subparsers.add_parser('version', help = 'Display the nrfjprog and JLinkARM DLL versions.')
    version_parser.set_defaults(func = nrf5x.version)

"""
Mutually exclusive groups. argparse will make sure one of the arguments in a mutually exclusive group was present on the command-line.

"""

def _add_erase_group(subparsers):
    erase_group = subparsers.add_mutually_exclusive_group()
{'fraction_non_alphanumeric': 0.07277239150507848, 'fraction_numerical': 0.0031163434903047093, 'mean_word_length': 4.615359688917692, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3058326', 'n_tokens_mistral': 5429, 'n_tokens_neox': 5241, 'n_words': 1428}