You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2013/08/13 21:20:32 UTC

[1/8] git commit: [#6554] Fixed incorrect uses of h.re_project_name causing 404 in REST

Updated Branches:
  refs/heads/db/6482 db0bacbd2 -> 8c5ed28fe (forced update)


[#6554] Fixed incorrect uses of h.re_project_name causing 404 in REST

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/9e3e3941
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/9e3e3941
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/9e3e3941

Branch: refs/heads/db/6482
Commit: 9e3e39413fc2879b6a52ffdd5b6b45e142cf1f72
Parents: 3cd0160
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Mon Aug 12 19:47:18 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Aug 12 19:47:18 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/rest.py           |  7 ++++++-
 Allura/allura/model/project.py              |  6 ++++--
 Allura/allura/tests/functional/test_rest.py |  9 +++++++++
 Allura/allura/tests/model/test_project.py   | 10 ++++++----
 4 files changed, 25 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9e3e3941/Allura/allura/controllers/rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index c976c21..6a41be3 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -32,6 +32,8 @@ from ming.utils import LazyProperty
 from allura import model as M
 from allura.lib import helpers as h
 from allura.lib import security
+from allura.lib import plugin
+from allura.lib.exceptions import Invalid
 
 log = logging.getLogger(__name__)
 action_logger = h.log_action(log, 'API:')
@@ -243,7 +245,10 @@ class NeighborhoodRestController(object):
 
     @expose()
     def _lookup(self, name, *remainder):
-        if not h.re_project_name.match(name):
+        provider = plugin.ProjectRegistrationProvider.get()
+        try:
+            provider.shortname_validator.to_python(name, check_allowed=False, neighborhood=self._neighborhood)
+        except Invalid as e:
             raise exc.HTTPNotFound, name
         name = self._neighborhood.shortname_prefix + name
         project = M.Project.query.get(shortname=name, neighborhood_id=self._neighborhood._id, deleted=False)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9e3e3941/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 435cbbb..db7da13 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -638,9 +638,11 @@ class Project(MappedClass, ActivityNode, ActivityObject):
                 return ac
 
     def new_subproject(self, name, install_apps=True, user=None, project_name=None):
-        if not h.re_project_name.match(name):
-            raise exceptions.ToolError, 'Mount point "%s" is invalid' % name
         provider = plugin.ProjectRegistrationProvider.get()
+        try:
+            provider.shortname_validator.to_python(name, check_allowed=False, neighborhood=self.neighborhood)
+        except exceptions.Invalid as e:
+            raise exceptions.ToolError, 'Mount point "%s" is invalid' % name
         return provider.register_subproject(self, name, user or c.user, install_apps, project_name=project_name)
 
     def ordered_mounts(self, include_hidden=False):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9e3e3941/Allura/allura/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index fcfb373..d5ed769 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -27,6 +27,7 @@ from nose.tools import assert_equal, assert_in, assert_not_in
 from allura.tests import decorators as td
 from alluratest.controller import TestRestApiBase
 from allura.lib import helpers as h
+from allura.lib.exceptions import Invalid
 from allura import model as M
 
 class TestRestHome(TestRestApiBase):
@@ -141,3 +142,11 @@ class TestRestHome(TestRestApiBase):
                         'qux_24hr': 0,
                     },
                 })
+
+    def test_name_validation(self):
+        r = self.api_get('/rest/p/test/')
+        assert r.status_int == 200
+        with mock.patch('allura.lib.plugin.ProjectRegistrationProvider') as Provider:
+            Provider.get().shortname_validator.to_python.side_effect = Invalid('name', 'value', {})
+            r = self.api_get('/rest/p/test/')
+            assert r.status_int == 404

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9e3e3941/Allura/allura/tests/model/test_project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_project.py b/Allura/allura/tests/model/test_project.py
index 33791f4..2cd7892 100644
--- a/Allura/allura/tests/model/test_project.py
+++ b/Allura/allura/tests/model/test_project.py
@@ -28,8 +28,8 @@ from allura import model as M
 from allura.lib import helpers as h
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test, setup_global_objects
-from allura.lib.exceptions import ToolError
-from mock import MagicMock
+from allura.lib.exceptions import ToolError, Invalid
+from mock import MagicMock, patch
 
 
 def setUp():
@@ -93,8 +93,10 @@ def test_project():
 def test_subproject():
     project = M.Project.query.get(shortname='test')
     with td.raises(ToolError):
-        # name exceeds 15 chars
-        sp = project.new_subproject('test-project-nose')
+        with patch('allura.lib.plugin.ProjectRegistrationProvider') as Provider:
+            Provider.get().shortname_validator.to_python.side_effect = Invalid('name', 'value', {})
+            # name doesn't validate
+            sp = project.new_subproject('test-proj-nose')
     sp = project.new_subproject('test-proj-nose')
     spp = sp.new_subproject('spp')
     ThreadLocalORMSession.flush_all()


[4/8] git commit: [#4818] add admin extensions

Posted by br...@apache.org.
[#4818] add admin extensions


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

Branch: refs/heads/db/6482
Commit: 9805cd0f3761dc0666b409a45d96f6552f445be9
Parents: d43c254
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Aug 9 19:41:07 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Aug 13 15:56:11 2013 +0000

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py        | 17 ++++++++++
 Allura/allura/lib/app_globals.py             |  1 +
 Allura/allura/lib/plugin.py                  | 32 +++++++++++++++++++
 Allura/allura/tests/functional/test_admin.py | 39 +++++++++++++++++++++++
 4 files changed, 89 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9805cd0f/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index f8c8983..92efacb 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -139,6 +139,10 @@ class AdminApp(Application):
             links.append(SitemapEntry('Statistics', nbhd_admin_url+ 'stats/'))
             links.append(None)
             links.append(SitemapEntry('Help', nbhd_admin_url+ 'help/'))
+
+        for name, admin_extension in g.entry_points['admin'].iteritems():
+            admin_extension().update_project_sidebar_menu(links)
+
         return links
 
     def admin_menu(self):
@@ -147,6 +151,18 @@ class AdminApp(Application):
     def install(self, project):
         pass
 
+
+class AdminExtensionLookup(object):
+    
+    @expose()
+    def _lookup(self, name, *remainder):
+        for ext_name, admin_extension in g.entry_points['admin'].iteritems():
+            controller = admin_extension().project_admin_controllers.get(name)
+            if controller:
+                return controller(), remainder
+        raise exc.HTTPNotFound, name
+
+
 class ProjectAdminController(BaseController):
 
     def _check_security(self):
@@ -156,6 +172,7 @@ class ProjectAdminController(BaseController):
         self.permissions = PermissionsController()
         self.groups = GroupsController()
         self.audit = AuditController()
+        self.ext = AdminExtensionLookup()
 
     @with_trailing_slash
     @expose('jinja:allura.ext.admin:templates/project_admin.html')

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9805cd0f/Allura/allura/lib/app_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index bdcacf7..7f45f69 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -197,6 +197,7 @@ class Globals(object):
             spam=_cache_eps('allura.spam'),
             stats=_cache_eps('allura.stats'),
             site_stats=_cache_eps('allura.site_stats'),
+            admin=_cache_eps('allura.admin'),
             )
 
         # Zarkov logger

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9805cd0f/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 4afd9fc..f972c26 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -915,3 +915,35 @@ class LocalUserPreferencesProvider(UserPreferencesProvider):
         users = M.User.query.find(dict(
                 display_name=name_regex)).sort('username').all()
         return users
+
+
+class AdminExtension(object):
+    """
+    A base class for extending the admin areas in Allura.
+
+    After extending this, expose the app by adding an entry point in your
+    setup.py::
+
+        [allura.admin]
+        myadmin = foo.bar.baz:MyCustomAdmin
+
+    :ivar dict project_admin_controllers: Mapping of str (url component) to
+        Controllers.  Can be implemented as a ``@property`` function.  The str
+        url components will be mounted at /p/someproject/admin/ext/STR/ and will
+        invoke the Controller.
+    """
+
+    project_admin_controllers = {}
+
+    def update_project_sidebar_menu(self, sidebar_links):
+        """
+        Implement this function to modify the project sidebar.
+        Check `c.project` if you want to limit when this displays
+        (e.g. nbhd project, subproject, etc)
+
+        :param sidebar_links: project admin side bar links
+        :type sidebar_links: list of :class:`allura.app.SitemapEntry`
+
+        :rtype: ``None``
+        """
+        pass

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9805cd0f/Allura/allura/tests/functional/test_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index 7d630c9..adeb71b 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -24,6 +24,10 @@ from contextlib import contextmanager
 import PIL
 from nose.tools import assert_equals
 from ming.orm.ormsession import ThreadLocalORMSession
+from tg import expose
+from pylons import tmpl_context as c, app_globals as g
+import mock
+from BeautifulSoup import BeautifulSoup
 
 try:
     import sfx
@@ -33,6 +37,8 @@ except ImportError:
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura import model as M
+from allura.app import SitemapEntry
+from allura.lib.plugin import AdminExtension
 
 @contextmanager
 def audits(*messages):
@@ -726,3 +732,36 @@ class TestProjectAdmin(TestController):
         assert {u'text': u'Does not have permission create', u'has': u'no', u'name': u'create'} in r.json[admin_id]
         assert {u'text': u'Does not have permission create', u'has': u'no', u'name': u'create'} in r.json[mem_id]
         assert {u'text': u'Does not have permission create', u'has': u'no', u'name': u'create'} in r.json[anon_id]
+
+
+    def test_admin_extension_sidebar(self):
+
+        class FooSettingsController(object):
+            @expose()
+            def index(self, *a, **kw):
+                return 'here the foo settings go'
+
+
+        class FooSettingsExtension(AdminExtension):
+            def update_project_sidebar_menu(self, sidebar_links):
+                base_url = c.project.url()+'admin/ext/'
+                sidebar_links.append(SitemapEntry('Foo Settings', base_url+'foo'))
+
+            @property
+            def project_admin_controllers(self):
+                return {
+                    'foo': FooSettingsController,
+                }
+
+        eps = {
+            'admin': {
+                'foo-settings': FooSettingsExtension,
+            }
+        }
+
+        with mock.patch.dict(g.entry_points, eps):
+            main_page = self.app.get('/admin/')
+            foo_page = main_page.click(description='Foo Settings')
+            url = foo_page.environ['PATH_INFO']
+            assert url.endswith('/admin/ext/foo'), url
+            assert_equals('here the foo settings go', foo_page.body)


[2/8] git commit: [#6554] let ProjectConflict be constructed with a single string, like it did before adding Invalid as a parent

Posted by br...@apache.org.
[#6554] let ProjectConflict be constructed with a single string, like it did before adding Invalid as a parent


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

Branch: refs/heads/db/6482
Commit: d43c25447577c512a991b6c70b703fc8438c4cc3
Parents: 9e3e394
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Mon Aug 12 21:34:43 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon Aug 12 21:34:43 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/exceptions.py | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/d43c2544/Allura/allura/lib/exceptions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/exceptions.py b/Allura/allura/lib/exceptions.py
index 4c33991..7611dd7 100644
--- a/Allura/allura/lib/exceptions.py
+++ b/Allura/allura/lib/exceptions.py
@@ -18,7 +18,14 @@
 from formencode import Invalid
 
 class ForgeError(Exception): pass
-class ProjectConflict(ForgeError, Invalid): pass
+
+class ProjectConflict(ForgeError, Invalid):
+
+    # support the single string constructor in addition to full set of params that Invalid.__init__ requires
+    def __init__(self, msg, value=None, state=None, error_list=None, error_dict=None):
+        super(ProjectConflict, self).__init__(msg, value, state, error_list, error_dict)
+
+
 class ProjectShortnameInvalid(ForgeError, Invalid): pass
 class ProjectOverlimitError(ForgeError): pass
 class ProjectRatelimitError(ForgeError): pass
@@ -45,4 +52,3 @@ class CompoundError(ForgeError):
                 parts.append('    ' + line)
         parts.append('</%s>\n' % self.__class__.__name__ )
         return ''.join(parts)
-                


[3/8] git commit: [#6482] import page for existing projects

Posted by br...@apache.org.
[#6482] import page for existing projects


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

Branch: refs/heads/db/6482
Commit: 42d01eacdd9efc256858d5ec1ee53c35ba02fca9
Parents: 9ac5e8c
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Aug 9 22:14:07 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Aug 13 15:56:11 2013 +0000

----------------------------------------------------------------------
 ForgeImporters/forgeimporters/base.py           | 45 ++++++++++++--
 .../forgeimporters/templates/list_all.html      | 62 ++++++++++++++++++++
 ForgeImporters/setup.py                         |  3 +
 3 files changed, 104 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42d01eac/ForgeImporters/forgeimporters/base.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index 8cc3b52..324516d 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -21,14 +21,16 @@ from pkg_resources import iter_entry_points
 
 from tg import expose, validate, flash, redirect, config
 from tg.decorators import with_trailing_slash
-from pylons import tmpl_context as c
+from pylons import tmpl_context as c, app_globals as g
 from formencode import validators as fev, schema
+from webob import exc
 
 from allura.lib.decorators import require_post
 from allura.lib.decorators import task
 from allura.lib.security import require_access
-from allura.lib.plugin import ProjectRegistrationProvider
+from allura.lib.plugin import ProjectRegistrationProvider, AdminExtension
 from allura.lib import exceptions
+from allura.app import SitemapEntry
 
 from paste.deploy.converters import aslist
 
@@ -189,16 +191,16 @@ class ToolImporter(object):
     source = None  # string description of source, must match project importer
     controller = None
 
-    @classmethod
-    def by_name(self, name):
+    @staticmethod
+    def by_name(name):
         """
         Return a ToolImporter subclass instance given its entry-point name.
         """
         for ep in iter_entry_points('allura.importers', name):
             return ep.load()()
 
-    @classmethod
-    def by_app(self, app):
+    @staticmethod
+    def by_app(app):
         """
         Return a ToolImporter subclass instance given its target_app class.
         """
@@ -266,3 +268,34 @@ class ToolsValidator(fev.Set):
             pl = 's' if len(invalid) > 1 else ''
             raise fev.Invalid('Invalid tool%s selected: %s' % (pl, ', '.join(invalid)), value, state)
         return valid
+
+class ProjectToolsImportController(object):
+    '''List all importers available'''
+
+    @with_trailing_slash
+    @expose('jinja:forgeimporters:templates/list_all.html')
+    def index(self, *a, **kw):
+        importers = {}
+        for app_name, app in g.entry_points['tool'].iteritems():
+            importers[app] = ToolImporter.by_app(app)
+        return {
+            'importers': importers
+        }
+
+    @expose()
+    def _lookup(self, name, *remainder):
+        import_tool = ToolImporter.by_name(name)
+        if import_tool:
+            return import_tool.controller(), remainder
+        else:
+            raise exc.HTTPNotFound
+
+class ImportAdminExtension(AdminExtension):
+    '''Add import link to project admin sidebar'''
+
+    project_admin_controllers = {'import': ProjectToolsImportController}
+
+    def update_project_sidebar_menu(self, sidebar_links):
+        base_url = c.project.url() + 'admin/ext/'
+        link = SitemapEntry('Import', base_url+'import')
+        sidebar_links.append(link)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42d01eac/ForgeImporters/forgeimporters/templates/list_all.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/templates/list_all.html b/ForgeImporters/forgeimporters/templates/list_all.html
new file mode 100644
index 0000000..58c9f34
--- /dev/null
+++ b/ForgeImporters/forgeimporters/templates/list_all.html
@@ -0,0 +1,62 @@
+{#-
+       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 g.theme.master %}
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
+
+{% block title %}{{c.project.name}} / Import{% endblock %}
+
+{% block header %}Import from external sources{% endblock %}
+
+{% block extra_css %}
+<style type="text/css">
+    .tool {
+        margin-bottom: 3em;
+    }
+    .tool img {
+        float: left;
+        margin: 0 1em;
+    }
+    .importer .descr {
+        margin: 0 2em 1em 2em;
+    }
+</style>
+{% endblock %}
+
+{% block content %}
+    {% for tool, tool_importers in importers.iteritems() %}
+        <div class="tool">
+        {% for importer_name, importer in tool_importers.iteritems() %}
+            {% if loop.first %}
+                <img src="{{ g.theme.app_icon_url(tool, 48) }}" alt="{{ tool.tool_label }} icon">
+                <h2>{{ tool.tool_label }}</h2>
+            {% endif %}
+            <div class="importer">
+                <a href="{{importer_name}}"><h3>
+                {{importer.source}}:
+                {{importer.tool_label}}
+                </h3>
+                </a>
+                <div class="descr">
+                {{importer.tool_description}}
+                </div>
+            </div>
+        {% endfor %}
+        </div>
+    {% endfor %}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42d01eac/ForgeImporters/setup.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/setup.py b/ForgeImporters/setup.py
index b19fd17..d9af953 100644
--- a/ForgeImporters/setup.py
+++ b/ForgeImporters/setup.py
@@ -41,4 +41,7 @@ setup(name='ForgeImporters',
       google-code-tracker = forgeimporters.google.tracker:GoogleCodeTrackerImporter
       google-code-repo = forgeimporters.google.code:GoogleRepoImporter
       trac-tickets = forgeimporters.trac.tickets:TracTicketImporter
+
+      [allura.admin]
+      importers = forgeimporters.base:ImportAdminExtension
       """,)


[5/8] git commit: [#4818] sort entry points for reliable ordering

Posted by br...@apache.org.
[#4818] sort entry points for reliable ordering


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

Branch: refs/heads/db/6482
Commit: 9ac5e8c12deac1b6f86f61682f268b7d9f7d57f0
Parents: 77ab85b
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Aug 9 21:47:00 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Aug 13 15:56:11 2013 +0000

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9ac5e8c1/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 98a34c8..06aaec1 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -140,7 +140,8 @@ class AdminApp(Application):
             links.append(None)
             links.append(SitemapEntry('Help', nbhd_admin_url+ 'help/'))
 
-        for name, admin_extension in g.entry_points['admin'].iteritems():
+        for ep_name in sorted(g.entry_points['admin'].keys()):
+            admin_extension = g.entry_points['admin'][ep_name]
             admin_extension().update_project_sidebar_menu(links)
 
         return links
@@ -156,7 +157,8 @@ class AdminExtensionLookup(object):
 
     @expose()
     def _lookup(self, name, *remainder):
-        for ext_name, admin_extension in g.entry_points['admin'].iteritems():
+        for ep_name in sorted(g.entry_points['admin'].keys()):
+            admin_extension = g.entry_points['admin'][ep_name]
             controller = admin_extension().project_admin_controllers.get(name)
             if controller:
                 return controller(), remainder


[8/8] git commit: [#6482] change page to show importers in a grid

Posted by br...@apache.org.
[#6482] change page to show importers in a grid


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

Branch: refs/heads/db/6482
Commit: 8c5ed28fe6b2d4b05ad8e8a98226b632ff9e0829
Parents: 42d01ea
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Tue Aug 13 19:20:11 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Aug 13 19:20:11 2013 +0000

----------------------------------------------------------------------
 ForgeImporters/forgeimporters/base.py           | 31 +++++++++--
 .../forgeimporters/templates/list_all.html      | 58 ++++++++------------
 2 files changed, 51 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/8c5ed28f/ForgeImporters/forgeimporters/base.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index 324516d..518a26d 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 import logging
+from collections import defaultdict
 
 from pkg_resources import iter_entry_points
 
@@ -275,11 +276,33 @@ class ProjectToolsImportController(object):
     @with_trailing_slash
     @expose('jinja:forgeimporters:templates/list_all.html')
     def index(self, *a, **kw):
-        importers = {}
-        for app_name, app in g.entry_points['tool'].iteritems():
-            importers[app] = ToolImporter.by_app(app)
+        # make dictionaries of both axis
+        importers_by_source = defaultdict(dict)
+        importers_by_tool = defaultdict(dict)
+        for ep in iter_entry_points('allura.importers'):
+            importer = ep.load()
+            importers_by_source[importer.source][ep.name] = importer
+            for tool in aslist(importer.target_app):
+                importers_by_tool[tool][ep.name] = importer
+
+        relevant_tools = sorted(importers_by_tool.keys(), key=lambda t: t.tool_label)
+
+        # build a full matrix including empty spots
+        importer_matrix = dict() # source -> [importer names]
+        for source, src_importers in importers_by_source.iteritems():
+            row = list()
+            for tool in relevant_tools:
+                for ep_name, importer in src_importers.iteritems():
+                    if tool in aslist(importer.target_app):
+                        row.append(ep_name)
+                        break
+                else:
+                    row.append(None)
+            importer_matrix[source] = row
+
         return {
-            'importers': importers
+            'tools': relevant_tools,
+            'importer_matrix': importer_matrix,
         }
 
     @expose()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/8c5ed28f/ForgeImporters/forgeimporters/templates/list_all.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/templates/list_all.html b/ForgeImporters/forgeimporters/templates/list_all.html
index 58c9f34..b91e0df 100644
--- a/ForgeImporters/forgeimporters/templates/list_all.html
+++ b/ForgeImporters/forgeimporters/templates/list_all.html
@@ -21,42 +21,32 @@
 
 {% block title %}{{c.project.name}} / Import{% endblock %}
 
-{% block header %}Import from external sources{% endblock %}
-
-{% block extra_css %}
-<style type="text/css">
-    .tool {
-        margin-bottom: 3em;
-    }
-    .tool img {
-        float: left;
-        margin: 0 1em;
-    }
-    .importer .descr {
-        margin: 0 2em 1em 2em;
-    }
-</style>
-{% endblock %}
+{% block header %}Import{% endblock %}
 
 {% block content %}
-    {% for tool, tool_importers in importers.iteritems() %}
-        <div class="tool">
-        {% for importer_name, importer in tool_importers.iteritems() %}
-            {% if loop.first %}
-                <img src="{{ g.theme.app_icon_url(tool, 48) }}" alt="{{ tool.tool_label }} icon">
-                <h2>{{ tool.tool_label }}</h2>
-            {% endif %}
-            <div class="importer">
-                <a href="{{importer_name}}"><h3>
-                {{importer.source}}:
-                {{importer.tool_label}}
-                </h3>
-                </a>
-                <div class="descr">
-                {{importer.tool_description}}
-                </div>
-            </div>
+<p>
+    To import from one of these external sources into your project, just click on "Import" and fill out the form.
+</p>
+<table>
+    <thead>
+    <tr>
+        <th></th>
+        {% for tool in tools %}
+            <th>{{tool.tool_label}}</th>
+        {% endfor %}
+    </tr>
+    </thead>
+    {% for source, importers in importer_matrix|dictsort %}
+        <tr>
+        <td><strong>{{ source }}</strong></td>
+        {% for importer_name in importers %}
+            <td>
+                {% if importer_name %}
+                <a href="{{importer_name}}">Import</a>
+                {% endif %}
+            </td>
         {% endfor %}
-        </div>
+        </tr>
     {% endfor %}
+</table>
 {% endblock %}


[6/8] git commit: [#4818] add documentation for extensions

Posted by br...@apache.org.
[#4818] add documentation for extensions


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

Branch: refs/heads/db/6482
Commit: 3e0087c2a62573a51a2ca5d181508410bc532f24
Parents: 9805cd0
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Aug 9 19:41:28 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Aug 13 15:56:11 2013 +0000

----------------------------------------------------------------------
 Allura/allura/app.py               |  2 +-
 Allura/allura/lib/plugin.py        | 10 +++---
 Allura/docs/api/app.rst            | 13 +-------
 Allura/docs/api/lib/plugin.rst     | 24 ++++++++++++++
 Allura/docs/api/lib/spam.rst       | 24 ++++++++++++++
 Allura/docs/extending.rst          | 55 +++++++++++++++++++++++++++++++++
 Allura/docs/guides/message_bus.rst |  4 ++-
 Allura/docs/index.rst              |  3 +-
 8 files changed, 115 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/allura/app.py
----------------------------------------------------------------------
diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index c1d2517..5ac11f2 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -164,7 +164,7 @@ class Application(object):
     The base Allura pluggable application
 
     After extending this, expose the app by adding an entry point in your
-    setup.py:
+    setup.py::
 
         [allura]
         myapp = foo.bar.baz:MyAppClass

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index f972c26..f600363 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -56,12 +56,12 @@ class AuthenticationProvider(object):
     '''
     An interface to provide authentication services for Allura.
 
-    To use a new provider, expose an entry point in setup.py:
+    To use a new provider, expose an entry point in setup.py::
 
         [allura.auth]
         myprovider = foo.bar:MyAuthProvider
 
-    Then in your .ini file, set auth.method=myprovider
+    Then in your .ini file, set ``auth.method=myprovider``
     '''
 
     def __init__(self, request):
@@ -346,7 +346,7 @@ class ProjectRegistrationProvider(object):
     and the default.  Extend this class with your own if you need to add more
     functionality.
 
-    To use a new provider, expose an entry point in setup.py:
+    To use a new provider, expose an entry point in setup.py::
 
         [allura.project_registration]
         myprovider = foo.bar:MyAuthProvider
@@ -625,7 +625,7 @@ class ThemeProvider(object):
     and the default.  Extend this class with your own if you need to add more
     functionality.
 
-    To use a new provider, expose an entry point in setup.py:
+    To use a new provider, expose an entry point in setup.py::
 
         [allura.theme]
         myprovider = foo.bar:MyThemeProvider
@@ -855,7 +855,7 @@ class UserPreferencesProvider(object):
     '''
     An interface for user preferences, like display_name and email_address
 
-    To use a new provider, expose an entry point in setup.py:
+    To use a new provider, expose an entry point in setup.py::
 
         [allura.user_prefs]
         myprefs = foo.bar:MyUserPrefProvider

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/docs/api/app.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/api/app.rst b/Allura/docs/api/app.rst
index 491d0b4..f99a0c2 100644
--- a/Allura/docs/api/app.rst
+++ b/Allura/docs/api/app.rst
@@ -22,15 +22,4 @@
 
 .. automodule:: allura.app
 
-  .. autoclass:: Application
-      :members:
-
-  .. autoclass:: ConfigOption
-      :members:
-
-  .. autoclass:: DefaultAdminController
-      :members:
-
-  .. autoclass:: SitemapEntry
-      :members:
-
+    :members:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/docs/api/lib/plugin.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/api/lib/plugin.rst b/Allura/docs/api/lib/plugin.rst
new file mode 100644
index 0000000..77e619b
--- /dev/null
+++ b/Allura/docs/api/lib/plugin.rst
@@ -0,0 +1,24 @@
+..     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.
+
+.. _plugin_module:
+
+:mod:`allura.lib.plugin`
+-------------------------------------
+
+.. automodule:: allura.lib.plugin
+    :members:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/docs/api/lib/spam.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/api/lib/spam.rst b/Allura/docs/api/lib/spam.rst
new file mode 100644
index 0000000..b9558a3
--- /dev/null
+++ b/Allura/docs/api/lib/spam.rst
@@ -0,0 +1,24 @@
+..     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.
+
+.. _spam_module:
+
+:mod:`allura.lib.spam`
+-------------------------------------
+
+.. automodule:: allura.lib.spam
+    :members:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/docs/extending.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/extending.rst b/Allura/docs/extending.rst
new file mode 100644
index 0000000..a430202
--- /dev/null
+++ b/Allura/docs/extending.rst
@@ -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.
+
+Extending Allura with Entry Points
+===================================
+
+There are many extension points to extending Allura.  They all make themselves
+known to Allura via python entry points defined in ``setup.py``.  Many are then
+available immediately.  Others, such as authentication providers or themes, need
+to be specified in your ``.ini`` file, since you may only have one enabled at a time.
+
+The available extension points for Allura are:
+
+* :class:`allura.app.Application` (aka tool) and :class:`allura.app.Artifact`
+* :class:`allura.lib.plugin.ThemeProvider`
+* :class:`allura.lib.plugin.ProjectRegistrationProvider`
+* :class:`allura.lib.plugin.AuthenticationProvider`
+* :class:`allura.lib.plugin.UserPreferencesProvider`
+* :class:`allura.lib.plugin.AdminExtension`
+* :class:`allura.lib.spam.SpamFilter`
+* ``site_stats`` in the root API data.  Docs in :class:`allura.controllers.rest.RestController`
+* :mod:`allura.lib.package_path_loader` (for overriding templates)
+
+A listing of available 3rd-party extensions is at https://sourceforge.net/p/allura/wiki/Extensions/
+
+Other entry points are used to provider ``paster`` commands and ``easy_widget`` configuration.
+
+
+Event Handlers
+==============
+
+Another way to extend Allura is set up event handlers to respond to Allura events.
+There is documentation and examples at :ref:`events`.
+
+The events that allura publishes are:
+
+* project_created
+* project_updated
+* repo_cloned
+* repo_refreshed
+* repo_clone_task_failed
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/docs/guides/message_bus.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/guides/message_bus.rst b/Allura/docs/guides/message_bus.rst
index f8285e1..11067c9 100644
--- a/Allura/docs/guides/message_bus.rst
+++ b/Allura/docs/guides/message_bus.rst
@@ -61,6 +61,8 @@ well::
 
     commit()
 
+.. _events:
+
 Events
 -------------------
 
@@ -82,7 +84,7 @@ Under the covers, this is scheduling an `event` task that calls all the handlers
 for a particular named event.  Note that you can pass arguments (\*args, and
 \*\*kwargs) to event handlers just like you do to tasks, with the exception that
 the topic name (above, this would be 'project_updated') is always the first
-parameter passed to the event handler.  
+parameter passed to the event handler.
 
 Running the Task Daemon
 ----------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3e0087c2/Allura/docs/index.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/index.rst b/Allura/docs/index.rst
index 56b1b52..877b98d 100644
--- a/Allura/docs/index.rst
+++ b/Allura/docs/index.rst
@@ -57,12 +57,13 @@ Inside the Platform Components
    guides/message_bus
    guides/email
    guides/permissions
+   extending
 
 API Documentation
 ==================
 
 .. toctree::
-   :maxdepth: 1
+   :maxdepth: 2
    :glob:
 
    api/*


[7/8] git commit: [#4818] don't error if tool doesn't exist any more

Posted by br...@apache.org.
[#4818] don't error if tool doesn't exist any more


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

Branch: refs/heads/db/6482
Commit: 77ab85b6e0dd27e1540d323adc6c7469ac2f5b4a
Parents: 3e0087c
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Aug 9 20:01:21 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Aug 13 15:56:11 2013 +0000

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/77ab85b6/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 92efacb..98a34c8 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -153,7 +153,7 @@ class AdminApp(Application):
 
 
 class AdminExtensionLookup(object):
-    
+
     @expose()
     def _lookup(self, name, *remainder):
         for ext_name, admin_extension in g.entry_points['admin'].iteritems():
@@ -177,8 +177,11 @@ class ProjectAdminController(BaseController):
     @with_trailing_slash
     @expose('jinja:allura.ext.admin:templates/project_admin.html')
     def index(self, **kw):
-        scm_tools = [tool for tool in c.project.app_configs if issubclass(
-                g.entry_points["tool"][tool.tool_name], RepositoryApp)]
+        scm_tools = []
+        for tool in c.project.app_configs:
+            app = g.entry_points["tool"].get(tool.tool_name)
+            if app and issubclass(app, RepositoryApp):
+                scm_tools.append(tool)
         return dict(scm_tools=scm_tools)
 
     @without_trailing_slash