Repository: dateutil/dateutil (Python)

Issue:
__all__ not defined on root package
Hi, I don't know if this is a problem or intentionally planed, but because of namespace conflicts, we typically import the base package and not deep into it. For example:
```
import dateutil

dateutil.parser.parse('Fri Jun 30 12:00:56 EDT 2017')
```

However this appears to fail with the error:
> AttributeError: 'module' object has no attribute 'parser'

The solution appears to be: `from dateutil import parser` and then call parser, I'm guessing this is because the `__all__` in the root `__init__.py` doesn't exist thus not listing any packages. Is this intended behavior? Should I just use my above workaround?
Thanks!


Hints:
@tebriel Yes, this is almost certainly by design. I don't think adding `__all__` would be sufficient to allow access to the submodules from `dateutil`, though, I think they would have to be actively imported in the `__init__.py`. The problem with doing this, though, is that as far as I know, if I actively import all the submodules in the parent, whenever *any* module is imported, *all* modules would need to be imported.

I tested this by adding `print('Easter imported')` into the `easter` module, then modifying the `__init__.py` as such:

```python
# -*- coding: utf-8 -*-
__version__ = "2.6.1"

__all__ = ['parser', 'easter', 'tz', 'rrule', 'relativedelta', 'zoneinfo']

try:
    import tz.win
except ImportError:
    pass

from . import parser, easter, tz, rrule, relativedelta, zoneinfo
```

Then:

```python
>>> from dateutil import parser
Easter imported
```

I would prefer to avoid this unnecessary all-or-nothing style. There may be some fancy trickery I'm not aware of that lets you have your cake and eat it too, with lazy-loaded modules, but I'm not sure that really fits in with the zen of python.

That said, it's probably worth defining an `__all__` anyway, since `__all__` by itself will let you do things like `from dateutil import *` (not that I condone such behavior).

For now, the correct thing to do is explicitly import submodules - `import dateutil.parser` or `from dateutil import parser`.
okay, that makes sense, thanks for your quick response!

Patch:
diff --git a/dateutil/__init__.py b/dateutil/__init__.py
--- a/dateutil/__init__.py
+++ b/dateutil/__init__.py
@@ -1,2 +1,5 @@
 # -*- coding: utf-8 -*-
 from ._version import VERSION as __version__
+
+__all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz',
+           'utils', 'zoneinfo']


Test patch:
diff --git a/dateutil/test/test_import_star.py b/dateutil/test/test_import_star.py
new file mode 100644
--- /dev/null
+++ b/dateutil/test/test_import_star.py
@@ -0,0 +1,33 @@
+"""Test for the "import *" functionality.
+
+As imort * can be only done at module level, it has been added in a separate file
+"""
+import unittest
+
+prev_locals = list(locals())
+from dateutil import *
+new_locals = {name:value for name,value in locals().items()
+              if name not in prev_locals}
+new_locals.pop('prev_locals')
+
+class ImportStarTest(unittest.TestCase):
+    """ Test that `from dateutil import *` adds the modules in __all__ locally"""
+
+    def testImportedModules(self):
+        import dateutil.easter
+        import dateutil.parser
+        import dateutil.relativedelta
+        import dateutil.rrule
+        import dateutil.tz
+        import dateutil.utils
+        import dateutil.zoneinfo
+
+        self.assertEquals(dateutil.easter, new_locals.pop("easter"))
+        self.assertEquals(dateutil.parser, new_locals.pop("parser"))
+        self.assertEquals(dateutil.relativedelta, new_locals.pop("relativedelta"))
+        self.assertEquals(dateutil.rrule, new_locals.pop("rrule"))
+        self.assertEquals(dateutil.tz, new_locals.pop("tz"))
+        self.assertEquals(dateutil.utils, new_locals.pop("utils"))
+        self.assertEquals(dateutil.zoneinfo, new_locals.pop("zoneinfo"))
+
+        self.assertFalse(new_locals)