# Buggy code
def lookup():
    replies = []
    source_inbox = (
        Reply.query.filter(Reply.source_id == g.source.id)
        .filter(Reply.deleted_by_source == False)
        .all()
    )  # noqa

    for reply in source_inbox:
        reply_path = current_app.storage.path(
            g.filesystem_id,
            reply.filename,
        )
        try:
            with io.open(reply_path, "rb") as f:
                contents = f.read()
            reply_obj = current_app.crypto_util.decrypt(g.codename, contents)
            reply.decrypted = reply_obj
        except UnicodeDecodeError:
            current_app.logger.error("Could not decode reply %s" % reply.filename)
        else:
            reply.date = datetime.utcfromtimestamp(os.stat(reply_path).st_mtime)
            replies.append(reply)

    # Sort the replies by date
    replies.sort(key=operator.attrgetter("date"), reverse=True)

    # Generate a keypair to encrypt replies from the journalist
    # Only do this if the journalist has flagged the source as one
    # that they would like to reply to. (Issue #140.)
    if (
        not current_app.crypto_util.get_fingerprint(g.filesystem_id)
        and g.source.flagged
    ):
        db_uri = current_app.config["SQLALCHEMY_DATABASE_URI"]
        async_genkey(current_app.crypto_util, db_uri, g.filesystem_id, g.codename)

    return render_template(
        "lookup.html",
        allow_document_uploads=current_app.instance_config.allow_document_uploads,
        codename=g.codename,
        replies=replies,
        flagged=g.source.flagged,
        new_user=session.get("new_user", None),
        haskey=current_app.crypto_util.get_fingerprint(g.filesystem_id),
        form=SubmissionForm(),
    )


# Traceback (FileNotFoundError)
[Wed Jul 22 22:10:08.442888 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108] [2020-07-22 22:10:08,442] ERROR in app: Exception on /lookup [GET]
[Wed Jul 22 22:10:08.442937 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108] Traceback (most recent call last):
[Wed Jul 22 22:10:08.442946 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/opt/venvs/securedrop-app-code/lib/python3.5/site-packages/flask/app.py", line 2292, in wsgi_app
[Wed Jul 22 22:10:08.442953 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     response = self.full_dispatch_request()
[Wed Jul 22 22:10:08.442959 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/opt/venvs/securedrop-app-code/lib/python3.5/site-packages/flask/app.py", line 1815, in full_dispatch_request
[Wed Jul 22 22:10:08.442966 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     rv = self.handle_user_exception(e)
[Wed Jul 22 22:10:08.442972 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/opt/venvs/securedrop-app-code/lib/python3.5/site-packages/flask/app.py", line 1718, in handle_user_exception
[Wed Jul 22 22:10:08.442979 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     reraise(exc_type, exc_value, tb)
[Wed Jul 22 22:10:08.442985 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/opt/venvs/securedrop-app-code/lib/python3.5/site-packages/flask/_compat.py", line 35, in reraise
[Wed Jul 22 22:10:08.442992 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     raise value
[Wed Jul 22 22:10:08.442998 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/opt/venvs/securedrop-app-code/lib/python3.5/site-packages/flask/app.py", line 1813, in full_dispatch_request
[Wed Jul 22 22:10:08.443005 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     rv = self.dispatch_request()
[Wed Jul 22 22:10:08.443011 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/opt/venvs/securedrop-app-code/lib/python3.5/site-packages/flask/app.py", line 1799, in dispatch_request
[Wed Jul 22 22:10:08.443017 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     return self.view_functions[rule.endpoint](**req.view_args)
[Wed Jul 22 22:10:08.443023 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/var/www/securedrop/source_app/decorators.py", line 12, in decorated_function
[Wed Jul 22 22:10:08.443029 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     return f(*args, **kwargs)
[Wed Jul 22 22:10:08.443060 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]   File "/var/www/securedrop/source_app/main.py", line 115, in lookup
[Wed Jul 22 22:10:08.443067 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]     with io.open(reply_path, "rb") as f:
[Wed Jul 22 22:10:08.443076 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108] FileNotFoundError: [Errno 2] No such file or directory: '/var/lib/securedrop/store/YJSI6RQBP5JTHYYMZ4L4MUTQWAI7MNTK5ZUU4K2OXSD34PALIFT7DK6LTAYT43VLGAEOPWBBNV6JWDTHQPFITD6UFPLNYN25RHMJJOY=/2-damp_burner-reply.gpg'
[Wed Jul 22 22:10:08.443111 2020] [wsgi:error] [pid 11154:tid 115647289255680] [remote 127.0.0.1:40108]

# Fixed code
def lookup():
    replies = []
    source_inbox = (
        Reply.query.filter(Reply.source_id == g.source.id)
        .filter(Reply.deleted_by_source == False)
        .all()
    )  # noqa

    for reply in source_inbox:
        reply_path = current_app.storage.path(
            g.filesystem_id,
            reply.filename,
        )
        try:
            with io.open(reply_path, "rb") as f:
                contents = f.read()
            reply_obj = current_app.crypto_util.decrypt(g.codename, contents)
            reply.decrypted = reply_obj
        except UnicodeDecodeError:
            current_app.logger.error("Could not decode reply %s" % reply.filename)
        except FileNotFoundError:
            current_app.logger.error("Reply file missing: %s" % reply.filename)
        else:
            reply.date = datetime.utcfromtimestamp(os.stat(reply_path).st_mtime)
            replies.append(reply)

    # Sort the replies by date
    replies.sort(key=operator.attrgetter("date"), reverse=True)

    # Generate a keypair to encrypt replies from the journalist
    # Only do this if the journalist has flagged the source as one
    # that they would like to reply to. (Issue #140.)
    if (
        not current_app.crypto_util.get_fingerprint(g.filesystem_id)
        and g.source.flagged
    ):
        db_uri = current_app.config["SQLALCHEMY_DATABASE_URI"]
        async_genkey(current_app.crypto_util, db_uri, g.filesystem_id, g.codename)

    return render_template(
        "lookup.html",
        allow_document_uploads=current_app.instance_config.allow_document_uploads,
        codename=g.codename,
        replies=replies,
        flagged=g.source.flagged,
        new_user=session.get("new_user", None),
        haskey=current_app.crypto_util.get_fingerprint(g.filesystem_id),
        form=SubmissionForm(),
    )