/usr/share/rapid-photo-downloader/rapid/ValidatedEntry.py is in rapid-photo-downloader 0.4.10-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | # Copyright (c) 2006, Daniel J. Popowich
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Send bug reports and contributions to:
#
# dpopowich AT astro dot umass dot edu
#
'''
ValidatedEntry.py
Provides ValidatedEntry, a subclass of gtk.Entry which validates
input.
Usage: create an instance of ValidatedEntry, specifying the function
to validate input. E.g.:
: def money(text):
: "validate input to be monetary value"
: ...
:
: money_entry = ValidatedEntry(money)
Validation functions must accept one argument, the text to be
validated, and must return one of:
1: the input is valid.
0: the input is invalid and should not be displayed.
-1: the input is partially valid and will be displayed (and by
default with a different background color).
Three module-level variables are defined for the convenience of
validation function writers: VALID (1), INVALID (0), PARTIAL (-1).
There is one public method, isvalid(), which will return True if the
current text is valid.
Note: care should be taken when implementing validation functions to
allow empty strings to be VALID or at least PARTIAL. An empty string
should never be INVALID.
Note: the hooks for calling the validation function are implemented by
connecting the object to handlers for the gtk.Editable "insert-text"
and "delete-text" signals. These handlers are connected to instances
in the constructor, so will, by default, be called before other
handlers connected to the widgets for "*-text" signals. When input is
INVALID, stop_emission() is called, so later handlers for "*-text"
signals will not be called.
See the doc string for ValidatedEntry.__init__ for more details.
'''
import pygtk
pygtk.require('2.0')
import gtk
import gtk.gdk
if gtk.gtk_version < (2, 8):
import warnings
msg ='''This module was developed and tested with version 2.8.9 of gtk.
You are using version %d.%d.%d. Your milage may vary''' % gtk.gtk_version
warnings.warn(msg)
# major, minor, patch
version = 1, 0, 4
PARTIAL, INVALID, VALID = range(-1,2)
class ValidatedEntry(gtk.Entry):
white = gtk.gdk.color_parse('white')
yellow = gtk.gdk.color_parse('yellow')
def __init__(self, valid_func,
max=0,
use_bg=True, valid_bg=white, partial_bg=yellow,
error_func=None):
'''
Create instance of validating gtk.Entry.
valid_func: the function to validate input. See module doc
string for details.
max: passed to gtk.Entry constructor. (default: 0)
use_bg: if True (the default) set the base color of the
widget to indicate validity; see valid_bg and partial_bg.
valid_bg: a gtk.gdk.Color; the base color of the widget when
the input is valid. (default: white)
partial_bg: a gtk.gdk.Color; the base color of the widget when
the input is partially valid. (default: yellow)
error_func: a function to call (with no arguments) when
valid_func returns INVALID. If None (the default)
the default action will be to emit a short beep.
'''
assert valid_func('') != INVALID, 'valid_func cannot return INVALID for an empty string'
gtk.Entry.__init__(self, max)
self.__valid_func = valid_func
self.__use_bg = use_bg
self.__valid_bg = valid_bg
self.__partial_bg = partial_bg
self.__error_func = (error_func or
gtk.gdk.display_get_default().beep)
self.connect('insert-text', self.__insert_text_cb)
self.connect('delete-text', self.__delete_text_cb)
# bootstrap with an empty string (so the box will appear with
# the partial_bg if an empty string is PARTIAL)
self.insert_text('')
def isvalid(self):
return self.__isvalid
def __insert_text_cb(self, entry, text, length, position):
'callback for "insert-text" signal'
# generate what the new text will be
text = text[:length]
pos = self.get_position()
old = self.get_text()
new = old[:pos] + text + old[pos:]
# validate the new text
self.__validate(new, 'insert-text')
def __delete_text_cb(self, entry, start, end):
'callback for "delete-text" signal'
# generate what the new text will be
old = self.get_text()
new = old[:start] + old[end:]
# validate the new text
self.__validate(new, 'delete-text')
def __validate(self, text, signal):
'calls the user-provided validation function'
# validate
r = self.__valid_func(text)
if r == VALID:
self.__isvalid = True
if self.__use_bg:
self.modify_base(gtk.STATE_NORMAL, self.__valid_bg)
elif r == PARTIAL:
self.__isvalid = False
if self.__use_bg:
self.modify_base(gtk.STATE_NORMAL, self.__partial_bg)
else:
# don't set self.__isvalid: since we're not displaying the
# new value, the validity should be whatever it was before
self.stop_emission(signal)
self.__error_func()
######################################################################
#
# Sample validation functions to use with ValidatedEntry
#
######################################################################
import re
# STRING (non-empty after stripping)
def v_nonemptystring(value):
'''
VALID: non-empty string after stripping whitespace
PARTAL: empty or all whitespace
INVALID: N/A
'''
if value.strip():
return VALID
return PARTIAL
# INT
def v_int(value):
'''
VALID: any postive or negative integer
PARTAL: empty or leading "-"
INVALID: non-numeral
'''
v = value.strip()
if not v or v == '-':
return PARTIAL
try:
int(value)
return VALID
except:
return INVALID
# FLOAT
def v_float(value):
'''
VALID: any postive or negative floating point
PARTAL: empty or leading "-", "."
INVALID: non-numeral
'''
v = value.strip()
if not v or v in ('-', '.', '-.'):
return PARTIAL
try:
float(value)
return VALID
except:
return INVALID
# ISBN
_isbnpartial = re.compile('[0-9]{0,9}[0-9xX]?$')
def v_isbn(v):
'''Validate ISBN input.
From the isbn manual, section 4.4:
The check digit is the last digit of an ISBN. It is calculated on
a modulus 11 with weights 10-2, using X in lieu of 10 where ten
would occur as a check digit. This means that each of the first
nine digits of the ISBN -- excluding the check digit itself -- is
multiplied by a number ranging from 10 to 2 and that the resulting
sum of the products, plus the check digit, must be divisible by 11
without a remainder.'''
if _isbnpartial.match(v):
# isbn is ten characters in length
if len(v) < 10:
return PARTIAL
s = 0
for i, c in enumerate(v):
s += (c in 'xX' and 10 or int(c)) * (10 - i)
if s % 11 == 0:
return VALID
return INVALID
# MONEY
# re for (possibly negative) money
_money_re = re.compile('-?\d*(\.\d{1,2})?$')
# validation function for money
def v_money(value):
'''
VALID: any postive or negative floating point with at most two
digits after the decimal point.
PARTAL: empty or leading "-", "."
INVALID: non-numeral or more than two digits after the decimal
point.
'''
if not value or value == '-' or value[-1] == '.':
return PARTIAL
if _money_re.match(value):
return VALID
return INVALID
# PHONE
# the characters in a phone number
_phonechars = re.compile('[- 0-9]*$')
# valid phone number: [AC +]EXT-LINE
_phone = re.compile('([2-9][0-8][0-9]\s+)?[2-9][0-9]{2}-[0-9]{4}$')
def v_phone(value):
'''
VALID: any phone number of the form: EXT-LINE -or- AC EXT-LINE.
PARTAL: any characters that make up a valid #.
INVALID: characters that are not used in a phone #.
'''
if _phone.match(value):
return VALID
if _phonechars.match(value):
return PARTIAL
return INVALID
def empty_valid(vfunc):
'''
empty_valid is a factory function returning a validation function.
All of the validation functions in this module return PARTIAL for
empty strings which, in effect, forces non-empty input. There may
be a case where, e.g., you want money input to be optional, but
v_money will not consider empty input VALID. Instead of writing
another validation function you can instead use empty_valid(). By
wrapping a validation function with empty_valid(), input (after
stripping), if empty, will be considered VALID. E.g.:
ventry = ValidatedEntry(empty_valid(v_money))
It is recommended that all your validation functions treat empty
input as PARTIAL, for consistency across all validation functions
and for use with empty_valid().
'''
def validate(value):
if not value.strip():
return VALID
return vfunc(value)
return validate
def bounded(vfunc, conv, minv=None, maxv=None):
'''
bounded is a factory function returning a validation function
providing bounded input. E.g., you may want an entry that accepts
integers, but within a range, say, a score on a test graded in
whole numbers from 0 to 100:
score_entry = ValidatedEntry(bounded(v_int, int, 0, 100))
Arguments:
vfunc: A validation function.
conv: A callable that accepts a string argument (the text in
the entry) and returns a value to be compared to minv
and maxv.
minv: None or a value of the same type returned by conv. If
None, there is no minimum value enforced. If a value,
it will be the minimum value considered VALID.
maxv: None or a value of the same type returned by conv. If
None, there is no maximum value enforced. If a value,
it will be the maximum value considered VALID.
One or both of minv/maxv must be specified.
The function returned will call vfunc on entry input and if vfunc
returns VALID, the input will be converted by conv and compared to
minv/maxv. If the converted value is within the bounds of
minv/maxv then VALID will be returned, else PARTIAL will be
returned.
'''
assert minv is not None or maxv is not None, \
'One of minv/maxv must be specified'
def F(value):
r = vfunc(value)
if r == VALID:
v = conv(value)
if minv is not None and v < minv:
return PARTIAL
if maxv is not None and v > maxv:
return PARTIAL
return r
return F
|