Repository: ansible/ansible

Issue:
ansible-doc does not work with -M/--module-path anymore
It prints "ERROR! Unexpected Exception, this is probably a bug: 'list' object has no attribute 'split'" when used with `-M` option.

ansible-console behaves similarly..

Looks like it is broken since this change, when options.module_path became a list: https://github.com/ansible/ansible/commit/2165bac212ec916e906f6b3aa5ed845a7bfa8da4#diff-bdd6c847fae8976ab8a7259d0b583f34R427

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
cli/doc, cli/console
##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.0 (devel 02cd881697) last updated 2017/10/14 21:11:59 (GMT +200)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/user/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/user/ansible/ansible/lib/ansible
  executable location = /home/user/.virtualenvs/ansible/bin/ansible
  python version = 2.7.9 (default, Jun 29 2016, 13:08:31) [GCC 4.9.2]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"

Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).

-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->

##### SUMMARY
`ansible-doc --module-path some_path some_module` reports `ERROR! Unexpected Exception, this is probably a bug: 'list' object has no attribute 'split'`
##### STEPS TO REPRODUCE
ansible-doc -M . raw -s -vvv 

##### EXPECTED RESULTS
```
- name: Executes a low-down and dirty SSH command
  raw:
      executable:            # change the shell used to execute the command. Should be an absolute path to the executable. when using privilege escalation (`become'), a default shell will be
                               assigned if one is not provided as privilege escalation requires a shell.
      free_form:             # (required) the raw module takes a free form command to run. There is no parameter actually named 'free form'; see the examples!
```
##### ACTUAL RESULTS
```
ERROR! Unexpected Exception, this is probably a bug: 'list' object has no attribute 'split'
the full traceback was:

Traceback (most recent call last):
  File "/home/user/ansible/ansible/bin/ansible-doc", line 109, in <module>
    exit_code = cli.run()
  File "/home/user/ansible/ansible/lib/ansible/cli/doc.py", line 107, in run
    for i in self.options.module_path.split(os.pathsep):
AttributeError: 'list' object has no attribute 'split'
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/cli/console.py b/lib/ansible/cli/console.py
--- a/lib/ansible/cli/console.py
+++ b/lib/ansible/cli/console.py
@@ -126,9 +126,10 @@ def set_prompt(self):
 
     def list_modules(self):
         modules = set()
-        if self.options.module_path is not None:
-            for i in self.options.module_path.split(os.pathsep):
-                module_loader.add_directory(i)
+        if self.options.module_path:
+            for path in self.options.module_path:
+                if path:
+                    module_loader.add_directory(path)
 
         module_paths = module_loader._get_paths()
         for path in module_paths:
diff --git a/lib/ansible/cli/doc.py b/lib/ansible/cli/doc.py
--- a/lib/ansible/cli/doc.py
+++ b/lib/ansible/cli/doc.py
@@ -103,9 +103,10 @@ def run(self):
             loader = module_loader
 
         # add to plugin path from command line
-        if self.options.module_path is not None:
-            for i in self.options.module_path.split(os.pathsep):
-                loader.add_directory(i)
+        if self.options.module_path:
+            for path in self.options.module_path:
+                if path:
+                    loader.add_directory(path)
 
         # save only top level paths for errors
         search_paths = DocCLI.print_paths(loader)


Test patch: