Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logging configuration to app.py, related tests and Makefile. #23

Merged
merged 4 commits into from
Sep 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
omit = securedrop_client/__init__.py
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,6 @@ venv.bak/

# mypy
.mypy_cache/

# Vim
*.swp
38 changes: 38 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
XARGS := xargs -0 $(shell test $$(uname) = Linux && echo -r)
GREP_T_FLAG := $(shell test $$(uname) = Linux && echo -T)
export PYFLAKES_BUILTINS=_

all:
@echo "\nThere is no default Makefile target right now. Try:\n"
@echo "make clean - reset the project and remove auto-generated assets."
@echo "make test - run the unit test suite."
@echo "make coverage - view a report on unit test coverage."
@echo "make check - run all checkers and tests."

clean:
rm -rf build
rm -rf dist
rm -rf securedrop_client.egg-info
rm -rf .coverage
rm -rf .eggs
rm -rf docs/_build
rm -rf .pytest_cache
rm -rf lib
find . \( -name '*.py[co]' -o -name dropin.cache \) -delete
find . \( -name '*.bak' -o -name dropin.cache \) -delete
find . \( -name '*.tgz' -o -name dropin.cache \) -delete
find . | grep -E "(__pycache__)" | xargs rm -rf

test: clean
pytest

pyflakes:
find . \( -name _build -o -name var -o -path ./docs -o -path \) -type d -prune -o -name '*.py' -print0 | $(XARGS) pyflakes

pycodestyle:
find . \( -name _build -o -name var \) -type d -prune -o -name '*.py' -print0 | $(XARGS) -n 1 pycodestyle --repeat --exclude=build/*,docs/*,.vscode/* --ignore=E731,E402,W504

coverage: clean
pytest --cov-config .coveragerc --cov-report term-missing --cov=securedrop_client tests/

check: clean pycodestyle pyflakes coverage
3 changes: 3 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ alembic = "*"
[dev-packages]
pytest = "*"
pip-tools = "*"
coverage = "*"
pytest-cov = "*"
pytest-random-order = "*"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not know about this pytest-random-order plugin, looks pretty handy 👀

flake8 = "*"
121 changes: 98 additions & 23 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pipenv shell
## Run tests

```
pytest -v
make test
```

## Generate and run database migrations
Expand Down
1 change: 1 addition & 0 deletions securedrop_client/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = '0.0.1-alpha.1'
79 changes: 79 additions & 0 deletions securedrop_client/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""
SecureDrop client - an easy to use interface for SecureDrop in Qubes.

Copyright (C) 2018 The Freedom of the Press Foundation.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging
import pathlib
import os
import sys
from logging.handlers import TimedRotatingFileHandler
from securedrop_client import __version__


LOG_DIR = os.path.join(str(pathlib.Path.home()), '.securedrop_client')
LOG_FILE = os.path.join(LOG_DIR, 'securedrop_client.log')
ENCODING = 'utf-8'


def excepthook(*exc_args):
"""
This function is called in the event of a catastrophic failure.
Log exception and exit cleanly.
"""
logging.error('Unrecoverable error', exc_info=(exc_args))
sys.__excepthook__(*exc_args)
sys.exit(1)


def configure_logging():
"""
All logging related settings are set up by this function.
"""
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
# set logging format
log_fmt = ('%(asctime)s - %(name)s:%(lineno)d(%(funcName)s) '
'%(levelname)s: %(message)s')
formatter = logging.Formatter(log_fmt)
# define log handlers such as for rotating log files
handler = TimedRotatingFileHandler(LOG_FILE, when='midnight',
backupCount=5, delay=0,
encoding=ENCODING)
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
# set up primary log
log = logging.getLogger()
log.setLevel(logging.DEBUG)
log.addHandler(handler)
# override excepthook to capture a log of catastrophic failures.
sys.excepthook = excepthook


def run():
"""
Create all the top-level assets for the application, set things up and
run the application. Specific tasks include:

- set up logging.

ToDo:

- create an application object.
- create a window for the app.
"""
configure_logging()
logging.info('Starting SecureDrop Client {}'.format(__version__))
14 changes: 6 additions & 8 deletions securedrop_client/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ class Submission(Base):
is_read = Column(Boolean, default=False)

source_id = Column(Integer, ForeignKey('sources.id'))
source = relationship(
"Source",
backref=backref("submissions", order_by=id, cascade="delete")
)
source = relationship("Source",
backref=backref("submissions", order_by=id,
cascade="delete"))

def __init__(self, source, uuid, filename):
self.source_id = source.id
Expand All @@ -64,10 +63,9 @@ class Reply(Base):
__tablename__ = 'replies'
id = Column(Integer, primary_key=True)
source_id = Column(Integer, ForeignKey('sources.id'))
source = relationship(
"Source",
backref=backref("replies", order_by=id, cascade="delete")
)
source = relationship("Source",
backref=backref("replies", order_by=id,
cascade="delete"))

journalist_id = Column(Integer, ForeignKey('users.id'))
journalist = relationship(
Expand Down
File renamed without changes.
Loading