import itertools import matplotlib.pyplot as plt from django.core.management.base import BaseCommand, CommandError from django.db.models import Q from django.utils.dateparse import parse_date from django.utils.timezone import make_aware, make_naive from eodb.events.models import Commit, Email, Redmine, Formdata class GraphCommand(BaseCommand): def add_arguments(self, parser): parser.add_argument('--username', metavar='USERNAME') parser.add_argument('--module', metavar='MODULE') parser.add_argument('--datemin', metavar='DATEMIN') parser.add_argument('--datemax', metavar='DATEMAX') parser.add_argument('--committime', action='store_true', help='use commit datetime instead of author datetime') parser.add_argument('--events', default='git', help='use event of this type (git (default), emails, redmine)') parser.add_argument('--notitle', action='store_true') parser.add_argument('--entrouvert', action='store_true', help='limit to @entrouvert persons') parser.add_argument('--filename', metavar='FILENAME') def get_series(self, options): usernames = options['username'].split(',') if options.get('username') else [] modules = options['module'].split(',') if options.get('module') else [] if len(usernames) > 1 and len(modules) > 1: raise CommandError('only one dimension is allowed') if len(usernames) > 1: for username in usernames: options['username'] = username yield (username, self.get_events(options)) elif len(modules) > 1: for module in modules: options['module'] = module yield (module, self.get_events(options)) else: yield (None, self.get_events(options)) def get_event_datetime(self, event, options): datetime_var = 'author_datetime' if options.get('committime'): datetime_var = 'commit_datetime' try: return make_aware(make_naive(getattr(event, datetime_var))) except: # maybe pytz.exceptions.AmbiguousTimeError return getattr(event, datetime_var) def get_events(self, options): if options.get('entrouvert'): domain_filter = Q(author_email__endswith='@entrouvert.com') | \ Q(author_email__endswith='@entrouvert.org') elif options['events'] in ('formdata',): domain_filter = Q(author_datetime__isnull=False) else: domain_filter = Q() filters = {} if options.get('username'): filters['author_email__startswith'] = options['username'] + '@' if options.get('module'): filters['module'] = options['module'] datetime_var = 'author_datetime' if options.get('committime'): datetime_var = 'commit_datetime' if options.get('datemin'): filters[datetime_var + '__gte'] = parse_date(options['datemin']) if options.get('datemax'): filters[datetime_var + '__lt'] = parse_date(options['datemax']) if options['events'] == 'all': return itertools.chain( Email.objects.filter(domain_filter).filter(**filters), Redmine.objects.filter(domain_filter).filter(**filters), Commit.objects.filter(domain_filter).filter(**filters), ) return {'emails': Email, 'redmine': Redmine, 'git': Commit, 'formdata': Formdata}[ options['events']].objects.filter(domain_filter).filter(**filters) def get_title(self, options): title = { 'emails': 'Email activity', 'git': 'Git activity', 'redmine': 'Redmine activity', 'formdata': 'Formdata activity', 'all': 'Global activity', }[options['events']] if options.get('username'): title += ' for %s' % options['username'] if options.get('module'): title += ' in module %s' % options['module'] if options.get('datemin'): title += ' from %s' % options['datemin'] if options.get('datemax'): title += ' until %s' % options['datemax'] return title def plot(self, options): if not options.get('notitle'): plt.title(self.get_title(options)) if options.get('filename'): plt.savefig(options['filename']) else: plt.show()