diff --git a/wx/lib/masked/maskededit.py b/wx/lib/masked/maskededit.py index b676f0cc..02184f81 100644 --- a/wx/lib/masked/maskededit.py +++ b/wx/lib/masked/maskededit.py @@ -5,9 +5,9 @@ # Created: 02/11/2003 # Copyright: (c) 2003 by Jeff Childers, Will Sadkin, 2003 # Portions: (c) 2002 by Will Sadkin, 2002-2007 -# RCS-ID: $Id$ +# # License: wxWidgets license -# Tags: phoenix-port, py3-port +# Tags: phoenix-port, py3-port #---------------------------------------------------------------------------- # NOTE: # MaskedEdit controls are based on a suggestion made on [wxPython-Users] by @@ -811,7 +811,8 @@ import string import sys import wx - +import wx.lib.six as six + if sys.version < '3': unicode = unicode else: @@ -1645,14 +1646,14 @@ class Field: right_signpos = -1 intStr = intStr.replace(' ', '') # drop extra spaces - intStr = string.replace(intStr,self._fillChar,"") # drop extra fillchars - intStr = string.replace(intStr,"-","") # drop sign, if any - intStr = string.replace(intStr, self._groupChar, "") # lose commas/dots + intStr = intStr.replace(self._fillChar,"") # drop extra fillchars + intStr = intStr.replace("-","") # drop sign, if any + intStr = intStr.replace(self._groupChar, "") # lose commas/dots #### dbg('intStr:"%s"' % intStr) start, end = self._extent field_len = end - start if not self._padZero and len(intStr) != field_len and intStr.strip(): - intStr = str(long(intStr)) + intStr = str(int(intStr)) #### dbg('raw int str: "%s"' % intStr) #### dbg('self._groupdigits:', self._groupdigits, 'self._formatcodes:', self._formatcodes) if self._groupdigits: @@ -1750,7 +1751,7 @@ class MaskedEditMixin: # Validate legitimate set of parameters: for key in kwargs.keys(): - if key.replace('Color', 'Colour') not in MaskedEditMixin.valid_ctrl_params.keys() + Field.valid_params.keys(): + if key.replace('Color', 'Colour') not in list(MaskedEditMixin.valid_ctrl_params.keys()) + list(Field.valid_params.keys()): raise TypeError('%s: invalid parameter "%s"' % (name, key)) ## Set up dictionary that can be used by subclasses to override or add to default @@ -2354,7 +2355,7 @@ class MaskedEditMixin: if 1 not in self._fields: self._fields[1] = Field() - self._decimalpos = string.find( self._mask, '.') + self._decimalpos = self._mask.find('.') ## dbg('decimal pos =', self._decimalpos) formatcodes = self._fields[0]._GetParameter('formatcodes') @@ -3063,15 +3064,22 @@ class MaskedEditMixin: if 'unicode' in wx.PlatformInfo: if key < 256: char = chr(key) # (must work if we got this far) - char = char.decode(self._defaultEncoding) + if not six.PY3: + char = char.decode(self._defaultEncoding) else: char = unichr(event.GetUnicodeKey()) ## dbg('unicode char:', char) excludes = unicode() if not isinstance(field._excludeChars, unicode): - excludes += field._excludeChars.decode(self._defaultEncoding) + if not six.PY3: + excludes += field._excludeChars.decode(self._defaultEncoding) + else: + excludes += field._excludeChars if not isinstance(self._ctrl_constraints, unicode): - excludes += self._ctrl_constraints._excludeChars.decode(self._defaultEncoding) + if not six.PY3: + excludes += self._ctrl_constraints._excludeChars.decode(self._defaultEncoding) + else: + excludes += self._ctrl_constraints._excludeChars else: char = chr(key) # (must work if we got this far) excludes = field._excludeChars + self._ctrl_constraints._excludeChars @@ -3104,7 +3112,7 @@ class MaskedEditMixin: wx.CallAfter(self._SetInsertionPoint, self._decimalpos) if not keep_processing: ## dbg("key disallowed by validation") - if not wx.Validator_IsSilent() and orig_pos == pos: + if not wx.Validator.IsSilent() and orig_pos == pos: wx.Bell() if keep_processing: @@ -3150,7 +3158,7 @@ class MaskedEditMixin: elif keep_processing: ## dbg('char not allowed') keep_processing = False - if (not wx.Validator_IsSilent()) and orig_pos == pos: + if (not wx.Validator.IsSilent()) and orig_pos == pos: wx.Bell() self._applyFormatting() @@ -3321,7 +3329,7 @@ class MaskedEditMixin: else: if( (sel_to == self._fields[0]._extent[0] and keycode in (wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT) ) or (sel_to == self._masklength and keycode in (wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT) ) ): - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() else: # treat arrows as normal, allowing selection @@ -3435,7 +3443,7 @@ class MaskedEditMixin: and sel_start == sel_to and sel_to == self._masklength - 1 and value[sel_to] == ' ' and key in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and not field._insertRight) ): - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() ## dbg(indent=0) return False @@ -3618,7 +3626,7 @@ class MaskedEditMixin: ## dbg('field._validRequired?', field._validRequired) ## dbg('field.IsValid("%s")?' % newstr[start:end], field.IsValid(newstr[start:end])) if field._validRequired and not field.IsValid(newstr[start:end]): - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() ## dbg(indent=0) return False @@ -3632,7 +3640,7 @@ class MaskedEditMixin: # if erasure results in an invalid value, disallow it: if self._ctrl_constraints._validRequired and not self.IsValid(newstr): - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() ## dbg(indent=0) return False @@ -3835,7 +3843,7 @@ class MaskedEditMixin: if field._stopFieldChangeIfInvalid and not field.IsValid(slice): ## dbg('field invalid; field change disallowed') - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() ## dbg(indent=0) return False @@ -3851,7 +3859,7 @@ class MaskedEditMixin: if pos < field_start: ## dbg('cursor before 1st field; cannot change to a previous field') - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() ## dbg(indent=0) return False @@ -3968,7 +3976,7 @@ class MaskedEditMixin: slice = self._GetValue()[start:end] if field._stopFieldChangeIfInvalid and not field.IsValid(slice): - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() return False @@ -4079,7 +4087,7 @@ class MaskedEditMixin: groupchar = self._fields[0]._groupChar if not self._isCharAllowed(groupchar, pos, checkRegex=True): keep_processing = False - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() if keep_processing: @@ -4087,7 +4095,7 @@ class MaskedEditMixin: ## dbg("str with '%s' inserted:" % groupchar, '"%s"' % newstr) if self._ctrl_constraints._validRequired and not self.IsValid(newstr): keep_processing = False - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() if keep_processing: @@ -4439,7 +4447,7 @@ class MaskedEditMixin: ## dbg('intStr "%(intStr)s"' % locals()) ## dbg('lenInt:', lenInt) - intStr = string.rjust( intStr[-lenInt:], lenInt) + intStr = intStr[-lenInt:].rjust(lenInt) ## dbg('right-justifed intStr = "%(intStr)s"' % locals()) newvalue = intStr + self._decimalChar + fracStr @@ -4523,7 +4531,7 @@ class MaskedEditMixin: year_field = 2 ## dbg('getYear: "%s"' % _getYear(text, self._datestyle)) - year = string.replace( _getYear( text, self._datestyle),self._fields[year_field]._fillChar,"") # drop extra fillChars + year = _getYear( text, self._datestyle).replace(self._fields[year_field]._fillChar,"") # drop extra fillChars month = _getMonth( text, self._datestyle) day = _getDay( text, self._datestyle) ## dbg('self._datestyle:', self._datestyle, 'year:', year, 'Month', month, 'day:', day) @@ -4629,7 +4637,7 @@ class MaskedEditMixin: # convert okchars to unicode if required; will force subsequent appendings to # result in unicode strings - if 'unicode' in wx.PlatformInfo and not isinstance(okchars, unicode): + if not six.PY3 and 'unicode' in wx.PlatformInfo and not isinstance(okchars, unicode): okchars = okchars.decode(self._defaultEncoding) field = self._FindField(pos) @@ -5221,7 +5229,8 @@ class MaskedEditMixin: if 'unicode' in wx.PlatformInfo and not isinstance(char, unicode): # convert the keyboard constant to a unicode value, to # ensure it can be concatenated into the control value: - char = char.decode(self._defaultEncoding) + if not six.PY3: + char = char.decode(self._defaultEncoding) newtext = left + char + right #### dbg('left: "%s"' % left) @@ -5756,7 +5765,7 @@ class MaskedEditMixin: else: item = 'selection' ## dbg('maxlength:', maxlength) - if 'unicode' in wx.PlatformInfo and not isinstance(paste_text, unicode): + if not six.PY3 and 'unicode' in wx.PlatformInfo and not isinstance(paste_text, unicode): paste_text = paste_text.decode(self._defaultEncoding) length_considered = len(paste_text) @@ -5863,7 +5872,7 @@ class MaskedEditMixin: if paste_text is not None: - if 'unicode' in wx.PlatformInfo and not isinstance(paste_text, unicode): + if not six.PY3 and 'unicode' in wx.PlatformInfo and not isinstance(paste_text, unicode): paste_text = paste_text.decode(self._defaultEncoding) ## dbg('paste text: "%s"' % paste_text) @@ -5960,7 +5969,7 @@ class MaskedEditMixin: if not valid_paste: ## dbg('paste text not legal for the selection or portion of the control following the cursor;') - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() ## dbg(indent=0) return None, -1 @@ -5969,7 +5978,7 @@ class MaskedEditMixin: new_text = text[:sel_start] + replacement_text + text[replace_to:] if new_text: - new_text = string.ljust(new_text,self._masklength) + new_text = new_text.ljust(self._masklength) if signed: new_text, signpos, right_signpos = self._getSignedValue(candidate=new_text) if new_text: diff --git a/wx/lib/masked/numctrl.py b/wx/lib/masked/numctrl.py index 56b1cda1..6383b0ac 100644 --- a/wx/lib/masked/numctrl.py +++ b/wx/lib/masked/numctrl.py @@ -3,11 +3,9 @@ # Author: Will Sadkin # Created: 09/06/2003 # Copyright: (c) 2003-2007 by Will Sadkin -# RCS-ID: $Id$ +# # License: wxWidgets license -# # Tags: phoenix-port, py3-port, unittest, documented -# #---------------------------------------------------------------------------- # NOTE: # This was written to provide a numeric edit control for wxPython that @@ -406,6 +404,8 @@ import types import wx +import wx.lib.six as six + from sys import maxsize MAXINT = maxsize # (constants should be in upper case) MININT = -maxsize-1 @@ -563,15 +563,15 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): ## dbg(indent=0) # Process initial fields for the control, as part of construction: - if type(init_args['integerWidth']) != types.IntType: + if not isinstance(init_args['integerWidth'], int): raise AttributeError('invalid integerWidth (%s) specified; expected integer' % repr(init_args['integerWidth'])) elif init_args['integerWidth'] < 1: raise AttributeError('invalid integerWidth (%s) specified; must be > 0' % repr(init_args['integerWidth'])) fields = {} - if init_args.has_key('fractionWidth'): - if type(init_args['fractionWidth']) != types.IntType: + if 'fractionWidth' in init_args: + if not isinstance(init_args['fractionWidth'], int): raise AttributeError('invalid fractionWidth (%s) specified; expected integer' % repr(self._fractionWidth)) elif init_args['fractionWidth'] < 0: raise AttributeError('invalid fractionWidth (%s) specified; must be >= 0' % repr(init_args['fractionWidth'])) @@ -661,14 +661,14 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): reset_fraction_width = False - if( (kwargs.has_key('integerWidth') and kwargs['integerWidth'] != self._integerWidth) - or (kwargs.has_key('fractionWidth') and kwargs['fractionWidth'] != self._fractionWidth) - or (kwargs.has_key('groupDigits') and kwargs['groupDigits'] != self._groupDigits) - or (kwargs.has_key('autoSize') and kwargs['autoSize'] != self._autoSize) ): + if( ('integerWidth' in kwargs and kwargs['integerWidth'] != self._integerWidth) + or ('fractionWidth' in kwargs and kwargs['fractionWidth'] != self._fractionWidth) + or ('groupDigits' in kwargs and kwargs['groupDigits'] != self._groupDigits) + or ('autoSize' in kwargs and kwargs['autoSize'] != self._autoSize) ): fields = {} - if kwargs.has_key('fractionWidth'): + if 'fractionWidth' in kwargs: if type(kwargs['fractionWidth']) != types.IntType: raise AttributeError('invalid fractionWidth (%s) specified; expected integer' % repr(kwargs['fractionWidth'])) elif kwargs['fractionWidth'] < 0: @@ -686,7 +686,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): fracmask = '' ## dbg('fracmask:', fracmask) - if kwargs.has_key('integerWidth'): + if 'integerWidth' in kwargs: if type(kwargs['integerWidth']) != types.IntType: ## dbg(indent=0) raise AttributeError('invalid integerWidth (%s) specified; expected integer' % repr(kwargs['integerWidth'])) @@ -696,7 +696,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): else: self._integerWidth = kwargs['integerWidth'] - if kwargs.has_key('groupDigits'): + if 'groupDigits' in kwargs: self._groupDigits = kwargs['groupDigits'] if self._groupDigits: @@ -710,14 +710,14 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): maskededit_kwargs['fields'] = fields # don't bother to reprocess these arguments: - if kwargs.has_key('integerWidth'): + if 'integerWidth' in kwargs: del kwargs['integerWidth'] - if kwargs.has_key('fractionWidth'): + if 'fractionWidth' in kwargs: del kwargs['fractionWidth'] maskededit_kwargs['mask'] = intmask+fracmask - if kwargs.has_key('groupChar') or kwargs.has_key('decimalChar'): + if 'groupChar' in kwargs or 'decimalChar' in kwargs: old_groupchar = self._groupChar # save so we can reformat properly old_decimalchar = self._decimalChar ## dbg("old_groupchar: '%s'" % old_groupchar) @@ -726,10 +726,10 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): decimalchar = old_decimalchar old_numvalue = self._GetNumValue(self._GetValue()) - if kwargs.has_key('groupChar'): + if 'groupChar' in kwargs: maskededit_kwargs['groupChar'] = kwargs['groupChar'] groupchar = kwargs['groupChar'] - if kwargs.has_key('decimalChar'): + if 'decimalChar' in kwargs: maskededit_kwargs['decimalChar'] = kwargs['decimalChar'] decimalchar = kwargs['decimalChar'] @@ -754,7 +754,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): # reprocess existing format codes to ensure proper resulting format: formatcodes = self.GetCtrlParameter('formatcodes') - if kwargs.has_key('allowNegative'): + if 'allowNegative' in kwargs: if kwargs['allowNegative'] and '-' not in formatcodes: formatcodes += '-' maskededit_kwargs['formatcodes'] = formatcodes @@ -762,7 +762,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): formatcodes = formatcodes.replace('-','') maskededit_kwargs['formatcodes'] = formatcodes - if kwargs.has_key('groupDigits'): + if 'groupDigits' in kwargs: if kwargs['groupDigits'] and ',' not in formatcodes: formatcodes += ',' maskededit_kwargs['formatcodes'] = formatcodes @@ -770,7 +770,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): formatcodes = formatcodes.replace(',','') maskededit_kwargs['formatcodes'] = formatcodes - if kwargs.has_key('selectOnEntry'): + if 'selectOnEntry' in kwargs: self._selectOnEntry = kwargs['selectOnEntry'] ## dbg("kwargs['selectOnEntry']?", kwargs['selectOnEntry'], "'S' in formatcodes?", 'S' in formatcodes) if kwargs['selectOnEntry'] and 'S' not in formatcodes: @@ -780,7 +780,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): formatcodes = formatcodes.replace('S','') maskededit_kwargs['formatcodes'] = formatcodes - if kwargs.has_key('autoSize'): + if 'autoSize' in kwargs: self._autoSize = kwargs['autoSize'] if kwargs['autoSize'] and 'F' not in formatcodes: formatcodes += 'F' @@ -798,14 +798,14 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): maskededit_kwargs['formatcodes'] = formatcodes - if kwargs.has_key('limited'): + if 'limited' in kwargs: if kwargs['limited'] and not self._limited: maskededit_kwargs['validRequired'] = True elif not kwargs['limited'] and self._limited: maskededit_kwargs['validRequired'] = False self._limited = kwargs['limited'] - if kwargs.has_key('limitOnFieldChange'): + if 'limitOnFieldChange' in kwargs: if kwargs['limitOnFieldChange'] and not self._limitOnFieldChange: maskededit_kwargs['stopFieldChangeIfInvalid'] = True elif kwargs['limitOnFieldChange'] and self._limitOnFieldChange: @@ -839,7 +839,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): # Set min and max as appropriate: - if kwargs.has_key('min'): + if 'min' in kwargs: min = kwargs['min'] if( self._max is None or min is None @@ -858,7 +858,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): pass - if kwargs.has_key('max'): + if 'max' in kwargs: max = kwargs['max'] if( self._min is None or max is None @@ -876,16 +876,16 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): ## dbg('ignoring max') pass - if kwargs.has_key('allowNegative'): + if 'allowNegative' in kwargs: self._allowNegative = kwargs['allowNegative'] # Ensure current value of control obeys any new restrictions imposed: text = self._GetValue() ## dbg('text value: "%s"' % text) - if kwargs.has_key('groupChar') and self._groupChar != old_groupchar and text.find(old_groupchar) != -1: + if 'groupChar' in kwargs and self._groupChar != old_groupchar and text.find(old_groupchar) != -1: text = old_numvalue ## dbg('old_groupchar: "%s" newgroupchar: "%s"' % (old_groupchar, self._groupChar)) - if kwargs.has_key('decimalChar') and self._decimalChar != old_decimalchar and text.find(old_decimalchar) != -1: + if 'decimalChar' in kwargs and self._decimalChar != old_decimalchar and text.find(old_decimalchar) != -1: text = old_numvalue if text != self._GetValue(): @@ -954,7 +954,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): if not value: return 0.0 else: - return string.atof(fracstring) + return float(fracstring) def _OnChangeSign(self, event): ## dbg('NumCtrl::_OnChangeSign', indent=1) @@ -968,7 +968,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): # limited and -1 is out of bounds if self._typedSign: self._isNeg = False - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() sel_start, sel_to = self._GetSelection() ## dbg('queuing reselection of (%d, %d)' % (sel_start, sel_to)) @@ -1049,7 +1049,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): intstart, intend = self._fields[0]._extent ## dbg('intstart, intend:', intstart, intend) ## dbg('raw integer:"%s"' % value[intstart:intend]) - int = self._GetNumValue(value[intstart:intend]) + int_str = self._GetNumValue(value[intstart:intend]) numval = self._fromGUI(value) ## dbg('integer: "%s"' % int) @@ -1075,11 +1075,11 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): # a limits check and see if the value is otherwise ok... ## dbg('self._isNeg?', self._isNeg) - if int == '-' and self._oldvalue < 0 and not self._typedSign: + if int_str == '-' and self._oldvalue < 0 and not self._typedSign: ## dbg('just a negative sign; old value < 0; setting replacement of 0') replacement = 0 self._isNeg = False - elif int[:2] == '-0': + elif int_str[:2] == '-0': if self._oldvalue < 0: ## dbg('-0; setting replacement of 0') replacement = 0 @@ -1094,7 +1094,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): ## dbg(indent=0) return - elif int == '-' and (self._oldvalue >= 0 or self._typedSign): + elif int_str == '-' and (self._oldvalue >= 0 or self._typedSign): if not self._limited or (self._min < -1 and self._max >= -1): ## dbg('just a negative sign; setting replacement of -1') replacement = -1 @@ -1105,7 +1105,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): return elif( self._typedSign - and int.find('-') != -1 + and int_str.find('-') != -1 and self._limited and not self._min <= numval <= self._max): # changed sign resulting in value that's now out-of-bounds; @@ -1115,15 +1115,15 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): return if replacement is None: - if int and int != '-': + if int_str and int_str != '-': try: - string.atol(int) + int(int_str) except ValueError: # integer requested is not legal. This can happen if the user # is attempting to insert a digit in the middle of the control # resulting in something like " 3 45". Disallow such actions: ## dbg('>>>>>>>>>>>>>>>> "%s" does not convert to a long!' % int) - if not wx.Validator_IsSilent(): + if not wx.Validator.IsSilent(): wx.Bell() sel_start, sel_to = self._GetSelection() ## dbg('queuing reselection of (%d, %d)' % (sel_start, sel_to)) @@ -1136,9 +1136,9 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): # finally, (potentially re) verify that numvalue will pass any limits imposed: try: if self._fractionWidth: - value = self._toGUI(string.atof(numvalue)) + value = self._toGUI(float(numvalue)) else: - value = self._toGUI(string.atol(numvalue)) + value = self._toGUI(int(numvalue)) except ValueError as e: ## dbg('Exception:', e, 'must be out of bounds; disallow value') self._disallowValue() @@ -1644,7 +1644,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): ## dbg(indent=0) return self._template - elif type(value) in (types.StringType, types.UnicodeType): + elif isinstance(value, six.string_types): value = self._GetNumValue(value) ## dbg('cleansed num value: "%s"' % value) if value == "": @@ -1664,7 +1664,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): ## dbg('exception raised:', e, indent=0) raise ValueError ('NumCtrl requires numeric value, passed %s'% repr(value) ) - elif type(value) not in (types.IntType, types.LongType, types.FloatType): + elif not isinstance(value, (int, float)): ## dbg(indent=0) raise ValueError ( 'NumCtrl requires numeric value, passed %s'% repr(value) )