0

I have a GUI where I ask the user to enter some values. When the user submits the data I do some validation:

  1. first I check if the user has entered a value for each input
  2. then I check if each of the inputted values are integers

Trying not to repeat myself to much I came up with this, but the second part of the validation looks more like a hack. Is there a more pythonic way of rewriting this, short of spelling everything out like in the first part of the validation?

    errors = []
    # 1) check if values exist
    if not self.startInput.GetValue():
        errors.append("Please provide a start")
    if not self.stopInput.GetValue():
        errors.append("Please provide a stop")
    if not self.valueInput.GetValue():
        errors.append("Please provide a value")
    # 2) check if values are integers
    try:
        self.start = int(self.startInput.GetValue())
        self.stop = int(self.stopInput.GetValue())
        self.value = int(self.valueInput.GetValue())
    except ValueError as err:
        tb = traceback.format_exc()
        func = re.search('self\.(.*) =', tb).groups()[0]
        errors.append("Value for {0} needs to be an integer.".format(func)) 
    if errors:
        raise RuntimeError('\n'.join(errors))

3 Answers 3

4

Since you're checking for integers, and not floats, you can simply do:

if self.start.GetValue().strip().isdigit():
    pass

isdigit() returns False for both cases where the input is an empty string, and when the input contains non-digits.

If you want to send specific errors for incorrect assignment:

startValue = self.start.GetValue().strip()

if not startValue: 
    errors.append("Please provide a start.")

if not startValue.isdigit():
    errors.append("Value of start must be an integer.")
Sign up to request clarification or add additional context in comments.

2 Comments

This seems like a good option, but then I don't have a way of giving different error messages based on whether the data is missing ("Please provide a start value") versus the data exists but is not an integer ("Value for start needs to be an integer"). Correct?
@BioGeek: True, if you want that functionality, I would go with either two if statements, or a try...except block. Either one is perfectly pythonic.
1

If you have these inputs in a dictionary called inputs you can do:

errors = []
for inputname, inputval in self.inputs.items():
    if not inputval:
        errors.append("Please provide a {}".format(inputname))
    try:
        setattr(self, inputname, int(inputval.GetValue()))
    except:
        errors.append("Value for {0} needs to be an integer.".format(inputname)) 
if errors:
    raise RuntimeError('\n'.join(errors))

1 Comment

+1 for including all incorrectly formatted values in the error list, not just the first one
1

I think the try: ... except is perfectly Pythonic. I would have uses an helper function instead of searching through an error message get_int_of_name(name, value, error) which return an int and update error if needed:

def get_int_of_name(name, value, error):
    try:
        res = int(value)
    except ValueError:
        error.append("...")
        return 0
    else:
        return res

3 Comments

I agree that try...except is beautifully explicit and therefore pythonic. You should, however, avoid catching naked exceptions. I would do except ValueError:, instead of except:.
@Joel: It is more the parsing with a regex of the traceback when there is a ValueError that seemed unpythonic to me.
@Joel Cornett: Sure ! I was checking which exception I wanted to put here and forgot to put the right one. I fixed it now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.