'Is there a way I can access the attribute in an Attribute Error without parsing the string?

My python version is 3.6

I am trying to give a more helpful message on attribute errors in a CLI framework that I am building. I have the following code

print(cli_config.test_exension_config.input_menu)

Which produces the error AttributeError: 'CLIConfig' object has no attribute 'test_exension_config'

Perfect, however now I want to give a recommendation on the closest attribute match as the attributes are dynamically created from a yaml file.

test_extension:
  input_menu: # "InputMenuConfig_instantiation_test"
    var:

So the closest attribute match would be test_extension_config.

Below is me catching the error and about to give a recommendation.

    def __getattribute__(self, name) -> Any:
        try:
            return super().__getattribute__(name)
        except AttributeError as ae:
            # chance to handle the attribute differently
            attr = get_erroring_attr(ae)
            closest_match = next(get_close_matches(attr, list(vars(self).keys())))
            if closest_match: # probably will have some threshold based on 'edit distance'
                return closest_match
                
            # if not, re-raise the exception
            raise ae

I am wanting to just receive the attribute I can parse the args of AttributeError but I wanted to know if there was another way to access the actual attribute name that is erroring without parsing the message.

In other words, in the last code block I have a method get_erroring_attr(ae) that takes in the AttributeError.

What would be the cleanest definition of def get_erroring_attr(ae) that will return the erroring attribute?

UPDATE:

So I did this and it works. I would just like to remove parsing as much as possible.

    def __getattribute__(self, name) -> Any:
        try:
            return super().__getattribute__(name)
        except AttributeError as ae:
            # chance to handle the attribute differently
            attr = self.get_erroring_attr(ae)
            closest_match = next(match for match in get_close_matches(attr, list(vars(self).keys())))
            if closest_match: # probably will have some threshold based on 'edit distance'
                traceback.print_exc()
                print(CLIColors.build_error_string(f"ERROR: Did you mean {CLIColors.build_value_string(closest_match)}?"))
                sys.exit()

            # if not, re-raise the exception
            raise ae
            
    def get_erroring_attr(self, attr_error: AttributeError):
        message = attr_error.args[0]
        _, error_attr_name = self.parse_attr_error_message(message)
        return error_attr_name

    def parse_attr_error_message(self, attr_err_msg: str):
        parsed_msg = re.findall("'([^']*)'", attr_err_msg)
        return parsed_msg

Which produces enter image description here



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source