Merge conflicts in testsuite
This commit is contained in:
150
pint/babel_names.py
Normal file
150
pint/babel_names.py
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
pint.babel
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
:copyright: 2016 by Pint Authors, see AUTHORS for more details.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pint.compat import HAS_PROPER_BABEL
|
||||||
|
|
||||||
|
_babel_units = dict(
|
||||||
|
standard_gravity='acceleration-g-force',
|
||||||
|
millibar='pressure-millibar',
|
||||||
|
metric_ton='mass-metric-ton',
|
||||||
|
megawatt='power-megawatt',
|
||||||
|
degF='temperature-fahrenheit',
|
||||||
|
dietary_calorie='energy-foodcalorie',
|
||||||
|
millisecond='duration-millisecond',
|
||||||
|
mph='speed-mile-per-hour',
|
||||||
|
acre_foot='volume-acre-foot',
|
||||||
|
mebibit='digital-megabit',
|
||||||
|
gibibit='digital-gigabit',
|
||||||
|
tebibit='digital-terabit',
|
||||||
|
mebibyte='digital-megabyte',
|
||||||
|
kibibyte='digital-kilobyte',
|
||||||
|
mm_Hg='pressure-millimeter-of-mercury',
|
||||||
|
month='duration-month',
|
||||||
|
kilocalorie='energy-kilocalorie',
|
||||||
|
cubic_mile='volume-cubic-mile',
|
||||||
|
arcsecond='angle-arc-second',
|
||||||
|
byte='digital-byte',
|
||||||
|
metric_cup='volume-cup-metric',
|
||||||
|
kilojoule='energy-kilojoule',
|
||||||
|
meter_per_second_squared='acceleration-meter-per-second-squared',
|
||||||
|
pint='volume-pint',
|
||||||
|
square_centimeter='area-square-centimeter',
|
||||||
|
in_Hg='pressure-inch-hg',
|
||||||
|
milliampere='electric-milliampere',
|
||||||
|
arcminute='angle-arc-minute',
|
||||||
|
MPG='consumption-mile-per-gallon',
|
||||||
|
hertz='frequency-hertz',
|
||||||
|
day='duration-day',
|
||||||
|
mps='speed-meter-per-second',
|
||||||
|
kilometer='length-kilometer',
|
||||||
|
square_yard='area-square-yard',
|
||||||
|
kelvin='temperature-kelvin',
|
||||||
|
kilogram='mass-kilogram',
|
||||||
|
kilohertz='frequency-kilohertz',
|
||||||
|
megahertz='frequency-megahertz',
|
||||||
|
meter='length-meter',
|
||||||
|
cubic_inch='volume-cubic-inch',
|
||||||
|
kilowatt_hour='energy-kilowatt-hour',
|
||||||
|
second='duration-second',
|
||||||
|
yard='length-yard',
|
||||||
|
light_year='length-light-year',
|
||||||
|
millimeter='length-millimeter',
|
||||||
|
metric_horsepower='power-horsepower',
|
||||||
|
gibibyte='digital-gigabyte',
|
||||||
|
## 'temperature-generic',
|
||||||
|
liter='volume-liter',
|
||||||
|
turn='angle-revolution',
|
||||||
|
microsecond='duration-microsecond',
|
||||||
|
pound='mass-pound',
|
||||||
|
ounce='mass-ounce',
|
||||||
|
calorie='energy-calorie',
|
||||||
|
centimeter='length-centimeter',
|
||||||
|
inch='length-inch',
|
||||||
|
centiliter='volume-centiliter',
|
||||||
|
troy_ounce='mass-ounce-troy',
|
||||||
|
gream='mass-gram',
|
||||||
|
kilowatt='power-kilowatt',
|
||||||
|
knot='speed-knot',
|
||||||
|
lux='light-lux',
|
||||||
|
hectoliter='volume-hectoliter',
|
||||||
|
microgram='mass-microgram',
|
||||||
|
degC='temperature-celsius',
|
||||||
|
tablespoon='volume-tablespoon',
|
||||||
|
cubic_yard='volume-cubic-yard',
|
||||||
|
square_foot='area-square-foot',
|
||||||
|
tebibyte='digital-terabyte',
|
||||||
|
square_inch='area-square-inch',
|
||||||
|
carat='mass-carat',
|
||||||
|
hectopascal='pressure-hectopascal',
|
||||||
|
gigawatt='power-gigawatt',
|
||||||
|
watt='power-watt',
|
||||||
|
micrometer='length-micrometer',
|
||||||
|
volt='electric-volt',
|
||||||
|
bit='digital-bit',
|
||||||
|
gigahertz='frequency-gigahertz',
|
||||||
|
teaspoon='volume-teaspoon',
|
||||||
|
ohm='electric-ohm',
|
||||||
|
joule='energy-joule',
|
||||||
|
cup='volume-cup',
|
||||||
|
square_mile='area-square-mile',
|
||||||
|
nautical_mile='length-nautical-mile',
|
||||||
|
square_meter='area-square-meter',
|
||||||
|
mile='length-mile',
|
||||||
|
acre='area-acre',
|
||||||
|
nanometer='length-nanometer',
|
||||||
|
hour='duration-hour',
|
||||||
|
astronomical_unit='length-astronomical-unit',
|
||||||
|
liter_per_100kilometers ='consumption-liter-per-100kilometers',
|
||||||
|
megaliter='volume-megaliter',
|
||||||
|
ton='mass-ton',
|
||||||
|
hectare='area-hectare',
|
||||||
|
square_kilometer='area-square-kilometer',
|
||||||
|
kibibit='digital-kilobit',
|
||||||
|
mile_scandinavian='length-mile-scandinavian',
|
||||||
|
liter_per_kilometer='consumption-liter-per-kilometer',
|
||||||
|
century='duration-century',
|
||||||
|
cubic_foot='volume-cubic-foot',
|
||||||
|
deciliter='volume-deciliter',
|
||||||
|
##pint='volume-pint-metric',
|
||||||
|
cubic_meter='volume-cubic-meter',
|
||||||
|
cubic_kilometer='volume-cubic-kilometer',
|
||||||
|
quart='volume-quart',
|
||||||
|
cc='volume-cubic-centimeter',
|
||||||
|
pound_force_per_square_inch='pressure-pound-per-square-inch',
|
||||||
|
milligram='mass-milligram',
|
||||||
|
kph='speed-kilometer-per-hour',
|
||||||
|
minute='duration-minute',
|
||||||
|
parsec='length-parsec',
|
||||||
|
picometer='length-picometer',
|
||||||
|
degree='angle-degree',
|
||||||
|
milliwatt='power-milliwatt',
|
||||||
|
week='duration-week',
|
||||||
|
ampere='electric-ampere',
|
||||||
|
milliliter='volume-milliliter',
|
||||||
|
decimeter='length-decimeter',
|
||||||
|
fluid_ounce='volume-fluid-ounce',
|
||||||
|
nanosecond='duration-nanosecond',
|
||||||
|
foot='length-foot',
|
||||||
|
karat='proportion-karat',
|
||||||
|
year='duration-year',
|
||||||
|
gallon='volume-gallon',
|
||||||
|
radian='angle-radian',
|
||||||
|
)
|
||||||
|
|
||||||
|
if not HAS_PROPER_BABEL:
|
||||||
|
_babel_units = dict()
|
||||||
|
|
||||||
|
_babel_systems = dict(
|
||||||
|
mks='metric',
|
||||||
|
imperial='uksystem',
|
||||||
|
US='ussystem',
|
||||||
|
)
|
||||||
|
|
||||||
|
_babel_lengths = ['narrow', 'short', 'long']
|
||||||
|
|
||||||
@@ -118,3 +118,13 @@ except ImportError:
|
|||||||
ufloat = None
|
ufloat = None
|
||||||
HAS_UNCERTAINTIES = False
|
HAS_UNCERTAINTIES = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
from babel import Locale as Loc
|
||||||
|
from babel import units as babel_units
|
||||||
|
HAS_BABEL = True
|
||||||
|
HAS_PROPER_BABEL = hasattr(babel_units, 'format_unit')
|
||||||
|
except ImportError:
|
||||||
|
HAS_PROPER_BABEL = HAS_BABEL = False
|
||||||
|
|
||||||
|
if not HAS_PROPER_BABEL:
|
||||||
|
Loc = babel_units = None
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ from __future__ import division, unicode_literals, print_function, absolute_impo
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from .babel_names import _babel_units, _babel_lengths
|
||||||
|
from pint.compat import babel_units, Loc
|
||||||
|
|
||||||
__JOIN_REG_EXP = re.compile("\{\d*\}")
|
__JOIN_REG_EXP = re.compile("\{\d*\}")
|
||||||
|
|
||||||
|
|
||||||
@@ -100,7 +103,8 @@ _FORMATS = {
|
|||||||
|
|
||||||
def formatter(items, as_ratio=True, single_denominator=False,
|
def formatter(items, as_ratio=True, single_denominator=False,
|
||||||
product_fmt=' * ', division_fmt=' / ', power_fmt='{0} ** {1}',
|
product_fmt=' * ', division_fmt=' / ', power_fmt='{0} ** {1}',
|
||||||
parentheses_fmt='({0})', exp_call=lambda x: '{0:n}'.format(x)):
|
parentheses_fmt='({0})', exp_call=lambda x: '{0:n}'.format(x),
|
||||||
|
locale=None, babel_length='long', babel_plural_form='one'):
|
||||||
"""Format a list of (name, exponent) pairs.
|
"""Format a list of (name, exponent) pairs.
|
||||||
|
|
||||||
:param items: a list of (name, exponent) pairs.
|
:param items: a list of (name, exponent) pairs.
|
||||||
@@ -111,6 +115,9 @@ def formatter(items, as_ratio=True, single_denominator=False,
|
|||||||
:param division_fmt: the format used for division.
|
:param division_fmt: the format used for division.
|
||||||
:param power_fmt: the format used for exponentiation.
|
:param power_fmt: the format used for exponentiation.
|
||||||
:param parentheses_fmt: the format used for parenthesis.
|
:param parentheses_fmt: the format used for parenthesis.
|
||||||
|
:param locale: the locale object as defined in babel.
|
||||||
|
:param babel_length: the length of the translated unit, as defined in babel cldr.
|
||||||
|
:param babel_plural_form: the plural form, calculated as defined in babel.
|
||||||
|
|
||||||
:return: the formula as a string.
|
:return: the formula as a string.
|
||||||
"""
|
"""
|
||||||
@@ -126,6 +133,28 @@ def formatter(items, as_ratio=True, single_denominator=False,
|
|||||||
pos_terms, neg_terms = [], []
|
pos_terms, neg_terms = [], []
|
||||||
|
|
||||||
for key, value in sorted(items):
|
for key, value in sorted(items):
|
||||||
|
if locale and babel_length and babel_plural_form and key in _babel_units:
|
||||||
|
_key = _babel_units[key]
|
||||||
|
locale = Loc.parse(locale)
|
||||||
|
unit_patterns = locale._data['unit_patterns']
|
||||||
|
compound_unit_patterns = locale._data["compound_unit_patterns"]
|
||||||
|
plural = 'one' if abs(value) <= 0 else babel_plural_form
|
||||||
|
if babel_length not in _babel_lengths:
|
||||||
|
other_lengths = [
|
||||||
|
_babel_length for _babel_length in reversed(_babel_lengths) \
|
||||||
|
if babel_length != _babel_length
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
other_lengths = []
|
||||||
|
for _babel_length in [babel_length] + other_lengths:
|
||||||
|
pat = unit_patterns.get(_key, {}).get(_babel_length, {}).get(plural)
|
||||||
|
print(plural, _babel_length, pat)
|
||||||
|
if pat is not None:
|
||||||
|
key = pat.replace('{0}', '').strip()
|
||||||
|
break
|
||||||
|
division_fmt = compound_unit_patterns.get("per", {}).get(babel_length, division_fmt)
|
||||||
|
power_fmt = '{0}{1}'
|
||||||
|
exp_call = _pretty_fmt_exponent
|
||||||
if value == 1:
|
if value == 1:
|
||||||
pos_terms.append(key)
|
pos_terms.append(key)
|
||||||
elif value > 0:
|
elif value > 0:
|
||||||
@@ -177,12 +206,13 @@ def _parse_spec(spec):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def format_unit(unit, spec):
|
def format_unit(unit, spec, **kwspec):
|
||||||
if not unit:
|
if not unit:
|
||||||
return 'dimensionless'
|
return 'dimensionless'
|
||||||
|
|
||||||
spec = _parse_spec(spec)
|
spec = _parse_spec(spec)
|
||||||
fmt = _FORMATS[spec]
|
fmt = dict(_FORMATS[spec])
|
||||||
|
fmt.update(kwspec)
|
||||||
|
|
||||||
if spec == 'L':
|
if spec == 'L':
|
||||||
rm = [(r'\mathrm{{{0}}}'.format(u), p) for u, p in unit.items()]
|
rm = [(r'\mathrm{{{0}}}'.format(u), p) for u, p in unit.items()]
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from .compat import string_types, ndarray, np, _to_magnitude, long_type
|
|||||||
from .util import (logger, UnitsContainer, SharedRegistryObject,
|
from .util import (logger, UnitsContainer, SharedRegistryObject,
|
||||||
to_units_container, infer_base_unit,
|
to_units_container, infer_base_unit,
|
||||||
fix_str_conversions)
|
fix_str_conversions)
|
||||||
|
from pint.compat import Loc
|
||||||
|
|
||||||
|
|
||||||
def _eq(first, second, check_all):
|
def _eq(first, second, check_all):
|
||||||
@@ -171,6 +172,24 @@ class _Quantity(SharedRegistryObject):
|
|||||||
ustr = ustr[2:]
|
ustr = ustr[2:]
|
||||||
return allf.format(mstr, ustr).strip()
|
return allf.format(mstr, ustr).strip()
|
||||||
|
|
||||||
|
def format_babel(self, spec='', **kwspec):
|
||||||
|
spec = spec or self.default_format
|
||||||
|
|
||||||
|
# standard cases
|
||||||
|
if '#' in spec:
|
||||||
|
spec = spec.replace('#', '')
|
||||||
|
obj = self.to_compact()
|
||||||
|
else:
|
||||||
|
obj = self
|
||||||
|
kwspec = dict(kwspec)
|
||||||
|
if 'length' in kwspec:
|
||||||
|
kwspec['babel_length'] = kwspec.pop('length')
|
||||||
|
kwspec['locale'] = Loc.parse(kwspec['locale'])
|
||||||
|
kwspec['babel_plural_form'] = kwspec['locale'].plural_form(obj.magnitude)
|
||||||
|
return '{0} {1}'.format(
|
||||||
|
format(obj.magnitude, remove_custom_flags(spec)),
|
||||||
|
obj.units.format_babel(spec, **kwspec)).replace('\n', '')
|
||||||
|
|
||||||
# IPython related code
|
# IPython related code
|
||||||
def _repr_html_(self):
|
def _repr_html_(self):
|
||||||
return self.__format__('H')
|
return self.__format__('H')
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import re
|
|||||||
from .definitions import Definition, UnitDefinition
|
from .definitions import Definition, UnitDefinition
|
||||||
from .errors import DefinitionSyntaxError, RedefinitionError
|
from .errors import DefinitionSyntaxError, RedefinitionError
|
||||||
from .util import to_units_container, SharedRegistryObject, SourceIterator
|
from .util import to_units_container, SharedRegistryObject, SourceIterator
|
||||||
|
from .babel_names import _babel_systems
|
||||||
|
from pint.compat import Loc
|
||||||
|
|
||||||
|
|
||||||
class _Group(SharedRegistryObject):
|
class _Group(SharedRegistryObject):
|
||||||
@@ -336,6 +338,17 @@ class _System(SharedRegistryObject):
|
|||||||
|
|
||||||
self.invalidate_members()
|
self.invalidate_members()
|
||||||
|
|
||||||
|
def format_babel(self, locale):
|
||||||
|
"""translate the name of the system
|
||||||
|
|
||||||
|
:type locale: Locale
|
||||||
|
"""
|
||||||
|
if locale and self.name in _babel_systems:
|
||||||
|
name = _babel_systems[self.name]
|
||||||
|
locale = Loc.parse(locale)
|
||||||
|
return locale.measurement_systems[name]
|
||||||
|
return self.name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_lines(cls, lines, get_root_func):
|
def from_lines(cls, lines, get_root_func):
|
||||||
lines = SourceIterator(lines)
|
lines = SourceIterator(lines)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import doctest
|
|||||||
from distutils.version import StrictVersion
|
from distutils.version import StrictVersion
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from pint.compat import HAS_NUMPY, HAS_UNCERTAINTIES, NUMPY_VER, PYTHON3
|
from pint.compat import HAS_NUMPY, HAS_PROPER_BABEL, HAS_UNCERTAINTIES, NUMPY_VER, PYTHON3
|
||||||
from pint.testsuite.compat import unittest
|
from pint.testsuite.compat import unittest
|
||||||
|
|
||||||
|
|
||||||
@@ -31,6 +31,10 @@ def requires_not_numpy():
|
|||||||
return unittest.skipIf(HAS_NUMPY, 'Requires NumPy is not installed.')
|
return unittest.skipIf(HAS_NUMPY, 'Requires NumPy is not installed.')
|
||||||
|
|
||||||
|
|
||||||
|
def requires_proper_babel():
|
||||||
|
return unittest.skipUnless(HAS_PROPER_BABEL, 'Requires Babel with units support')
|
||||||
|
|
||||||
|
|
||||||
def requires_uncertainties():
|
def requires_uncertainties():
|
||||||
return unittest.skipUnless(HAS_UNCERTAINTIES, 'Requires Uncertainties')
|
return unittest.skipUnless(HAS_UNCERTAINTIES, 'Requires Uncertainties')
|
||||||
|
|
||||||
|
|||||||
39
pint/testsuite/test_babel.py
Normal file
39
pint/testsuite/test_babel.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import division, unicode_literals, print_function, absolute_import
|
||||||
|
|
||||||
|
from pint.testsuite import helpers, BaseTestCase
|
||||||
|
from pint import UnitRegistry
|
||||||
|
import os
|
||||||
|
|
||||||
|
class TestBabel(BaseTestCase):
|
||||||
|
|
||||||
|
@helpers.requires_proper_babel()
|
||||||
|
def test_babel(self):
|
||||||
|
ureg = UnitRegistry()
|
||||||
|
dirname = os.path.dirname(__file__)
|
||||||
|
ureg.load_definitions(os.path.join(dirname, '../xtranslated.txt'))
|
||||||
|
|
||||||
|
distance = 24.0 * ureg.meter
|
||||||
|
self.assertEqual(
|
||||||
|
distance.format_babel(locale='fr_FR', length='long'),
|
||||||
|
"24.0 mètres"
|
||||||
|
)
|
||||||
|
time = 8.0 * ureg.second
|
||||||
|
self.assertEqual(
|
||||||
|
time.format_babel(locale='fr_FR', length='long'),
|
||||||
|
"8.0 secondes"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
time.format_babel(locale='ro', length='short'),
|
||||||
|
"8.0 s"
|
||||||
|
)
|
||||||
|
acceleration = distance / time ** 2
|
||||||
|
self.assertEqual(
|
||||||
|
acceleration.format_babel(locale='fr_FR', length='long'),
|
||||||
|
"0.375 mètre par seconde²"
|
||||||
|
)
|
||||||
|
mks = ureg.get_system('mks')
|
||||||
|
self.assertEqual(
|
||||||
|
mks.format_babel(locale='fr_FR'),
|
||||||
|
"métrique"
|
||||||
|
)
|
||||||
15
pint/unit.py
15
pint/unit.py
@@ -95,6 +95,21 @@ class _Unit(SharedRegistryObject):
|
|||||||
|
|
||||||
return '%s' % (format(units, spec))
|
return '%s' % (format(units, spec))
|
||||||
|
|
||||||
|
def format_babel(self, spec='', **kwspec):
|
||||||
|
spec = spec or self.default_format
|
||||||
|
|
||||||
|
if '~' in spec:
|
||||||
|
if self.dimensionless:
|
||||||
|
return ''
|
||||||
|
units = UnitsContainer(dict((self._REGISTRY._get_symbol(key),
|
||||||
|
value)
|
||||||
|
for key, value in self._units.items()))
|
||||||
|
spec = spec.replace('~', '')
|
||||||
|
else:
|
||||||
|
units = self._units
|
||||||
|
|
||||||
|
return '%s' % (units.format_babel(spec, **kwspec))
|
||||||
|
|
||||||
# IPython related code
|
# IPython related code
|
||||||
def _repr_html_(self):
|
def _repr_html_(self):
|
||||||
return self.__format__('H')
|
return self.__format__('H')
|
||||||
|
|||||||
@@ -327,6 +327,9 @@ class UnitsContainer(Mapping):
|
|||||||
def __format__(self, spec):
|
def __format__(self, spec):
|
||||||
return format_unit(self, spec)
|
return format_unit(self, spec)
|
||||||
|
|
||||||
|
def format_babel(self, spec, **kwspec):
|
||||||
|
return format_unit(self, spec, **kwspec)
|
||||||
|
|
||||||
def __copy__(self):
|
def __copy__(self):
|
||||||
return UnitsContainer(self._d)
|
return UnitsContainer(self._d)
|
||||||
|
|
||||||
|
|||||||
26
pint/xtranslated.txt
Normal file
26
pint/xtranslated.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
# a few unit definitions added to use the translations by unicode cldr
|
||||||
|
|
||||||
|
dietary_calorie = 1000 * calorie = Calorie
|
||||||
|
metric_cup = liter / 4
|
||||||
|
mps = meter / second
|
||||||
|
square_inch = inch ** 2 = sq_in
|
||||||
|
square_mile = mile ** 2 = sq_mile
|
||||||
|
square_meter = kilometer ** 2 = sq_m
|
||||||
|
square_kilometer = kilometer ** 2 = sq_km
|
||||||
|
mile_scandinavian = 10000 * meter
|
||||||
|
century = 100 * year
|
||||||
|
cubic_mile = 1 * mile ** 3 = cu_mile = cubic_miles
|
||||||
|
cubic_yard = 1 * yard ** 3 = cu_yd = cubic_yards
|
||||||
|
cubic_foot = 1 * foot ** 3 = cu_ft = cubic_feet
|
||||||
|
cubic_inch = 1 * inch ** 3 = cu_in = cubic_inches
|
||||||
|
cubic_meter = 1 * meter ** 3 = cu_m
|
||||||
|
cubic_kilometer = 1 * kilometer ** 3 = cu_km
|
||||||
|
karat = [purity] = Karat
|
||||||
|
|
||||||
|
[consumption] = [volume] / [length]
|
||||||
|
liter_per_kilometer = liter / kilometer
|
||||||
|
liter_per_100kilometers = liter / (100 * kilometers)
|
||||||
|
|
||||||
|
[US_consumption] = [length] / [volume]
|
||||||
|
MPG = mile / gallon
|
||||||
Reference in New Issue
Block a user