The right tool is definitely the re
module.
Here is a regular expression that should do the job:
(\+|\-)?\d+(,\d+)?$
Let's break it down:
(\+|\-)?\d+(,\d+)?$
\+|\- Starts with a + or a -...
( )? ... but not necessarily
\d+ Contains a repetition of at least one digits
,\d+ Is followed by a comma and at least one digits...
( )? ... but not necessarily
$ Stops here: nothing follows the trailing digits
Now, your validate
function only has to return True
if the input matches that regex, and False
if it does not.
def validate(string):
result = re.match(r"(\+|\-)?\d+(,\d+)?$", string)
return result is not None
Some tests:
# Valid inputs
>>> validate("123")
True
>>> validate("123,2")
True
>>> validate("+123,2")
True
>>> validate("-123,2")
True
# Invalid inputs
>>> validate("123,")
False
>>> validate("123,2,")
False
>>> validate("+123,2,")
False
>>> validate("hello")
False
Edit
I understand now that you want to check in real-time if the input is valid.
So here is an example of what you can do:
import tkinter as tk
import re
def validate(string):
regex = re.compile(r"(\+|\-)?[0-9,]*$")
result = regex.match(string)
return (string == ""
or (string.count('+') <= 1
and string.count('-') <= 1
and string.count(',') <= 1
and result is not None
and result.group(0) != ""))
def on_validate(P):
return validate(P)
root = tk.Tk()
entry = tk.Entry(root, validate="key")
vcmd = (entry.register(on_validate), '%P')
entry.config(validatecommand=vcmd)
entry.pack()
root.mainloop()
The validate
function now checks more or less the same thing, but more loosely.
Then if the regex results in a match, some additional checks are performed:
- Allow the input to be empty;
- Prevent the input to have more than one
'+'
/'-'
, and more than one ','
;
- Ignore a match against the empty string, because the pattern allows it, so
"a"
would result in a match but we don't want it.
The command is registered, and works with the '%P'
parameter, that corresponds to the string if the input were accepted.
Please not however that forcing the input to be always correct is somewhat harsh, and might be counter-intuitive.
A more commonly used approach is to update a string next to the entry, and have the user know when their input is valid or invalid.