Repository: pywemo/pywemo (language: python)

Issue:
ModuleNotFoundError: No Module named six
Hi!

I'm trying to use pywemo for a little project of mine, I'm running into an error with`import pywemo`.

to minimally reproduce the error:

```
mkdir six_error_example
cd six_error_example
python -m venv env
source env/bin/activate
pip install pywemo
python -c "import pywemo"
```
this spits out the following error:
```
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/dan/src/six_error_example/env/lib/python3.9/site-packages/pywemo/__init__.py", line 4, in <module>
    from .discovery import discover_devices, setup_url_for_address
  File "/Users/dan/src/six_error_example/env/lib/python3.9/site-packages/pywemo/discovery.py", line 10, in <module>
    from . import ssdp
  File "/Users/dan/src/six_error_example/env/lib/python3.9/site-packages/pywemo/ssdp.py", line 12, in <module>
    from .ouimeaux_device.api.long_press import VIRTUAL_DEVICE_UDN
  File "/Users/dan/src/six_error_example/env/lib/python3.9/site-packages/pywemo/ouimeaux_device/__init__.py", line 23, in <module>
    from .api.long_press import LongPressMixin
  File "/Users/dan/src/six_error_example/env/lib/python3.9/site-packages/pywemo/ouimeaux_device/api/long_press.py", line 15, in <module>
    from .service import RequiredService, RequiredServicesMixin
  File "/Users/dan/src/six_error_example/env/lib/python3.9/site-packages/pywemo/ouimeaux_device/api/service.py", line 23, in <module>
    from .xsd import service as serviceParser
  File "/Users/dan/src/six_error_example/env/lib/python3.9/site-packages/pywemo/ouimeaux_device/api/xsd/service.py", line 26, in <module>
    from six.moves import zip_longest
ModuleNotFoundError: No module named 'six'
```

it looks like it's trying to import the `six` library [on this line](https://github.com/pywemo/pywemo/blob/0ad58a9e7874d05787e3615f922f18ee38b7f919/pywemo/ouimeaux_device/api/xsd/service.py#L26).

doing a `pip freeze` shows that six isn't installed:
```
(env) ➜  six_error_example pip freeze
certifi==2021.10.8
charset-normalizer==2.0.11
idna==3.3
ifaddr==0.1.7
lxml==4.7.1
pywemo==0.7.0
requests==2.27.1
urllib3==1.26.8
```

I do see `six` in some of the entries in `poetry.lock`. I'm still learning how poetry projects work (I'm using it in the little project of mine), but it seems like `six` ought to be in the pip freeze output if some of the underlying libraries need it.

Let me know if you need anything more info from me!


Discussion / hints:
Thanks for reporting!

I agree with you. `six` should either be in our [direct dependencies](https://github.com/pywemo/pywemo/blob/0ad58a9e7874d05787e3615f922f18ee38b7f919/pyproject.toml#L19) so that pip installs it, or we should look into removing it from the code. I'll try to have a fix tonight.

Fix patch:
diff --git a/pywemo/ouimeaux_device/api/xsd/device.py b/pywemo/ouimeaux_device/api/xsd/device.py
index 619521d8..b4b99ae5 100644
--- a/pywemo/ouimeaux_device/api/xsd/device.py
+++ b/pywemo/ouimeaux_device/api/xsd/device.py
@@ -23,7 +23,7 @@
     ModulenotfoundExp_ = ModuleNotFoundError
 except NameError:
     ModulenotfoundExp_ = ImportError
-from six.moves import zip_longest
+from itertools import zip_longest
 import os
 import re as re_
 import base64
diff --git a/pywemo/ouimeaux_device/api/xsd/service.py b/pywemo/ouimeaux_device/api/xsd/service.py
index 8d2d87ec..1ecf0a15 100644
--- a/pywemo/ouimeaux_device/api/xsd/service.py
+++ b/pywemo/ouimeaux_device/api/xsd/service.py
@@ -23,7 +23,7 @@
     ModulenotfoundExp_ = ModuleNotFoundError
 except NameError:
     ModulenotfoundExp_ = ImportError
-from six.moves import zip_longest
+from itertools import zip_longest
 import os
 import re as re_
 import base64


Test patch:
diff --git a/tests/ouimeaux_device/api/unit/test_xsd_types.py b/tests/ouimeaux_device/api/unit/test_xsd_types.py
index c3b54fb1..1197e32e 100644
--- a/tests/ouimeaux_device/api/unit/test_xsd_types.py
+++ b/tests/ouimeaux_device/api/unit/test_xsd_types.py
@@ -1,5 +1,6 @@
 """Tests for interfacing with the generated XSD classes."""
 
+import ast
 import unittest.mock as mock
 
 import pytest
@@ -230,3 +231,22 @@ def test_device_parser_raises():
     ):
         mock_parser.parseString.side_effect = Exception
         xsd_types.DeviceDescription.from_xml(b'')
+
+
+def test_no_six_import():
+    # device.py & service.py were manually edited to remove the dependency on
+    # 'six' for https://github.com/pywemo/pywemo/issues/344. Ensure this
+    # dependency is not added again next time these files are re-generated.
+    with open("pywemo/ouimeaux_device/api/xsd/device.py") as device_py:
+        device_ast = ast.parse(device_py.read())
+    import_modules = [
+        e.module for e in device_ast.body if isinstance(e, ast.ImportFrom)
+    ]
+    assert 'six.moves' not in import_modules
+
+    with open("pywemo/ouimeaux_device/api/xsd/service.py") as service_py:
+        service_ast = ast.parse(service_py.read())
+    import_modules = [
+        e.module for e in service_ast.body if isinstance(e, ast.ImportFrom)
+    ]
+    assert 'six.moves' not in import_modules