You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by jo...@apache.org on 2013/08/09 18:33:45 UTC

[1/6] git commit: [#6464] Changed tool_label on GC code importer

Updated Branches:
  refs/heads/cj/6464 8649c85bb -> ff155b60f (forced update)


[#6464] Changed tool_label on GC code importer

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/0457b1ff
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/0457b1ff
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/0457b1ff

Branch: refs/heads/cj/6464
Commit: 0457b1ffccff910752742b1ec01c83614e271864
Parents: 7676318
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Wed Aug 7 01:14:26 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Aug 8 18:36:00 2013 +0000

----------------------------------------------------------------------
 ForgeImporters/forgeimporters/google/code.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0457b1ff/ForgeImporters/forgeimporters/google/code.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/google/code.py b/ForgeImporters/forgeimporters/google/code.py
index c88d42a..2268e99 100644
--- a/ForgeImporters/forgeimporters/google/code.py
+++ b/ForgeImporters/forgeimporters/google/code.py
@@ -97,7 +97,7 @@ class GoogleRepoImporter(ToolImporter):
     target_app = TARGET_APPS
     source = 'Google Code'
     controller = GoogleRepoImportController
-    tool_label = 'Google Code Source Importer'
+    tool_label = 'Source'
     tool_description = 'Import your SVN, Git, or Hg repo from Google Code'
 
     def import_tool(self, project, user, project_name=None, mount_point=None,
@@ -105,7 +105,7 @@ class GoogleRepoImporter(ToolImporter):
         """ Import a Google Code repo into a new SVN, Git, or Hg Allura tool.
 
         """
-        extractor = GoogleCodeProjectExtractor(project, project_name, 'source_browse')
+        extractor = GoogleCodeProjectExtractor(project_name, 'source_browse')
         repo_type = extractor.get_repo_type()
         repo_url = get_repo_url(project_name, repo_type)
         app = project.install_app(


[4/6] git commit: [#6464] Added skip_mod_date to GC tracker importer

Posted by jo...@apache.org.
[#6464] Added skip_mod_date to GC tracker importer

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/7b967a3a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/7b967a3a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/7b967a3a

Branch: refs/heads/cj/6464
Commit: 7b967a3acdce634b0ba71c46257b162cd71903a5
Parents: cf27f31
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Thu Aug 8 21:10:24 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Aug 8 21:10:24 2013 +0000

----------------------------------------------------------------------
 ForgeImporters/forgeimporters/google/tracker.py | 23 ++++++++++++--------
 1 file changed, 14 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7b967a3a/ForgeImporters/forgeimporters/google/tracker.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/google/tracker.py b/ForgeImporters/forgeimporters/google/tracker.py
index a997429..bd3a57f 100644
--- a/ForgeImporters/forgeimporters/google/tracker.py
+++ b/ForgeImporters/forgeimporters/google/tracker.py
@@ -21,6 +21,7 @@ from datetime import datetime
 from pylons import tmpl_context as c
 from ming.orm import session, ThreadLocalORMSession
 
+from allura import model as M
 from allura.lib import helpers as h
 
 from forgetracker.tracker_main import ForgeTrackerApp
@@ -48,15 +49,19 @@ class GoogleCodeTrackerImporter(ToolImporter):
         c.app.globals.open_status_names = 'New Accepted Started'
         c.app.globals.closed_status_names = 'Fixed Verified Invalid Duplicate WontFix Done'
         self.custom_fields = {}
-        for issue in GoogleCodeProjectExtractor.iter_issues(project_name):
-            ticket = TM.Ticket.new()
-            self.process_fields(ticket, issue)
-            self.process_labels(ticket, issue)
-            self.process_comments(ticket, issue)
-            session(ticket).flush(ticket)
-            session(ticket).expunge(ticket)
-        self.postprocess_custom_fields()
-        ThreadLocalORMSession.flush_all()
+        try:
+            M.session.artifact_orm_session._get().skip_mod_date = True
+            for issue in GoogleCodeProjectExtractor.iter_issues(project_name):
+                ticket = TM.Ticket.new()
+                self.process_fields(ticket, issue)
+                self.process_labels(ticket, issue)
+                self.process_comments(ticket, issue)
+                session(ticket).flush(ticket)
+                session(ticket).expunge(ticket)
+            self.postprocess_custom_fields()
+            ThreadLocalORMSession.flush_all()
+        finally:
+            M.session.artifact_orm_session._get().skip_mod_date = False
 
     def custom_field(self, name):
         if name not in self.custom_fields:


[6/6] git commit: [#6464] Added tests for GC tracker attachments and comments

Posted by jo...@apache.org.
[#6464] Added tests for GC tracker attachments and comments

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/ff155b60
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/ff155b60
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/ff155b60

Branch: refs/heads/cj/6464
Commit: ff155b60f3f8b93989d3ef0d5a5bf38be6d0dfff
Parents: eadde65
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Fri Aug 9 16:25:01 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Fri Aug 9 16:33:13 2013 +0000

----------------------------------------------------------------------
 .../forgeimporters/google/__init__.py           |  2 +-
 .../tests/data/google/test-issue.html           | 38 +++++++++++++
 .../tests/google/test_extractor.py              | 59 ++++++++++++++++++++
 .../forgeimporters/tests/google/test_tracker.py |  4 +-
 4 files changed, 100 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ff155b60/ForgeImporters/forgeimporters/google/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/google/__init__.py b/ForgeImporters/forgeimporters/google/__init__.py
index f39fcb1..a69f757 100644
--- a/ForgeImporters/forgeimporters/google/__init__.py
+++ b/ForgeImporters/forgeimporters/google/__init__.py
@@ -197,7 +197,7 @@ class Comment(object):
     def __init__(self, tag):
         self.author = UserLink(tag.find('span', 'author').find('a', 'userlink'))
         self.created_date = tag.find('span', 'date').get('title')
-        self.body = _as_text(tag.find('pre'))
+        self.body = _as_text(tag.find('pre')).strip()
         self._get_updates(tag)
         self._get_attachments(tag)
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ff155b60/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/data/google/test-issue.html b/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
index 04667ac..dbef54e 100644
--- a/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
+++ b/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
@@ -282,6 +282,44 @@ That's all
 
 
 </pre>
+<div class="attachments">
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at1.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=7&amp;aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255">Download</a>
+</td>
+</tr>
+</table>
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000001&amp;name=at2.txt&amp;token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at2.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=7&amp;aid=70000001&amp;name=at2.txt&amp;token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000001&amp;name=at2.txt&amp;token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255">Download</a>
+</td>
+</tr>
+</table>
+</div>
 </div>
 <div class="cursor_off vt issuecomment" id="hc1">
 <div style="float:right; margin-right:.3em; text-align:right">

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ff155b60/ForgeImporters/forgeimporters/tests/google/test_extractor.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/google/test_extractor.py b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
index 9d176f6..d433fd2 100644
--- a/ForgeImporters/forgeimporters/tests/google/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
@@ -175,3 +175,62 @@ class TestGoogleCodeProjectExtractor(TestCase):
                 'OpSys-Windows',
                 'OpSys-OSX',
             ])
+
+    def test_get_issue_attachments(self):
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
+        gpe = self._make_extractor(test_issue)
+        attachments = gpe.get_issue_attachments()
+        self.assertEqual(len(attachments), 2)
+        self.assertEqual(attachments[0].filename, 'at1.txt')
+        self.assertEqual(attachments[0].url, 'http://allura-google-importer.googlecode.com/issues/attachment?aid=70000000&name=at1.txt&token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255')
+        self.assertIsNone(attachments[0].type)
+        self.assertEqual(attachments[1].filename, 'at2.txt')
+        self.assertEqual(attachments[1].url, 'http://allura-google-importer.googlecode.com/issues/attachment?aid=70000001&name=at2.txt&token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255')
+        self.assertIsNone(attachments[1].type)
+
+    def test_iter_comments(self):
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
+        gpe = self._make_extractor(test_issue)
+        comments = list(gpe.iter_comments())
+        self.assertEqual(len(comments), 4)
+        expected = [
+                {
+                    'author.name': 'john...@gmail.com',
+                    'author.link': 'http://code.google.com/u/101557263855536553789/',
+                    'created_date': 'Thu Aug  8 15:35:15 2013',
+                    'body': 'Test *comment* is a comment',
+                    'updates': {'Status:': 'Started', 'Labels:': '-OpSys-Linux OpSys-Windows'},
+                    'attachments': ['at2.txt'],
+                },
+                {
+                    'author.name': 'john...@gmail.com',
+                    'author.link': 'http://code.google.com/u/101557263855536553789/',
+                    'created_date': 'Thu Aug  8 15:35:34 2013',
+                    'body': 'Another comment',
+                    'updates': {},
+                    'attachments': [],
+                },
+                {
+                    'author.name': 'john...@gmail.com',
+                    'author.link': 'http://code.google.com/u/101557263855536553789/',
+                    'created_date': 'Thu Aug  8 15:36:39 2013',
+                    'body': 'Last comment',
+                    'updates': {},
+                    'attachments': ['at4.txt', 'at1.txt'],
+                },
+                {
+                    'author.name': 'john...@gmail.com',
+                    'author.link': 'http://code.google.com/u/101557263855536553789/',
+                    'created_date': 'Thu Aug  8 15:36:57 2013',
+                    'body': 'Oh, I forgot one',
+                    'updates': {'Labels:': 'OpSys-OSX'},
+                    'attachments': [],
+                },
+            ]
+        for actual, expected in zip(comments, expected):
+            self.assertEqual(actual.author.name, expected['author.name'])
+            self.assertEqual(actual.author.link, expected['author.link'])
+            self.assertEqual(actual.created_date, expected['created_date'])
+            self.assertEqual(actual.body, expected['body'])
+            self.assertEqual(actual.updates, expected['updates'])
+            self.assertEqual([a.filename for a in actual.attachments], expected['attachments'])

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ff155b60/ForgeImporters/forgeimporters/tests/google/test_tracker.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/google/test_tracker.py b/ForgeImporters/forgeimporters/tests/google/test_tracker.py
index 62493bd..a1f0a28 100644
--- a/ForgeImporters/forgeimporters/tests/google/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/google/test_tracker.py
@@ -116,7 +116,7 @@ class TestTrackerImporter(TestCase):
             return u
         issue = mock.Mock(
                 get_issue_summary=lambda:'summary',
-                get_issue_description=lambda:'description',
+                get_issue_description=lambda:'my *description* fool',
                 get_issue_status=lambda:'status',
                 get_issue_created_date=lambda:'created_date',
                 get_issue_mod_date=lambda:'mod_date',
@@ -128,7 +128,7 @@ class TestTrackerImporter(TestCase):
             dt.strptime.side_effect = lambda s,f: s
             importer.process_fields(ticket, issue)
             self.assertEqual(ticket.summary, 'summary')
-            self.assertEqual(ticket.description, '*Originally created by:* [cname](clink)\n*Originally owned by:* [oname](olink)\n\ndescription')
+            self.assertEqual(ticket.description, '*Originally created by:* [cname](clink)\n*Originally owned by:* [oname](olink)\n\nmy \*description\* fool')
             self.assertEqual(ticket.status, 'status')
             self.assertEqual(ticket.created_date, 'created_date')
             self.assertEqual(ticket.mod_date, 'mod_date')


[3/6] git commit: [#6464] Use plain2markdown to escape ticket description and comments in GC Issues importer

Posted by jo...@apache.org.
[#6464] Use plain2markdown to escape ticket description and comments in GC Issues importer

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/cf27f311
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/cf27f311
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/cf27f311

Branch: refs/heads/cj/6464
Commit: cf27f311449972993f2c28aa543695e26023c7f3
Parents: 52f4555
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Thu Aug 8 20:44:54 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Aug 8 20:44:54 2013 +0000

----------------------------------------------------------------------
 ForgeImporters/forgeimporters/google/tracker.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/cf27f311/ForgeImporters/forgeimporters/google/tracker.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/google/tracker.py b/ForgeImporters/forgeimporters/google/tracker.py
index 297f65a..a997429 100644
--- a/ForgeImporters/forgeimporters/google/tracker.py
+++ b/ForgeImporters/forgeimporters/google/tracker.py
@@ -80,7 +80,7 @@ class GoogleCodeTrackerImporter(ToolImporter):
                 '{body}').format(
                     creator=issue.get_issue_creator(),
                     owner=issue.get_issue_owner(),
-                    body=issue.get_issue_description(),
+                    body=h.plain2markdown(issue.get_issue_description(), True),
                 )
         ticket.add_multiple_attachments(issue.get_issue_attachments())
 
@@ -108,7 +108,7 @@ class GoogleCodeTrackerImporter(ToolImporter):
                         '\n'
                         '{updates}').format(
                             author=comment.author,
-                            body=comment.body,
+                            body=h.plain2markdown(comment.body, True),
                             updates='\n'.join(
                                 '**%s** %s' % (k,v)
                                 for k,v in comment.updates.items()


[2/6] git commit: [#6464] Refactored plain2markdown to Allura helpers

Posted by jo...@apache.org.
[#6464] Refactored plain2markdown to Allura helpers

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/52f45556
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/52f45556
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/52f45556

Branch: refs/heads/cj/6464
Commit: 52f455564ad0538a5bd6897f29883778a149ac07
Parents: 0457b1f
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Thu Aug 8 18:49:51 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Aug 8 18:49:51 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/helpers.py            | 44 ++++++++++++++++++++++++++++
 ForgeBlog/forgeblog/command/rssfeeds.py | 36 +----------------------
 2 files changed, 45 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/52f45556/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 1604aa9..9f6fbfc 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -78,6 +78,26 @@ re_clean_vardec_key = re.compile(r'''\A
 )+
 \Z''', re.VERBOSE)
 
+# markdown escaping regexps
+re_amp = re.compile(r'''
+    [&]          # amp
+    (?=          # look ahead for:
+      ([a-zA-Z0-9]+;)  # named HTML entity
+      |
+      (\#[0-9]+;)      # decimal entity
+      |
+      (\#x[0-9A-F]+;)  # hex entity
+    )
+    ''', re.VERBOSE)
+re_leading_spaces = re.compile(r'^[\t ]+', re.MULTILINE)
+re_preserve_spaces = re.compile(r'''
+    [ ]           # space
+    (?=[ ])       # lookahead for a space
+    ''', re.VERBOSE)
+re_angle_bracket_open = re.compile('<')
+re_angle_bracket_close = re.compile('>')
+md_chars_matcher_all = re.compile(r"([`\*_{}\[\]\(\)#!\\.+-])")
+
 def make_safe_path_portion(ustr, relaxed=True):
     """Return an ascii representation of ``ustr`` that conforms to mount point
     naming :attr:`rules <re_tool_mount_point_fragment>`.
@@ -857,3 +877,27 @@ def split_select_field_options(field_options):
         # so we're getting rid of those.
         field_options = [o.replace('"', '') for o in field_options]
     return field_options
+
+
+def plain2markdown(text, preserve_multiple_spaces=False, has_html_entities=False):
+    if not has_html_entities:
+        # prevent &foo; and &#123; from becoming HTML entities
+        text = re_amp.sub('&amp;', text)
+    # avoid accidental 4-space indentations creating code blocks
+    if preserve_multiple_spaces:
+        text = text.replace('\t', ' ' * 4)
+        text = re_preserve_spaces.sub('&nbsp;', text)
+    else:
+        text = re_leading_spaces.sub('', text)
+    try:
+        # try to use html2text for most of the escaping
+        import html2text
+        html2text.BODY_WIDTH = 0
+        text = html2text.escape_md_section(text, snob=True)
+    except ImportError:
+        # fall back to just escaping any MD-special chars
+        text = md_chars_matcher.sub(r"\\\\1", text)
+    # prevent < and > from becoming tags
+    text = re_angle_bracket_open.sub('&lt;', text)
+    text = re_angle_bracket_close.sub('&gt;', text)
+    return text

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/52f45556/ForgeBlog/forgeblog/command/rssfeeds.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/command/rssfeeds.py b/ForgeBlog/forgeblog/command/rssfeeds.py
index 9f44fd4..8297c79 100644
--- a/ForgeBlog/forgeblog/command/rssfeeds.py
+++ b/ForgeBlog/forgeblog/command/rssfeeds.py
@@ -34,6 +34,7 @@ from forgeblog import version
 from forgeblog.main import ForgeBlogApp
 from allura.lib import exceptions
 from allura.lib.decorators import exceptionless
+from allura.lib.helpers import plain2markdown
 
 ## Everything in this file depends on html2text,
 ## so import attempt is placed in global scope.
@@ -45,41 +46,6 @@ except ImportError:
 
 html2text.BODY_WIDTH = 0
 
-re_amp = re.compile(r'''
-    [&]          # amp
-    (?=          # look ahead for:
-      ([a-zA-Z0-9]+;)  # named HTML entity
-      |
-      (\#[0-9]+;)      # decimal entity
-      |
-      (\#x[0-9A-F]+;)  # hex entity
-    )
-    ''', re.VERBOSE)
-re_leading_spaces = re.compile(r'^[\t ]+', re.MULTILINE)
-re_preserve_spaces = re.compile(r'''
-    [ ]           # space
-    (?=[ ])       # lookahead for a space
-    ''', re.VERBOSE)
-re_angle_bracket_open = re.compile('<')
-re_angle_bracket_close = re.compile('>')
-def plain2markdown(text, preserve_multiple_spaces=False, has_html_entities=False):
-    if not has_html_entities:
-        # prevent &foo; and &#123; from becoming HTML entities
-        text = re_amp.sub('&amp;', text)
-    # avoid accidental 4-space indentations creating code blocks
-    if preserve_multiple_spaces:
-        text = text.replace('\t', ' ' * 4)
-        text = re_preserve_spaces.sub('&nbsp;', text)
-    else:
-        text = re_leading_spaces.sub('', text)
-    # use html2text for most of the escaping
-    text = html2text.escape_md_section(text, snob=True)
-    # prevent < and > from becoming tags
-    text = re_angle_bracket_open.sub('&lt;', text)
-    text = re_angle_bracket_close.sub('&gt;', text)
-    return text
-
-
 class RssFeedsCommand(base.BlogCommand):
     summary = 'Rss feed client'
     parser = base.BlogCommand.standard_parser(verbose=True)


[5/6] git commit: [#6464] Fixed attribute error on missing / empty GC issue fields and added tests

Posted by jo...@apache.org.
[#6464] Fixed attribute error on missing / empty GC issue fields and added tests

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/eadde653
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/eadde653
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/eadde653

Branch: refs/heads/cj/6464
Commit: eadde6536dce9becd89623f84463133ccd83c42c
Parents: 7b967a3
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Fri Aug 9 14:35:59 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Fri Aug 9 14:35:59 2013 +0000

----------------------------------------------------------------------
 .../forgeimporters/google/__init__.py           |  14 +-
 .../tests/data/google/empty-issue.html          | 306 ++++++++++++
 .../tests/data/google/test-issue.html           | 488 +++++++++++++++++++
 .../tests/google/test_extractor.py              |  58 +++
 4 files changed, 863 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/eadde653/ForgeImporters/forgeimporters/google/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/google/__init__.py b/ForgeImporters/forgeimporters/google/__init__.py
index a2a335d..f39fcb1 100644
--- a/ForgeImporters/forgeimporters/google/__init__.py
+++ b/ForgeImporters/forgeimporters/google/__init__.py
@@ -146,7 +146,7 @@ class GoogleCodeProjectExtractor(object):
         return self.page.find(id='issueheader').findAll('td', limit=2)[1].span.string.strip()
 
     def get_issue_description(self):
-        return _as_text(self.page.find(id='hc0').pre)
+        return _as_text(self.page.find(id='hc0').pre).strip()
 
     def get_issue_created_date(self):
         return self.page.find(id='hc0').find('span', 'date').get('title')
@@ -160,10 +160,18 @@ class GoogleCodeProjectExtractor(object):
         return UserLink(a)
 
     def get_issue_status(self):
-        return self.page.find(id='issuemeta').find('th', text=re.compile('Status:')).findNext().span.string.strip()
+        tag = self.page.find(id='issuemeta').find('th', text=re.compile('Status:')).findNext().span
+        if tag:
+            return tag.string.strip()
+        else:
+            return ''
 
     def get_issue_owner(self):
-        return UserLink(self.page.find(id='issuemeta').find('th', text=re.compile('Owner:')).findNext().a)
+        tag = self.page.find(id='issuemeta').find('th', text=re.compile('Owner:')).findNext().a
+        if tag:
+            return UserLink(tag)
+        else:
+            return None
 
     def get_issue_labels(self):
         label_nodes = self.page.find(id='issuemeta').findAll('a', 'label')

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/eadde653/ForgeImporters/forgeimporters/tests/data/google/empty-issue.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/data/google/empty-issue.html b/ForgeImporters/forgeimporters/tests/data/google/empty-issue.html
new file mode 100644
index 0000000..a8fb1d5
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/data/google/empty-issue.html
@@ -0,0 +1,306 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+<meta name="ROBOTS" content="NOARCHIVE" />
+<link rel="icon" type="image/vnd.microsoft.icon" href="http://www.gstatic.com/codesite/ph/images/phosting.ico" />
+<script type="text/javascript">
+
+
+
+
+ var codesite_token = null;
+
+
+ var CS_env = {"assetHostPath":"http://www.gstatic.com/codesite/ph","projectHomeUrl":"/p/allura-google-importer","relativeBaseUrl":"","domainName":null,"projectName":"allura-google-importer","loggedInUserEmail":null,"profileUrl":null,"token":null,"assetVersionPath":"http://www.gstatic.com/codesite/ph/3783617020303179221"};
+ var _gaq = _gaq || [];
+ _gaq.push(
+ ['siteTracker._setAccount', 'UA-18071-1'],
+ ['siteTracker._trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
+ })();
+
+ </script>
+<title>Issue 5 -
+ allura-google-importer -
+
+ Empty Issue -
+ Import Google Code projects to an Allura forge - Google Project Hosting
+ </title>
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/core.css" />
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/ph_detail.css" />
+<!--[if IE]>
+ <link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/d_ie.css" >
+<![endif]-->
+<style type="text/css">
+ .menuIcon.off { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -42px }
+ .menuIcon.on { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -28px }
+ .menuIcon.down { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 0; }
+
+
+ .attachments { width:33%; border-top:2px solid #999; padding-top: 3px; margin-left: .7em;}
+ .attachments table { margin-bottom: 0.75em; }
+ .attachments table tr td { padding: 0; margin: 0; font-size: 95%; }
+ .preview { border: 2px solid #c3d9ff; padding: 1px; }
+ .preview:hover { border: 2px solid blue; }
+ .label { white-space: nowrap; }
+ .derived { font-style:italic }
+ .cursor_on .author {
+ background: url(http://www.gstatic.com/codesite/ph/images/show-arrow.gif) no-repeat 2px;
+ }
+ .hiddenform {
+ display: none;
+ }
+
+
+ </style>
+</head>
+<body class="t3">
+<script type="text/javascript">
+ window.___gcfg = {lang: 'en'};
+ (function()
+ {var po = document.createElement("script");
+ po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(po, s);
+ })();
+</script>
+<div class="headbg">
+<div id="gaia">
+<span>
+<a href="#" id="projects-dropdown" onclick="return false;"><u>My favorites</u> <small>&#9660;</small></a>
+ | <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D5&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D5" onclick="_CS_click('/gb/ph/signin');"><u>Sign in</u></a>
+</span>
+</div>
+<div class="gbh" style="left: 0pt;"></div>
+<div class="gbh" style="right: 0pt;"></div>
+<div style="height: 1px"></div>
+<!--[if lte IE 7]>
+<div style="text-align:center;">
+Your version of Internet Explorer is not supported. Try a browser that
+contributes to open source, such as <a href="http://www.firefox.com">Firefox</a>,
+<a href="http://www.google.com/chrome">Google Chrome</a>, or
+<a href="http://code.google.com/chrome/chromeframe/">Google Chrome Frame</a>.
+</div>
+<![endif]-->
+<table style="padding:0px; margin: 0px 0px 10px 0px; width:100%" cellpadding="0" cellspacing="0" itemscope="itemscope" itemtype="http://schema.org/CreativeWork">
+<tr style="height: 58px;">
+<td id="plogo">
+<link itemprop="url" href="/p/allura-google-importer" />
+<a href="/p/allura-google-importer/">
+<img src="/p/allura-google-importer/logo?cct=1374769571" alt="Logo" itemprop="image" />
+</a>
+</td>
+<td style="padding-left: 0.5em">
+<div id="pname">
+<a href="/p/allura-google-importer/"><span itemprop="name">allura-google-importer</span></a>
+</div>
+<div id="psum">
+<a id="project_summary_link" href="/p/allura-google-importer/"><span itemprop="description">Import Google Code projects to an Allura forge</span></a>
+</div>
+</td>
+<td style="white-space:nowrap;text-align:right; vertical-align:bottom;">
+<form action="/hosting/search">
+<input size="30" name="q" value="" type="text" />
+<input type="submit" name="projectsearch" value="Search projects" />
+</form>
+</td></tr>
+</table>
+</div>
+<div id="mt" class="gtb">
+<a href="/p/allura-google-importer/" class="tab ">Project&nbsp;Home</a>
+<a href="/p/allura-google-importer/wiki/TestPage?tm=6" class="tab ">Wiki</a>
+<a href="/p/allura-google-importer/issues/list" class="tab active">Issues</a>
+<a href="/p/allura-google-importer/source/checkout" class="tab ">Source</a>
+<div class="gtbc"></div>
+</div>
+<table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st">
+<tr>
+<td class="subt">
+<div class="issueDetail">
+<div class="isf">
+<span class="inIssueEntry">
+<a class="buttonify" href="entry" onclick="return _newIssuePrompt();">New issue</a>
+</span> &nbsp;
+
+ <span class="inIssueList">
+<span>Search</span>
+</span><form action="list" method="GET" style="display:inline">
+<select id="can" name="can">
+<option disabled="disabled">Search within:</option>
+<option value="1">&nbsp;All issues</option>
+<option value="2" selected="selected">&nbsp;Open issues</option>
+<option value="6">&nbsp;New issues</option>
+<option value="7">&nbsp;Issues to verify</option>
+</select>
+<span>for</span>
+<span id="qq"><input type="text" size="38" id="searchq" name="q" value="" autocomplete="off" onkeydown="_blurOnEsc(event)" /></span>
+<span id="search_colspec"><input type="hidden" name="colspec" value="ID Type Status Priority Milestone Owner Summary" /></span>
+<input type="hidden" name="cells" value="tiles" />
+<input type="submit" value="Search" />
+</form>
+ &nbsp;
+ <span class="inIssueAdvSearch">
+<a href="advsearch">Advanced search</a>
+</span> &nbsp;
+ <span class="inIssueSearchTips">
+<a href="searchtips">Search tips</a>
+</span> &nbsp;
+ <span class="inIssueSubscriptions">
+<a href="/p/allura-google-importer/issues/subscriptions">Subscriptions</a>
+</span>
+</div>
+</div>
+</td>
+<td align="right" valign="top" class="bevel-right"></td>
+</tr>
+</table>
+<script type="text/javascript">
+ var cancelBubble = false;
+ function _go(url) { document.location = url; }
+</script>
+<div id="maincol">
+<div id="color_control" class="">
+<div id="issueheader">
+<table cellpadding="0" cellspacing="0" width="100%"><tbody>
+<tr>
+<td class="vt h3" nowrap="nowrap" style="padding:0 5px">
+
+
+ Issue <a href="detail?id=5">5</a>:
+ </td>
+<td width="90%" class="vt">
+<span class="h3">Empty Issue</span>
+</td>
+<td>
+<div class="pagination">
+<a href="../../allura-google-importer/issues/detail?id=4" title="Prev">&lsaquo; Prev</a>
+ 5 of 5
+
+ </div>
+</td>
+</tr>
+<tr>
+<td></td>
+<td nowrap="nowrap">
+
+
+ 1 person starred this issue and may be notified of changes.
+
+
+
+ </td>
+<td align="center" nowrap="nowrap">
+<a href="http://code.google.com/p/allura-google-importer/issues/list?cursor=allura-google-importer%3A5">Back to list</a>
+</td>
+</tr>
+</tbody></table>
+</div>
+<table width="100%" cellpadding="0" cellspacing="0" border="0" class="issuepage" id="meta-container">
+<tbody class="collapse">
+<tr>
+<td id="issuemeta">
+<div id="meta-float">
+<table cellspacing="0" cellpadding="0">
+<tr><th align="left">Status:&nbsp;</th>
+<td width="100%">
+
+
+ ----
+
+
+ </td>
+</tr>
+<tr><th align="left">Owner:&nbsp;</th><td>
+
+
+ ----
+
+
+ </td>
+</tr>
+<tr><td colspan="2">
+</td></tr>
+</table>
+<div class="rel_issues">
+</div>
+<br /><br />
+<div style="white-space:nowrap"><a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D5&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D5">Sign in</a> to add a comment</div>
+</div>&nbsp;
+ </td>
+<td class="vt issuedescription" width="100%" id="cursorarea">
+<div class="cursor_off vt issuedescription" id="hc0">
+<div class="author">
+<span class="role_label">Project Member</span>
+ Reported by
+
+
+ <a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a>,
+ <span class="date" title="Thu Aug  8 14:56:23 2013">Today (15 minutes ago)</span>
+</div>
+<pre>
+Empty
+</pre>
+</div>
+</td>
+</tr>
+<tr>
+<td></td>
+<td class="vt issuecomment">
+<span class="indicator">&#9658;</span> <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D5&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D5">Sign in</a> to add a comment
+ </td>
+</tr>
+</tbody>
+</table>
+<br />
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/dit_scripts.js"></script>
+</div>
+<form name="delcom" action="delComment.do?q=&amp;can=2&amp;groupby=&amp;sort=&amp;colspec=ID+Type+Status+Priority+Milestone+Owner+Summary" method="POST">
+<input type="hidden" name="sequence_num" value="" />
+<input type="hidden" name="mode" value="" />
+<input type="hidden" name="id" value="5" />
+<input type="hidden" name="token" value="" />
+</form>
+<div id="helparea"></div>
+<script type="text/javascript">
+ _onload();
+ function delComment(sequence_num, delete_mode) {
+ var f = document.forms["delcom"];
+ f.sequence_num.value = sequence_num;
+ f.mode.value = delete_mode;
+
+ f.submit();
+ return false;
+ }
+
+ _floatMetadata();
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/kibbles.js"></script>
+<script type="text/javascript">
+ _setupKibblesOnDetailPage(
+ 'http://code.google.com/p/allura-google-importer/issues/list?cursor\x3dallura-google-importer%3A5',
+ '/p/allura-google-importer/issues/entry',
+ '../../allura-google-importer/issues/detail?id\x3d4',
+ '',
+ '', 'allura-google-importer', 5,
+ false, false, codesite_token);
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/ph_core.js"></script>
+</div>
+<div id="footer" dir="ltr">
+<div class="text">
+<a href="/projecthosting/terms.html">Terms</a> -
+ <a href="http://www.google.com/privacy.html">Privacy</a> -
+ <a href="/p/support/">Project Hosting Help</a>
+</div>
+</div>
+<div class="hostedBy" style="margin-top: -20px;">
+<span style="vertical-align: top;">Powered by <a href="http://code.google.com/projecthosting/">Google Project Hosting</a></span>
+</div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/eadde653/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/data/google/test-issue.html b/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
new file mode 100644
index 0000000..04667ac
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
@@ -0,0 +1,488 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+<meta name="ROBOTS" content="NOARCHIVE" />
+<link rel="icon" type="image/vnd.microsoft.icon" href="http://www.gstatic.com/codesite/ph/images/phosting.ico" />
+<script type="text/javascript">
+
+
+
+
+ var codesite_token = null;
+
+
+ var CS_env = {"loggedInUserEmail":null,"relativeBaseUrl":"","projectHomeUrl":"/p/allura-google-importer","assetVersionPath":"http://www.gstatic.com/codesite/ph/3783617020303179221","assetHostPath":"http://www.gstatic.com/codesite/ph","domainName":null,"projectName":"allura-google-importer","token":null,"profileUrl":null};
+ var _gaq = _gaq || [];
+ _gaq.push(
+ ['siteTracker._setAccount', 'UA-18071-1'],
+ ['siteTracker._trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
+ })();
+
+ </script>
+<title>Issue 6 -
+ allura-google-importer -
+
+ Test Issue -
+ Import Google Code projects to an Allura forge - Google Project Hosting
+ </title>
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/core.css" />
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/ph_detail.css" />
+<!--[if IE]>
+ <link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/d_ie.css" >
+<![endif]-->
+<style type="text/css">
+ .menuIcon.off { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -42px }
+ .menuIcon.on { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -28px }
+ .menuIcon.down { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 0; }
+
+
+ .attachments { width:33%; border-top:2px solid #999; padding-top: 3px; margin-left: .7em;}
+ .attachments table { margin-bottom: 0.75em; }
+ .attachments table tr td { padding: 0; margin: 0; font-size: 95%; }
+ .preview { border: 2px solid #c3d9ff; padding: 1px; }
+ .preview:hover { border: 2px solid blue; }
+ .label { white-space: nowrap; }
+ .derived { font-style:italic }
+ .cursor_on .author {
+ background: url(http://www.gstatic.com/codesite/ph/images/show-arrow.gif) no-repeat 2px;
+ }
+ .hiddenform {
+ display: none;
+ }
+
+
+ </style>
+</head>
+<body class="t3">
+<script type="text/javascript">
+ window.___gcfg = {lang: 'en'};
+ (function()
+ {var po = document.createElement("script");
+ po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(po, s);
+ })();
+</script>
+<div class="headbg">
+<div id="gaia">
+<span>
+<a href="#" id="projects-dropdown" onclick="return false;"><u>My favorites</u> <small>&#9660;</small></a>
+ | <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6" onclick="_CS_click('/gb/ph/signin');"><u>Sign in</u></a>
+</span>
+</div>
+<div class="gbh" style="left: 0pt;"></div>
+<div class="gbh" style="right: 0pt;"></div>
+<div style="height: 1px"></div>
+<!--[if lte IE 7]>
+<div style="text-align:center;">
+Your version of Internet Explorer is not supported. Try a browser that
+contributes to open source, such as <a href="http://www.firefox.com">Firefox</a>,
+<a href="http://www.google.com/chrome">Google Chrome</a>, or
+<a href="http://code.google.com/chrome/chromeframe/">Google Chrome Frame</a>.
+</div>
+<![endif]-->
+<table style="padding:0px; margin: 0px 0px 10px 0px; width:100%" cellpadding="0" cellspacing="0" itemscope="itemscope" itemtype="http://schema.org/CreativeWork">
+<tr style="height: 58px;">
+<td id="plogo">
+<link itemprop="url" href="/p/allura-google-importer" />
+<a href="/p/allura-google-importer/">
+<img src="/p/allura-google-importer/logo?cct=1374769571" alt="Logo" itemprop="image" />
+</a>
+</td>
+<td style="padding-left: 0.5em">
+<div id="pname">
+<a href="/p/allura-google-importer/"><span itemprop="name">allura-google-importer</span></a>
+</div>
+<div id="psum">
+<a id="project_summary_link" href="/p/allura-google-importer/"><span itemprop="description">Import Google Code projects to an Allura forge</span></a>
+</div>
+</td>
+<td style="white-space:nowrap;text-align:right; vertical-align:bottom;">
+<form action="/hosting/search">
+<input size="30" name="q" value="" type="text" />
+<input type="submit" name="projectsearch" value="Search projects" />
+</form>
+</td></tr>
+</table>
+</div>
+<div id="mt" class="gtb">
+<a href="/p/allura-google-importer/" class="tab ">Project&nbsp;Home</a>
+<a href="/p/allura-google-importer/wiki/TestPage?tm=6" class="tab ">Wiki</a>
+<a href="/p/allura-google-importer/issues/list" class="tab active">Issues</a>
+<a href="/p/allura-google-importer/source/checkout" class="tab ">Source</a>
+<div class="gtbc"></div>
+</div>
+<table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st">
+<tr>
+<td class="subt">
+<div class="issueDetail">
+<div class="isf">
+<span class="inIssueEntry">
+<a class="buttonify" href="entry" onclick="return _newIssuePrompt();">New issue</a>
+</span> &nbsp;
+
+ <span class="inIssueList">
+<span>Search</span>
+</span><form action="list" method="GET" style="display:inline">
+<select id="can" name="can">
+<option disabled="disabled">Search within:</option>
+<option value="1">&nbsp;All issues</option>
+<option value="2" selected="selected">&nbsp;Open issues</option>
+<option value="6">&nbsp;New issues</option>
+<option value="7">&nbsp;Issues to verify</option>
+</select>
+<span>for</span>
+<span id="qq"><input type="text" size="38" id="searchq" name="q" value="" autocomplete="off" onkeydown="_blurOnEsc(event)" /></span>
+<span id="search_colspec"><input type="hidden" name="colspec" value="ID Type Status Priority Milestone Owner Summary" /></span>
+<input type="hidden" name="cells" value="tiles" />
+<input type="submit" value="Search" />
+</form>
+ &nbsp;
+ <span class="inIssueAdvSearch">
+<a href="advsearch">Advanced search</a>
+</span> &nbsp;
+ <span class="inIssueSearchTips">
+<a href="searchtips">Search tips</a>
+</span> &nbsp;
+ <span class="inIssueSubscriptions">
+<a href="/p/allura-google-importer/issues/subscriptions">Subscriptions</a>
+</span>
+</div>
+</div>
+</td>
+<td align="right" valign="top" class="bevel-right"></td>
+</tr>
+</table>
+<script type="text/javascript">
+ var cancelBubble = false;
+ function _go(url) { document.location = url; }
+</script>
+<div id="maincol">
+<div id="color_control" class="">
+<div id="issueheader">
+<table cellpadding="0" cellspacing="0" width="100%"><tbody>
+<tr>
+<td class="vt h3" nowrap="nowrap" style="padding:0 5px">
+
+
+ Issue <a href="detail?id=6">6</a>:
+ </td>
+<td width="90%" class="vt">
+<span class="h3">Test Issue</span>
+</td>
+<td>
+<div class="pagination">
+<a href="../../allura-google-importer/issues/detail?id=5" title="Prev">&lsaquo; Prev</a>
+ 6 of 6
+
+ </div>
+</td>
+</tr>
+<tr>
+<td></td>
+<td nowrap="nowrap">
+
+
+ 1 person starred this issue and may be notified of changes.
+
+
+
+ </td>
+<td align="center" nowrap="nowrap">
+<a href="http://code.google.com/p/allura-google-importer/issues/list?cursor=allura-google-importer%3A6">Back to list</a>
+</td>
+</tr>
+</tbody></table>
+</div>
+<table width="100%" cellpadding="0" cellspacing="0" border="0" class="issuepage" id="meta-container">
+<tbody class="collapse">
+<tr>
+<td id="issuemeta">
+<div id="meta-float">
+<table cellspacing="0" cellpadding="0">
+<tr><th align="left">Status:&nbsp;</th>
+<td width="100%">
+<span title="Work on this issue has begun">Started</span>
+</td>
+</tr>
+<tr><th align="left">Owner:&nbsp;</th><td>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a>
+</td>
+</tr>
+<tr><td colspan="2">
+<div style="padding-top:2px">
+<a href="list?q=label:Type-Defect" title="Report of a software defect" class="label"><b>Type-</b>Defect</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Priority-Medium" title="Normal priority" class="label"><b>Priority-</b>Medium</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Milestone-Release1.0" title="All essential functionality working" class="label"><b>Milestone-</b>Release1.0</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-All" title="Affects all operating systems" class="label"><b>OpSys-</b>All</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Component-Logic" title="Issue relates to application logic" class="label"><b>Component-</b>Logic</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Performance" title="Performance issue" class="label">Performance</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Security" title="Security risk to users" class="label">Security</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-Windows" title="Affects Windows users" class="label"><b>OpSys-</b>Windows</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-OSX" title="Affects Mac OS X users" class="label"><b>OpSys-</b>OSX</a>
+</div>
+</td></tr>
+</table>
+<div class="rel_issues">
+</div>
+<br /><br />
+<div style="white-space:nowrap"><a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6">Sign in</a> to add a comment</div>
+</div>&nbsp;
+ </td>
+<td class="vt issuedescription" width="100%" id="cursorarea">
+<div class="cursor_off vt issuedescription" id="hc0">
+<div class="author">
+<span class="role_label">Project Member</span>
+ Reported by
+
+
+ <a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a>,
+ <span class="date" title="Thu Aug  8 15:33:52 2013">Today (3 minutes ago)</span>
+</div>
+<pre>
+Test *Issue* for testing
+
+  1. Test List
+  2. Item
+
+**Testing**
+
+ * Test list 2
+ * Item
+
+# Test Section
+
+    p = source.test_issue.post()
+    p.count = p.count *5 #* 6
+
+That's all
+
+
+</pre>
+</div>
+<div class="cursor_off vt issuecomment" id="hc1">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:35:15 2013">
+ Today (2 minutes ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c1" href="/p/allura-google-importer/issues/detail?id=6#c1">#1</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Test *comment* is a comment
+</pre>
+<div class="attachments">
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60001000&amp;name=at2.txt&amp;token=JOSo4duwaN2FCKZrwYOQ-nx9r7U%3A1376001446667">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at2.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=6&amp;aid=60001000&amp;name=at2.txt&amp;token=JOSo4duwaN2FCKZrwYOQ-nx9r7U%3A1376001446667" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60001000&amp;name=at2.txt&amp;token=JOSo4duwaN2FCKZrwYOQ-nx9r7U%3A1376001446667">Download</a>
+</td>
+</tr>
+</table>
+</div>
+<div class="updates">
+<div class="round4"></div>
+<div class="round2"></div>
+<div class="round1"></div>
+<div class="box-inner">
+<b>Status:</b>
+ Started
+
+ <br />
+<b>Labels:</b>
+ -OpSys-Linux OpSys-Windows
+
+ <br />
+</div>
+<div class="round1"></div>
+<div class="round2"></div>
+<div class="round4"></div>
+</div>
+</div>
+<div class="cursor_off vt issuecomment" id="hc2">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:35:34 2013">
+ Today (1 minute ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c2" href="/p/allura-google-importer/issues/detail?id=6#c2">#2</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Another comment
+</pre>
+</div>
+<div class="cursor_off vt issuecomment" id="hc3">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:36:39 2013">
+ Today (moments ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c3" href="/p/allura-google-importer/issues/detail?id=6#c3">#3</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Last comment
+</pre>
+<div class="attachments">
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003000&amp;name=at4.txt&amp;token=6Ny2zYHmV6b82dqxyoiH6HUYoC4%3A1376001446667">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at4.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=6&amp;aid=60003000&amp;name=at4.txt&amp;token=6Ny2zYHmV6b82dqxyoiH6HUYoC4%3A1376001446667" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003000&amp;name=at4.txt&amp;token=6Ny2zYHmV6b82dqxyoiH6HUYoC4%3A1376001446667">Download</a>
+</td>
+</tr>
+</table>
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003001&amp;name=at1.txt&amp;token=NS8aMvWsKzTAPuY2kniJG5aLzPg%3A1376001446667">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at1.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=6&amp;aid=60003001&amp;name=at1.txt&amp;token=NS8aMvWsKzTAPuY2kniJG5aLzPg%3A1376001446667" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003001&amp;name=at1.txt&amp;token=NS8aMvWsKzTAPuY2kniJG5aLzPg%3A1376001446667">Download</a>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="cursor_off vt issuecomment" id="hc4">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:36:57 2013">
+ Today (moments ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c4" href="/p/allura-google-importer/issues/detail?id=6#c4">#4</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Oh, I forgot one
+</pre>
+<div class="updates">
+<div class="round4"></div>
+<div class="round2"></div>
+<div class="round1"></div>
+<div class="box-inner">
+<b>Labels:</b>
+ OpSys-OSX
+
+ <br />
+</div>
+<div class="round1"></div>
+<div class="round2"></div>
+<div class="round4"></div>
+</div>
+</div>
+</td>
+</tr>
+<tr>
+<td></td>
+<td class="vt issuecomment">
+<span class="indicator">&#9658;</span> <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6">Sign in</a> to add a comment
+ </td>
+</tr>
+</tbody>
+</table>
+<br />
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/dit_scripts.js"></script>
+</div>
+<form name="delcom" action="delComment.do?q=&amp;can=2&amp;groupby=&amp;sort=&amp;colspec=ID+Type+Status+Priority+Milestone+Owner+Summary" method="POST">
+<input type="hidden" name="sequence_num" value="" />
+<input type="hidden" name="mode" value="" />
+<input type="hidden" name="id" value="6" />
+<input type="hidden" name="token" value="" />
+</form>
+<div id="helparea"></div>
+<script type="text/javascript">
+ _onload();
+ function delComment(sequence_num, delete_mode) {
+ var f = document.forms["delcom"];
+ f.sequence_num.value = sequence_num;
+ f.mode.value = delete_mode;
+
+ f.submit();
+ return false;
+ }
+
+ _floatMetadata();
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/kibbles.js"></script>
+<script type="text/javascript">
+ _setupKibblesOnDetailPage(
+ 'http://code.google.com/p/allura-google-importer/issues/list?cursor\x3dallura-google-importer%3A6',
+ '/p/allura-google-importer/issues/entry',
+ '../../allura-google-importer/issues/detail?id\x3d5',
+ '',
+ '', 'allura-google-importer', 6,
+ false, false, codesite_token);
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/ph_core.js"></script>
+</div>
+<div id="footer" dir="ltr">
+<div class="text">
+<a href="/projecthosting/terms.html">Terms</a> -
+ <a href="http://www.google.com/privacy.html">Privacy</a> -
+ <a href="/p/support/">Project Hosting Help</a>
+</div>
+</div>
+<div class="hostedBy" style="margin-top: -20px;">
+<span style="vertical-align: top;">Powered by <a href="http://code.google.com/projecthosting/">Google Project Hosting</a></span>
+</div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/eadde653/ForgeImporters/forgeimporters/tests/google/test_extractor.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/google/test_extractor.py b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
index a2e4183..9d176f6 100644
--- a/ForgeImporters/forgeimporters/tests/google/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from unittest import TestCase
+import pkg_resources
 
 import mock
 
@@ -117,3 +118,60 @@ class TestGoogleCodeProjectExtractor(TestCase):
         with self.assertRaises(Exception) as cm:
             extractor.get_repo_type()
         self.assertEqual(str(cm.exception), "Unknown repo type: cvs")
+
+    def test_empty_issue(self):
+        empty_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/empty-issue.html')).read()
+        gpe = self._make_extractor(empty_issue)
+        self.assertIsNone(gpe.get_issue_owner())
+        self.assertEqual(gpe.get_issue_status(), '')
+        self.assertEqual(gpe.get_issue_attachments(), [])
+        self.assertEqual(list(gpe.iter_comments()), [])
+
+    def test_get_issue_basic_fields(self):
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
+        gpe = self._make_extractor(test_issue)
+        self.assertEqual(gpe.get_issue_creator().name, 'john...@gmail.com')
+        self.assertEqual(gpe.get_issue_creator().link, 'http://code.google.com/u/101557263855536553789/')
+        self.assertEqual(gpe.get_issue_owner().name, 'john...@gmail.com')
+        self.assertEqual(gpe.get_issue_owner().link, 'http://code.google.com/u/101557263855536553789/')
+        self.assertEqual(gpe.get_issue_status(), 'Started')
+        self.assertEqual(gpe.get_issue_summary(), 'Test Issue')
+        self.assertEqual(gpe.get_issue_description(),
+                'Test *Issue* for testing\n'
+                '\n'
+                '  1. Test List\n'
+                '  2. Item\n'
+                '\n'
+                '**Testing**\n'
+                '\n'
+                ' * Test list 2\n'
+                ' * Item\n'
+                '\n'
+                '# Test Section\n'
+                '\n'
+                '    p = source.test_issue.post()\n'
+                '    p.count = p.count *5 #* 6\n'
+                '\n'
+                'That\'s all'
+            )
+        self.assertEqual(gpe.get_issue_created_date(), 'Thu Aug  8 15:33:52 2013')
+
+    def test_get_issue_mod_date(self):
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
+        gpe = self._make_extractor(test_issue)
+        self.assertEqual(gpe.get_issue_mod_date(), 'Thu Aug  8 15:36:57 2013')
+
+    def test_get_issue_labels(self):
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
+        gpe = self._make_extractor(test_issue)
+        self.assertEqual(gpe.get_issue_labels(), [
+                'Type-Defect',
+                'Priority-Medium',
+                'Milestone-Release1.0',
+                'OpSys-All',
+                'Component-Logic',
+                'Performance',
+                'Security',
+                'OpSys-Windows',
+                'OpSys-OSX',
+            ])