diff --git a/quantiphy.py b/quantiphy.py index cb7c176..3ea5d6c 100644 --- a/quantiphy.py +++ b/quantiphy.py @@ -457,9 +457,19 @@ def add_constant(value, alias=None, unit_systems=None): SMALL_SCALE_FACTORS = 'munpfazy' # These must be given in order, one for every three decades. +# Supported currency symbols (these go on left side of number) +CURRENCY_SYMBOLS = '$£€ɃΞ' if sys.version_info.major == 3 else '$' + # Regular expression for recognizing and decomposing string .format method codes -FORMAT_SPEC = re.compile(r'\A([<>]?)(\d*)(?:\.(\d+))?(?:([qQrRusSeEfFgGdn])([a-zA-Z°ÅΩ℧$%][-^/()\w]*)?)?\Z') -# ^align ^width ^prec ^format ^units +FORMAT_SPEC = re.compile(r'''\A + ([<>]?) # alignment + (\d*) # width + (?:\.(\d+))? # precision + (?: + ([qQrRusSeEfFgGdn]) # format + ([a-zA-Z°ÅΩ℧%{cs}][-^/()\w]*)? # units + )? +\Z'''.format(cs=CURRENCY_SYMBOLS), re.VERBOSE) # Defaults {{{1 DEFAULTS = { @@ -486,7 +496,6 @@ def add_constant(value, alias=None, unit_systems=None): 'strip_zeros': True, 'unity_sf': '', } -CURRENCY_SYMBOLS = '$£€ɃΞ' if sys.version_info.major == 3 else '$' # Quantity class {{{1 @@ -1659,21 +1668,18 @@ def __format__(self, template): value = getattr(self, 'name', '') elif ftype == 'd': value = getattr(self, 'desc', '') - else: # pragma: no cover - raise ValueError( - "Unknown format code '%s' for object of type 'Quantity'." % ftype - ) return '{0:{1}{2}s}'.format(value, align, width) label = ftype.isupper() - if ftype in 'sS': # note that ftype = '' matches this case + ftype = ftype.lower() + if ftype in 's': # note that ftype = '' matches this case label = label if ftype else None value = self.render(prec=prec, show_label=label, scale=scale) - elif ftype in 'qQ': + elif ftype == 'q': value = self.render( prec=prec, show_si=True, show_units=True, show_label=label, scale=scale ) - elif ftype in 'rR': + elif ftype == 'r': value = self.render( prec=prec, show_si=True, show_units=False, show_label=label, scale=scale @@ -1691,16 +1697,15 @@ def __format__(self, template): prec = self.prec if prec == 'full': prec = self.full_prec - if ftype in 'gG': + if ftype == 'g': prec += 1 - value = '{0:.{1}{2}}'.format(value, prec, ftype.lower()) - if ftype.isupper(): + value = '{0:.{1}{2}}'.format(value, prec, ftype) + if label: value = self._label(value, True) width = '' if width == '0' else '' return '{0:{1}{2}s}'.format(value, align, width) else: - # unrecognized format, just provide something reasonable - return self.render() + raise ValueError("Invalid format specifier '{}' for {}.".format(template, self.render())) # extract() {{{2 @classmethod diff --git a/test_format.py b/test_format.py index 3fb4292..d1e0cc8 100644 --- a/test_format.py +++ b/test_format.py @@ -23,7 +23,6 @@ def test_format(): assert '{:G}'.format(q) == 'f = 1.4204e+09' assert '{:n}'.format(q) == 'f' assert '{:d}'.format(q) == 'frequency of hydrogen line' - assert '{:X}'.format(q) == '1.4204 GHz' q=Quantity('2ns') assert float(q) == 2e-9 @@ -49,7 +48,6 @@ def test_full_format(): assert '{:G}'.format(q) == 'f = 1420405751.786' assert '{:n}'.format(q) == 'f' assert '{:d}'.format(q) == 'frequency of hydrogen line' - assert '{:X}'.format(q) == '1.420405751786 GHz' q=Quantity('2ns') assert float(q) == 2e-9 @@ -76,7 +74,6 @@ def test_scaled_format(): assert '{:G°F}'.format(q) == 'Tboil = 212' assert '{:n°F}'.format(q) == 'Tboil' assert '{:d°F}'.format(q) == 'boiling point of water' - assert '{:X°F}'.format(q) == '100 °C' assert '{!r}'.format(q) == "Quantity('100 °C')" assert '{:.8s°C}'.format(q) == '100 °C'