Tanishq Kashyap
Tanishq Kashyap

Reputation: 53

Is there a way to return the input values in different variables from self-defined function if the user doesn't input parameters in command-line form?

I am making a basic MAC changer application in Kali Linux that takes argument in the following form:

python mac_changer.py -i <interface> -m <new MAC address>

In PyCharm I have made the following functions that take the arguments and returns it, I can store the returned values that are parsed but I also want to allow program to ask user for interface and new MAC address in case the user does not input the interface and MAC in the command. I can return the parsed arguments in the form of options variable, I can also return the inputted arguments but is there any way to store the inputted arguments? all the modules are properly imported and the following code is a part of the full program

def get_arguments():
    parser = optparse.OptionParser()
    parser.add_option("-i", "--interface", dest="interface", help="Interface to change its MAC address")
    parser.add_option("-m", "--mac", dest="new_mac", help="New MAC address")
    (options, arguments) = parser.parse_args()
    if options.interface and options.new_mac:
        if not options.interface:
            #Code to handle error
            parser.error(("[-] Please specify an interface, use --help for more info"))
        elif not options.new_mac:
            #Code to handle error
            parser.error(("[-] Please specify a new MAC, use --help for more info"))
        return options
    else:
        return input("Inteface> "),input("New MAC> ")

options = get_arguments()
printf(options.interface)
printf(options.new_mac)

This outputs the given arguments from the above command line but I also want to store and use the arguments that code gets from the user using the input function alongside the parsed arguments.

Upvotes: -1

Views: 115

Answers (1)

Samwise
Samwise

Reputation: 71542

Your code basically works, but this is problematic because you have two different return types:

        return options  # argparse.Namespace object
    else:
        return input("Inteface> "),input("New MAC> ")  # tuple of two strings

options = get_arguments()
printf(options.interface)
printf(options.new_mac)

If you use a type checker on this code and annotate the return type, one or other of these lines will raise an error. If you return options as a tuple and the caller tries to access options.interface, it's going to raise an AttributeError because the tuple doesn't have a field called interface.

The easiest fix would be to just say that the function returns interface and new_mac as a string tuple in either case:

from typing import Tuple

def get_arguments() -> Tuple[str, str]:
    """Returns interface, new_mac args, either from command line or user input"""
    ...

and then:

        return options.interface, options.new_mac
    else:
        return input("Interface> "),input("New MAC> ")

interface, new_mac = get_arguments()
print(interface)
print(new_mac)

A slightly nicer solution IMO would be to use a NamedTuple, which is basically a tuple that you can give a name to, as well as names of its individual fields:

from typing import NamedTuple

class ChangerOptions(NamedTuple):
    interface: str
    new_mac: str

def get_arguments() -> ChangerOptions:

    ...

        return ChangerOptions(options.interface, options.new_mac)
    else:
        return ChangerOptions(input("Interface> "),input("New MAC> "))

options = get_arguments()
print(options.interface)
print(options.new_mac)

If you're forced to call a function that has no type annotations and multiple possible return types at runtime (i.e. you're using someone else's code and they're a terrible person who wants you to suffer), it's possible to deal with it in the calling code by doing something like:

        return options  # argparse.Namespace object
    else:
        return input("Inteface> "),input("New MAC> ")  # tuple of two strings


options = get_arguments()
try:
    # this will raise an AttributeError if no fields with these names
    interface, new_mac = options.interface, options.new_mac
except AttributeError:
    # whoops -- maybe it's a tuple?
    # this will raise a TypeError if that wasn't right either...
    interface, new_mac = options
print(interface)
print(new_mac)

Upvotes: 0

Related Questions