We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
bower_module thrown an error if bower_components dir already exists
I run next task in my playbook:

``` yaml
    - name: install bower vendor dependencies
      bower: path="/path/to/project" state=latest
```

And if `bower_components` dir not exists in `/path/to/project`, it download all dependencies and works fine, but if I run this task again, I get a next error:

```
< TASK: install bower vendor dependencies >
<transformation.server.ndv.net.ua> ESTABLISH CONNECTION FOR USER: srvadmin
<transformation.server.ndv.net.ua> REMOTE_MODULE bower path="/var/www/sites/transformation/web" state=latest
<transformation.server.ndv.net.ua> EXEC ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath="/home/victor/.ansible/cp/ansible-ssh-%h-%p-%r" -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=srvadmin -o ConnectTimeout=10 transformation.server.ndv.net.ua /bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340 && chmod a+rx $HOME/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340 && echo $HOME/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340'
<transformation.server.ndv.net.ua> PUT /tmp/tmpjZzhjm TO /home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower
<transformation.server.ndv.net.ua> EXEC ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath="/home/victor/.ansible/cp/ansible-ssh-%h-%p-%r" -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=srvadmin -o ConnectTimeout=10 transformation.server.ndv.net.ua /bin/sh -c 'sudo -k && sudo -H -S -p "[sudo via ansible, key=vilcuzdrghmtlvfndvzibzqgxnyjsrmj] password: " -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-vilcuzdrghmtlvfndvzibzqgxnyjsrmj; LANG=C LC_CTYPE=C /usr/bin/python /home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower; rm -rf /home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/ >/dev/null 2>&1'"'"''

failed: [localhost] => {"failed": true, "parsed": false}

BECOME-SUCCESS-vilcuzdrghmtlvfndvzibzqgxnyjsrmj
Traceback (most recent call last):
  File "/home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower", line 1786, in <module>
    main()
  File "/home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower", line 173, in main
    installed, missing, outdated = bower.list()
  File "/home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower", line 121, in list
    elif data['dependencies'][dep]['pkgMeta']['version'] != data['dependencies'][dep]['update']['latest']:
KeyError: 'version'
debug3: mux_client_read_packet: read header failed: Broken pipe
debug2: Received exit status from master 0
Shared connection to transformation.server.ndv.net.ua closed.
```

It looks like a bug.

P.S. I run playbook with `-vvvv` key. Remote machine is Ubuntu 12.04, bower is installed and work correctly if I run it manually with `bower install` or `bower update`

My workaround is to remove manually `bower_components` folder first if exists and then execute `install bower vendor dependencies` task.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `packaging/language/bower.py`
Content:
```
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 
4 # (c) 2014, Michael Warkentin <mwarkentin@gmail.com>
5 #
6 # This file is part of Ansible
7 #
8 # Ansible is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # Ansible is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
20 
21 DOCUMENTATION = '''
22 ---
23 module: bower
24 short_description: Manage bower packages with bower
25 description:
26   - Manage bower packages with bower
27 version_added: 1.9
28 author: "Michael Warkentin (@mwarkentin)"
29 options:
30   name:
31     description:
32       - The name of a bower package to install
33     required: false
34   offline:
35     description:
36       - Install packages from local cache, if the packages were installed before
37     required: false
38     default: no
39     choices: [ "yes", "no" ]
40   path:
41     description:
42       - The base path where to install the bower packages
43     required: true
44   state:
45     description:
46       - The state of the bower package
47     required: false
48     default: present
49     choices: [ "present", "absent", "latest" ]
50   version:
51     description:
52       - The version to be installed
53     required: false
54 '''
55 
56 EXAMPLES = '''
57 description: Install "bootstrap" bower package.
58 - bower: name=bootstrap
59 
60 description: Install "bootstrap" bower package on version 3.1.1.
61 - bower: name=bootstrap version=3.1.1
62 
63 description: Remove the "bootstrap" bower package.
64 - bower: name=bootstrap state=absent
65 
66 description: Install packages based on bower.json.
67 - bower: path=/app/location
68 
69 description: Update packages based on bower.json to their latest version.
70 - bower: path=/app/location state=latest
71 '''
72 
73 
74 class Bower(object):
75     def __init__(self, module, **kwargs):
76         self.module = module
77         self.name = kwargs['name']
78         self.offline = kwargs['offline']
79         self.path = kwargs['path']
80         self.version = kwargs['version']
81 
82         if kwargs['version']:
83             self.name_version = self.name + '#' + self.version
84         else:
85             self.name_version = self.name
86 
87     def _exec(self, args, run_in_check_mode=False, check_rc=True):
88         if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
89             cmd = ["bower"] + args + ['--config.interactive=false', '--allow-root']
90 
91             if self.name:
92                 cmd.append(self.name_version)
93 
94             if self.offline:
95                 cmd.append('--offline')
96 
97             # If path is specified, cd into that path and run the command.
98             cwd = None
99             if self.path:
100                 if not os.path.exists(self.path):
101                     os.makedirs(self.path)
102                 if not os.path.isdir(self.path):
103                     self.module.fail_json(msg="path %s is not a directory" % self.path)
104                 cwd = self.path
105 
106             rc, out, err = self.module.run_command(cmd, check_rc=check_rc, cwd=cwd)
107             return out
108         return ''
109 
110     def list(self):
111         cmd = ['list', '--json']
112 
113         installed = list()
114         missing = list()
115         outdated = list()
116         data = json.loads(self._exec(cmd, True, False))
117         if 'dependencies' in data:
118             for dep in data['dependencies']:
119                 if 'missing' in data['dependencies'][dep] and data['dependencies'][dep]['missing']:
120                     missing.append(dep)
121                 elif data['dependencies'][dep]['pkgMeta']['version'] != data['dependencies'][dep]['update']['latest']:
122                     outdated.append(dep)
123                 elif 'incompatible' in data['dependencies'][dep] and data['dependencies'][dep]['incompatible']:
124                     outdated.append(dep)
125                 else:
126                     installed.append(dep)
127         # Named dependency not installed
128         else:
129             missing.append(self.name)
130 
131         return installed, missing, outdated
132 
133     def install(self):
134         return self._exec(['install'])
135 
136     def update(self):
137         return self._exec(['update'])
138 
139     def uninstall(self):
140         return self._exec(['uninstall'])
141 
142 
143 def main():
144     arg_spec = dict(
145         name=dict(default=None),
146         offline=dict(default='no', type='bool'),
147         path=dict(required=True),
148         state=dict(default='present', choices=['present', 'absent', 'latest', ]),
149         version=dict(default=None),
150     )
151     module = AnsibleModule(
152         argument_spec=arg_spec
153     )
154 
155     name = module.params['name']
156     offline = module.params['offline']
157     path = os.path.expanduser(module.params['path'])
158     state = module.params['state']
159     version = module.params['version']
160 
161     if state == 'absent' and not name:
162         module.fail_json(msg='uninstalling a package is only available for named packages')
163 
164     bower = Bower(module, name=name, offline=offline, path=path, version=version)
165 
166     changed = False
167     if state == 'present':
168         installed, missing, outdated = bower.list()
169         if len(missing):
170             changed = True
171             bower.install()
172     elif state == 'latest':
173         installed, missing, outdated = bower.list()
174         if len(missing) or len(outdated):
175             changed = True
176             bower.update()
177     else:  # Absent
178         installed, missing, outdated = bower.list()
179         if name in installed:
180             changed = True
181             bower.uninstall()
182 
183     module.exit_json(changed=changed)
184 
185 # Import module snippets
186 from ansible.module_utils.basic import *
187 main()
188
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/packaging/language/bower.py b/packaging/language/bower.py
--- a/packaging/language/bower.py
+++ b/packaging/language/bower.py
@@ -116,11 +116,15 @@
         data = json.loads(self._exec(cmd, True, False))
         if 'dependencies' in data:
             for dep in data['dependencies']:
-                if 'missing' in data['dependencies'][dep] and data['dependencies'][dep]['missing']:
+                dep_data = data['dependencies'][dep]
+                if dep_data.get('missing', False):
                     missing.append(dep)
-                elif data['dependencies'][dep]['pkgMeta']['version'] != data['dependencies'][dep]['update']['latest']:
+                elif \
+                  'version' in dep_data['pkgMeta'] and \
+                  'update' in dep_data and \
+                  dep_data['pkgMeta']['version'] != dep_data['update']['latest']:
                     outdated.append(dep)
-                elif 'incompatible' in data['dependencies'][dep] and data['dependencies'][dep]['incompatible']:
+                elif dep_data.get('incompatible', False):
                     outdated.append(dep)
                 else:
                     installed.append(dep)

{"golden_diff": "diff --git a/packaging/language/bower.py b/packaging/language/bower.py\n--- a/packaging/language/bower.py\n+++ b/packaging/language/bower.py\n@@ -116,11 +116,15 @@\n         data = json.loads(self._exec(cmd, True, False))\n         if 'dependencies' in data:\n             for dep in data['dependencies']:\n-                if 'missing' in data['dependencies'][dep] and data['dependencies'][dep]['missing']:\n+                dep_data = data['dependencies'][dep]\n+                if dep_data.get('missing', False):\n                     missing.append(dep)\n-                elif data['dependencies'][dep]['pkgMeta']['version'] != data['dependencies'][dep]['update']['latest']:\n+                elif \\\n+                  'version' in dep_data['pkgMeta'] and \\\n+                  'update' in dep_data and \\\n+                  dep_data['pkgMeta']['version'] != dep_data['update']['latest']:\n                     outdated.append(dep)\n-                elif 'incompatible' in data['dependencies'][dep] and data['dependencies'][dep]['incompatible']:\n+                elif dep_data.get('incompatible', False):\n                     outdated.append(dep)\n                 else:\n                     installed.append(dep)\n", "issue": "bower_module thrown an error if bower_components dir already exists\nI run next task in my playbook:\n\n``` yaml\n    - name: install bower vendor dependencies\n      bower: path=\"/path/to/project\" state=latest\n```\n\nAnd if `bower_components` dir not exists in `/path/to/project`, it download all dependencies and works fine, but if I run this task again, I get a next error:\n\n```\n< TASK: install bower vendor dependencies >\n<transformation.server.ndv.net.ua> ESTABLISH CONNECTION FOR USER: srvadmin\n<transformation.server.ndv.net.ua> REMOTE_MODULE bower path=\"/var/www/sites/transformation/web\" state=latest\n<transformation.server.ndv.net.ua> EXEC ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=\"/home/victor/.ansible/cp/ansible-ssh-%h-%p-%r\" -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=srvadmin -o ConnectTimeout=10 transformation.server.ndv.net.ua /bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340 && chmod a+rx $HOME/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340 && echo $HOME/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340'\n<transformation.server.ndv.net.ua> PUT /tmp/tmpjZzhjm TO /home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower\n<transformation.server.ndv.net.ua> EXEC ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=\"/home/victor/.ansible/cp/ansible-ssh-%h-%p-%r\" -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=srvadmin -o ConnectTimeout=10 transformation.server.ndv.net.ua /bin/sh -c 'sudo -k && sudo -H -S -p \"[sudo via ansible, key=vilcuzdrghmtlvfndvzibzqgxnyjsrmj] password: \" -u root /bin/sh -c '\"'\"'echo BECOME-SUCCESS-vilcuzdrghmtlvfndvzibzqgxnyjsrmj; LANG=C LC_CTYPE=C /usr/bin/python /home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower; rm -rf /home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/ >/dev/null 2>&1'\"'\"''\n\nfailed: [localhost] => {\"failed\": true, \"parsed\": false}\n\nBECOME-SUCCESS-vilcuzdrghmtlvfndvzibzqgxnyjsrmj\nTraceback (most recent call last):\n  File \"/home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower\", line 1786, in <module>\n    main()\n  File \"/home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower\", line 173, in main\n    installed, missing, outdated = bower.list()\n  File \"/home/srvadmin/.ansible/tmp/ansible-tmp-1431673951.26-168306551298340/bower\", line 121, in list\n    elif data['dependencies'][dep]['pkgMeta']['version'] != data['dependencies'][dep]['update']['latest']:\nKeyError: 'version'\ndebug3: mux_client_read_packet: read header failed: Broken pipe\ndebug2: Received exit status from master 0\nShared connection to transformation.server.ndv.net.ua closed.\n```\n\nIt looks like a bug.\n\nP.S. I run playbook with `-vvvv` key. Remote machine is Ubuntu 12.04, bower is installed and work correctly if I run it manually with `bower install` or `bower update`\n\nMy workaround is to remove manually `bower_components` folder first if exists and then execute `install bower vendor dependencies` task.\n\n", "before_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# (c) 2014, Michael Warkentin <mwarkentin@gmail.com>\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nDOCUMENTATION = '''\n---\nmodule: bower\nshort_description: Manage bower packages with bower\ndescription:\n  - Manage bower packages with bower\nversion_added: 1.9\nauthor: \"Michael Warkentin (@mwarkentin)\"\noptions:\n  name:\n    description:\n      - The name of a bower package to install\n    required: false\n  offline:\n    description:\n      - Install packages from local cache, if the packages were installed before\n    required: false\n    default: no\n    choices: [ \"yes\", \"no\" ]\n  path:\n    description:\n      - The base path where to install the bower packages\n    required: true\n  state:\n    description:\n      - The state of the bower package\n    required: false\n    default: present\n    choices: [ \"present\", \"absent\", \"latest\" ]\n  version:\n    description:\n      - The version to be installed\n    required: false\n'''\n\nEXAMPLES = '''\ndescription: Install \"bootstrap\" bower package.\n- bower: name=bootstrap\n\ndescription: Install \"bootstrap\" bower package on version 3.1.1.\n- bower: name=bootstrap version=3.1.1\n\ndescription: Remove the \"bootstrap\" bower package.\n- bower: name=bootstrap state=absent\n\ndescription: Install packages based on bower.json.\n- bower: path=/app/location\n\ndescription: Update packages based on bower.json to their latest version.\n- bower: path=/app/location state=latest\n'''\n\n\nclass Bower(object):\n    def __init__(self, module, **kwargs):\n        self.module = module\n        self.name = kwargs['name']\n        self.offline = kwargs['offline']\n        self.path = kwargs['path']\n        self.version = kwargs['version']\n\n        if kwargs['version']:\n            self.name_version = self.name + '#' + self.version\n        else:\n            self.name_version = self.name\n\n    def _exec(self, args, run_in_check_mode=False, check_rc=True):\n        if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):\n            cmd = [\"bower\"] + args + ['--config.interactive=false', '--allow-root']\n\n            if self.name:\n                cmd.append(self.name_version)\n\n            if self.offline:\n                cmd.append('--offline')\n\n            # If path is specified, cd into that path and run the command.\n            cwd = None\n            if self.path:\n                if not os.path.exists(self.path):\n                    os.makedirs(self.path)\n                if not os.path.isdir(self.path):\n                    self.module.fail_json(msg=\"path %s is not a directory\" % self.path)\n                cwd = self.path\n\n            rc, out, err = self.module.run_command(cmd, check_rc=check_rc, cwd=cwd)\n            return out\n        return ''\n\n    def list(self):\n        cmd = ['list', '--json']\n\n        installed = list()\n        missing = list()\n        outdated = list()\n        data = json.loads(self._exec(cmd, True, False))\n        if 'dependencies' in data:\n            for dep in data['dependencies']:\n                if 'missing' in data['dependencies'][dep] and data['dependencies'][dep]['missing']:\n                    missing.append(dep)\n                elif data['dependencies'][dep]['pkgMeta']['version'] != data['dependencies'][dep]['update']['latest']:\n                    outdated.append(dep)\n                elif 'incompatible' in data['dependencies'][dep] and data['dependencies'][dep]['incompatible']:\n                    outdated.append(dep)\n                else:\n                    installed.append(dep)\n        # Named dependency not installed\n        else:\n            missing.append(self.name)\n\n        return installed, missing, outdated\n\n    def install(self):\n        return self._exec(['install'])\n\n    def update(self):\n        return self._exec(['update'])\n\n    def uninstall(self):\n        return self._exec(['uninstall'])\n\n\ndef main():\n    arg_spec = dict(\n        name=dict(default=None),\n        offline=dict(default='no', type='bool'),\n        path=dict(required=True),\n        state=dict(default='present', choices=['present', 'absent', 'latest', ]),\n        version=dict(default=None),\n    )\n    module = AnsibleModule(\n        argument_spec=arg_spec\n    )\n\n    name = module.params['name']\n    offline = module.params['offline']\n    path = os.path.expanduser(module.params['path'])\n    state = module.params['state']\n    version = module.params['version']\n\n    if state == 'absent' and not name:\n        module.fail_json(msg='uninstalling a package is only available for named packages')\n\n    bower = Bower(module, name=name, offline=offline, path=path, version=version)\n\n    changed = False\n    if state == 'present':\n        installed, missing, outdated = bower.list()\n        if len(missing):\n            changed = True\n            bower.install()\n    elif state == 'latest':\n        installed, missing, outdated = bower.list()\n        if len(missing) or len(outdated):\n            changed = True\n            bower.update()\n    else:  # Absent\n        installed, missing, outdated = bower.list()\n        if name in installed:\n            changed = True\n            bower.uninstall()\n\n    module.exit_json(changed=changed)\n\n# Import module snippets\nfrom ansible.module_utils.basic import *\nmain()\n", "path": "packaging/language/bower.py"}], "after_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# (c) 2014, Michael Warkentin <mwarkentin@gmail.com>\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nDOCUMENTATION = '''\n---\nmodule: bower\nshort_description: Manage bower packages with bower\ndescription:\n  - Manage bower packages with bower\nversion_added: 1.9\nauthor: \"Michael Warkentin (@mwarkentin)\"\noptions:\n  name:\n    description:\n      - The name of a bower package to install\n    required: false\n  offline:\n    description:\n      - Install packages from local cache, if the packages were installed before\n    required: false\n    default: no\n    choices: [ \"yes\", \"no\" ]\n  path:\n    description:\n      - The base path where to install the bower packages\n    required: true\n  state:\n    description:\n      - The state of the bower package\n    required: false\n    default: present\n    choices: [ \"present\", \"absent\", \"latest\" ]\n  version:\n    description:\n      - The version to be installed\n    required: false\n'''\n\nEXAMPLES = '''\ndescription: Install \"bootstrap\" bower package.\n- bower: name=bootstrap\n\ndescription: Install \"bootstrap\" bower package on version 3.1.1.\n- bower: name=bootstrap version=3.1.1\n\ndescription: Remove the \"bootstrap\" bower package.\n- bower: name=bootstrap state=absent\n\ndescription: Install packages based on bower.json.\n- bower: path=/app/location\n\ndescription: Update packages based on bower.json to their latest version.\n- bower: path=/app/location state=latest\n'''\n\n\nclass Bower(object):\n    def __init__(self, module, **kwargs):\n        self.module = module\n        self.name = kwargs['name']\n        self.offline = kwargs['offline']\n        self.path = kwargs['path']\n        self.version = kwargs['version']\n\n        if kwargs['version']:\n            self.name_version = self.name + '#' + self.version\n        else:\n            self.name_version = self.name\n\n    def _exec(self, args, run_in_check_mode=False, check_rc=True):\n        if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):\n            cmd = [\"bower\"] + args + ['--config.interactive=false', '--allow-root']\n\n            if self.name:\n                cmd.append(self.name_version)\n\n            if self.offline:\n                cmd.append('--offline')\n\n            # If path is specified, cd into that path and run the command.\n            cwd = None\n            if self.path:\n                if not os.path.exists(self.path):\n                    os.makedirs(self.path)\n                if not os.path.isdir(self.path):\n                    self.module.fail_json(msg=\"path %s is not a directory\" % self.path)\n                cwd = self.path\n\n            rc, out, err = self.module.run_command(cmd, check_rc=check_rc, cwd=cwd)\n            return out\n        return ''\n\n    def list(self):\n        cmd = ['list', '--json']\n\n        installed = list()\n        missing = list()\n        outdated = list()\n        data = json.loads(self._exec(cmd, True, False))\n        if 'dependencies' in data:\n            for dep in data['dependencies']:\n                dep_data = data['dependencies'][dep]\n                if dep_data.get('missing', False):\n                    missing.append(dep)\n                elif \\\n                  'version' in dep_data['pkgMeta'] and \\\n                  'update' in dep_data and \\\n                  dep_data['pkgMeta']['version'] != dep_data['update']['latest']:\n                    outdated.append(dep)\n                elif dep_data.get('incompatible', False):\n                    outdated.append(dep)\n                else:\n                    installed.append(dep)\n        # Named dependency not installed\n        else:\n            missing.append(self.name)\n\n        return installed, missing, outdated\n\n    def install(self):\n        return self._exec(['install'])\n\n    def update(self):\n        return self._exec(['update'])\n\n    def uninstall(self):\n        return self._exec(['uninstall'])\n\n\ndef main():\n    arg_spec = dict(\n        name=dict(default=None),\n        offline=dict(default='no', type='bool'),\n        path=dict(required=True),\n        state=dict(default='present', choices=['present', 'absent', 'latest', ]),\n        version=dict(default=None),\n    )\n    module = AnsibleModule(\n        argument_spec=arg_spec\n    )\n\n    name = module.params['name']\n    offline = module.params['offline']\n    path = os.path.expanduser(module.params['path'])\n    state = module.params['state']\n    version = module.params['version']\n\n    if state == 'absent' and not name:\n        module.fail_json(msg='uninstalling a package is only available for named packages')\n\n    bower = Bower(module, name=name, offline=offline, path=path, version=version)\n\n    changed = False\n    if state == 'present':\n        installed, missing, outdated = bower.list()\n        if len(missing):\n            changed = True\n            bower.install()\n    elif state == 'latest':\n        installed, missing, outdated = bower.list()\n        if len(missing) or len(outdated):\n            changed = True\n            bower.update()\n    else:  # Absent\n        installed, missing, outdated = bower.list()\n        if name in installed:\n            changed = True\n            bower.uninstall()\n\n    module.exit_json(changed=changed)\n\n# Import module snippets\nfrom ansible.module_utils.basic import *\nmain()\n", "path": "packaging/language/bower.py"}]}