fix compatibility with redmine 2.4, support start/end/tracker/priority (courtesy of François Revol)
This commit is contained in:
parent
57da45d9b0
commit
07a1d04bb6
5 changed files with 234 additions and 22 deletions
|
|
@ -26,12 +26,14 @@ from smtplib import SMTP
|
|||
import sys
|
||||
import os
|
||||
import re
|
||||
import unicodedata
|
||||
|
||||
from weboob.capabilities.base import empty, CapBaseObject
|
||||
from weboob.capabilities.bugtracker import ICapBugTracker, Query, Update, Project, Issue, IssueError
|
||||
from weboob.tools.application.repl import ReplApplication, defaultcount
|
||||
from weboob.tools.application.formatters.iformatter import IFormatter, PrettyFormatter
|
||||
from weboob.tools.misc import html2text
|
||||
from weboob.tools.date import parse_french_date
|
||||
|
||||
|
||||
__all__ = ['BoobTracker']
|
||||
|
|
@ -63,7 +65,9 @@ class IssueFormatter(IFormatter):
|
|||
result += '\n%s\n\n' % obj.body
|
||||
result += self.format_key('Author', '%s (%s)' % (obj.author.name, obj.creation))
|
||||
result += self.format_attr(obj, 'status')
|
||||
result += self.format_attr(obj, 'priority')
|
||||
result += self.format_attr(obj, 'version')
|
||||
result += self.format_attr(obj, 'tracker')
|
||||
result += self.format_attr(obj, 'category')
|
||||
result += self.format_attr(obj, 'assignee')
|
||||
if hasattr(obj, 'fields') and not empty(obj.fields):
|
||||
|
|
@ -122,8 +126,12 @@ class BoobTracker(ReplApplication):
|
|||
group.add_option('--title')
|
||||
group.add_option('--assignee')
|
||||
group.add_option('--target-version', dest='version')
|
||||
group.add_option('--tracker')
|
||||
group.add_option('--category')
|
||||
group.add_option('--status')
|
||||
group.add_option('--priority')
|
||||
group.add_option('--start')
|
||||
group.add_option('--due')
|
||||
|
||||
@defaultcount(10)
|
||||
def do_search(self, line):
|
||||
|
|
@ -246,8 +254,12 @@ class BoobTracker(ReplApplication):
|
|||
ISSUE_FIELDS = (('title', (None, False)),
|
||||
('assignee', ('members', True)),
|
||||
('version', ('versions', True)),
|
||||
('tracker', (None, False)),#XXX
|
||||
('category', ('categories', False)),
|
||||
('status', ('statuses', True)),
|
||||
('priority', (None, False)),#XXX
|
||||
('start', (None, False)),
|
||||
('due', (None, False)),
|
||||
)
|
||||
|
||||
def get_list_item(self, objects_list, name):
|
||||
|
|
@ -263,6 +275,12 @@ class BoobTracker(ReplApplication):
|
|||
|
||||
raise ValueError('"%s" is not found' % name)
|
||||
|
||||
def sanitize_key(self, key):
|
||||
if isinstance(key, str):
|
||||
key = unicode(key, "utf8")
|
||||
key = unicodedata.normalize('NFKD', key).encode("ascii", "ignore")
|
||||
return key.replace(' ', '-').capitalize()
|
||||
|
||||
def issue2text(self, issue, backend=None):
|
||||
if backend is not None and 'username' in backend.config:
|
||||
sender = backend.config['username'].get()
|
||||
|
|
@ -285,14 +303,15 @@ class BoobTracker(ReplApplication):
|
|||
if len(objects_list) == 0:
|
||||
continue
|
||||
|
||||
output += '%s: %s\n' % (key.capitalize(), value)
|
||||
output += '%s: %s\n' % (self.sanitize_key(key), value)
|
||||
if list_name is not None:
|
||||
availables = ', '.join(['<%s>' % (o if isinstance(o, basestring) else o.name)
|
||||
for o in objects_list])
|
||||
output += 'X-Available-%s: %s\n' % (key.capitalize(), availables)
|
||||
output += 'X-Available-%s: %s\n' % (self.sanitize_key(key), availables)
|
||||
|
||||
for key, value in issue.fields.iteritems():
|
||||
output += '%s: %s\n' % (key, value or '')
|
||||
output += '%s: %s\n' % (self.sanitize_key(key), value or '')
|
||||
# TODO: Add X-Available-* for lists
|
||||
|
||||
output += '\n%s' % (issue.body or 'Please write your bug report here.')
|
||||
return output
|
||||
|
|
@ -312,17 +331,25 @@ class BoobTracker(ReplApplication):
|
|||
if part[1]:
|
||||
new_value += unicode(part[0], part[1])
|
||||
else:
|
||||
new_value += unicode(part[0])
|
||||
new_value += part[0].decode('utf-8')
|
||||
value = new_value
|
||||
|
||||
if is_list_object:
|
||||
objects_list = getattr(issue.project, list_name)
|
||||
value = self.get_list_item(objects_list, value)
|
||||
|
||||
# FIXME: autodetect
|
||||
if key in ['start', 'due']:
|
||||
if len(value) > 0:
|
||||
#value = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
||||
value = parse_french_date(value)
|
||||
else:
|
||||
value = None
|
||||
|
||||
setattr(issue, key, value)
|
||||
|
||||
for key in issue.fields.keys():
|
||||
value = m.get(key)
|
||||
value = m.get(self.sanitize_key(key))
|
||||
if value is not None:
|
||||
issue.fields[key] = value.decode('utf-8')
|
||||
|
||||
|
|
@ -336,7 +363,7 @@ class BoobTracker(ReplApplication):
|
|||
if charset is not None:
|
||||
content += unicode(s, charset)
|
||||
else:
|
||||
content += unicode(s)
|
||||
content += unicode(s, encoding='utf-8')
|
||||
except UnicodeError as e:
|
||||
self.logger.warning('Unicode error: %s' % e)
|
||||
continue
|
||||
|
|
@ -367,7 +394,7 @@ class BoobTracker(ReplApplication):
|
|||
except ValueError as e:
|
||||
if not sys.stdin.isatty():
|
||||
raise
|
||||
raw_input("%s -- Press Enter to continue..." % e)
|
||||
raw_input("%s -- Press Enter to continue..." % unicode(e).encode("utf-8"))
|
||||
continue
|
||||
|
||||
try:
|
||||
|
|
@ -382,7 +409,7 @@ class BoobTracker(ReplApplication):
|
|||
except IssueError as e:
|
||||
if not sys.stdin.isatty():
|
||||
raise
|
||||
raw_input("%s -- Press Enter to continue..." % e)
|
||||
raw_input("%s -- Press Enter to continue..." % unicode(e).encode("utf-8"))
|
||||
|
||||
def send_notification(self, email_to, issue):
|
||||
text = """Hi,
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@ class Project(CapBaseObject):
|
|||
name = StringField('Name of the project')
|
||||
members = Field('Members of projects', list)
|
||||
versions = Field('List of versions available for this project', list)
|
||||
trackers = Field('All trackers', list)
|
||||
categories = Field('All categories', list)
|
||||
statuses = Field('Available statuses for issues', list)
|
||||
priorities = Field('Available priorities for issues', list)
|
||||
|
||||
def __init__(self, id, name):
|
||||
CapBaseObject.__init__(self, id)
|
||||
|
|
@ -199,14 +201,18 @@ class Issue(CapBaseObject):
|
|||
body = StringField('Text of issue')
|
||||
creation = DateField('Date when this issue has been created')
|
||||
updated = DateField('Date when this issue has been updated for the last time')
|
||||
start = DateField('Date when this issue starts')
|
||||
due = DateField('Date when this issue is due for')
|
||||
attachments = Field('List of attached files', list, tuple)
|
||||
history = Field('History of updates', list, tuple)
|
||||
author = Field('Author of this issue', User)
|
||||
assignee = Field('User assigned to this issue', User)
|
||||
tracker = StringField('Name of the tracker')
|
||||
category = StringField('Name of the category')
|
||||
version = Field('Target version of this issue', Version)
|
||||
status = Field('Status of this issue', Status)
|
||||
fields = Field('Custom fields (key,value)', dict)
|
||||
priority = StringField('Priority of the issue') #XXX
|
||||
|
||||
|
||||
class Query(CapBaseObject):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue