Cellframe Node CLI module

The node.cli module provides a set of classes for registering CLI (Command Line Interface) commands.

This example demonstrates the usage of the node.cli module to register and handle CLI commands. The documentation is available at the link. Here’s a brief overview of the functionalities and classes used in this example:

  • ReplyObject from node.cli: Used to provide messages about the result of command execution.

Warning

ReplyObject.reply(message) method sets up a data buffer that will be passed in response to the calling party (JSON-RPC client or cellframe-node-cli utility).

  • When multiple consecutive reply calls are made, for example reply("a"), reply("b"), reply("c"), only the content of the last reply call will actually be sent in response. So, in response to the CLI, only “c” will be included.
  • CFCliCommand from node.cli: A class for registering CLI commands and its options using optparse Python module.

Note

Commands will be processed by a callback handler with this signature:

  • func(arg1, arg2,…, reply_object: ReplyObject, opt1, opt2,…, **kwargs)
  • all arguments will be set up as first-n position-based arguments of a callback.
  • all options will be set up as keyword arguments of a callback.
  • all options not listed in keyword arguments can be found in the kwargs dictionary.

The example includes two command handlers:

  1. my_callback: a simple function that adds two numbers passed from the command line.
  2. hash_callback: a more complex function that checks for hash presence in a dictionary and returns its keys depending on the provided options.

The init() function initializes the module and registers the CLI commands. Here’s how it works:

  1. Command objects are created with alias, callback function, and help text.
  2. Options are added to the commands using the add_option() method, which is provided by OptionParser.
  3. Registered commands are added to the list of registered commands for execution inside Cellframe Node. To call commands, use cellframe-node-cli utility by following: cellframe-node-cli my_command 1 2, or use 1. Introduction client.
from optparse import OptionParser
from pycfhelpers.node.cli import ReplyObject, CFCliCommand, ReplyId
from pycfhelpers.node.logging import CFLog
 
# The node.cli module provides a set of classes
# for registering CLI commands.
 
 
# Create a simple callback handler, which adds
# two numbers from the command prompt
 
def my_callback(arg1, arg2, reply_object: ReplyObject, **kwargs):
    """Simple processing function.
 
    Args:
        arg1 (str): The first argument from the command line.
        arg2 (str): The second argument from the command line.
        reply_object (ReplyObject): ReplyObject to provide a message about the result.
    """
    option_verbose = kwargs.get("verbose")
    result = int(arg1) + int(arg2)
 
    # Process the logic in the case when the command
    # is called with and without option.
    # The returned response is determined by reply_object.reply("result")
    # function, where "result" is the message being returned.
 
    if option_verbose:
        result_message = "Verbose message: Command executed successfully."
        result_message += f"\nThe result of the execution is {result}."
        reply_object.reply(f"{result_message}")
    else:
        reply_object.reply(f"Command executed successfully.\n{result}")
 
 
# Create a more complex callback handler.
# Let the function check for a hash in the dictionary and
# return its keys depending on the options provided.
 
hsh_dict = {
    "hash1": {"nonce": 123, "gas": 10000},
    "hash2": {"nonce": 456, "gas": 20000},
}
 
 
def hash_callback(hsh, reply_object: ReplyObject, nonce, gas):
    """Processing function based on a provided hash.
 
    Args:
        hsh (str): Hash from the command line.
        reply_object (ReplyObject): ReplyObject to provide a message about the result.
        nonce: Nonce option.
        gas: Gas option.
    """
 
    # Process the logic in the case when the command
    # is called with and without option.
 
    if hsh in hsh_dict:
        nonce_value = hsh_dict[hsh]["nonce"]
        gas_value = hsh_dict[hsh]["gas"]
 
        if nonce and gas:
            reply_object.reply(f"Hash {hsh} found. Nonce: {nonce_value}, Gas: {gas_value}")
        elif nonce:
            reply_object.reply(f"Hash {hsh} found. Nonce: {nonce_value}")
        elif gas:
            reply_object.reply(f"Hash {hsh} found. Gas: {gas_value}")
        else:
            reply_object.reply(f"Hash {hsh} found.")
    else:
        reply_object.reply(f"Hash {hsh} not found in the dictionary.")
 
 
def init():
    # Create a command object.
    # Specify an alias, a processing function,
    # and help text, if necessary.
 
    my_command = CFCliCommand("my_command", my_callback,
                              "This is a sample command.")
 
    # Add options to the command.
    # my_command.parser is an OptionParser instance, therefore,
    # configure the options via the add_option method.
    # For more complex scenarios, see the official documentation:
    # https://docs.python.org/3/library/optparse.html
 
    my_command.parser.add_option("-v", "--verbose",
                                 action="store_true",
                                 dest="verbose",
                                 default=False,
                                 help="Print verbose output")
 
    # Register the command
    my_command.register()
 
    # Set up and register the other callback
    # functions in the same way.
 
    proc_command = CFCliCommand("fhash", hash_callback, "Find hash data")
 
    proc_command.parser.add_option("-n", "--nonce",
                                   action="store_true",
                                   dest="nonce",
                                   default=False)
                                   
    proc_command.parser.add_option("-g", "--gas",
                                   action="store_true",
                                   dest="gas",
                                   default=False)
    proc_command.register()
 
    return 0
 
# To check the operability of the commands, activate the Cellframe-node.
# Enter commands in the command prompt with the addition of
# the prefix "cellframe-node-cli".
 
# To check these examples, enter:
 
# cellframe-node-cli my_command 1 2
# > Command executed successfully.
# > 3
 
# cellframe-node-cli my_command 1 2 -v
# > Verbose message: Command executed successfully.
# > The result of the execution is 3.
 
# cellframe-node-cli fhash hash1
# > Hash hash1 found.