Repository: freedomofpress/securedrop

Issue:
Pyenchant depends on enchant and dev env is borked
# Bug

## Description

`pyenchant` depends on `enchant` which is incompatible with other dev dependencies.

## Steps to Reproduce

Running `vagrant up` on `develop` yields this error.

```
 Traceback (most recent call last):
 File \"<string>\", line 17, in <module>
 File \"/tmp/pip_build_root/pyenchant/setup.py\", line 212, in <module>
 import enchant
 File \"enchant/__init__.py\", line 92, in <module>
 from enchant import _enchant as _e
 File \"enchant/_enchant.py\", line 145, in <module>
 raise ImportError(msg)
 ImportError: The 'enchant' C library was not found. Please install it via your OS package manager, or use a pre-built binary wheel from PyPI.
 Complete output from command python setup.py egg_info:
 Traceback (most recent call last):
 File \"<string>\", line 17, in <module>
 File \"/tmp/pip_build_root/pyenchant/setup.py\", line 212, in <module>
 import enchant
 File \"enchant/__init__.py\", line 92, in <module>
 from enchant import _enchant as _e
 File \"enchant/_enchant.py\", line 145, in <module
 raise ImportError(msg)
ImportError: The 'enchant' C library was not found. Please install it via your OS package manager, or use a pre-built binary wheel from PyPI.
----------------------------------------
Cleaning up...
Command python setup.py egg_info failed with error code 1 in /tmp/pip_build_root/pyenchant
Storing debug log for failure in /root/.pip/pip.log
```

However, adding `enchant` to `development_dependencies` yields this error:

```
TASK [app-test : Install Firefox 46.0.1 for compatibility with Selenium 2.53.6.] ***
fatal: [development]: FAILED! => {"changed": false, "failed": true, "msg": "Breaks existing package 'hunspell-en-us' that conflict: 'iceweasel'. But the '/opt/firefox_46.0.1+build1-0ubuntu0.14.04.3_amd64.deb' provides it via: 'gnome-www-browser,iceweasel,www-browser'"}
```

## Expected Behavior

I can start the dev environment.

## Actual Behavior

I can't

## Notes

This was introduced by #2905, but I think it came from #2780 originally.


Discussion:
I confirmed the problem locally. It was not noticed because the CI does not **vagrant up** and developers only rarely destroy the development VM and reprovision it.

Resolving patch:
diff --git a/securedrop/db.py b/securedrop/db.py
--- a/securedrop/db.py
+++ b/securedrop/db.py
@@ -6,7 +6,7 @@
 # Find the best implementation available on this platform
 try:
     from cStringIO import StringIO
-except:
+except ImportError:
     from StringIO import StringIO
 
 from sqlalchemy import create_engine, ForeignKey
diff --git a/securedrop/i18n.py b/securedrop/i18n.py
--- a/securedrop/i18n.py
+++ b/securedrop/i18n.py
@@ -87,7 +87,7 @@ def get_locale(config):
             sep = '_'
         try:
             accept_languages.append(str(core.Locale.parse(l, sep)))
-        except:
+        except Exception:
             pass
     if 'l' in request.args:
         if len(request.args['l']) == 0:
diff --git a/securedrop/journalist_app/utils.py b/securedrop/journalist_app/utils.py
--- a/securedrop/journalist_app/utils.py
+++ b/securedrop/journalist_app/utils.py
@@ -95,7 +95,7 @@ def validate_user(username, password, token, error_message=None):
                     login_flashed_msg += gettext(
                         "Please wait for a new code from your two-factor token"
                         " or application before trying again.")
-            except:
+            except Exception:
                 pass
 
         flash(login_flashed_msg, "error")


Test patch:
diff --git a/securedrop/tests/functional/functional_test.py b/securedrop/tests/functional/functional_test.py
--- a/securedrop/tests/functional/functional_test.py
+++ b/securedrop/tests/functional/functional_test.py
@@ -144,7 +144,7 @@ def start_journalist_server():
             try:
                 requests.get(self.source_location)
                 requests.get(self.journalist_location)
-            except:
+            except Exception:
                 time.sleep(1)
             else:
                 break