You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by tv...@apache.org on 2014/01/10 19:19:52 UTC

[28/32] PEP8 cleanup

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/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 f60bd39..607c151 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -52,13 +52,16 @@ from allura.lib.widgets.project_list import ProjectScreenshots
 
 log = logging.getLogger(__name__)
 
+
 class W:
     markdown_editor = ffw.MarkdownEdit()
     label_edit = ffw.LabelEdit()
-    mount_delete = ffw.Lightbox(name='mount_delete',trigger='a.mount_delete')
-    admin_modal = ffw.Lightbox(name='admin_modal',trigger='a.admin_modal')
-    install_modal = ffw.Lightbox(name='install_modal',trigger='a.install_trig')
-    explain_export_modal = ffw.Lightbox(name='explain_export',trigger='#why_export')
+    mount_delete = ffw.Lightbox(name='mount_delete', trigger='a.mount_delete')
+    admin_modal = ffw.Lightbox(name='admin_modal', trigger='a.admin_modal')
+    install_modal = ffw.Lightbox(
+        name='install_modal', trigger='a.install_trig')
+    explain_export_modal = ffw.Lightbox(
+        name='explain_export', trigger='#why_export')
     group_card = aw.GroupCard()
     permission_card = aw.PermissionCard()
     group_settings = aw.GroupSettings()
@@ -67,11 +70,11 @@ class W:
     screenshot_list = ProjectScreenshots()
     metadata_admin = aw.MetadataAdmin()
     audit = aw.AuditLog()
-    page_list=ffw.PageList()
-
+    page_list = ffw.PageList()
 
 
 class AdminApp(Application):
+
     '''This is the admin app.  It is pretty much required for
     a functioning allura project.
     '''
@@ -79,10 +82,10 @@ class AdminApp(Application):
     _installable_tools = None
     max_instances = 0
     tool_label = 'admin'
-    icons={
-        24:'images/admin_24.png',
-        32:'images/admin_32.png',
-        48:'images/admin_48.png'
+    icons = {
+        24: 'images/admin_24.png',
+        32: 'images/admin_32.png',
+        48: 'images/admin_48.png'
     }
     exportable = True
 
@@ -91,8 +94,9 @@ class AdminApp(Application):
         self.root = ProjectAdminController()
         self.api_root = ProjectAdminRestController()
         self.admin = AdminAppAdminController(self)
-        self.templates = pkg_resources.resource_filename('allura.ext.admin', 'templates')
-        self.sitemap = [ SitemapEntry('Admin','.')]
+        self.templates = pkg_resources.resource_filename(
+            'allura.ext.admin', 'templates')
+        self.sitemap = [SitemapEntry('Admin', '.')]
 
     def is_visible_to(self, user):
         '''Whether the user can view the app.'''
@@ -106,10 +110,11 @@ class AdminApp(Application):
             app = App(project, cfg)
             if app.installable:
                 tools.append(dict(name=name, app=App))
-            session(cfg).expunge(cfg)  # prevent from saving temporary config to db
+            # prevent from saving temporary config to db
+            session(cfg).expunge(cfg)
         tools.sort(key=lambda t: (t['app'].status_int(), t['app'].ordinal))
         return [t for t in tools
-            if t['app'].status in project.allowed_tool_status]
+                if t['app'].status in project.allowed_tool_status]
 
     @staticmethod
     def exportable_tools_for(project):
@@ -128,37 +133,40 @@ class AdminApp(Application):
     @h.exceptionless([], log)
     def sidebar_menu(self):
         links = []
-        admin_url = c.project.url()+'admin/'
-
+        admin_url = c.project.url() + 'admin/'
 
         if c.project.is_nbhd_project:
-            links.append(SitemapEntry('Add Project', c.project.url()+'add_project', ui_icon=g.icons['plus']))
-            nbhd_admin_url = c.project.neighborhood.url()+'_admin/'
+            links.append(SitemapEntry('Add Project', c.project.url()
+                         + 'add_project', ui_icon=g.icons['plus']))
+            nbhd_admin_url = c.project.neighborhood.url() + '_admin/'
             links = links + [
-                     SitemapEntry('Neighborhood'),
-                     SitemapEntry('Overview', nbhd_admin_url+'overview'),
-                     SitemapEntry('Awards', nbhd_admin_url+'accolades')]
+                SitemapEntry('Neighborhood'),
+                SitemapEntry('Overview', nbhd_admin_url + 'overview'),
+                SitemapEntry('Awards', nbhd_admin_url + 'accolades')]
         else:
-            links += [SitemapEntry('Metadata', admin_url+'overview'),]
+            links += [SitemapEntry('Metadata', admin_url + 'overview'), ]
             if c.project.neighborhood.name != "Users":
                 links += [
-                    SitemapEntry('Screenshots', admin_url+'screenshots'),
-                    SitemapEntry('Categorization', admin_url+'trove')
+                    SitemapEntry('Screenshots', admin_url + 'screenshots'),
+                    SitemapEntry('Categorization', admin_url + 'trove')
                 ]
-        links.append(SitemapEntry('Tools', admin_url+'tools'))
+        links.append(SitemapEntry('Tools', admin_url + 'tools'))
         if asbool(config.get('bulk_export_enabled', True)):
             links.append(SitemapEntry('Export', admin_url + 'export'))
         if c.project.is_root and has_access(c.project, 'admin')():
-            links.append(SitemapEntry('User Permissions', admin_url+'groups/'))
+            links.append(
+                SitemapEntry('User Permissions', admin_url + 'groups/'))
         if not c.project.is_root and has_access(c.project, 'admin')():
-            links.append(SitemapEntry('Permissions', admin_url+'permissions/'))
+            links.append(
+                SitemapEntry('Permissions', admin_url + 'permissions/'))
         if len(c.project.neighborhood_invitations):
-            links.append(SitemapEntry('Invitation(s)', admin_url+'invitations'))
-        links.append(SitemapEntry('Audit Trail', admin_url+ 'audit/'))
+            links.append(
+                SitemapEntry('Invitation(s)', admin_url + 'invitations'))
+        links.append(SitemapEntry('Audit Trail', admin_url + 'audit/'))
         if c.project.is_nbhd_project:
-            links.append(SitemapEntry('Statistics', nbhd_admin_url+ 'stats/'))
+            links.append(SitemapEntry('Statistics', nbhd_admin_url + 'stats/'))
             links.append(None)
-            links.append(SitemapEntry('Help', nbhd_admin_url+ 'help/'))
+            links.append(SitemapEntry('Help', nbhd_admin_url + 'help/'))
 
         for ep_name in sorted(g.entry_points['admin'].keys()):
             admin_extension = g.entry_points['admin'][ep_name]
@@ -245,10 +253,13 @@ class ProjectAdminController(BaseController):
     @expose('jinja:allura.ext.admin:templates/project_trove.html')
     def trove(self):
         c.label_edit = W.label_edit
-        base_troves = M.TroveCategory.query.find(dict(trove_parent_id=0)).sort('fullname').all()
-        topic_trove = M.TroveCategory.query.get(trove_parent_id=0,shortname='topic')
-        license_trove = M.TroveCategory.query.get(trove_parent_id=0,shortname='license')
-        return dict(base_troves=base_troves,license_trove=license_trove,topic_trove=topic_trove)
+        base_troves = M.TroveCategory.query.find(
+            dict(trove_parent_id=0)).sort('fullname').all()
+        topic_trove = M.TroveCategory.query.get(
+            trove_parent_id=0, shortname='topic')
+        license_trove = M.TroveCategory.query.get(
+            trove_parent_id=0, shortname='license')
+        return dict(base_troves=base_troves, license_trove=license_trove, topic_trove=topic_trove)
 
     @without_trailing_slash
     @expose('jinja:allura.ext.admin:templates/project_tools.html')
@@ -262,7 +273,8 @@ class ProjectAdminController(BaseController):
         return dict(
             mounts=mounts,
             installable_tools=AdminApp.installable_tools_for(c.project),
-            roles=M.ProjectRole.query.find(dict(project_id=c.project.root_project._id)).sort('_id').all(),
+            roles=M.ProjectRole.query.find(
+                dict(project_id=c.project.root_project._id)).sort('_id').all(),
             categories=M.ProjectCategory.query.find(dict(parent_id=None)).sort('label').all())
 
     @expose()
@@ -272,7 +284,8 @@ class ProjectAdminController(BaseController):
             grouping_threshold = int(grouping_threshold)
             if grouping_threshold < 1:
                 raise ValueError('Invalid threshold')
-            c.project.set_tool_data('allura', grouping_threshold=grouping_threshold)
+            c.project.set_tool_data(
+                'allura', grouping_threshold=grouping_threshold)
         except ValueError as e:
             flash('Invalid threshold', 'error')
         redirect('tools')
@@ -353,22 +366,26 @@ class ProjectAdminController(BaseController):
             c.project.removal = removal
             c.project.removal_changed_date = datetime.utcnow()
         if 'delete_icon' in kw:
-            M.ProjectFile.query.remove(dict(project_id=c.project._id, category='icon'))
+            M.ProjectFile.query.remove(
+                dict(project_id=c.project._id, category='icon'))
             M.AuditLog.log('remove project icon')
             h.log_action(log, 'remove project icon').info('')
             g.post_event('project_updated')
             redirect('overview')
         elif 'delete' in kw:
-            allow_project_delete = asbool(config.get('allow_project_delete', True))
+            allow_project_delete = asbool(
+                config.get('allow_project_delete', True))
             if allow_project_delete or not c.project.is_root:
                 M.AuditLog.log('delete project')
                 h.log_action(log, 'delete project').info('')
-                plugin.ProjectRegistrationProvider.get().delete_project(c.project, c.user)
+                plugin.ProjectRegistrationProvider.get().delete_project(
+                    c.project, c.user)
             redirect('overview')
         elif 'undelete' in kw:
             h.log_action(log, 'undelete project').info('')
             M.AuditLog.log('undelete project')
-            plugin.ProjectRegistrationProvider.get().undelete_project(c.project, c.user)
+            plugin.ProjectRegistrationProvider.get().undelete_project(
+                c.project, c.user)
             redirect('overview')
         if name != c.project.name:
             h.log_action(log, 'change project name').info('')
@@ -389,7 +406,8 @@ class ProjectAdminController(BaseController):
             c.project.category_id = category
         if external_homepage != c.project.external_homepage:
             h.log_action(log, 'change external home page').info('')
-            M.AuditLog.log('change external home page to %s', external_homepage)
+            M.AuditLog.log('change external home page to %s',
+                           external_homepage)
             c.project.external_homepage = external_homepage
         if support_page != c.project.support_page:
             h.log_action(log, 'change project support page').info('')
@@ -398,31 +416,37 @@ class ProjectAdminController(BaseController):
         old_twitter = c.project.social_account('Twitter')
         if not old_twitter or twitter_handle != old_twitter.accounturl:
             h.log_action(log, 'change project twitter handle').info('')
-            M.AuditLog.log('change project twitter handle to %s', twitter_handle)
+            M.AuditLog.log('change project twitter handle to %s',
+                           twitter_handle)
             c.project.set_social_account('Twitter', twitter_handle)
         old_facebook = c.project.social_account('Facebook')
         if not old_facebook or facebook_page != old_facebook.accounturl:
             if not facebook_page or 'facebook.com' in urlparse(facebook_page).netloc:
                 h.log_action(log, 'change project facebook page').info('')
-                M.AuditLog.log('change project facebook page to %s', facebook_page)
+                M.AuditLog.log(
+                    'change project facebook page to %s', facebook_page)
                 c.project.set_social_account('Facebook', facebook_page)
         if support_page_url != c.project.support_page_url:
             h.log_action(log, 'change project support page url').info('')
-            M.AuditLog.log('change project support page url to %s', support_page_url)
+            M.AuditLog.log('change project support page url to %s',
+                           support_page_url)
             c.project.support_page_url = support_page_url
         if moved_to_url != c.project.moved_to_url:
             h.log_action(log, 'change project moved to url').info('')
             M.AuditLog.log('change project moved to url to %s', moved_to_url)
             c.project.moved_to_url = moved_to_url
         if export_controlled != c.project.export_controlled:
-            h.log_action(log, 'change project export controlled status').info('')
-            M.AuditLog.log('change project export controlled status to %s', export_controlled)
+            h.log_action(
+                log, 'change project export controlled status').info('')
+            M.AuditLog.log(
+                'change project export controlled status to %s', export_controlled)
             c.project.export_controlled = not not export_controlled
             if not export_controlled:
                 export_control_type = None
         if export_control_type != c.project.export_control_type:
             h.log_action(log, 'change project export control type').info('')
-            M.AuditLog.log('change project export control type to %s', export_control_type)
+            M.AuditLog.log('change project export control type to %s',
+                           export_control_type)
             c.project.export_control_type = export_control_type
         if tracking_id != c.project.tracking_id:
             h.log_action(log, 'change project tracking ID').info('')
@@ -431,21 +455,22 @@ class ProjectAdminController(BaseController):
 
         if icon is not None and icon != '':
             if c.project.icon:
-                M.ProjectFile.remove(dict(project_id=c.project._id, category='icon'))
+                M.ProjectFile.remove(
+                    dict(project_id=c.project._id, category='icon'))
             M.AuditLog.log('update project icon')
             M.ProjectFile.save_image(
                 icon.filename, icon.file, content_type=icon.type,
-                square=True, thumbnail_size=(48,48),
-                thumbnail_meta=dict(project_id=c.project._id,category='icon'))
+                square=True, thumbnail_size=(48, 48),
+                thumbnail_meta=dict(project_id=c.project._id, category='icon'))
         g.post_event('project_updated')
         flash('Saved', 'success')
         redirect('overview')
 
     def _add_trove(self, type, new_trove):
-        current_troves = getattr(c.project,'trove_%s'%type)
+        current_troves = getattr(c.project, 'trove_%s' % type)
         trove_obj = M.TroveCategory.query.get(trove_cat_id=int(new_trove))
         error_msg = None
-        if type in ['license','audience','developmentstatus','language'] and len(current_troves) >= 6:
+        if type in ['license', 'audience', 'developmentstatus', 'language'] and len(current_troves) >= 6:
             error_msg = 'You may not have more than 6 of this category.'
         elif type in ['topic'] and len(current_troves) >= 3:
             error_msg = 'You may not have more than 3 of this category.'
@@ -453,7 +478,8 @@ class ProjectAdminController(BaseController):
             if trove_obj._id not in current_troves:
                 current_troves.append(trove_obj._id)
                 M.AuditLog.log('add trove %s: %s', type, trove_obj.fullpath)
-                ThreadLocalORMSession.flush_all()  # just in case the event handling is super fast
+                # just in case the event handling is super fast
+                ThreadLocalORMSession.flush_all()
                 c.project.last_updated = datetime.utcnow()
                 g.post_event('project_updated')
             else:
@@ -465,7 +491,7 @@ class ProjectAdminController(BaseController):
     def add_trove_js(self, type, new_trove, **kw):
         require_access(c.project, 'update')
         trove_obj, error_msg = self._add_trove(type, new_trove)
-        return dict(trove_full_path = trove_obj.fullpath, trove_cat_id = trove_obj.trove_cat_id, error_msg=error_msg)
+        return dict(trove_full_path=trove_obj.fullpath, trove_cat_id=trove_obj.trove_cat_id, error_msg=error_msg)
 
     @expose()
     @require_post()
@@ -473,7 +499,7 @@ class ProjectAdminController(BaseController):
         require_access(c.project, 'update')
         trove_obj, error_msg = self._add_trove(type, new_trove)
         if error_msg:
-            flash(error_msg,'error')
+            flash(error_msg, 'error')
         redirect('trove')
 
     @expose()
@@ -481,11 +507,12 @@ class ProjectAdminController(BaseController):
     def delete_trove(self, type, trove, **kw):
         require_access(c.project, 'update')
         trove_obj = M.TroveCategory.query.get(trove_cat_id=int(trove))
-        current_troves = getattr(c.project,'trove_%s'%type)
+        current_troves = getattr(c.project, 'trove_%s' % type)
         if trove_obj is not None and trove_obj._id in current_troves:
             M.AuditLog.log('remove trove %s: %s', type, trove_obj.fullpath)
             current_troves.remove(trove_obj._id)
-            ThreadLocalORMSession.flush_all()  # just in case the event handling is super fast
+            # just in case the event handling is super fast
+            ThreadLocalORMSession.flush_all()
             c.project.last_updated = datetime.utcnow()
             g.post_event('project_updated')
         redirect('trove')
@@ -497,7 +524,8 @@ class ProjectAdminController(BaseController):
         require_access(c.project, 'update')
         screenshots = c.project.get_screenshots()
         if len(screenshots) >= 6:
-            flash('You may not have more than 6 screenshots per project.','error')
+            flash('You may not have more than 6 screenshots per project.',
+                  'error')
         elif screenshot is not None and screenshot != '':
             M.AuditLog.log('add screenshot')
             sort = 1 + max([ss.sort or 0 for ss in screenshots] or [0])
@@ -509,8 +537,8 @@ class ProjectAdminController(BaseController):
                     category='screenshot',
                     caption=caption,
                     sort=sort),
-                square=True, thumbnail_size=(150,150),
-                thumbnail_meta=dict(project_id=c.project._id,category='screenshot_thumb'))
+                square=True, thumbnail_size=(150, 150),
+                thumbnail_meta=dict(project_id=c.project._id, category='screenshot_thumb'))
             g.post_event('project_updated')
         redirect('screenshots')
 
@@ -536,7 +564,8 @@ class ProjectAdminController(BaseController):
         require_access(c.project, 'update')
         if id is not None and id != '':
             M.AuditLog.log('remove screenshot')
-            M.ProjectFile.query.remove(dict(project_id=c.project._id, _id=ObjectId(id)))
+            M.ProjectFile.query.remove(
+                dict(project_id=c.project._id, _id=ObjectId(id)))
             g.post_event('project_updated')
         redirect('screenshots')
 
@@ -545,7 +574,8 @@ class ProjectAdminController(BaseController):
     def edit_screenshot(self, id=None, caption=None, **kw):
         require_access(c.project, 'update')
         if id is not None and id != '':
-            M.ProjectFile.query.get(project_id=c.project._id, _id=ObjectId(id)).caption=caption
+            M.ProjectFile.query.get(
+                project_id=c.project._id, _id=ObjectId(id)).caption = caption
             g.post_event('project_updated')
         redirect('screenshots')
 
@@ -578,12 +608,15 @@ class ProjectAdminController(BaseController):
                 p.ordinal = int(sp['ordinal'])
         if tools:
             for p in tools:
-                c.project.app_config(p['mount_point']).options.ordinal = int(p['ordinal'])
+                c.project.app_config(
+                    p['mount_point']).options.ordinal = int(p['ordinal'])
         redirect('tools')
 
     def _update_mounts(self, subproject=None, tool=None, new=None, **kw):
-        if subproject is None: subproject = []
-        if tool is None: tool = []
+        if subproject is None:
+            subproject = []
+        if tool is None:
+            tool = []
         for sp in subproject:
             p = M.Project.query.get(shortname=sp['shortname'],
                                     neighborhood_id=c.project.neighborhood_id)
@@ -594,7 +627,8 @@ class ProjectAdminController(BaseController):
                     'delete subproject %s', sp['shortname'],
                     meta=dict(name=sp['shortname']))
                 p.removal = 'deleted'
-                plugin.ProjectRegistrationProvider.get().delete_project(p, c.user)
+                plugin.ProjectRegistrationProvider.get().delete_project(
+                    p, c.user)
             elif not new:
                 M.AuditLog.log('update subproject %s', sp['shortname'])
                 p.name = sp['name']
@@ -620,7 +654,7 @@ class ProjectAdminController(BaseController):
                 M.AuditLog.log('create subproject %s', mount_point)
                 h.log_action(log, 'create subproject').info(
                     'create subproject %s', mount_point,
-                    meta=dict(mount_point=mount_point,name=new['mount_label']))
+                    meta=dict(mount_point=mount_point, name=new['mount_label']))
                 sp = c.project.new_subproject(mount_point)
                 sp.name = new['mount_label']
                 sp.ordinal = int(new['ordinal'])
@@ -635,7 +669,8 @@ class ProjectAdminController(BaseController):
                 h.log_action(log, 'install tool').info(
                     'install tool %s', mount_point,
                     meta=dict(tool_type=ep_name, mount_point=mount_point, mount_label=new['mount_label']))
-                c.project.install_app(ep_name, mount_point, mount_label=new['mount_label'], ordinal=new['ordinal'])
+                c.project.install_app(
+                    ep_name, mount_point, mount_label=new['mount_label'], ordinal=new['ordinal'])
         g.post_event('project_updated')
 
     @h.vardec
@@ -660,7 +695,8 @@ class ProjectAdminController(BaseController):
                 flash(str(e), 'error')
                 redirect('.')
             else:
-                flash('Export scheduled.  You will recieve an email with download instructions when complete.', 'ok')
+                flash(
+                    'Export scheduled.  You will recieve an email with download instructions when complete.', 'ok')
                 redirect('export')
 
         exportable_tools = AdminApp.exportable_tools_for(c.project)
@@ -671,6 +707,7 @@ class ProjectAdminController(BaseController):
 
 
 class ProjectAdminRestController(BaseController):
+
     """
     Exposes RESTful APi for project admin actions.
     """
@@ -703,8 +740,9 @@ class ProjectAdminRestController(BaseController):
         if not asbool(config.get('bulk_export_enabled', True)):
             raise exc.HTTPNotFound()
         if not tools:
-            raise exc.HTTPBadRequest('Must give at least one tool mount point to export')
-        tools = aslist(tools,',')
+            raise exc.HTTPBadRequest(
+                'Must give at least one tool mount point to export')
+        tools = aslist(tools, ',')
         exportable_tools = AdminApp.exportable_tools_for(c.project)
         allowed = set(t.options.mount_point for t in exportable_tools)
         if not set(tools).issubset(allowed):
@@ -717,9 +755,9 @@ class ProjectAdminRestController(BaseController):
         filename = c.project.bulk_export_filename()
         export_tasks.bulk_export.post(tools, filename, send_email=send_email)
         return {
-                'status': 'in progress',
-                'filename': filename,
-            }
+            'status': 'in progress',
+            'filename': filename,
+        }
 
     @expose('json:')
     def export_status(self, **kw):
@@ -781,18 +819,19 @@ class ProjectAdminRestController(BaseController):
         if order is None:
             order = 'last'
         mounts = [{
-                'ordinal': ac.options.ordinal,
-                'label': ac.options.mount_label,
-                'mount': ac.options.mount_point,
-                'type': ac.tool_name.lower(),
-            } for ac in c.project.app_configs]
-        subs = {p.shortname: p for p in M.Project.query.find({'parent_id': c.project._id})}
+            'ordinal': ac.options.ordinal,
+            'label': ac.options.mount_label,
+            'mount': ac.options.mount_point,
+            'type': ac.tool_name.lower(),
+        } for ac in c.project.app_configs]
+        subs = {p.shortname:
+                p for p in M.Project.query.find({'parent_id': c.project._id})}
         for sub in subs.values():
             mounts.append({
-                    'ordinal': sub.ordinal,
-                    'mount': sub.shortname,
-                    'type': 'sub-project',
-                })
+                'ordinal': sub.ordinal,
+                'mount': sub.shortname,
+                'type': 'sub-project',
+            })
         mounts.sort(key=itemgetter('ordinal'))
         if order == 'first':
             ordinal = 0
@@ -831,7 +870,7 @@ class ProjectAdminRestController(BaseController):
         return {'success': True,
                 'info': 'Tool %s with mount_point %s and mount_label %s was created.'
                         % (tool, mount_point, mount_label)
-        }
+                }
 
 
 class PermissionsController(BaseController):
@@ -857,18 +896,20 @@ class PermissionsController(BaseController):
             new_group_ids = args.get('new', [])
             group_ids = args.get('value', [])
             if isinstance(new_group_ids, basestring):
-                new_group_ids = [ new_group_ids ]
+                new_group_ids = [new_group_ids]
             if isinstance(group_ids, basestring):
-                group_ids = [ group_ids ]
+                group_ids = [group_ids]
             # make sure the admin group has the admin permission
             if perm == 'admin':
                 if c.project.is_root:
                     pid = c.project._id
                 else:
                     pid = c.project.parent_id
-                admin_group_id = str(M.ProjectRole.query.get(project_id=pid, name='Admin')._id)
+                admin_group_id = str(
+                    M.ProjectRole.query.get(project_id=pid, name='Admin')._id)
                 if admin_group_id not in group_ids + new_group_ids:
-                    flash('You cannot remove the admin group from the admin permission.','warning')
+                    flash(
+                        'You cannot remove the admin group from the admin permission.', 'warning')
                     group_ids.append(admin_group_id)
             permissions[perm] = []
             role_ids = map(ObjectId, group_ids + new_group_ids)
@@ -876,23 +917,24 @@ class PermissionsController(BaseController):
         c.project.acl = []
         for perm, role_ids in permissions.iteritems():
             role_names = lambda ids: ','.join(sorted(
-                    pr.name for pr in M.ProjectRole.query.find(dict(_id={'$in':ids}))))
+                pr.name for pr in M.ProjectRole.query.find(dict(_id={'$in': ids}))))
             old_role_ids = old_permissions.get(perm, [])
             if old_role_ids != role_ids:
                 M.AuditLog.log('updated "%s" permissions: "%s" => "%s"',
-                               perm,role_names(old_role_ids), role_names(role_ids))
+                               perm, role_names(old_role_ids), role_names(role_ids))
             c.project.acl += [M.ACE.allow(rid, perm) for rid in role_ids]
         g.post_event('project_updated')
         redirect('.')
 
     def _index_permissions(self):
         permissions = dict(
-            (p,[]) for p in c.project.permissions)
+            (p, []) for p in c.project.permissions)
         for ace in c.project.acl:
             if ace.access == M.ACE.ALLOW:
                 permissions[ace.permission].append(ace.role_id)
         return permissions
 
+
 class GroupsController(BaseController):
 
     def _check_security(self):
@@ -900,7 +942,7 @@ class GroupsController(BaseController):
 
     def _index_permissions(self):
         permissions = dict(
-            (p,[]) for p in c.project.permissions)
+            (p, []) for p in c.project.permissions)
         for ace in c.project.acl:
             if ace.access == M.ACE.ALLOW:
                 permissions[ace.permission].append(ace.role_id)
@@ -908,14 +950,15 @@ class GroupsController(BaseController):
 
     def _map_group_permissions(self):
         roles = c.project.named_roles
-        permissions=self._index_permissions()
+        permissions = self._index_permissions()
         permissions_by_role = dict()
         auth_role = M.ProjectRole.authenticated()
         anon_role = M.ProjectRole.anonymous()
-        for role in roles+[auth_role, anon_role]:
+        for role in roles + [auth_role, anon_role]:
             permissions_by_role[str(role._id)] = []
             for perm in permissions:
-                perm_info = dict(has="no", text="Does not have permission %s" % perm, name=perm)
+                perm_info = dict(has="no", text="Does not have permission %s" %
+                                 perm, name=perm)
                 role_ids = permissions[perm]
                 if role._id in role_ids:
                     perm_info['text'] = "Has permission %s" % perm
@@ -923,15 +966,18 @@ class GroupsController(BaseController):
                 else:
                     for r in role.child_roles():
                         if r._id in role_ids:
-                            perm_info['text'] = "Inherited permission %s from %s" % (perm, r.name)
+                            perm_info['text'] = "Inherited permission %s from %s" % (
+                                perm, r.name)
                             perm_info['has'] = "inherit"
                             break
                 if perm_info['has'] == "no":
                     if anon_role._id in role_ids:
-                        perm_info['text'] = "Inherited permission %s from Anonymous" % perm
+                        perm_info[
+                            'text'] = "Inherited permission %s from Anonymous" % perm
                         perm_info['has'] = "inherit"
                     elif auth_role._id in role_ids and role != anon_role:
-                        perm_info['text'] = "Inherited permission %s from Authenticated" % perm
+                        perm_info[
+                            'text'] = "Inherited permission %s from Authenticated" % perm
                         perm_info['has'] = "inherit"
                 permissions_by_role[str(role._id)].append(perm_info)
         return permissions_by_role
@@ -968,14 +1014,16 @@ class GroupsController(BaseController):
     @require_post()
     @h.vardec
     def change_perm(self, role_id, permission, allow="true", **kw):
-        if allow=="true":
-            M.AuditLog.log('granted permission %s to group %s', permission, M.ProjectRole.query.get(_id=ObjectId(role_id)).name)
+        if allow == "true":
+            M.AuditLog.log('granted permission %s to group %s', permission,
+                           M.ProjectRole.query.get(_id=ObjectId(role_id)).name)
             c.project.acl.append(M.ACE.allow(ObjectId(role_id), permission))
         else:
             admin_group_id = str(M.ProjectRole.by_name('Admin')._id)
             if admin_group_id == role_id and permission == 'admin':
                 return dict(error='You cannot remove the admin permission from the admin group.')
-            M.AuditLog.log('revoked permission %s from group %s', permission, M.ProjectRole.query.get(_id=ObjectId(role_id)).name)
+            M.AuditLog.log('revoked permission %s from group %s', permission,
+                           M.ProjectRole.query.get(_id=ObjectId(role_id)).name)
             c.project.acl.remove(M.ACE.allow(ObjectId(role_id), permission))
         g.post_event('project_updated')
         return self._map_group_permissions()
@@ -985,7 +1033,7 @@ class GroupsController(BaseController):
     @require_post()
     @h.vardec
     def add_user(self, role_id, username, **kw):
-        if not username or username=='*anonymous':
+        if not username or username == '*anonymous':
             return dict(error='You must choose a user to add.')
         group = M.ProjectRole.query.get(_id=ObjectId(role_id))
         user = M.User.by_username(username.strip())
@@ -1036,9 +1084,9 @@ class GroupsController(BaseController):
             user_ids = pr.get('value', [])
             new_users = pr.get('new', [])
             if isinstance(user_ids, basestring):
-                user_ids = [ user_ids ]
+                user_ids = [user_ids]
             if isinstance(new_users, basestring):
-                new_users = [ new_users ]
+                new_users = [new_users]
             # Handle new users in groups
             user_added = False
             for username in new_users:
@@ -1047,9 +1095,10 @@ class GroupsController(BaseController):
                     flash('User %s not found' % username, 'error')
                     redirect('.')
                 if not user._id:
-                    continue # never add anon users to groups
+                    continue  # never add anon users to groups
                 M.AuditLog.log('add user %s to %s', username, group.name)
-                M.ProjectRole.by_user(user, upsert=True).roles.append(group._id)
+                M.ProjectRole.by_user(
+                    user, upsert=True).roles.append(group._id)
                 user_added = True
             # Make sure we aren't removing all users from the Admin group
             if group.name == u'Admin' and not (user_ids or user_added):
@@ -1060,10 +1109,12 @@ class GroupsController(BaseController):
             user_ids = set(
                 uid and ObjectId(uid)
                 for uid in user_ids)
-            for role in M.ProjectRole.query.find(dict(user_id={'$ne':None}, roles=group._id)):
+            for role in M.ProjectRole.query.find(dict(user_id={'$ne': None}, roles=group._id)):
                 if role.user_id and role.user_id not in user_ids:
-                    role.roles = [ rid for rid in role.roles if rid != group._id ]
-                    M.AuditLog.log('remove user %s from %s', role.user.username, group.name)
+                    role.roles = [
+                        rid for rid in role.roles if rid != group._id]
+                    M.AuditLog.log('remove user %s from %s',
+                                   role.user.username, group.name)
         g.post_event('project_updated')
         redirect('.')
 
@@ -1093,6 +1144,7 @@ class GroupsController(BaseController):
     def _lookup(self, name, *remainder):
         return GroupController(name), remainder
 
+
 class GroupController(BaseController):
 
     def __init__(self, name):
@@ -1132,6 +1184,7 @@ class GroupController(BaseController):
         flash('%s updated' % name)
         redirect('..')
 
+
 class AuditController(BaseController):
 
     @with_trailing_slash
@@ -1146,7 +1199,7 @@ class AuditController(BaseController):
         if count > limit:
             q = q.limit(limit)
         else:
-            limit=count
+            limit = count
         c.widget = W.audit
         return dict(
             entries=q.all(),
@@ -1154,6 +1207,8 @@ class AuditController(BaseController):
             page=page,
             count=count)
 
+
 class AdminAppAdminController(DefaultAdminController):
+
     '''Administer the admin app'''
     pass

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/ext/admin/widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/widgets.py b/Allura/allura/ext/admin/widgets.py
index 8eed0be..7457d28 100644
--- a/Allura/allura/ext/admin/widgets.py
+++ b/Allura/allura/ext/admin/widgets.py
@@ -30,6 +30,7 @@ from allura.lib.widgets import form_fields as ffw
 
 from bson import ObjectId
 
+
 class CardField(ew._Jinja2Widget):
     template = 'jinja:allura.ext.admin:templates/admin_widgets/card_field.html'
     sort_key = None
@@ -74,8 +75,10 @@ width: 148px;
     });
 });''')
 
+
 class GroupCard(CardField):
-    new_item=ew.InputField(field_type='text', attrs=dict(placeholder='type a username'))
+    new_item = ew.InputField(
+        field_type='text', attrs=dict(placeholder='type a username'))
     sort_key = 'user.username'
 
     def item_display(self, item):
@@ -87,6 +90,7 @@ class GroupCard(CardField):
     def role_name(self, role_id):
         return M.ProjectRole.query.get(_id=ObjectId(role_id)).name
 
+
 class _GroupSelect(ew.SingleSelectField):
 
     def options(self):
@@ -94,11 +98,12 @@ class _GroupSelect(ew.SingleSelectField):
         anon_role = M.ProjectRole.anonymous()
         options = [
             ew.Option(py_value=role._id, label=role.name)
-            for role in c.project.named_roles ]
+            for role in c.project.named_roles]
         options.append(ew.Option(py_value=auth_role._id, label=auth_role.name))
         options.append(ew.Option(py_value=anon_role._id, label=anon_role.name))
         return options
 
+
 class PermissionCard(CardField):
     new_item = _GroupSelect()
     sort_key = 'name'
@@ -111,7 +116,7 @@ class PermissionCard(CardField):
 
 
 class GroupSettings(ff.CsrfForm):
-    submit_text=None
+    submit_text = None
 
     @property
     def hidden_fields(self):
@@ -126,27 +131,32 @@ class GroupSettings(ff.CsrfForm):
         save = ew.SubmitButton(label='Save')
         delete = ew.SubmitButton(label='Delete Group')
 
+
 class NewGroupSettings(ff.AdminForm):
-    submit_text='Save'
+    submit_text = 'Save'
+
     class fields(ew_core.NameList):
         name = ew.InputField(label='Name')
 
+
 class ScreenshotAdmin(ff.AdminForm):
-    defaults=dict(
+    defaults = dict(
         ff.AdminForm.defaults,
         enctype='multipart/form-data')
 
     @property
     def fields(self):
         fields = [
-            ew.InputField(name='screenshot', field_type='file', label='New Screenshot'),
+            ew.InputField(name='screenshot', field_type='file',
+                          label='New Screenshot'),
             ew.InputField(name='caption', field_type="text", label='Caption')
         ]
         return fields
 
+
 class MetadataAdmin(ff.AdminForm):
     template = 'jinja:allura.ext.admin:templates/admin_widgets/metadata_admin.html'
-    defaults=dict(
+    defaults = dict(
         ff.AdminForm.defaults,
         show_export_control=False,
         enctype='multipart/form-data')
@@ -155,14 +165,14 @@ class MetadataAdmin(ff.AdminForm):
         name = ew.InputField(field_type='text',
                              label='Name',
                              validator=formencode.All(
-                                fev.UnicodeString(not_empty=True, max=40),
-                                V.MaxBytesValidator(max=40)),
+                                 fev.UnicodeString(not_empty=True, max=40),
+                                 V.MaxBytesValidator(max=40)),
                              attrs=dict(maxlength=40,
                                         title="This is the publicly viewable name of the project, and will appear on project listings. It should be what you want to see as the project title in search listing."))
         summary = ew.InputField(field_type="text", label='Short Summary',
                                 validator=formencode.All(
-                                   fev.UnicodeString(max=70),
-                                   V.MaxBytesValidator(max=70)),
+                                    fev.UnicodeString(max=70),
+                                    V.MaxBytesValidator(max=70)),
                                 attrs=dict(maxlength=70))
         short_description = ew.TextArea(label='Full Description',
                                         validator=formencode.All(
@@ -173,24 +183,31 @@ class MetadataAdmin(ff.AdminForm):
         external_homepage = ew.InputField(field_type="text", label='Homepage',
                                           validator=fev.URL(add_http=True))
         support_page = ew.InputField(field_type="text", label='Support Page')
-        support_page_url = ew.InputField(field_type="text", label='Support Page URL',
-                                         validator=fev.URL(add_http=True, if_empty=''))
+        support_page_url = ew.InputField(
+            field_type="text", label='Support Page URL',
+            validator=fev.URL(add_http=True, if_empty=''))
         removal = ew.InputField(field_type="text", label='Removal')
-        moved_to_url = ew.InputField(field_type="text", label='Moved Project to URL',
-                                     validator=fev.URL(add_http=True, if_empty=''))
-        export_controlled = ew.InputField(field_type="text", label='Export Control')
-        export_control_type = ew.InputField(field_type="text", label='Export Control Type')
+        moved_to_url = ew.InputField(
+            field_type="text", label='Moved Project to URL',
+            validator=fev.URL(add_http=True, if_empty=''))
+        export_controlled = ew.InputField(
+            field_type="text", label='Export Control')
+        export_control_type = ew.InputField(
+            field_type="text", label='Export Control Type')
         delete = ew.InputField(field_type="hidden", label='Delete')
         delete_icon = ew.InputField(field_type="hidden", label='Delete Icon')
         undelete = ew.InputField(field_type="hidden", label='Undelete')
-        tracking_id = ew.InputField(field_type="text", label="Analytics Tracking ID")
-        twitter_handle = ew.InputField(field_type="text", label='Twitter Handle')
+        tracking_id = ew.InputField(
+            field_type="text", label="Analytics Tracking ID")
+        twitter_handle = ew.InputField(
+            field_type="text", label='Twitter Handle')
         facebook_page = ew.InputField(field_type="text", label='Facebook page',
                                       validator=fev.URL(add_http=True))
 
+
 class AuditLog(ew_core.Widget):
-    template='jinja:allura.ext.admin:templates/widgets/audit.html'
-    defaults=dict(
+    template = 'jinja:allura.ext.admin:templates/widgets/audit.html'
+    defaults = dict(
         ew_core.Widget.defaults,
         entries=None,
         limit=None,
@@ -198,8 +215,8 @@ class AuditLog(ew_core.Widget):
         count=0)
 
     class fields(ew_core.NameList):
-        page_list=ffw.PageList()
-        page_size=ffw.PageSize()
+        page_list = ffw.PageList()
+        page_size = ffw.PageSize()
 
     def resources(self):
         for f in self.fields:
@@ -209,14 +226,15 @@ class AuditLog(ew_core.Widget):
 
 class BlockUser(ffw.Lightbox):
     defaults = dict(
-            ffw.Lightbox.defaults,
-            name='block-user-modal',
-            trigger='a.block-user',
-            content_template='allura.ext.admin:templates/widgets/block_user.html')
+        ffw.Lightbox.defaults,
+        name='block-user-modal',
+        trigger='a.block-user',
+        content_template='allura.ext.admin:templates/widgets/block_user.html')
+
 
 class BlockList(ffw.Lightbox):
     defaults = dict(
-            ffw.Lightbox.defaults,
-            name='block-list-modal',
-            trigger='a.block-list',
-            content_template='allura.ext.admin:templates/widgets/block_list.html')
+        ffw.Lightbox.defaults,
+        name='block-list-modal',
+        trigger='a.block-list',
+        content_template='allura.ext.admin:templates/widgets/block_list.html')

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/ext/project_home/project_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/project_home/project_main.py b/Allura/allura/ext/project_home/project_main.py
index 76ec1d2..378ca0a 100644
--- a/Allura/allura/ext/project_home/project_main.py
+++ b/Allura/allura/ext/project_home/project_main.py
@@ -35,12 +35,12 @@ log = logging.getLogger(__name__)
 class ProjectHomeApp(Application):
     __version__ = version.__version__
     tool_label = 'home'
-    default_mount_label='Project Home'
+    default_mount_label = 'Project Home'
     max_instances = 0
-    icons={
-        24:'images/home_24.png',
-        32:'images/home_32.png',
-        48:'images/home_48.png'
+    icons = {
+        24: 'images/home_24.png',
+        32: 'images/home_32.png',
+        48: 'images/home_48.png'
     }
 
     def __init__(self, project, config):
@@ -57,20 +57,20 @@ class ProjectHomeApp(Application):
         '''Apps should provide their entries to be added to the main nav
         :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
         '''
-        return [ SitemapEntry(
-                self.config.options.mount_label,
-                '..')]
+        return [SitemapEntry(
+            self.config.options.mount_label,
+            '..')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
         menu_id = 'Home'
         return [
-            SitemapEntry('Home', '..') ]
+            SitemapEntry('Home', '..')]
 
     @h.exceptionless([], log)
     def sidebar_menu(self):
-        return [ ]
+        return []
 
     def admin_menu(self):
         return []
@@ -81,7 +81,7 @@ class ProjectHomeApp(Application):
         if pr:
             self.config.acl = [
                 model.ACE.allow(pr._id, perm)
-                for perm in self.permissions ]
+                for perm in self.permissions]
 
 
 class ProjectHomeController(BaseController):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/ext/search/search_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/search/search_main.py b/Allura/allura/ext/search/search_main.py
index 920c29f..99c5dfc 100644
--- a/Allura/allura/ext/search/search_main.py
+++ b/Allura/allura/ext/search/search_main.py
@@ -31,34 +31,38 @@ from allura.controllers import BaseController
 
 log = logging.getLogger(__name__)
 
+
 class SearchApp(Application):
+
     '''This is the HelloWorld application for Allura, showing
     all the rich, creamy goodness that is installable apps.
     '''
     __version__ = version.__version__
     max_instances = 0
     hidden = True
-    sitemap=[]
+    sitemap = []
 
     def __init__(self, project, config):
         Application.__init__(self, project, config)
         self.root = SearchController()
-        self.templates = pkg_resources.resource_filename('allura.ext.search', 'templates')
+        self.templates = pkg_resources.resource_filename(
+            'allura.ext.search', 'templates')
 
-    def main_menu(self): # pragma no cover
+    def main_menu(self):  # pragma no cover
         return []
 
-    def sidebar_menu(self): # pragma no cover
-        return [ ]
+    def sidebar_menu(self):  # pragma no cover
+        return []
 
-    def admin_menu(self): # pragma no cover
+    def admin_menu(self):  # pragma no cover
         return []
 
     def install(self, project):
-        pass # pragma no cover
+        pass  # pragma no cover
 
     def uninstall(self, project):
-        pass # pragma no cover
+        pass  # pragma no cover
+
 
 class SearchController(BaseController):
 
@@ -70,10 +74,10 @@ class SearchController(BaseController):
         c.search_results = SearchResults()
         c.help_modal = SearchHelp(comments=False)
         pids = [c.project._id] + [
-            p._id for p in c.project.subprojects ]
+            p._id for p in c.project.subprojects]
         project_match = ' OR '.join(
             'project_id_s:%s' % pid
-            for pid in pids )
+            for pid in pids)
         search_params = kw
         search_params.update({
             'q': q,

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/ext/user_profile/user_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index a668430..a9ab929 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -49,10 +49,10 @@ class UserProfileApp(Application):
     __version__ = version.__version__
     tool_label = 'Profile'
     max_instances = 0
-    icons={
-        24:'images/home_24.png',
-        32:'images/home_32.png',
-        48:'images/home_48.png'
+    icons = {
+        24: 'images/home_24.png',
+        32: 'images/home_32.png',
+        48: 'images/home_48.png'
     }
 
     def __init__(self, user, config):
@@ -81,9 +81,9 @@ class UserProfileApp(Application):
         if pr:
             self.config.acl = [
                 ACE.allow(pr._id, perm)
-                for perm in self.permissions ]
+                for perm in self.permissions]
 
-    def uninstall(self, project): # pragma no cover
+    def uninstall(self, project):  # pragma no cover
         pass
 
 
@@ -99,12 +99,12 @@ class UserProfileController(BaseController, FeedController):
 
         if not (from_user and from_user.get_pref('email_address')):
             flash('In order to send messages, you must have an email address '
-                    'associated with your account.', 'info')
+                  'associated with your account.', 'info')
             redirect(request.referer)
 
         if not (to_user and to_user.get_pref('email_address')):
             flash('This user can not receive messages because they do not have '
-                    'an email address associated with their account.', 'info')
+                  'an email address associated with their account.', 'info')
             redirect(request.referer)
 
         if to_user.get_pref('disable_user_messages'):
@@ -157,11 +157,11 @@ class UserProfileController(BaseController, FeedController):
         if cc:
             cc = c.user.get_pref('email_address')
         if c.user.can_send_user_message():
-            c.user.send_user_message(c.project.user_project_of, subject, message, cc)
+            c.user.send_user_message(
+                c.project.user_project_of, subject, message, cc)
             flash("Message sent.")
         else:
             flash("You can't send more than %i messages per %i seconds" % (
                 c.user.user_message_max_messages,
                 c.user.user_message_time_interval), 'error')
         return redirect(c.project.user_project_of.url())
-

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/lib/AsciiDammit.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/AsciiDammit.py b/Allura/allura/lib/AsciiDammit.py
index 47236f1..e4ea156 100644
--- a/Allura/allura/lib/AsciiDammit.py
+++ b/Allura/allura/lib/AsciiDammit.py
@@ -26,135 +26,136 @@ import re
 import string
 import types
 
-CHARS = { '\x80' : ('EUR', 'euro'),
-          '\x81' : ' ',
-          '\x82' : (',', 'sbquo'),
-          '\x83' : ('f', 'fnof'),
-          '\x84' : (',,', 'bdquo'),
-          '\x85' : ('...', 'hellip'),
-          '\x86' : ('+', 'dagger'),
-          '\x87' : ('++', 'Dagger'),
-          '\x88' : ('^', 'caret'),
-          '\x89' : '%',
-          '\x8A' : ('S', 'Scaron'),
-          '\x8B' : ('<', 'lt;'),
-          '\x8C' : ('OE', 'OElig'),
-          '\x8D' : '?',
-          '\x8E' : 'Z',
-          '\x8F' : '?',
-          '\x90' : '?',
-          '\x91' : ("'", 'lsquo'),
-          '\x92' : ("'", 'rsquo'),
-          '\x93' : ('"', 'ldquo'),
-          '\x94' : ('"', 'rdquo'),
-          '\x95' : ('*', 'bull'),
-          '\x96' : ('-', 'ndash'),
-          '\x97' : ('--', 'mdash'),
-          '\x98' : ('~', 'tilde'),
-          '\x99' : ('(TM)', 'trade'),
-          '\x9a' : ('s', 'scaron'),
-          '\x9b' : ('>', 'gt'),
-          '\x9c' : ('oe', 'oelig'),
-          '\x9d' : '?',
-          '\x9e' : 'z',
-          '\x9f' : ('Y', 'Yuml'),
-          '\xa0' : (' ', 'nbsp'),
-          '\xa1' : ('!', 'iexcl'),
-          '\xa2' : ('c', 'cent'),
-          '\xa3' : ('GBP', 'pound'),
-          '\xa4' : ('$', 'curren'), #This approximation is especially lame.
-          '\xa5' : ('YEN', 'yen'),
-          '\xa6' : ('|', 'brvbar'),
-          '\xa7' : ('S', 'sect'),
-          '\xa8' : ('..', 'uml'),
-          '\xa9' : ('', 'copy'),
-          '\xaa' : ('(th)', 'ordf'),
-          '\xab' : ('<<', 'laquo'),
-          '\xac' : ('!', 'not'),
-          '\xad' : (' ', 'shy'),
-          '\xae' : ('(R)', 'reg'),
-          '\xaf' : ('-', 'macr'),
-          '\xb0' : ('o', 'deg'),
-          '\xb1' : ('+-', 'plusmm'),
-          '\xb2' : ('2', 'sup2'),
-          '\xb3' : ('3', 'sup3'),
-          '\xb4' : ("'", 'acute'),
-          '\xb5' : ('u', 'micro'),
-          '\xb6' : ('P', 'para'),
-          '\xb7' : ('*', 'middot'),
-          '\xb8' : (',', 'cedil'),
-          '\xb9' : ('1', 'sup1'),
-          '\xba' : ('(th)', 'ordm'),
-          '\xbb' : ('>>', 'raquo'),
-          '\xbc' : ('1/4', 'frac14'),
-          '\xbd' : ('1/2', 'frac12'),
-          '\xbe' : ('3/4', 'frac34'),
-          '\xbf' : ('?', 'iquest'),
-          '\xc0' : ('A', "Agrave"),
-          '\xc1' : ('A', "Aacute"),
-          '\xc2' : ('A', "Acirc"),
-          '\xc3' : ('A', "Atilde"),
-          '\xc4' : ('A', "Auml"),
-          '\xc5' : ('A', "Aring"),
-          '\xc6' : ('AE', "Aelig"),
-          '\xc7' : ('C', "Ccedil"),
-          '\xc8' : ('E', "Egrave"),
-          '\xc9' : ('E', "Eacute"),
-          '\xca' : ('E', "Ecirc"),
-          '\xcb' : ('E', "Euml"),
-          '\xcc' : ('I', "Igrave"),
-          '\xcd' : ('I', "Iacute"),
-          '\xce' : ('I', "Icirc"),
-          '\xcf' : ('I', "Iuml"),
-          '\xd0' : ('D', "Eth"),
-          '\xd1' : ('N', "Ntilde"),
-          '\xd2' : ('O', "Ograve"),
-          '\xd3' : ('O', "Oacute"),
-          '\xd4' : ('O', "Ocirc"),
-          '\xd5' : ('O', "Otilde"),
-          '\xd6' : ('O', "Ouml"),
-          '\xd7' : ('*', "times"),
-          '\xd8' : ('O', "Oslash"),
-          '\xd9' : ('U', "Ugrave"),
-          '\xda' : ('U', "Uacute"),
-          '\xdb' : ('U', "Ucirc"),
-          '\xdc' : ('U', "Uuml"),
-          '\xdd' : ('Y', "Yacute"),
-          '\xde' : ('b', "Thorn"),
-          '\xdf' : ('B', "szlig"),
-          '\xe0' : ('a', "agrave"),
-          '\xe1' : ('a', "aacute"),
-          '\xe2' : ('a', "acirc"),
-          '\xe3' : ('a', "atilde"),
-          '\xe4' : ('a', "auml"),
-          '\xe5' : ('a', "aring"),
-          '\xe6' : ('ae', "aelig"),
-          '\xe7' : ('c', "ccedil"),
-          '\xe8' : ('e', "egrave"),
-          '\xe9' : ('e', "eacute"),
-          '\xea' : ('e', "ecirc"),
-          '\xeb' : ('e', "euml"),
-          '\xec' : ('i', "igrave"),
-          '\xed' : ('i', "iacute"),
-          '\xee' : ('i', "icirc"),
-          '\xef' : ('i', "iuml"),
-          '\xf0' : ('o', "eth"),
-          '\xf1' : ('n', "ntilde"),
-          '\xf2' : ('o', "ograve"),
-          '\xf3' : ('o', "oacute"),
-          '\xf4' : ('o', "ocirc"),
-          '\xf5' : ('o', "otilde"),
-          '\xf6' : ('o', "ouml"),
-          '\xf7' : ('/', "divide"),
-          '\xf8' : ('o', "oslash"),
-          '\xf9' : ('u', "ugrave"),
-          '\xfa' : ('u', "uacute"),
-          '\xfb' : ('u', "ucirc"),
-          '\xfc' : ('u', "uuml"),
-          '\xfd' : ('y', "yacute"),
-          '\xfe' : ('b', "thorn"),
-          '\xff' : ('y', "yuml"),
-          }
+CHARS = {'\x80': ('EUR', 'euro'),
+         '\x81': ' ',
+         '\x82': (',', 'sbquo'),
+         '\x83': ('f', 'fnof'),
+         '\x84': (',,', 'bdquo'),
+         '\x85': ('...', 'hellip'),
+         '\x86': ('+', 'dagger'),
+         '\x87': ('++', 'Dagger'),
+         '\x88': ('^', 'caret'),
+         '\x89': '%',
+         '\x8A': ('S', 'Scaron'),
+         '\x8B': ('<', 'lt;'),
+         '\x8C': ('OE', 'OElig'),
+         '\x8D': '?',
+         '\x8E': 'Z',
+         '\x8F': '?',
+         '\x90': '?',
+         '\x91': ("'", 'lsquo'),
+         '\x92': ("'", 'rsquo'),
+         '\x93': ('"', 'ldquo'),
+         '\x94': ('"', 'rdquo'),
+         '\x95': ('*', 'bull'),
+         '\x96': ('-', 'ndash'),
+         '\x97': ('--', 'mdash'),
+         '\x98': ('~', 'tilde'),
+         '\x99': ('(TM)', 'trade'),
+         '\x9a': ('s', 'scaron'),
+         '\x9b': ('>', 'gt'),
+         '\x9c': ('oe', 'oelig'),
+         '\x9d': '?',
+         '\x9e': 'z',
+         '\x9f': ('Y', 'Yuml'),
+         '\xa0': (' ', 'nbsp'),
+         '\xa1': ('!', 'iexcl'),
+         '\xa2': ('c', 'cent'),
+         '\xa3': ('GBP', 'pound'),
+         '\xa4': ('$', 'curren'),  # This approximation is especially lame.
+         '\xa5': ('YEN', 'yen'),
+         '\xa6': ('|', 'brvbar'),
+         '\xa7': ('S', 'sect'),
+         '\xa8': ('..', 'uml'),
+         '\xa9': ('', 'copy'),
+         '\xaa': ('(th)', 'ordf'),
+         '\xab': ('<<', 'laquo'),
+         '\xac': ('!', 'not'),
+         '\xad': (' ', 'shy'),
+         '\xae': ('(R)', 'reg'),
+         '\xaf': ('-', 'macr'),
+         '\xb0': ('o', 'deg'),
+         '\xb1': ('+-', 'plusmm'),
+         '\xb2': ('2', 'sup2'),
+         '\xb3': ('3', 'sup3'),
+         '\xb4': ("'", 'acute'),
+         '\xb5': ('u', 'micro'),
+         '\xb6': ('P', 'para'),
+         '\xb7': ('*', 'middot'),
+         '\xb8': (',', 'cedil'),
+         '\xb9': ('1', 'sup1'),
+         '\xba': ('(th)', 'ordm'),
+         '\xbb': ('>>', 'raquo'),
+         '\xbc': ('1/4', 'frac14'),
+         '\xbd': ('1/2', 'frac12'),
+         '\xbe': ('3/4', 'frac34'),
+         '\xbf': ('?', 'iquest'),
+         '\xc0': ('A', "Agrave"),
+         '\xc1': ('A', "Aacute"),
+         '\xc2': ('A', "Acirc"),
+         '\xc3': ('A', "Atilde"),
+         '\xc4': ('A', "Auml"),
+         '\xc5': ('A', "Aring"),
+         '\xc6': ('AE', "Aelig"),
+         '\xc7': ('C', "Ccedil"),
+         '\xc8': ('E', "Egrave"),
+         '\xc9': ('E', "Eacute"),
+         '\xca': ('E', "Ecirc"),
+         '\xcb': ('E', "Euml"),
+         '\xcc': ('I', "Igrave"),
+         '\xcd': ('I', "Iacute"),
+         '\xce': ('I', "Icirc"),
+         '\xcf': ('I', "Iuml"),
+         '\xd0': ('D', "Eth"),
+         '\xd1': ('N', "Ntilde"),
+         '\xd2': ('O', "Ograve"),
+         '\xd3': ('O', "Oacute"),
+         '\xd4': ('O', "Ocirc"),
+         '\xd5': ('O', "Otilde"),
+         '\xd6': ('O', "Ouml"),
+         '\xd7': ('*', "times"),
+         '\xd8': ('O', "Oslash"),
+         '\xd9': ('U', "Ugrave"),
+         '\xda': ('U', "Uacute"),
+         '\xdb': ('U', "Ucirc"),
+         '\xdc': ('U', "Uuml"),
+         '\xdd': ('Y', "Yacute"),
+         '\xde': ('b', "Thorn"),
+         '\xdf': ('B', "szlig"),
+         '\xe0': ('a', "agrave"),
+         '\xe1': ('a', "aacute"),
+         '\xe2': ('a', "acirc"),
+         '\xe3': ('a', "atilde"),
+         '\xe4': ('a', "auml"),
+         '\xe5': ('a', "aring"),
+         '\xe6': ('ae', "aelig"),
+         '\xe7': ('c', "ccedil"),
+         '\xe8': ('e', "egrave"),
+         '\xe9': ('e', "eacute"),
+         '\xea': ('e', "ecirc"),
+         '\xeb': ('e', "euml"),
+         '\xec': ('i', "igrave"),
+         '\xed': ('i', "iacute"),
+         '\xee': ('i', "icirc"),
+         '\xef': ('i', "iuml"),
+         '\xf0': ('o', "eth"),
+         '\xf1': ('n', "ntilde"),
+         '\xf2': ('o', "ograve"),
+         '\xf3': ('o', "oacute"),
+         '\xf4': ('o', "ocirc"),
+         '\xf5': ('o', "otilde"),
+         '\xf6': ('o', "ouml"),
+         '\xf7': ('/', "divide"),
+         '\xf8': ('o', "oslash"),
+         '\xf9': ('u', "ugrave"),
+         '\xfa': ('u', "uacute"),
+         '\xfb': ('u', "ucirc"),
+         '\xfc': ('u', "uuml"),
+         '\xfd': ('y', "yacute"),
+         '\xfe': ('b', "thorn"),
+         '\xff': ('y', "yuml"),
+         }
+
 
 def _makeRE(limit):
     """Returns a regular expression object that will match special characters
@@ -163,20 +164,23 @@ def _makeRE(limit):
 ALL = _makeRE('ff')
 ONLY_WINDOWS = _makeRE('9f')
 
+
 def _replHTML(match):
     "Replace the matched character with its HTML equivalent."
     return _repl(match, 1)
 
+
 def _repl(match, html=0):
     "Replace the matched character with its HTML or ASCII equivalent."
     g = match.group(0)
-    a = CHARS.get(g,g)
+    a = CHARS.get(g, g)
     if type(a) == types.TupleType:
         a = a[html]
         if html:
             a = '&' + a + ';'
     return a
 
+
 def _dammit(t, html=0, fixWindowsOnly=0):
     "Turns ISO-Latin-1 into an ASCII representation, dammit."
 
@@ -189,14 +193,17 @@ def _dammit(t, html=0, fixWindowsOnly=0):
 
     return re.sub(r, m, t)
 
+
 def asciiDammit(t, fixWindowsOnly=0):
     "Turns ISO-Latin-1 into a plain ASCII approximation, dammit."
     return _dammit(t, 0, fixWindowsOnly)
 
+
 def htmlDammit(t, fixWindowsOnly=0):
     "Turns ISO-Latin-1 into plain ASCII with HTML codes, dammit."
     return _dammit(t, 1, fixWindowsOnly=fixWindowsOnly)
 
+
 def demoronise(t):
     """Helper method named in honor of the original smart quotes
     remover, The Demoroniser:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/lib/app_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index 6c94870..8bc929e 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -52,9 +52,9 @@ from ming.utils import LazyProperty
 import allura.tasks.event_tasks
 from allura import model as M
 from allura.lib.markdown_extensions import (
-        ForgeExtension,
-        CommitMessageExtension,
-        )
+    ForgeExtension,
+    CommitMessageExtension,
+)
 from allura.eventslistener import PostEvent
 
 from allura.lib import gravatar, plugin, utils
@@ -69,9 +69,11 @@ log = logging.getLogger(__name__)
 
 
 class ForgeMarkdown(markdown.Markdown):
+
     def convert(self, source):
         if len(source) > asint(config.get('markdown_render_max_length', 40000)):
-            # if text is too big, markdown can take a long time to process it, so we return it as a plain text
+            # if text is too big, markdown can take a long time to process it,
+            # so we return it as a plain text
             log.info('Text is too big. Skipping markdown processing')
             escaped = cgi.escape(h.really_unicode(source))
             return h.html.literal(u'<pre>%s</pre>' % escaped)
@@ -97,8 +99,9 @@ class ForgeMarkdown(markdown.Markdown):
         cache_field_name = field_name + '_cache'
         cache = getattr(artifact, cache_field_name, None)
         if not cache:
-            log.warn('Skipping Markdown caching - Missing cache field "%s" on class %s',
-                    field_name, artifact.__class__.__name__)
+            log.warn(
+                'Skipping Markdown caching - Missing cache field "%s" on class %s',
+                field_name, artifact.__class__.__name__)
             return self.convert(source_text)
 
         md5 = None
@@ -117,7 +120,7 @@ class ForgeMarkdown(markdown.Markdown):
         except ValueError:
             threshold = None
             log.warn('Skipping Markdown caching - The value for config param '
-                    '"markdown_cache_threshold" must be a float.')
+                     '"markdown_cache_threshold" must be a float.')
 
         if threshold != None and render_time > threshold:
             if md5 is None:
@@ -127,6 +130,7 @@ class ForgeMarkdown(markdown.Markdown):
 
 
 class Globals(object):
+
     """Container for objects available throughout the life of the application.
 
     One instance of Globals is created during application initialization and
@@ -137,8 +141,10 @@ class Globals(object):
 
     def __init__(self):
         self.__dict__ = self.__shared_state
-        if self.__shared_state: return
-        self.allura_templates = pkg_resources.resource_filename('allura', 'templates')
+        if self.__shared_state:
+            return
+        self.allura_templates = pkg_resources.resource_filename(
+            'allura', 'templates')
         # Setup SOLR
         self.solr_server = aslist(config.get('solr.server'), ',')
         # skip empty strings in case of extra commas
@@ -147,11 +153,12 @@ class Globals(object):
         if asbool(config.get('solr.mock')):
             self.solr = self.solr_short_timeout = MockSOLR()
         elif self.solr_server:
-            self.solr = make_solr_from_config(self.solr_server, self.solr_query_server)
+            self.solr = make_solr_from_config(
+                self.solr_server, self.solr_query_server)
             self.solr_short_timeout = make_solr_from_config(
                 self.solr_server, self.solr_query_server,
                 timeout=int(config.get('solr.short_timeout', 10)))
-        else: # pragma no cover
+        else:  # pragma no cover
             self.solr = None
             self.solr_short_timeout = None
         self.use_queue = asbool(config.get('use_queue', False))
@@ -159,7 +166,8 @@ class Globals(object):
         # Load login/logout urls; only used for SFX logins
         self.login_url = config.get('auth.login_url', '/auth/')
         self.logout_url = config.get('auth.logout_url', '/auth/logout')
-        self.login_fragment_url = config.get('auth.login_fragment_url', '/auth/login_fragment')
+        self.login_fragment_url = config.get(
+            'auth.login_fragment_url', '/auth/login_fragment')
 
         # Setup Gravatar
         self.gravatar = gravatar.url
@@ -231,6 +239,7 @@ class Globals(object):
             return d
 
         class entry_point_loading_dict(dict):
+
             def __missing__(self, key):
                 self[key] = _cache_eps(key)
                 return self[key]
@@ -245,7 +254,7 @@ class Globals(object):
             stats=_cache_eps('allura.stats'),
             site_stats=_cache_eps('allura.site_stats'),
             admin=_cache_eps('allura.admin'),
-            )
+        )
 
         # Zarkov logger
         self._zarkov = None
@@ -272,18 +281,25 @@ class Globals(object):
             return activitystream.director()
         else:
             class NullActivityStreamDirector(object):
+
                 def connect(self, *a, **kw):
                     pass
+
                 def disconnect(self, *a, **kw):
                     pass
+
                 def is_connected(self, *a, **kw):
                     return False
+
                 def create_activity(self, *a, **kw):
                     pass
+
                 def create_timeline(self, *a, **kw):
                     pass
+
                 def create_timelines(self, *a, **kw):
                     pass
+
                 def get_timeline(self, *a, **kw):
                     return []
             return NullActivityStreamDirector()
@@ -307,9 +323,9 @@ class Globals(object):
         allura.tasks.event_tasks.event.post(topic, *args, **kwargs)
 
     def zarkov_event(
-        self, event_type,
-        user=None, neighborhood=None, project=None, app=None,
-        extra=None):
+            self, event_type,
+            user=None, neighborhood=None, project=None, app=None,
+            extra=None):
         context = dict(
             user=None,
             neighborhood=None, project=None, tool=None,
@@ -322,7 +338,8 @@ class Globals(object):
         user = user or getattr(c, 'user', None)
         project = project or getattr(c, 'project', None)
         app = app or getattr(c, 'app', None)
-        if user: context['user'] = user.username
+        if user:
+            context['user'] = user.username
         if project:
             context.update(
                 project=project.shortname,
@@ -346,7 +363,7 @@ class Globals(object):
         except Exception, ex:
             self._zarkov = None
             log.error('Error sending zarkov event(%r): %r', ex, dict(
-                    type=event_type, context=context, extra=extra))
+                type=event_type, context=context, extra=extra))
 
     @LazyProperty
     def theme(self):
@@ -380,7 +397,8 @@ class Globals(object):
             if c.user in (None, M.User.anonymous()):
                 try:
                     limit = session['results_per_page']
-                except (KeyError, TypeError):  # TypeError if no session registered for thread
+                # TypeError if no session registered for thread
+                except (KeyError, TypeError):
                     limit = default
             else:
                 limit = c.user.get_pref('results_per_page') or default
@@ -403,26 +421,33 @@ class Globals(object):
             return h.html.literal('<em>Empty file</em>')
         # Don't use line numbers for diff highlight's, as per [#1484]
         if lexer == 'diff':
-            formatter = pygments.formatters.HtmlFormatter(cssclass='codehilite', linenos=False)
+            formatter = pygments.formatters.HtmlFormatter(
+                cssclass='codehilite', linenos=False)
         else:
             formatter = self.pygments_formatter
         if lexer is None:
             try:
-                lexer = pygments.lexers.get_lexer_for_filename(filename, encoding='chardet')
+                lexer = pygments.lexers.get_lexer_for_filename(
+                    filename, encoding='chardet')
             except pygments.util.ClassNotFound:
-                # no highlighting, but we should escape, encode, and wrap it in a <pre>
+                # no highlighting, but we should escape, encode, and wrap it in
+                # a <pre>
                 text = h.really_unicode(text)
                 text = cgi.escape(text)
                 return h.html.literal(u'<pre>' + text + u'</pre>')
         else:
-            lexer = pygments.lexers.get_lexer_by_name(lexer, encoding='chardet')
+            lexer = pygments.lexers.get_lexer_by_name(
+                lexer, encoding='chardet')
         return h.html.literal(pygments.highlight(text, lexer, formatter))
 
     def forge_markdown(self, **kwargs):
         '''return a markdown.Markdown object on which you can call convert'''
         return ForgeMarkdown(
-                extensions=['codehilite', ForgeExtension(**kwargs), 'tables', 'toc', 'nl2br'], # 'fenced_code'
-                output_format='html4')
+            # 'fenced_code'
+            extensions=['codehilite',
+                        ForgeExtension(
+                            **kwargs), 'tables', 'toc', 'nl2br'],
+            output_format='html4')
 
     @property
     def markdown(self):
@@ -444,7 +469,7 @@ class Globals(object):
         """
         app = getattr(c, 'app', None)
         return ForgeMarkdown(extensions=[CommitMessageExtension(app), 'nl2br'],
-                output_format='html4')
+                             output_format='html4')
 
     @property
     def production_mode(self):
@@ -485,7 +510,7 @@ class Globals(object):
             for size in (24, 32, 48):
                 url = self.theme.app_icon_url(tool_name.lower(), size)
                 css += '.ui-icon-tool-%s-%i {background: url(%s) no-repeat;}\n' % (
-                        tool_name, size, url)
+                    tool_name, size, url)
         return css, hashlib.md5(css).hexdigest()
 
     @property
@@ -580,10 +605,13 @@ class Globals(object):
     def year(self):
         return datetime.datetime.utcnow().year
 
+
 class Icon(object):
+
     def __init__(self, char, css):
         self.char = char
         self.css = css
 
+
 def connect_amqp(config):
     return

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/lib/async.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/async.py b/Allura/allura/lib/async.py
index 6e03d6c..d299160 100644
--- a/Allura/allura/lib/async.py
+++ b/Allura/allura/lib/async.py
@@ -20,6 +20,7 @@ from Queue import Queue
 
 log = logging.getLogger(__name__)
 
+
 class Connection(object):
 
     def __init__(self, hostname, port, userid, password, vhost):
@@ -37,6 +38,7 @@ class Connection(object):
         self._conn = self._connection_pool.acquire()
         self.queue = self._conn.SimpleQueue('task')
 
+
 class MockAMQ(object):
 
     def __init__(self, globals):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/lib/base.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/base.py b/Allura/allura/lib/base.py
index 409b77c..bac6a2b 100644
--- a/Allura/allura/lib/base.py
+++ b/Allura/allura/lib/base.py
@@ -24,7 +24,9 @@ from tg import TGController, config
 
 __all__ = ['WsgiDispatchController']
 
+
 class WsgiDispatchController(TGController):
+
     """
     Base class for the controllers in the application.
 
@@ -43,13 +45,15 @@ class WsgiDispatchController(TGController):
     def __call__(self, environ, start_response):
         try:
             self._setup_request()
-            response = super(WsgiDispatchController, self).__call__(environ, start_response)
+            response = super(WsgiDispatchController, self).__call__(
+                environ, start_response)
             return self.cleanup_iterator(response)
         except exc.HTTPException, err:
             return err(environ, start_response)
 
     def cleanup_iterator(self, response):
-        for chunk in response: yield chunk
+        for chunk in response:
+            yield chunk
         self._cleanup_request()
 
     def _get_dispatchable(self, url_path):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/lib/custom_middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 940c534..9cb20da 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -38,13 +38,15 @@ log = logging.getLogger(__name__)
 
 tool_entry_points = list(h.iter_entry_points('allura'))
 
+
 class StaticFilesMiddleware(object):
+
     '''Custom static file middleware
 
     Map everything in allura/public/nf/* to <script_name>/*
     For each plugin, map everything <module>/nf/<ep_name>/* to <script_name>/<ep_name>/*
     '''
-    CACHE_MAX_AGE=60*60*24*365
+    CACHE_MAX_AGE = 60 * 60 * 24 * 365
 
     def __init__(self, app, script_name=''):
         self.app = app
@@ -74,16 +76,18 @@ class StaticFilesMiddleware(object):
                         ep.name.lower(),
                         filename))
                 return fileapp.FileApp(file_path, [
-                        ('Access-Control-Allow-Origin', '*')])
+                    ('Access-Control-Allow-Origin', '*')])
         filename = environ['PATH_INFO'][len(self.script_name):]
         file_path = pkg_resources.resource_filename(
             'allura', os.path.join(
                 'public', 'nf',
                 filename))
         return fileapp.FileApp(file_path, [
-                ('Access-Control-Allow-Origin', '*')])
+            ('Access-Control-Allow-Origin', '*')])
+
 
 class LoginRedirectMiddleware(object):
+
     '''Actually converts a 401 into a 302 so we can do a redirect to a different
     app for login.  (StatusCodeRedirect does a WSGI-only redirect which cannot
     go to a URL not managed by the WSGI stack).'''
@@ -110,13 +114,16 @@ class LoginRedirectMiddleware(object):
         start_response(status, headers, exc_info)
         return app_iter
 
+
 class CSRFMiddleware(object):
+
     '''On POSTs, looks for a special field name that matches the value of a given
     cookie.  If this field is missing, the cookies are cleared to anonymize the
     request.'''
 
     def __init__(self, app, cookie_name, param_name=None):
-        if param_name is None: param_name = cookie_name
+        if param_name is None:
+            param_name = cookie_name
         self._app = app
         self._param_name = param_name
         self._cookie_name = cookie_name
@@ -131,7 +138,8 @@ class CSRFMiddleware(object):
             if cookie != param:
                 log.warning('CSRF attempt detected, %r != %r', cookie, param)
                 environ.pop('HTTP_COOKIE', None)
-        def session_start_response(status, headers, exc_info = None):
+
+        def session_start_response(status, headers, exc_info=None):
             if dict(headers).get('Content-Type', '').startswith('text/html'):
                 headers.append(
                     ('Set-cookie',
@@ -139,7 +147,9 @@ class CSRFMiddleware(object):
             return start_response(status, headers, exc_info)
         return self._app(environ, session_start_response)
 
+
 class SSLMiddleware(object):
+
     'Verify the https/http schema is correct'
 
     def __init__(self, app, no_redirect_pattern=None, force_ssl_pattern=None):
@@ -168,8 +178,10 @@ class SSLMiddleware(object):
         # This SFUSER check is SourceForge-specific (to require all logged-in users to use https)
         # BUT has the additional affect of not forcing SSL for regular Allura instances
         # This is important for local development, at least.  When we remove SFUSER (perhaps by requiring SSL everywhere),
-        # we can use `no_redirect.pattern = .` for local development to work without SSL
-        force_ssl = req.cookies.get('SFUSER') or self._force_ssl_re.match(environ['PATH_INFO'])
+        # we can use `no_redirect.pattern = .` for local development to work
+        # without SSL
+        force_ssl = req.cookies.get(
+            'SFUSER') or self._force_ssl_re.match(environ['PATH_INFO'])
         if not secure and force_ssl:
             resp = exc.HTTPFound(location='https://' + srv_path)
         elif secure and not force_ssl:
@@ -179,7 +191,9 @@ class SSLMiddleware(object):
             resp = self.app
         return resp(environ, start_response)
 
+
 class AlluraTimerMiddleware(TimerMiddleware):
+
     def timers(self):
         import genshi
         import jinja2
@@ -191,42 +205,50 @@ class AlluraTimerMiddleware(TimerMiddleware):
         import activitystream
 
         return self.entry_point_timers() + [
-            Timer('activitystream.director.{method_name}', allura.model.timeline.Director,
+            Timer(
+                'activitystream.director.{method_name}', allura.model.timeline.Director,
                 'create_activity', 'create_timeline', 'get_timeline'),
-            Timer('activitystream.aggregator.{method_name}', allura.model.timeline.Aggregator, '*'),
-            Timer('activitystream.node_manager.{method_name}', activitystream.managers.NodeManager, '*'),
-            Timer('activitystream.activity_manager.{method_name}', activitystream.managers.ActivityManager, '*'),
+            Timer('activitystream.aggregator.{method_name}',
+                  allura.model.timeline.Aggregator, '*'),
+            Timer('activitystream.node_manager.{method_name}',
+                  activitystream.managers.NodeManager, '*'),
+            Timer('activitystream.activity_manager.{method_name}',
+                  activitystream.managers.ActivityManager, '*'),
             Timer('jinja', jinja2.Template, 'render', 'stream', 'generate'),
             Timer('markdown', markdown.Markdown, 'convert'),
             Timer('ming', ming.odm.odmsession.ODMCursor, 'next',  # FIXME: this may captures timings ok, but is misleading for counts
                   debug_each_call=False),
             Timer('ming', ming.odm.odmsession.ODMSession, 'flush', 'find'),
             Timer('ming', ming.schema.Document, 'validate',
-                debug_each_call=False),
+                  debug_each_call=False),
             Timer('ming', ming.schema.FancySchemaItem, '_validate_required',
-                '_validate_fast_missing', '_validate_optional',
-                debug_each_call=False),
+                  '_validate_fast_missing', '_validate_optional',
+                  debug_each_call=False),
             Timer('mongo', pymongo.collection.Collection, 'count', 'find',
-                'find_one'),
+                  'find_one'),
             Timer('mongo', pymongo.cursor.Cursor, 'count', 'distinct',
-                '_refresh'),
+                  '_refresh'),
             # urlopen and socket io may or may not overlap partially
             Timer('render', genshi.Stream, 'render'),
             Timer('repo.Blob.{method_name}', allura.model.repo.Blob, '*'),
             Timer('repo.Commit.{method_name}', allura.model.repo.Commit, '*'),
-            Timer('repo.LastCommit.{method_name}', allura.model.repo.LastCommit, '*'),
+            Timer('repo.LastCommit.{method_name}',
+                  allura.model.repo.LastCommit, '*'),
             Timer('repo.Tree.{method_name}', allura.model.repo.Tree, '*'),
             Timer('socket_read', socket._fileobject, 'read', 'readline',
-                'readlines', debug_each_call=False),
+                  'readlines', debug_each_call=False),
             Timer('socket_write', socket._fileobject, 'write', 'writelines',
-                'flush', debug_each_call=False),
+                  'flush', debug_each_call=False),
             Timer('solr', pysolr.Solr, 'add', 'delete', 'search', 'commit'),
             Timer('template', genshi.template.Template, '_prepare', '_parse',
-                'generate'),
+                  'generate'),
             Timer('urlopen', urllib2, 'urlopen'),
-            Timer('base_repo_tool.{method_name}', allura.model.repository.RepositoryImplementation, 'last_commit_ids'),
+            Timer('base_repo_tool.{method_name}',
+                  allura.model.repository.RepositoryImplementation, 'last_commit_ids'),
             Timer('_diffs_copied', allura.model.repo.Commit, '_diffs_copied'),
-            Timer('sequencematcher.{method_name}', allura.model.repo.SequenceMatcher, 'ratio', 'quick_ratio', 'real_quick_ratio'),
+            Timer(
+                'sequencematcher.{method_name}', allura.model.repo.SequenceMatcher,
+                'ratio', 'quick_ratio', 'real_quick_ratio'),
             Timer('unified_diff', allura.model.repo, 'unified_diff'),
         ] + [Timer('sidebar', ep.load(), 'sidebar_menu') for ep in tool_entry_points]
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/lib/decorators.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/decorators.py b/Allura/allura/lib/decorators.py
index 8604a92..28ad5bf 100644
--- a/Allura/allura/lib/decorators.py
+++ b/Allura/allura/lib/decorators.py
@@ -56,7 +56,7 @@ def task(*args, **kw):
             delay = kwargs.pop('delay', 0)
             project = getattr(c, 'project', None)
             cm = (h.notifications_disabled if project and
-                    kw.get('notifications_disabled') else h.null_contextmanager)
+                  kw.get('notifications_disabled') else h.null_contextmanager)
             with cm(project):
                 from allura import model as M
                 return M.MonQTask.post(func, args, kwargs, delay=delay)
@@ -68,7 +68,9 @@ def task(*args, **kw):
         return task_(args[0])
     return task_
 
+
 class event_handler(object):
+
     '''Decorator to register event handlers'''
     listeners = defaultdict(set)
 
@@ -80,6 +82,7 @@ class event_handler(object):
             self.listeners[t].add(func)
         return func
 
+
 class require_post(object):
 
     def __init__(self, redir=None):
@@ -90,18 +93,20 @@ class require_post(object):
             if request.method != 'POST':
                 if self.redir is not None:
                     redirect(self.redir)
-                raise exc.HTTPMethodNotAllowed(headers={'Allow':'POST'})
+                raise exc.HTTPMethodNotAllowed(headers={'Allow': 'POST'})
         before_validate(check_method)(func)
         return func
 
-class log_action(object): # pragma no cover
+
+class log_action(object):  # pragma no cover
 
     def __init__(self,
                  logger=None,
                  level=logging.INFO,
                  msg=None,
                  *args, **kwargs):
-        if logger is None: logger = logging
+        if logger is None:
+            logger = logging
         self._logger = logger
         self._level = level
         self._msg = msg
@@ -119,7 +124,7 @@ class log_action(object): # pragma no cover
         self._extra_proto.update(action=func.__name__)
         if self._msg is None:
             self._msg = func.__name__
-        result = lambda *args,**kwargs: self._wrapper(*args,**kwargs)
+        result = lambda *args, **kwargs: self._wrapper(*args, **kwargs)
         # assert not hasattr(func, 'decoration')
         if hasattr(func, 'decoration'):
             result.decoration = func.decoration
@@ -166,9 +171,9 @@ class log_action(object): # pragma no cover
                          user_id=user.id)
         # Save the project info
         if (result
-            and isinstance(result, dict)
-            and 'p' in result
-            and result['p'] is not None):
+                and isinstance(result, dict)
+                and 'p' in result
+                and result['p'] is not None):
             extra.update(
                 source=result['p']['source'],
                 project_name=result['p']['shortname'],
@@ -184,16 +189,18 @@ class log_action(object): # pragma no cover
         extra['referer_link'] = referer_link
         return extra
 
+
 def Property(function):
     '''Decorator to easily assign descriptors based on sub-function names
     See <http://code.activestate.com/recipes/410698-property-decorator-for-python-24/>
     '''
     keys = 'fget', 'fset', 'fdel'
-    func_locals = {'doc':function.__doc__}
+    func_locals = {'doc': function.__doc__}
+
     def probeFunc(frame, event, arg):
         if event == 'return':
             locals = frame.f_locals
-            func_locals.update(dict((k,locals.get(k)) for k in keys))
+            func_locals.update(dict((k, locals.get(k)) for k in keys))
             sys.settrace(None)
         return probeFunc
     sys.settrace(probeFunc)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c93733ac/Allura/allura/lib/exceptions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/exceptions.py b/Allura/allura/lib/exceptions.py
index 7611dd7..8a33658 100644
--- a/Allura/allura/lib/exceptions.py
+++ b/Allura/allura/lib/exceptions.py
@@ -17,38 +17,77 @@
 
 from formencode import Invalid
 
-class ForgeError(Exception): pass
+
+class ForgeError(Exception):
+    pass
+
 
 class ProjectConflict(ForgeError, Invalid):
 
-    # support the single string constructor in addition to full set of params that Invalid.__init__ requires
+    # 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)
+        super(ProjectConflict, self).__init__(
+            msg, value, state, error_list, error_dict)
+
+
+class ProjectShortnameInvalid(ForgeError, Invalid):
+    pass
+
+
+class ProjectOverlimitError(ForgeError):
+    pass
+
+
+class ProjectRatelimitError(ForgeError):
+    pass
+
+
+class ToolError(ForgeError):
+    pass
+
+
+class NoSuchProjectError(ForgeError):
+    pass
+
 
+class NoSuchNeighborhoodError(ForgeError):
+    pass
+
+
+class NoSuchGlobalsError(ForgeError):
+    pass
+
+
+class MailError(ForgeError):
+    pass
+
+
+class AddressException(MailError):
+    pass
+
+
+class NoSuchNBFeatureError(ForgeError):
+    pass
+
+
+class InvalidNBFeatureValueError(ForgeError):
+    pass
 
-class ProjectShortnameInvalid(ForgeError, Invalid): pass
-class ProjectOverlimitError(ForgeError): pass
-class ProjectRatelimitError(ForgeError): pass
-class ToolError(ForgeError): pass
-class NoSuchProjectError(ForgeError): pass
-class NoSuchNeighborhoodError(ForgeError): pass
-class NoSuchGlobalsError(ForgeError): pass
-class MailError(ForgeError): pass
-class AddressException(MailError): pass
-class NoSuchNBFeatureError(ForgeError): pass
-class InvalidNBFeatureValueError(ForgeError): pass
 
 class CompoundError(ForgeError):
+
     def __repr__(self):
-        return '<%s>\n%s\n</%s>'  % (
+        return '<%s>\n%s\n</%s>' % (
             self.__class__.__name__,
             '\n'.join(map(repr, self.args)),
             self.__class__.__name__)
+
     def format_error(self):
         import traceback
-        parts = [ '<%s>\n' % self.__class__.__name__ ]
-        for tp,val,tb in self.args:
-            for line in traceback.format_exception(tp,val,tb):
+        parts = ['<%s>\n' % self.__class__.__name__]
+        for tp, val, tb in self.args:
+            for line in traceback.format_exception(tp, val, tb):
                 parts.append('    ' + line)
-        parts.append('</%s>\n' % self.__class__.__name__ )
+        parts.append('</%s>\n' % self.__class__.__name__)
         return ''.join(parts)