Repository: hgrecco/pint

Issue:
Problem with Setuptools
Hello guys, I have found a problem with setuptools.

In File quantity.py I needed to replace:
`from pkg_resources.extern.packaging import version`

with
`# from packaging import version`

I think pkg_resources.extern is no longer provided by setuptools.
This is the first time I am writing something on Github, maybe you can point me to
a resource or tell me what to do in case I find such bugs in open sources projects.

Discussion:

Patch:
diff --git a/AUTHORS b/AUTHORS
index 2f51bae..db3229e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -43,7 +43,6 @@ Other contributors, listed alphabetically, are:
 * Sundar Raman <cybertoast@gmail.com>
 * Tiago Coutinho <coutinho@esrf.fr>
 * Thomas Kluyver <takowl@gmail.com>
-* Tom Nicholas <tomnicholas1@gmail.com>
 * Tom Ritchford <tom@swirly.com>
 * Virgil Dupras <virgil.dupras@savoirfairelinux.com>
 * Zebedee Nicholls <zebedee.nicholls@climate-energy-college.org>
diff --git a/CHANGES b/CHANGES
index cfb9007..27a6c38 100644
--- a/CHANGES
+++ b/CHANGES
@@ -23,16 +23,6 @@ Pint Changelog
   when using to_compact()
 - Fixed crash when a Unit with prefix is declared for the first time while a Context
   containing unit redefinitions is active (Issue #1062, Thanks Guido Imperiale)
-- New implementation of 'Lx' String Format Type Option
-  The old implementation treated 'Lx' as 'S' as produced by 'uncertainties'
-  package, but that is not fully compatible with SIunitx. The new code protects
-  SIunitx by fixing what unceratinties produces.
-  (Issue #814)
-- Added link to budding `pint-xarray` interface library to the docs, next to
-  the link to pint-pandas. (Thanks Tom Nicholas.)
-- Removed outdated `_dir` attribute of `UnitsRegistry`, and added `__iter__`
-  method so that now `list(ureg)` returns a list of all units in registry.
-  (Issue #1072, Thanks Tom Nicholas)
 
 
 0.11 (2020-02-19)
diff --git a/docs/numpy.ipynb b/docs/numpy.ipynb
index c3e8fc9..7038eef 100644
--- a/docs/numpy.ipynb
+++ b/docs/numpy.ipynb
@@ -423,7 +423,7 @@
     "To aid in integration between various array types and Pint (such as by providing convenience methods), the following compatibility packages are available:\n",
     "\n",
     "- [pint-pandas](https://github.com/hgrecco/pint-pandas)\n",
-    "- [pint-xarray](https://github.com/TomNicholas/pint-xarray/) (in early development as of April 2020, with [extra discussion here](https://github.com/hgrecco/pint/issues/849#issuecomment-579992247) - please come and help!)\n",
+    "- pint-xarray ([in development](https://github.com/hgrecco/pint/issues/849), initial alpha release planned for April-May 2020)\n",
     "\n",
     "(Note: if you have developed a compatibility package for Pint, please submit a pull request to add it to this list!)"
    ]
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
index 474fa2a..cc8d0e7 100644
--- a/docs/tutorial.rst
+++ b/docs/tutorial.rst
@@ -389,7 +389,7 @@ The same is true for latex (`L`) and HTML (`H`) specs.
 The formatting specs (ie 'L', 'H', 'P') can be used with Python string 'formatting
 syntax'_ for custom float representations. For example, scientific notation:
 
-.. doctest::
+..doctest::
    >>> 'Scientific notation: {:.3e~L}'.format(accel)
    'Scientific notation: 1.300\\times 10^{0}\\ \\frac{\\mathrm{m}}{\\mathrm{s}^{2}}'
 
@@ -400,10 +400,7 @@ Pint also supports the LaTeX siunitx package:
    >>> 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}
-   >>> accel = accel.plus_minus(0.2)
-   >>> print('The siunitx representation is {:Lx}'.format(accel))
-   The siunitx representation is \SI{1.3 +- 0.2}{\meter\per\second\squared}
+   The siunitx representation is \SI[]{1.3}{\meter\per\second\squared}
 
 Additionally, you can specify a default format specification:
 
diff --git a/pint/formatting.py b/pint/formatting.py
index 4eae5cd..0e84f82 100644
--- a/pint/formatting.py
+++ b/pint/formatting.py
@@ -89,7 +89,6 @@ _FORMATS = {
         "power_fmt": "{}^[{}]",
         "parentheses_fmt": r"\left({}\right)",
     },
-    "Lx": {"siopts": "", "pm_fmt": " +- "},  # Latex format with SIunitx.
     "H": {  # HTML format.
         "as_ratio": True,
         "single_denominator": True,
diff --git a/pint/measurement.py b/pint/measurement.py
index dd0f592..c6d99f6 100644
--- a/pint/measurement.py
+++ b/pint/measurement.py
@@ -89,33 +89,14 @@ class Measurement(Quantity):
         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),
-            # using type code 'S', which siunitx actually accepts as input.
-            # However, the implimentation is incompatible with siunitx.
-            # Uncertainties will do 9.1(1.1), which is invalid, should be 9.1(11).
-            # TODO: add support for extracting options
-            #
-            # Get rid of this code, we'll deal with it here
-            spec = spec.replace("Lx", "")
-            # The most compatible format from uncertainties is the default format,
-            # but even this requires fixups.
-            # For one, SIUnitx does not except some formats that unc does, like 'P',
-            # and 'S' is broken as stated, so...
-            spec = spec.replace("S", "").replace("P", "")
-            # get SIunitx options
-            # TODO: allow user to set this value, somehow
-            opts = _FORMATS["Lx"]["siopts"]
-            if opts != "":
-                opts = r"[" + opts + r"]"
-            # SI requires space between "+-" (or "\pm") and the nominal value
-            # and uncertainty, and doesn't accept "+/-", so this setting
-            # selects the desired replacement.
-            pm_fmt = _FORMATS["Lx"]["pm_fmt"]
-            mstr = format(self.magnitude, spec).replace(r"+/-", pm_fmt)
-            # Also, SIunitx doesn't accept parentheses, which uncs uses with
-            # scientific notation ('e' or 'E' and somtimes 'g' or 'G').
-            mstr = mstr.replace("(", "").replace(")", " ")
+            # 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)
-            return r"\SI%s{%s}{%s}" % (opts, mstr, ustr)
+            return r"\SI[%s]{%s}{%s}" % (opts, mstr, ustr)
 
         # standard cases
         if "L" in spec:
diff --git a/pint/quantity.py b/pint/quantity.py
index c1ade31..c087b0c 100644
--- a/pint/quantity.py
+++ b/pint/quantity.py
@@ -19,7 +19,7 @@ import re
 import warnings
 from typing import List
 
-from pkg_resources.extern.packaging import version
+from packaging import version
 
 from .compat import (
     NUMPY_VER,
diff --git a/pint/registry.py b/pint/registry.py
index 5e1e0fa..a622a2d 100644
--- a/pint/registry.py
+++ b/pint/registry.py
@@ -177,6 +177,26 @@ class BaseRegistry(metaclass=RegistryMeta):
     #: Babel.Locale instance or None
     fmt_locale = None
 
+    #: List to be used in addition of units when dir(registry) is called.
+    #: Also used for autocompletion in IPython.
+    _dir = [
+        "Quantity",
+        "Unit",
+        "UnitsContainer",
+        "Measurement",
+        "define",
+        "load_definitions",
+        "get_name",
+        "get_symbol",
+        "get_dimensionality",
+        "get_base_units",
+        "get_root_units",
+        "parse_unit_name",
+        "parse_units",
+        "parse_expression",
+        "convert",
+    ]
+
     def __init__(
         self,
         filename="",
@@ -290,18 +310,7 @@ class BaseRegistry(metaclass=RegistryMeta):
         return self.parse_expression(item)
 
     def __dir__(self):
-        #: Calling dir(registry) gives all units, methods, and attributes.
-        #: Also used for autocompletion in IPython.
-        return list(self._units.keys()) + list(object.__dir__(self))
-
-    def __iter__(self):
-        """Allows for listing all units in registry with `list(ureg)`.
-
-        Returns
-        -------
-        Iterator over names of all units in registry, ordered alphabetically.
-        """
-        return iter(sorted(self._units.keys()))
+        return list(self._units.keys()) + self._dir
 
     def set_fmt_locale(self, loc):
         """Change the locale used by default by `format_babel`.
diff --git a/setup.cfg b/setup.cfg
index 2777599..75781e5 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -27,7 +27,7 @@ packages = pint
 zip_safe = True
 include_package_data = True
 python_requires = >=3.6
-install_requires = setuptools
+install_requires = setuptools; packaging
 setup_requires = setuptools; setuptools_scm
 test_suite = pint.testsuite.testsuite
 scripts = pint/pint-convert


Test patch:
diff --git a/pint/testsuite/test_measurement.py b/pint/testsuite/test_measurement.py
index 871e880..8f20e9b 100644
--- a/pint/testsuite/test_measurement.py
+++ b/pint/testsuite/test_measurement.py
@@ -50,13 +50,13 @@ class TestMeasurement(QuantityTestCase):
             ("{:L}", r"\left(4.00 \pm 0.10\right)\ \mathrm{second}^{2}"),
             ("{:H}", r"\[(4.00 &plusmn; 0.10)\ second^2\]"),
             ("{:C}", "(4.00+/-0.10) second**2"),
-            ("{:Lx}", r"\SI{4.00 +- 0.10}{\second\squared}"),
+            ("{:Lx}", r"\SI[separate-uncertainty=true]{4.00(10)}{\second\squared}"),
             ("{:.1f}", "(4.0 +/- 0.1) second ** 2"),
             ("{:.1fP}", "(4.0 ± 0.1) second²"),
             ("{:.1fL}", r"\left(4.0 \pm 0.1\right)\ \mathrm{second}^{2}"),
             ("{:.1fH}", r"\[(4.0 &plusmn; 0.1)\ second^2\]"),
             ("{:.1fC}", "(4.0+/-0.1) second**2"),
-            ("{:.1fLx}", r"\SI{4.0 +- 0.1}{\second\squared}"),
+            ("{:.1fLx}", r"\SI[separate-uncertainty=true]{4.0(1)}{\second\squared}"),
         ):
             with self.subTest(spec):
                 self.assertEqual(spec.format(m), result)
@@ -86,8 +86,11 @@ class TestMeasurement(QuantityTestCase):
             ("{:.3uL}", r"\left(0.2000 \pm 0.0100\right)\ \mathrm{second}^{2}"),
             ("{:.3uH}", r"\[(0.2000 &plusmn; 0.0100)\ second^2\]"),
             ("{:.3uC}", "(0.2000+/-0.0100) second**2"),
-            ("{:.3uLx}", r"\SI{0.2000 +- 0.0100}{\second\squared}",),
-            ("{:.1uLx}", r"\SI{0.20 +- 0.01}{\second\squared}"),
+            (
+                "{:.3uLx}",
+                r"\SI[separate-uncertainty=true]{0.2000(100)}{\second\squared}",
+            ),
+            ("{:.1uLx}", r"\SI[separate-uncertainty=true]{0.20(1)}{\second\squared}"),
         ):
             with self.subTest(spec):
                 self.assertEqual(spec.format(m), result)
@@ -134,7 +137,7 @@ class TestMeasurement(QuantityTestCase):
             ("{:L}", r"\left(4.00 \pm 0.10\right) \times 10^{20}\ \mathrm{second}^{2}"),
             ("{:H}", r"\[(4.00 &plusmn; 0.10)×10^{20}\ second^2\]"),
             ("{:C}", "(4.00+/-0.10)e+20 second**2"),
-            ("{:Lx}", r"\SI{4.00 +- 0.10 e+20}{\second\squared}"),
+            ("{:Lx}", r"\SI[separate-uncertainty=true]{4.00(10)e+20}{\second\squared}"),
         ):
             with self.subTest(spec):
                 self.assertEqual(spec.format(m), result)
@@ -151,7 +154,7 @@ class TestMeasurement(QuantityTestCase):
             ),
             ("{:H}", r"\[(4.00 &plusmn; 0.10)×10^{-20}\ second^2\]"),
             ("{:C}", "(4.00+/-0.10)e-20 second**2"),
-            ("{:Lx}", r"\SI{4.00 +- 0.10 e-20}{\second\squared}"),
+            ("{:Lx}", r"\SI[separate-uncertainty=true]{4.00(10)e-20}{\second\squared}"),
         ):
             with self.subTest(spec):
                 self.assertEqual(spec.format(m), result)
diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py
index 76082c9..d7eb649 100644
--- a/pint/testsuite/test_unit.py
+++ b/pint/testsuite/test_unit.py
@@ -240,10 +240,6 @@ class TestRegistry(QuantityTestCase):
         self.assertNotEqual(s1, s3)
         self.assertEqual(ureg.default_format, "~")
 
-    def test_iterate(self):
-        ureg = UnitRegistry()
-        self.assertTrue("meter" in list(ureg))
-
     def test_parse_number(self):
         self.assertEqual(self.ureg.parse_expression("pi"), math.pi)
         self.assertEqual(self.ureg.parse_expression("x", x=2), 2)