Support siPrefix with no suffix in SpinBox

This commit is contained in:
Kenneth Lyons 2021-02-03 09:15:32 -08:00
parent 66c77118dc
commit cd10719837
4 changed files with 60 additions and 12 deletions

View File

@ -31,6 +31,8 @@ spins = [
pg.SpinBox(value=1.0, suffix='V', siPrefix=True, dec=True, step=0.5, minStep=0.01)),
("Float with SI-prefixed units,<br>dec step=1.0, minStep=0.001",
pg.SpinBox(value=1.0, suffix='V', siPrefix=True, dec=True, step=1.0, minStep=0.001)),
("Float with SI prefix but no suffix",
pg.SpinBox(value=1e9, siPrefix=True)),
("Float with custom formatting",
pg.SpinBox(value=23.07, format='${value:0.02f}',
regex='\$?(?P<number>(-?\d+(\.\d+)?)|(-?\.\d+))$')),

View File

@ -119,10 +119,27 @@ def siFormat(x, precision=3, suffix='', space=True, error=None, minVal=1e-25, al
def siParse(s, regex=FLOAT_REGEX, suffix=None):
"""Convert a value written in SI notation to a tuple (number, si_prefix, suffix).
Example::
siParse('100 μV") # returns ('100', 'μ', 'V')
siParse('100 µV") # returns ('100', 'µ', 'V')
Note that in the above example, the µ symbol is the "micro sign" (UTF-8
0xC2B5), as opposed to the Greek letter mu (UTF-8 0xCEBC).
Parameters
----------
s : str
The string to parse.
regex : re.Pattern, optional
Compiled regular expression object for parsing. The default is a
general-purpose regex for parsing floating point expressions,
potentially containing an SI prefix and a suffix.
suffix : str, optional
Suffix to check for in ``s``. The default (None) indicates there may or
may not be a suffix contained in the string and it is returned if
found. An empty string ``""`` is handled differently: if the string
contains a suffix, it is discarded.
"""
s = asUnicode(s)
s = s.strip()
@ -130,15 +147,20 @@ def siParse(s, regex=FLOAT_REGEX, suffix=None):
if s[-len(suffix):] != suffix:
raise ValueError("String '%s' does not have the expected suffix '%s'" % (s, suffix))
s = s[:-len(suffix)] + 'X' # add a fake suffix so the regex still picks up the si prefix
# special case: discard any extra characters if suffix is explicitly empty
if suffix == "":
s += 'X'
m = regex.match(s)
if m is None:
raise ValueError('Cannot parse number "%s"' % s)
try:
sip = m.group('siPrefix')
except IndexError:
sip = ''
if suffix is None:
try:
suf = m.group('suffix')
@ -146,8 +168,8 @@ def siParse(s, regex=FLOAT_REGEX, suffix=None):
suf = ''
else:
suf = suffix
return m.group('number'), '' if sip is None else sip, '' if suf is None else suf
return m.group('number'), '' if sip is None else sip, '' if suf is None else suf
def siEval(s, typ=float, regex=FLOAT_REGEX, suffix=None):

View File

@ -423,6 +423,30 @@ def test_eq():
assert eq(set(range(10)), set(range(10)))
assert not eq(set(range(10)), set(range(9)))
if __name__ == '__main__':
test_interpolateArray()
@pytest.mark.parametrize("s,suffix,expected", [
# usual cases
("100 uV", "V", ("100", "u", "V")),
("100 µV", "V", ("100", "µ", "V")),
("4.2 nV", None, ("4.2", "n", "V")),
("1.2 m", "m", ("1.2", "", "m")),
("1.2 m", None, ("1.2", "", "m")),
("5.0e9", None, ("5.0e9", "", "")),
("2 units", "units", ("2", "", "units")),
# siPrefix with explicit empty suffix
("1.2 m", "", ("1.2", "m", "")),
("5.0e-9 M", "", ("5.0e-9", "M", "")),
# weirder cases that should return the reasonable thing
("4.2 nV", "nV", ("4.2", "", "nV")),
("4.2 nV", "", ("4.2", "n", "")),
("1.2 j", "", ("1.2", "", "")),
("1.2 j", None, ("1.2", "", "j")),
# expected error cases
("100 uV", "v", ValueError),
])
def test_siParse(s, suffix, expected):
if isinstance(expected, tuple):
assert pg.siParse(s, suffix=suffix) == expected
else:
with pytest.raises(expected):
pg.siParse(s, suffix=suffix)

View File

@ -466,7 +466,7 @@ class SpinBox(QtGui.QAbstractSpinBox):
# format the string
val = self.value()
if self.opts['siPrefix'] is True and len(self.opts['suffix']) > 0:
if self.opts['siPrefix'] is True:
# SI prefix was requested, so scale the value accordingly
if self.val == 0 and prev is not None:
@ -545,7 +545,7 @@ class SpinBox(QtGui.QAbstractSpinBox):
return False
# check suffix
if suffix != self.opts['suffix'] or (suffix == '' and siprefix != ''):
if suffix != self.opts['suffix']:
return False
# generate value