Merge branch 'master' of git://github.com/CD3/pint into CD3-master
This commit is contained in:
@@ -248,6 +248,15 @@ If you want to use abbreviated unit names, prefix the specification with `~`:
|
||||
|
||||
The same is true for latex (`L`) and HTML (`H`) specs.
|
||||
|
||||
Pint also supports the LaTeX siunitx package:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> accel = 1.3 * ureg['meter/second**2']
|
||||
>>> # siunitx Latex print
|
||||
>>> print('The siunitx representation is {:Lx}'.format(accel))
|
||||
The siunitx representation is \SI[]{1.3}{\meter\per\second\squared}
|
||||
|
||||
Finally, you can specify a default format specification:
|
||||
|
||||
>>> 'The acceleration is {}'.format(accel)
|
||||
|
||||
@@ -190,6 +190,43 @@ def format_unit(unit, spec):
|
||||
return result
|
||||
|
||||
|
||||
def siunitx_format_unit(units):
|
||||
'''Returns LaTeX code for the unit that can be put into an siunitx command.'''
|
||||
# NOTE: unit registry is required to identify unit prefixes.
|
||||
registry = units._REGISTRY
|
||||
|
||||
def _tothe(power):
|
||||
if power == 1:
|
||||
return ''
|
||||
elif power == 2:
|
||||
return r'\squared'
|
||||
elif power == 3:
|
||||
return r'\cubed'
|
||||
else:
|
||||
return r'\tothe{%d}' % (power)
|
||||
|
||||
l = []
|
||||
# loop through all units in the container
|
||||
for unit, power in sorted(units._units.items()):
|
||||
# remove unit prefix if it exists
|
||||
# siunit supports \prefix commands
|
||||
prefix = None
|
||||
for p in registry._prefixes.values():
|
||||
p = str(p)
|
||||
if len(p) > 0 and unit.find(p) == 0:
|
||||
prefix = p
|
||||
unit = unit.replace( prefix, '', 1 )
|
||||
|
||||
if power < 0:
|
||||
l.append(r'\per')
|
||||
if not prefix is None:
|
||||
l.append(r'\{0}'.format(prefix))
|
||||
l.append(r'\{0}'.format(unit))
|
||||
l.append(r'{0}'.format(_tothe(abs(power))))
|
||||
|
||||
return ''.join(l)
|
||||
|
||||
|
||||
def remove_custom_flags(spec):
|
||||
for flag in _KNOWN_TYPES:
|
||||
if flag:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
from __future__ import division, unicode_literals, print_function, absolute_import
|
||||
|
||||
from .compat import ufloat
|
||||
from .formatting import _FORMATS
|
||||
from .formatting import _FORMATS, siunitx_format_unit
|
||||
|
||||
MISSING = object()
|
||||
|
||||
@@ -65,6 +65,22 @@ class _Measurement(object):
|
||||
return '{0}'.format(self)
|
||||
|
||||
def __format__(self, spec):
|
||||
# special cases
|
||||
if 'Lx' in spec: # the LaTeX siunitx code
|
||||
# the uncertainties module supports formatting
|
||||
# numbers in value(unc) notation (i.e. 1.23(45) instead of 1.23 +/- 0.45),
|
||||
# which siunitx actually accepts as input. we just need to give the 'S'
|
||||
# formatting option for the uncertainties module.
|
||||
spec = spec.replace('Lx','S')
|
||||
# todo: add support for extracting options
|
||||
opts = 'separate-uncertainty=true'
|
||||
mstr = format( self.magnitude, spec )
|
||||
ustr = siunitx_format_unit(self.units)
|
||||
ret = r'\SI[%s]{%s}{%s}'%( opts, mstr, ustr )
|
||||
return ret
|
||||
|
||||
|
||||
# standard cases
|
||||
if 'L' in spec:
|
||||
newpm = pm = r' \pm '
|
||||
pars = _FORMATS['L']['parentheses_fmt']
|
||||
|
||||
@@ -15,7 +15,7 @@ import operator
|
||||
import functools
|
||||
import bisect
|
||||
|
||||
from .formatting import remove_custom_flags
|
||||
from .formatting import remove_custom_flags, siunitx_format_unit
|
||||
from .errors import (DimensionalityError, OffsetUnitCalculusError,
|
||||
UndefinedUnitError)
|
||||
from .definitions import UnitDefinition
|
||||
@@ -118,6 +118,18 @@ class _Quantity(SharedRegistryObject):
|
||||
|
||||
def __format__(self, spec):
|
||||
spec = spec or self.default_format
|
||||
|
||||
# special cases
|
||||
if 'Lx' in spec: # the LaTeX siunitx code
|
||||
spec = spec.replace('Lx','')
|
||||
# todo: add support for extracting options
|
||||
opts = ''
|
||||
mstr = format(self.magnitude,spec)
|
||||
ustr = siunitx_format_unit(self.units)
|
||||
ret = r'\SI[%s]{%s}{%s}'%( opts, mstr, ustr )
|
||||
return ret
|
||||
|
||||
# standard cases
|
||||
if '#' in spec:
|
||||
spec = spec.replace('#', '')
|
||||
obj = self.to_compact()
|
||||
|
||||
@@ -51,11 +51,13 @@ class TestMeasurement(QuantityTestCase):
|
||||
self.assertEqual('{0:L}'.format(m), r'\left(4.00 \pm 0.10\right) second^{2}')
|
||||
self.assertEqual('{0:H}'.format(m), '(4.00 ± 0.10) second<sup>2</sup>')
|
||||
self.assertEqual('{0:C}'.format(m), '(4.00+/-0.10) second**2')
|
||||
self.assertEqual('{0:Lx}'.format(m), r'\SI[separate-uncertainty=true]{4.00(10)}{\second\squared}')
|
||||
self.assertEqual('{0:.1f}'.format(m), '(4.0 +/- 0.1) second ** 2')
|
||||
self.assertEqual('{0:.1fP}'.format(m), '(4.0 ± 0.1) second²')
|
||||
self.assertEqual('{0:.1fL}'.format(m), r'\left(4.0 \pm 0.1\right) second^{2}')
|
||||
self.assertEqual('{0:.1fH}'.format(m), '(4.0 ± 0.1) second<sup>2</sup>')
|
||||
self.assertEqual('{0:.1fC}'.format(m), '(4.0+/-0.1) second**2')
|
||||
self.assertEqual('{0:.1fLx}'.format(m), '\SI[separate-uncertainty=true]{4.0(1)}{\second\squared}')
|
||||
|
||||
def test_format_paru(self):
|
||||
v, u = self.Q_(0.20, 's ** 2'), self.Q_(0.01, 's ** 2')
|
||||
@@ -75,6 +77,8 @@ class TestMeasurement(QuantityTestCase):
|
||||
self.assertEqual('{0:.3uL}'.format(m), r'\left(0.2000 \pm 0.0100\right) second^{2}')
|
||||
self.assertEqual('{0:.3uH}'.format(m), '(0.2000 ± 0.0100) second<sup>2</sup>')
|
||||
self.assertEqual('{0:.3uC}'.format(m), '(0.2000+/-0.0100) second**2')
|
||||
self.assertEqual('{0:.3uLx}'.format(m), '\SI[separate-uncertainty=true]{0.2000(100)}{\second\squared}')
|
||||
self.assertEqual('{0:.1uLx}'.format(m), '\SI[separate-uncertainty=true]{0.20(1)}{\second\squared}')
|
||||
|
||||
def test_format_percu(self):
|
||||
self.test_format_perce()
|
||||
|
||||
@@ -104,6 +104,7 @@ class TestQuantity(QuantityTestCase):
|
||||
('{0:P~}', '4.12345678 kg·m²/s'),
|
||||
('{0:H~}', '4.12345678 kg m<sup>2</sup>/s'),
|
||||
('{0:C~}', '4.12345678 kg*m**2/s'),
|
||||
('{0:Lx}', r'\SI[]{4.12345678}{\kilo\gram\meter\squared\per\second}'),
|
||||
):
|
||||
self.assertEqual(spec.format(x), result)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ class TestUnit(QuantityTestCase):
|
||||
('{0:P}', 'kilogram·meter²/second'),
|
||||
('{0:H}', 'kilogram meter<sup>2</sup>/second'),
|
||||
('{0:C}', 'kilogram*meter**2/second'),
|
||||
('{0:Lx}', r'\si[]{\kilo\gram\meter\squared\per\second}'),
|
||||
('{0:~}', 'kg * m ** 2 / s'),
|
||||
('{0:L~}', r'\frac{kg \cdot m^{2}}{s}'),
|
||||
('{0:P~}', 'kg·m²/s'),
|
||||
|
||||
@@ -30,6 +30,7 @@ from .util import (logger, pi_theorem, solve_dependencies, ParserHelper,
|
||||
find_shortest_path, UnitsContainer, _is_dim,
|
||||
SharedRegistryObject, to_units_container)
|
||||
from .compat import tokenizer, string_types, NUMERIC_TYPES, long_type, zip_longest
|
||||
from .formatting import siunitx_format_unit
|
||||
from .definitions import (Definition, UnitDefinition, PrefixDefinition,
|
||||
DimensionDefinition)
|
||||
from .converters import ScaleConverter
|
||||
@@ -99,6 +100,13 @@ class _Unit(SharedRegistryObject):
|
||||
|
||||
def __format__(self, spec):
|
||||
spec = spec or self.default_format
|
||||
# special cases
|
||||
if 'Lx' in spec: # the LaTeX siunitx code
|
||||
opts = ''
|
||||
ustr = siunitx_format_unit(self)
|
||||
ret = r'\si[%s]{%s}'%( opts, ustr )
|
||||
return ret
|
||||
|
||||
|
||||
if '~' in spec:
|
||||
if self.dimensionless:
|
||||
|
||||
@@ -22,7 +22,7 @@ from token import STRING, NAME, OP, NUMBER
|
||||
from tokenize import untokenize
|
||||
|
||||
from .compat import string_types, tokenizer, lru_cache, NullHandler, maketrans, NUMERIC_TYPES
|
||||
from .formatting import format_unit
|
||||
from .formatting import format_unit,siunitx_format_unit
|
||||
from .pint_eval import build_eval_tree
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
Reference in New Issue
Block a user