Maciej Fijalkowski avatar Maciej Fijalkowski committed 48d9453 Draft

progress

Comments (0)

Files changed (11)

 syntax: glob
 *.py[co]
 *~
+pypybugs_raw
+trakker.egg-info
-parsedatetime
 docutils
 flask
 jinja2
     url = '???',
     author = 'Maciej Fijalkowski',
     license = 'MIT',
-    install_requires = ['parsedatetime', 'docutils', 'flask'],
+    install_requires = ['docutils', 'flask'],
 )
 
 more of it
 
-Comment 1
----------
+On 12-04-2012, fijal said::
 
-xxx
+   xxx
 
-Comment 2
----------
+On 12-05-2012, arigo said::
 
-yyy
+   yyy
 

testing/example_storage/issue1.rst

 
 This is body
 
-Comment 1
----------
+On 12-04-2012, antocuni said::
 
-xxx
+  xxx
 
-Comment 2
----------
+On 12-06-2012, someone said::
 
-yyy
+  yyy

testing/test_files.py

 def test_parse_example():
     fname = str(py.path.local(__file__).join('..', 'example'))
     res = parse_file(0, str(fname))
-    assert res.comments[0].title == 'Comment 1'
+    assert res.comments[0].author == 'fijal'
+    assert res.comments[0].date == '12-04-2012'
+    assert res.comments[0].body == 'xxx'
     assert res.fields['keywords'] == ['pypy', 'bug tracker']
     assert res.body == 'This is body\n\nmore of it'
 

testing/test_model.py

 from trakker.model import Issue, Comment
 
 def test_render():
-    comments = [Comment('comment 0', {}, 'body 0'),
-                Comment('comment 1', {}, 'body 1')]
+    comments = [Comment('fijal', 'date 1', 'body 0'),
+                Comment('arigo', 'date 2', 'body 1')]
     i = Issue(0, 'title', {}, 'body with *bold*', comments)
     s = i.render()
     assert '=====\n' in s
     assert '*bold*' in s
-    assert 'comment 0\n---------\n' in s
+    assert 'On date 1, fijal said::\n\n  body 0' in s
 
 def test_check_renders():
     i = Issue(0, 'title', {}, 'body *bold*', [])
     i.check_renders() # did not explode
     i = Issue(0, 'title', {}, 'body *broken', [])
     py.test.raises(SystemMessage, i.check_renders)
+
+def test_render_fields():
+    fields = {'author': 'fijal'}
+    i = Issue(0, 'title', fields, 'body with *bold*', [])
+    s = i.render()
+    assert ':author:\n  fijal\n' in s

trakker/constants.py

 
-from parsedatetime.parsedatetime import Calendar
 split_by_coma = lambda arg : [arg.strip() for arg in arg.split(",")]
-cal = Calendar()
 
 KNOWN_FIELDS = {
     'keywords' : ('keywords associated with the bug', split_by_coma),
-    'date'   : ('date of post', cal.parse),
+    'date'   : ('date of post', unicode),
+    'author' : ('author of the post', unicode),
 }
 
-class Comment(object):
-    def __init__(self, title, fields, body):
-        self.title  = title
-        self.fields = fields
+class Base(object):
+    def render_author(self, v):
+        return [':author:', '  ' + v]
+
+    def render_date(self, v):
+        return [':date:', '  ' + v]
+    
+    def render_fields(self):
+        l = []
+        for name, value in self.fields.iteritems():
+            l.extend(getattr(self, 'render_%s' % name)(value))
+        return l + ['']
+
+class Comment(Base):
+    def __init__(self, author, date, body):
+        self.author = author
+        self.date   = date
         self.body   = body
 
     def render(self):
-        l = [self.title,
-            u'-' * len(self.title), u'',
-            self.body]
-        return u'\n'.join(l)
+        l = ['On %s, %s said::' % (self.date, self.author), '']
+        l.extend(['  ' + line for line in self.body.splitlines()])
+        return '\n'.join(l)
 
-class Issue(object):
+class Issue(Base):
     def __init__(self, num, title, fields, body, comments):
         self.num      = num
         self.title    = title
     def render(self):
         l = [u'=' * len(self.title),
             self.title,
-            u'=' * len(self.title), u'',
-            self.body, u'']
+            u'=' * len(self.title), u''] + self.render_fields() + [self.body]
         for c in self.comments:
             l.extend([c.render(), u''])
         return u'\n'.join(l)

trakker/parsing.py

+
+import re
 
 from docutils.parsers import rst
 from docutils.utils import new_document
         res[field_name] = KNOWN_FIELDS[field_name][1](field_body.astext())
     return res
 
+def try_parse_comment(txt, arg):
+    m = re.match('On (\d\d-\d\d-\d\d\d\d), (.*) said:', txt)
+    if m is None:
+        return None
+    return Comment(m.group(2), m.group(1), arg)
+
 def parse_paragraph(part, offset):
     so_far = []
-    while offset < len(part) and part[offset].tagname != 'section':
-        so_far.append(part[offset].astext())
+    txt = part[offset].astext()
+    while offset < len(part) and not try_parse_comment(txt, None):
+        so_far.append(txt)
         offset += 1
-    return u'\n\n'.join(so_far), offset
+        if offset < len(part):
+            txt = part[offset].astext()
+    comments = []
+    while offset < len(part):
+        comments.append(try_parse_comment(part[offset].astext(),
+                                          part[offset + 1].astext()))
+        offset += 2
+    return u'\n\n'.join(so_far), comments
 
 def parse_part(part, fname):
     if part[0].tagname != 'title':
     else:
         fields = {}
     offset += 1
-    body, offset = parse_paragraph(part, offset)
-    return title, fields, body, offset
+    body, comments = parse_paragraph(part, offset)
+    return title, fields, body, comments
 
 def parse_comment(part, fname):
     title, fields, body, _ = parse_part(part, fname)
     if len(doc) != 1:
         raise ParserError(fname, "one issue per file, seeing %d sections" % len(doc))
     issue = doc[0]
-    title, fields, body, offset = parse_part(issue, fname)
-    comments = []
-    for i in range(offset, len(issue)):
-        comments.append(parse_comment(issue[i], fname))
+    title, fields, body, comments = parse_part(issue, fname)
     return Issue(num, title, fields, body, comments)

trakker/roundup.py

 
 SQL_MSGS = "select _title, _issue.id, _msg.id, _summary from _msg, _issue, issue_messages where linkid == _msg.id and nodeid == _issue.id and _status <> 12 and _status <> 10 and _status <> 8 and _status <> 7 order by _msg.id;"
 
+SQL_AUTHORS = "select _msg.id, _username from _msg, _user where _msg._creator = _user.id;"
+
+SQL_DATES = "select _date, _msg.id from _msg;"
+
+SQL_FILES = "select _issue.id, _file._name from _issue, issue_files, _file where issue_files.nodeid = _file.id and _issue.id = linkid;"
+
 class RoundupSQL(object):
     def __init__(self, dirname):
         self.msg_dir = os.path.join(dirname, 'files', 'msg')
         cur.execute(SQL_MSGS)
         data = cur.fetchall()
         res = {}
+        res_msgs = {}
         for title, issue_id, msg_id, summary in data:
             msg_path = os.path.join(os.path.join(self.msg_dir, str(msg_id)[0]),
                                     'msg' + str(msg_id))
             try:
                 with open(msg_path) as f:
-                    msg = f.read().decode('utf-8')
+                    msg = f.read().replace('\r', '').decode('utf-8')
             except (OSError, IOError):
                 msg = summary
+            msg_lines = msg.splitlines()
+            msg = "\n  ".join(['::', ""] + msg_lines + [""])
             if issue_id not in res:
                 issue = Issue(issue_id, title, {}, msg, [])
                 res[issue_id] = issue
+                res_msgs[msg_id] = issue
             else:
                 comlen = len(res[issue_id].comments)
-                res[issue_id].comments.append(Comment('Comment %d' % comlen,
-                                                      {}, msg))
+                com = Comment('Comment %d' % comlen, {}, msg)
+                res[issue_id].comments.append(com)
+                res_msgs[msg_id] = com
+        # now let's populate fields
+        self.add_authors(res_msgs)
+        self.add_dates(res_msgs)
+        self.add_attachments(res_msgs)
         return res
+
+    def add_authors(self, res):
+        cur = self.con.cursor()
+        cur.execute(SQL_AUTHORS)
+        for msg_id, author in cur.fetchall():
+            try:
+                res[msg_id].fields['author'] = author
+            except KeyError:
+                pass
+
+    def add_dates(self, res):
+        cur = self.con.cursor()
+        cur.execute(SQL_DATES)
+        for date, msg_id in cur.fetchall():
+            year = date[:4]
+            month = date[4:6]
+            day = date[6:8]
+            hour = date[8:10]
+            minute = date[10:12]
+            date_str = "%s-%s-%s %s:%s" % (year, month,
+                                           day, hour, minute)
+            try:
+                res[msg_id].fields['date'] = date_str
+            except KeyError:
+                pass
+
+    def add_attachments(self, res):
+        xxx
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.