Refactor a bit the label methods for tracker
[mdk.git] / mdk / commands / tracker.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 """
5 Moodle Development Kit
6
7 Copyright (c) 2013 Frédéric Massart - FMCorz.net
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 http://github.com/FMCorz/mdk
23 """
24
25 from datetime import datetime
26 import textwrap
27 import re
28 from ..command import Command
29 from ..jira import Jira
30 from ..tools import parseBranch
31
32
33 class TrackerCommand(Command):
34
35 _arguments = [
36 (
37 ['-t', '--testing'],
38 {
39 'action': 'store_true',
40 'help': 'include testing instructions'
41 }
42 ),
43 (
44 ['issue'],
45 {
46 'help': 'MDL issue number. Guessed from the current branch if not specified.',
47 'nargs': '?'
48 }
49 ),
50 (
51 ['--add-labels'],
52 {
53 'action': 'store',
54 'dest': 'addlabels',
55 'help': 'add the specified labels to the issue',
56 'metavar': 'labels',
57 'nargs': '+',
58 }
59 ),
60 (
61 ['--remove-labels'],
62 {
63 'action': 'store',
64 'dest': 'removelabels',
65 'help': 'remove the specified labels from the issue',
66 'metavar': 'labels',
67 'nargs': '+',
68 }
69 )
70 ]
71 _description = 'Interact with Moodle tracker'
72
73 Jira = None
74 mdl = None
75
76 def run(self, args):
77
78 issue = None
79 if not args.issue:
80 M = self.Wp.resolve()
81 if M:
82 parsedbranch = parseBranch(M.currentBranch())
83 if parsedbranch:
84 issue = parsedbranch['issue']
85 else:
86 issue = args.issue
87
88 if not issue or not re.match('(MDL|mdl)?(-|_)?[1-9]+', issue):
89 raise Exception('Invalid or unknown issue number')
90
91 self.Jira = Jira()
92 self.mdl = 'MDL-' + re.sub(r'(MDL|mdl)(-|_)?', '', issue)
93
94 if args.addlabels:
95 self.Jira.addLabels(self.mdl, args.addlabels)
96
97 if args.removelabels:
98 self.Jira.removeLabels(self.mdl, args.removelabels)
99
100 self.info(args)
101
102 def info(self, args):
103 """Display classic information about an issue"""
104 issue = self.Jira.getIssue(self.mdl)
105
106 title = u'%s: %s' % (issue['key'], issue['fields']['summary'])
107 created = datetime.strftime(Jira.parseDate(issue['fields'].get('created')), '%Y-%m-%d %H:%M')
108 resolution = u'' if issue['fields']['resolution'] == None else u'(%s)' % (issue['fields']['resolution']['name'])
109 resolutiondate = u''
110 if issue['fields'].get('resolutiondate') != None:
111 resolutiondate = datetime.strftime(Jira.parseDate(issue['fields'].get('resolutiondate')), '%Y-%m-%d %H:%M')
112 print u'-' * 72
113 for l in textwrap.wrap(title, 68, initial_indent=' ', subsequent_indent=' '):
114 print l
115 print u' {0} - {1} - {2}'.format(issue['fields']['issuetype']['name'], issue['fields']['priority']['name'], u'https://tracker.moodle.org/browse/' + issue['key'])
116 status = u'{0} {1} {2}'.format(issue['fields']['status']['name'], resolution, resolutiondate).strip()
117 print u' {0}'.format(status)
118
119 print u'-' * 72
120 components = u'{0}: {1}'.format('Components', ', '.join([c['name'] for c in issue['fields']['components']]))
121 for l in textwrap.wrap(components, 68, initial_indent=' ', subsequent_indent=' '):
122 print l
123 if issue['fields']['labels']:
124 labels = u'{0}: {1}'.format('Labels', ', '.join(issue['fields']['labels']))
125 for l in textwrap.wrap(labels, 68, initial_indent=' ', subsequent_indent=' '):
126 print l
127
128 vw = u'[ V: %d - W: %d ]' % (issue['fields']['votes']['votes'], issue['fields']['watches']['watchCount'])
129 print '{0:->70}--'.format(vw)
130 print u'{0:<20}: {1} ({2}) on {3}'.format('Reporter', issue['fields']['reporter']['displayName'], issue['fields']['reporter']['name'], created)
131
132 if issue['fields'].get('assignee') != None:
133 print u'{0:<20}: {1} ({2})'.format('Assignee', issue['fields']['assignee']['displayName'], issue['fields']['assignee']['name'])
134 if issue['named'].get('Peer reviewer'):
135 print u'{0:<20}: {1} ({2})'.format('Peer reviewer', issue['named']['Peer reviewer']['displayName'], issue['named']['Peer reviewer']['name'])
136 if issue['named'].get('Integrator'):
137 print u'{0:<20}: {1} ({2})'.format('Integrator', issue['named']['Integrator']['displayName'], issue['named']['Integrator']['name'])
138 if issue['named'].get('Tester'):
139 print u'{0:<20}: {1} ({2})'.format('Tester', issue['named']['Tester']['displayName'], issue['named']['Tester']['name'])
140
141 if args.testing and issue['named'].get('Testing Instructions'):
142 print u'-' * 72
143 print u'Testing instructions:'
144 for l in issue['named'].get('Testing Instructions').split('\r\n'):
145 print ' ' + l
146
147 print u'-' * 72