0

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

5
  • "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." - to be clear: the issue is that you want each parameter_type from 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 in self.parameters? Commented Aug 30, 2023 at 22:07
  • see rogueleaderr's answer at the linked duplicate; it specifically covers the approach of adding a @staticmethod to 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 both Enum and str, then matching the enumeration values, as strings, to their names. Commented Aug 30, 2023 at 22:14
  • And yes, the standard library argparse will 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. argparse is 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). Commented Aug 30, 2023 at 22:16
  • I men, you can define something like def MessageTypeWrapper(s): return MessageType[s], no? if you just need a callable Commented Aug 30, 2023 at 22:18
  • I just upgraded to Python3.11 so I can use StrEnum :/ Commented Aug 30, 2023 at 22:34

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.