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/26 19:20:07 UTC

[3/6] git commit: [#6531] ticket:413 Project metadata importer for github

[#6531]  ticket:413 Project metadata importer for github


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

Branch: refs/heads/cj/6531
Commit: 69db59c23bf18cd9f53301bb3c048cdadf2b9e38
Parents: 1843655
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Tue Aug 20 13:18:20 2013 +0400
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Aug 26 17:19:57 2013 +0000

----------------------------------------------------------------------
 .../forgeimporters/github/__init__.py           | 43 +++++++++++++
 ForgeImporters/forgeimporters/github/project.py | 66 ++++++++++++++++++++
 ForgeImporters/forgeimporters/github/tasks.py   | 31 +++++++++
 .../github/templates/project.html               | 55 ++++++++++++++++
 .../forgeimporters/tests/github/__init__.py     | 17 +++++
 .../tests/github/functional/__init__.py         | 17 +++++
 .../tests/github/functional/test_github.py      | 28 +++++++++
 .../tests/github/test_extractor.py              | 48 ++++++++++++++
 .../forgeimporters/tests/github/test_tasks.py   | 31 +++++++++
 ForgeImporters/setup.py                         |  1 +
 10 files changed, 337 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/github/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/github/__init__.py b/ForgeImporters/forgeimporters/github/__init__.py
new file mode 100644
index 0000000..472429e
--- /dev/null
+++ b/ForgeImporters/forgeimporters/github/__init__.py
@@ -0,0 +1,43 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+
+import re
+import urllib
+import urllib2
+import json
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+import logging
+
+log = logging.getLogger(__name__)
+
+class GitHubProjectExtractor(object):
+    RE_REPO_TYPE = re.compile(r'(svn|hg|git)')
+    PAGE_MAP = {
+            'project_info': 'https://api.github.com/repos/%s',
+        }
+
+
+    def __init__(self, allura_project, gh_project_name, page):
+        self.project = allura_project
+        self.url = self.PAGE_MAP[page] % urllib.quote(gh_project_name)
+        self.page = json.loads(urllib2.urlopen(self.url).read().decode('utf8'))
+
+    def get_summmary(self):
+        self.project.summary = self.page['description']

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/github/project.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/github/project.py b/ForgeImporters/forgeimporters/github/project.py
new file mode 100644
index 0000000..4af2bdf
--- /dev/null
+++ b/ForgeImporters/forgeimporters/github/project.py
@@ -0,0 +1,66 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+
+import logging
+
+from formencode import validators as fev
+
+from tg import expose, validate
+from tg.decorators import with_trailing_slash
+
+from allura.lib.decorators import require_post
+
+from .. import base
+from . import tasks
+
+
+log = logging.getLogger(__name__)
+
+class GitHubProjectForm(base.ProjectImportForm):
+    project_name = fev.Regex(r'^[a-z0-9][a-z0-9-]{,61}$',
+            not_empty=True,
+            messages={
+                'invalid': 'Please use only letters, numbers, and dashes.',
+            })
+
+class GitHubProjectImporter(base.ProjectImporter):
+
+    source = 'GitHub'
+    index_template = 'jinja:forgeimporters.github:templates/project.html'
+    process_validator = GitHubProjectForm(source)
+
+    def after_project_create(self, project, **kw):
+        project.set_tool_data('github', project_name=project.name)
+        tasks.import_project_info.post(project.name)
+
+    @with_trailing_slash
+    @expose(index_template)
+    def index(self, **kw):
+        return super(self.__class__, self).index(**kw)
+
+    @require_post()
+    @expose()
+    @validate(process_validator)
+    def process(self, **kw):
+        kw['project_name'] = '%s/%s' % (kw['user_name'], kw['project_name'])
+        kw['tools'] = ''
+        return super(self.__class__, self).process(**kw)
+
+    @expose('json:')
+    @validate(process_validator)
+    def check_names(self, **kw):
+        return super(self.__class__, self).check_names(**kw)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/github/tasks.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/github/tasks.py b/ForgeImporters/forgeimporters/github/tasks.py
new file mode 100644
index 0000000..4fd928c
--- /dev/null
+++ b/ForgeImporters/forgeimporters/github/tasks.py
@@ -0,0 +1,31 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+
+from pylons import tmpl_context as c
+
+from ming.orm import ThreadLocalORMSession
+
+from allura.lib.decorators import task
+
+from . import GitHubProjectExtractor
+
+
+@task
+def import_project_info(project_name):
+    extractor = GitHubProjectExtractor(c.project, project_name, 'project_info')
+    extractor.get_summmary()
+    ThreadLocalORMSession.flush_all()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/github/templates/project.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/github/templates/project.html b/ForgeImporters/forgeimporters/github/templates/project.html
new file mode 100644
index 0000000..de42737
--- /dev/null
+++ b/ForgeImporters/forgeimporters/github/templates/project.html
@@ -0,0 +1,55 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+{% extends 'forgeimporters:templates/project_base.html' %}
+
+{% block project_fields %}
+    <div class="grid-6">
+        <label>GitHub User Name</label>
+    </div>
+     <div class="grid-10">
+        <input id="user_name" name="user_name" value="{{c.form_values['user_name']}}" autofocus/>
+         <div id="user_name_error" class="error{% if not c.form_errors['user_name'] %} hidden{% endif %}">
+            {{c.form_errors['user_name']}}
+        </div>
+    </div>
+
+
+    <div class="grid-6" style="clear:left">
+        <label>GitHub Project Name</label>
+    </div>
+     <div class="grid-10">
+        <input id="project_name" name="project_name" value="{{c.form_values['project_name']}}" autofocus/>
+        <div id="project_name_error" class="error{% if not c.form_errors['project_name'] %} hidden{% endif %}">
+            {{c.form_errors['project_name']}}
+        </div>
+    </div>
+
+    <div class="grid-6" style="clear:left">
+        <label>URL Name</label>
+    </div>
+    <div class="grid-10">
+        <input id="project_shortname" name="project_shortname" value="{{c.form_values['project_shortname']}}"/>
+        <div id="project_shortname_error" class="error{% if not c.form_errors['project_shortname'] %} hidden{% endif %}">
+            {{c.form_errors['project_shortname']}}
+        </div>
+        <div id="project-url">
+            http://{{request.environ['HTTP_HOST']}}{{importer.neighborhood.url()}}<span id="url-fragment">{{c.form_values['project_shortname']}}</span>
+        </div>
+    </div>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/tests/github/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/github/__init__.py b/ForgeImporters/forgeimporters/tests/github/__init__.py
new file mode 100644
index 0000000..77505f1
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/github/__init__.py
@@ -0,0 +1,17 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/tests/github/functional/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/github/functional/__init__.py b/ForgeImporters/forgeimporters/tests/github/functional/__init__.py
new file mode 100644
index 0000000..77505f1
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/github/functional/__init__.py
@@ -0,0 +1,17 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
new file mode 100644
index 0000000..6667e7b
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
@@ -0,0 +1,28 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+
+from unittest import TestCase
+from allura.tests import TestController
+
+class TestGitHubImportController(TestController, TestCase):
+
+    def test_index(self):
+        r = self.app.get('/p/import_project/github/')
+        assert 'GitHub Project Importer' in r
+        assert '<input id="user_name" name="user_name" value="" autofocus/>' in r
+        assert '<input id="project_name" name="project_name" value="" autofocus/>' in r
+        assert '<input id="project_shortname" name="project_shortname" value=""/>' in r

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/tests/github/test_extractor.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/github/test_extractor.py b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
new file mode 100644
index 0000000..a21f775
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
@@ -0,0 +1,48 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+
+from unittest import TestCase
+
+import mock
+
+from ... import github
+
+
+class TestGitHubProjectExtractor(TestCase):
+    def setUp(self):
+        self._p_urlopen = mock.patch.object(github.urllib2, 'urlopen')
+        self._p_json = mock.patch.object(github.json, 'loads')
+        self.urlopen = self._p_urlopen.start()
+        self.json = self._p_json.start()
+        self.project = mock.Mock(name='project')
+        self.project.get_tool_data.return_value = 'testproject'
+
+    def tearDown(self):
+        self._p_urlopen.stop()
+        self._p_json.stop()
+
+
+    def test_init(self):
+        extractor = github.GitHubProjectExtractor(self.project, 'testproject', 'project_info')
+        self.urlopen.assert_called_once_with('https://api.github.com/repos/testproject')
+        self.assertEqual(extractor.project, self.project)
+
+    def test_get_summary(self):
+        extractor = github.GitHubProjectExtractor(self.project, 'testproject', 'project_info')
+        extractor.page = {'description': 'test summary'}
+        extractor.get_summmary()
+        self.assertEqual(self.project.summary, 'test summary')

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/forgeimporters/tests/github/test_tasks.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/github/test_tasks.py b/ForgeImporters/forgeimporters/tests/github/test_tasks.py
new file mode 100644
index 0000000..b478bc9
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/github/test_tasks.py
@@ -0,0 +1,31 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+
+import mock
+
+from ...github import tasks
+
+
+@mock.patch.object(tasks, 'GitHubProjectExtractor')
+@mock.patch.object(tasks, 'ThreadLocalORMSession')
+@mock.patch.object(tasks, 'c')
+def test_import_project_info(c, session, ghpe):
+    c.project = mock.Mock(name='project')
+    tasks.import_project_info('my-project')
+    ghpe.assert_called_once_with(c.project, 'my-project', 'project_info')
+    ghpe.return_value.get_summmary.assert_called_once_with()
+    session.flush_all.assert_called_once_with()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69db59c2/ForgeImporters/setup.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/setup.py b/ForgeImporters/setup.py
index b19fd17..cec76b4 100644
--- a/ForgeImporters/setup.py
+++ b/ForgeImporters/setup.py
@@ -36,6 +36,7 @@ setup(name='ForgeImporters',
       [allura.project_importers]
       google-code = forgeimporters.google.project:GoogleCodeProjectImporter
       trac = forgeimporters.trac.project:TracProjectImporter
+      github = forgeimporters.github.project:GitHubProjectImporter
 
       [allura.importers]
       google-code-tracker = forgeimporters.google.tracker:GoogleCodeTrackerImporter