I have what is probably a very obscure problem. My python script is intended to be ran from the command line with some command line arguments. Each argument needs to be parsed into a type more useful than a string. I am doing the following:
typed_arguments = []
for argument, (parameter, parameter_type) in zip(arguments, self.parameters.items()):
try:
argument = parameter_type(argument)
typed_arguments.append(argument)
except ValueError:
print(self.usage_prompt)
raise TypeError(f"Invalid {parameter}! Must conform to {parmeter_type}.")
where arguments is sys.argv[1:] and self.parameters is an OrderedDict[str, type] mapping the names of the parameters to the type they should conform to.
One of the arguments needs to be of an enum type. I have the following:
from enum import Enum
class MessageType(Enum):
READ = 1
CREATE = 2
RESPONSE = 3
...
where the entry in the parameter dictionary is {"message_type" : MessageType}
The problem, is that the code MessageType("READ") throws an exception instead of returning <MessageType.READ: 1>. Converting string to enum is instead done like so MessageType["READ"], but this is not helpful for my above code.
Is there some way, maybe through overriding __new__, making a MetaClass, or somthing entirely different, that I can make MessageType("READ") give me MessageType.READ and not throw an error?
Also, whilst trying to solve this problem, I discovered the argparse module. However this doesn't really solve my problem. Performing
parser.add_argument("message_type", type=MessageType)
still gives me error: argument message_type: invalid MessageType value: 'READ', as I presume its trying to do the exact same thing
parameter_typefrom the iteration to have the consistent interface of being called, rather than subscripted, in order to enforce the type? ... Can you think of a way, given the enum class, to create a callable that would create the instance in the right way, and store it inself.parameters?@staticmethodto the enum type that provides the interface you want. (You can implement it in terms of the existing__getitem__rather than with custom logic, of course.) There's also an approach that involves inheriting from bothEnumandstr, then matching the enumeration values, as strings, to their names.argparsewill basically implement the logic of your first code snippet for you, but it will not bypass the need for the type-enforcer to be callable.argparseis also quite old and has some strange limitations and idiosyncracies; you may want to look in to third-party alternatives (but of course, such recommendations are off topic here).def MessageTypeWrapper(s): return MessageType[s], no? if you just need a callable