Reputation: 53
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
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