Repository: hgrecco/pint

Issue:
dir() mixes units with methods - implement __iter__ instead?
If I explore the directory the `UnitRegistry` with `dir(unit_registry)`, the result displays methods and attributes mixed in with actual choices of units - for example `parse_units` appears right next to `parsec`.

`__dir__` is conventionally used for methods and attributes: might it make for a cleaner interface to separate theses two distinct features of the class? 

I see that you need a way to list all the units easily, but I also notice `UnitRegistry` doesn't define an `__iter__` method. If `__iter__` returned the unit keys then you could instead list all the units with `list(unit_registry)`, which IMO would be a very intuitive syntax. You could of course then loop over units too for free. That would leave `__dir__` available to list just the actual class methods and attributes, which would make interactive exploration of the class structure easier.

Just a thought anyway.

Discussion:

Patch:
diff --git a/AUTHORS b/AUTHORS
index db3229e..2f51bae 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -43,6 +43,7 @@ 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 27a6c38..75e264d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -23,6 +23,9 @@ 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)
+- 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/pint/registry.py b/pint/registry.py
index a622a2d..5e1e0fa 100644
--- a/pint/registry.py
+++ b/pint/registry.py
@@ -177,26 +177,6 @@ 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="",
@@ -310,7 +290,18 @@ class BaseRegistry(metaclass=RegistryMeta):
         return self.parse_expression(item)
 
     def __dir__(self):
-        return list(self._units.keys()) + self._dir
+        #: 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()))
 
     def set_fmt_locale(self, loc):
         """Change the locale used by default by `format_babel`.


Test patch:
diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py
index d7eb649..76082c9 100644
--- a/pint/testsuite/test_unit.py
+++ b/pint/testsuite/test_unit.py
@@ -240,6 +240,10 @@ 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)