[PATCH 09/11] parsemail: Convert to a management command
Andy Doan
andy.doan at linaro.org
Wed Jul 20 07:33:06 AEST 2016
On 07/13/2016 04:40 AM, Stephen Finucane wrote:
> Management comands allow applications to register their own actions with
> 'manage.py'. This provides some advantages, like automatically
> configuring Django (removing the need for 'django.setup' calls) and
> removing the need to set the PYTHON_PATH. The 'parsemail' script is a
> natural fit for this type of application. Migrate 'parsemail' to a
> management command.
>
> This includes some extensive work on logging configuration, as logging
> is moved from code into settings. In addition, it removes a lot of the
> customizable logging previously introduced in the parsemail command, in
> favour of modifications to the settings files.
>
> Signed-off-by: Stephen Finucane <stephen.finucane at intel.com>
Couple of questions:
> Partial-bug: #17
> Closes-bug: #15
> ---
> patchwork/bin/parsemail.py | 113 ----------------------------
> patchwork/bin/parsemail.sh | 2 +-
> patchwork/management/commands/parsemail.py | 63 +++++++++++++++
> patchwork/parser.py | 12 ++--
> patchwork/settings/base.py | 52 +++++++++++++
> 5 files changed, 122 insertions(+), 120 deletions(-)
> delete mode 100755 patchwork/bin/parsemail.py
> create mode 100644 patchwork/management/commands/parsemail.py
>
> diff --git a/patchwork/bin/parsemail.py b/patchwork/bin/parsemail.py
> deleted file mode 100755
> index abcee04..0000000
> --- a/patchwork/bin/parsemail.py
> +++ /dev/null
> @@ -1,113 +0,0 @@
> -#!/usr/bin/env python
> -#
> -# Patchwork - automated patch tracking system
> -# Copyright (C) 2008 Jeremy Kerr <jk at ozlabs.org>
> -#
> -# This file is part of the Patchwork package.
> -#
> -# Patchwork is free software; you can redistribute it and/or modify
> -# it under the terms of the GNU General Public License as published by
> -# the Free Software Foundation; either version 2 of the License, or
> -# (at your option) any later version.
> -#
> -# Patchwork 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 General Public License for more details.
> -#
> -# You should have received a copy of the GNU General Public License
> -# along with Patchwork; if not, write to the Free Software
> -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> -
> -from __future__ import absolute_import
> -
> -import argparse
> -from email import message_from_file
> -import logging
> -import sys
> -
> -import django
> -from django.conf import settings
> -from django.utils.log import AdminEmailHandler
> -
> -from patchwork.parser import parse_mail
> -
> -LOGGER = logging.getLogger(__name__)
> -
> -VERBOSITY_LEVELS = {
> - 'debug': logging.DEBUG,
> - 'info': logging.INFO,
> - 'warning': logging.WARNING,
> - 'error': logging.ERROR,
> - 'critical': logging.CRITICAL
> -}
> -
> -extra_error_message = '''
> -== Mail
> -
> -%(mail)s
> -
> -
> -== Traceback
> -
> -'''
> -
> -
> -def setup_error_handler():
> - """Configure error handler.
> -
> - Ensure emails are send to settings.ADMINS when errors are
> - encountered.
> - """
> - if settings.DEBUG:
> - return
> -
> - mail_handler = AdminEmailHandler()
> - mail_handler.setLevel(logging.ERROR)
> - mail_handler.setFormatter(logging.Formatter(extra_error_message))
> -
> - logger = logging.getLogger('patchwork')
> - logger.addHandler(mail_handler)
> -
> - return logger
> -
> -
> -def main(args):
> - django.setup()
> - logger = setup_error_handler()
> - parser = argparse.ArgumentParser()
> -
> - def list_logging_levels():
> - """Give a summary of all available logging levels."""
> - return sorted(list(VERBOSITY_LEVELS.keys()),
> - key=lambda x: VERBOSITY_LEVELS[x])
> -
> - parser.add_argument('infile', nargs='?', type=argparse.FileType('r'),
> - default=sys.stdin, help='input mbox file (a filename '
> - 'or stdin)')
> -
> - group = parser.add_argument_group('Mail parsing configuration')
> - group.add_argument('--list-id', help='mailing list ID. If not supplied '
> - 'this will be extracted from the mail headers.')
> - group.add_argument('--verbosity', choices=list_logging_levels(),
> - help='debug level', default='info')
> -
> - args = vars(parser.parse_args())
> -
> - logging.basicConfig(level=VERBOSITY_LEVELS[args['verbosity']])
> -
> - mail = message_from_file(args['infile'])
> - try:
> - result = parse_mail(mail, args['list_id'])
> - if result:
> - return 0
> - return 1
> - except:
> - if logger:
> - logger.exception('Error when parsing incoming email', extra={
> - 'mail': mail.as_string(),
> - })
> - raise
> -
> -if __name__ == '__main__':
> - sys.exit(main(sys.argv))
> diff --git a/patchwork/bin/parsemail.sh b/patchwork/bin/parsemail.sh
> index 9973392..5a8ca58 100755
> --- a/patchwork/bin/parsemail.sh
> +++ b/patchwork/bin/parsemail.sh
> @@ -24,6 +24,6 @@ PATCHWORK_BASE=`readlink -e $BIN_DIR/../..`
>
> PYTHONPATH="$PATCHWORK_BASE":"$PATCHWORK_BASE/lib/python:$PYTHONPATH" \
> DJANGO_SETTINGS_MODULE=patchwork.settings.production \
> - "$PATCHWORK_BASE/patchwork/bin/parsemail.py"
> + "$PATCHWORK_BASE/patchwork/manage.py parsemail"
>
> exit 0
I've never been a consumer of this script, but it looks like you can't
pass options to it, so it will only read patches from stdin. Wouldn't be
a little cleaner if it was like:
PYTHONPATH="$PATCHWORK_BASE":"$PATCHWORK_BASE/lib/python:$PYTHONPATH" \
DJANGO_SETTINGS_MODULE=patchwork.settings.production \
exec "$PATCHWORK_BASE/patchwork/manage.py parsemail" $*
(NOTE i also added "exec" to be a little cleaner and exit with proper code)
> diff --git a/patchwork/management/commands/parsemail.py b/patchwork/management/commands/parsemail.py
> new file mode 100644
> index 0000000..ce6a63e
> --- /dev/null
> +++ b/patchwork/management/commands/parsemail.py
> @@ -0,0 +1,63 @@
> +# Patchwork - automated patch tracking system
> +# Copyright (C) 2016 Intel Corporation
> +#
> +# This file is part of the Patchwork package.
> +#
> +# Patchwork is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# Patchwork 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 General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with Patchwork; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> +
> +from email import message_from_file
> +import logging
> +from optparse import make_option
> +import sys
> +
> +from django.core.management import base
> +from django.utils import log
"log" looks like an unused import?
> +
> +from patchwork.parser import parse_mail
> +
> +logger = logging.getLogger(__name__)
> +
> +
> +class Command(base.BaseCommand):
> + help = 'Parse an mbox file and store any patch/comment found'
> + args = '<infile>' # Django < 1.8 compatibility
> + option_list = base.BaseCommand.option_list + (
> + make_option(
> + '--list-id',
> + help='mailing list ID. If not supplied, this will be extracted '
> + 'from the mail headers.'
> + ),
> + )
> +
> + def handle(self, *args, **options):
> + # Attempt to parse the path if provided, and fallback to stdin if not
> + if args:
> + logger.info('Parsing mail loaded by filename')
> + with open(args[0]) as file_:
> + mail = message_from_file(file_)
> + else:
> + logger.info('Parsing mail loaded from stdin')
> + mail = message_from_file(sys.stdin)
> +
> + try:
> + result = parse_mail(mail, options['list_id'])
> + if result:
> + sys.exit(0)
> + logger.warning('Failed to parse mail.')
> + sys.exit(1)
> + except Exception as exc:
> + logger.exception('Error when parsing incoming email',
> + extra={'mail': mail.as_string()})
> + raise exc
Do you really want to raise an exception since logger.exception will
show the stack trace? Maybe just a sys.exit(1)?
More information about the Patchwork
mailing list